diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md index d2096256..3a899456 100644 --- a/ATTRIBUTION.md +++ b/ATTRIBUTION.md @@ -186,3 +186,5 @@ its original `egui.wgsl` shader are retained; no images or other artwork are cop SolidCraft's narrow patch selects a safe 1x MSAA path on the chosen OpenGL adapter and shares that effective count with the surface attachments and CAD callbacks. Vulkan, DirectX 12, Metal and WebGPU retain their requested multisampling. +A frame whose meshes the GPU refuses to stage (device lost or out of memory) is +skipped with a warning instead of panicking (#1469). diff --git a/vendor/README.md b/vendor/README.md index 62cd65e6..e748f75e 100644 --- a/vendor/README.md +++ b/vendor/README.md @@ -147,6 +147,8 @@ SolidCraft changes: - `src/lib.rs`: use 1x MSAA on the selected OpenGL adapter before creating pipelines, exposing the effective sample count so host paint callbacks can match it. - `src/winit.rs`: use that same effective count for depth and resolve attachments. +- `src/renderer.rs`: when the GPU refuses a staging buffer for a frame's meshes (device lost + or out of memory), log a warning and draw nothing that frame instead of panicking (#1469). - Other backends retain requested MSAA, without another adapter or device probe. - `src/lib.rs`: clamp MSAA to the largest sample count the device supports for the surface and depth formats (`supported_msaa_samples`, `RenderState::msaa_supported`): a saved 8x on a diff --git a/vendor/egui-wgpu/src/renderer.rs b/vendor/egui-wgpu/src/renderer.rs index de8808de..05b29b8f 100644 --- a/vendor/egui-wgpu/src/renderer.rs +++ b/vendor/egui-wgpu/src/renderer.rs @@ -254,6 +254,11 @@ pub struct Renderer { options: RendererOptions, + /// The last `update_buffers` could not upload this frame's meshes (the GPU refused a + /// staging buffer: device lost or out of memory), so `render` draws nothing this frame + /// instead of panicking (SolidCraft #1469). + skip_frame: bool, + /// Storage for resources shared with all invocations of [`CallbackTrait`]'s methods. /// /// See also [`CallbackTrait`]. @@ -453,6 +458,7 @@ impl Renderer { slices: Vec::with_capacity(64), capacity: INDEX_BUFFER_START_CAPACITY, }, + skip_frame: false, uniform_buffer, // Buffers on wgpu are zero initialized, so this is indeed its current state! previous_uniform_buffer_content: UniformBuffer::zeroed(), @@ -484,6 +490,10 @@ impl Renderer { ) { profiling::function_scope!(); + if self.skip_frame { + return; + } + let pixels_per_point = screen_descriptor.pixels_per_point; let size_in_pixels = screen_descriptor.size_in_pixels; @@ -922,6 +932,7 @@ impl Renderer { ) -> Vec { profiling::function_scope!(); + self.skip_frame = false; let screen_size_in_points = screen_descriptor.screen_size_in_points(); let uniform_buffer_content = UniformBuffer { @@ -981,11 +992,13 @@ impl Renderer { ); let Some(mut index_buffer_staging) = index_buffer_staging else { - panic!( - "Failed to create staging buffer for index data. Index count: {index_count}. Required index buffer size: {required_index_buffer_size}. Actual size {} and capacity: {} (bytes)", + log::warn!( + "Failed to create staging buffer for index data; skipping this frame. Index count: {index_count}. Required index buffer size: {required_index_buffer_size}. Actual size {} and capacity: {} (bytes)", self.index_buffer.buffer.size(), self.index_buffer.capacity ); + self.skip_frame = true; + return Vec::new(); }; let mut index_offset = 0; @@ -1027,11 +1040,13 @@ impl Renderer { ); let Some(mut vertex_buffer_staging) = vertex_buffer_staging else { - panic!( - "Failed to create staging buffer for vertex data. Vertex count: {vertex_count}. Required vertex buffer size: {required_vertex_buffer_size}. Actual size {} and capacity: {} (bytes)", + log::warn!( + "Failed to create staging buffer for vertex data; skipping this frame. Vertex count: {vertex_count}. Required vertex buffer size: {required_vertex_buffer_size}. Actual size {} and capacity: {} (bytes)", self.vertex_buffer.buffer.size(), self.vertex_buffer.capacity ); + self.skip_frame = true; + return Vec::new(); }; let mut vertex_offset = 0;