From 5e9bc64757b4d0613af897b1da092880f6128029 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Fri, 29 Aug 2025 13:33:42 +0200 Subject: [PATCH 1/5] vulkan: make mixed device use a non-fatal error --- src/gfx_apis/vulkan.rs | 6 +++- src/gfx_apis/vulkan/image.rs | 5 ++-- src/gfx_apis/vulkan/renderer.rs | 51 +++++++++++++++++---------------- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/gfx_apis/vulkan.rs b/src/gfx_apis/vulkan.rs index 4b9282fa..c8295659 100644 --- a/src/gfx_apis/vulkan.rs +++ b/src/gfx_apis/vulkan.rs @@ -210,6 +210,10 @@ pub enum VulkanError { BusyInTransfer, #[error("Driver does not support descriptor buffers")] NoDescriptorBuffer, + #[error("A non-vulkan buffer was passed into the vulkan renderer")] + NonVulkanBuffer, + #[error("Mixed vulkan device use")] + MixedVulkanDeviceUse, } impl From for GfxError { @@ -284,7 +288,7 @@ impl GfxContext for Context { damage: Option<&[Rect]>, ) -> Result, GfxError> { if let Some(old) = old { - let old = (old as Rc).into_vk(&self.0.device.device); + let old = (old as Rc).into_vk(&self.0.device.device)?; let shm = match &old.ty { VulkanImageMemory::DmaBuf(_) => unreachable!(), VulkanImageMemory::Blend(_) => unreachable!(), diff --git a/src/gfx_apis/vulkan/image.rs b/src/gfx_apis/vulkan/image.rs index 09f4bf7a..4216e84e 100644 --- a/src/gfx_apis/vulkan/image.rs +++ b/src/gfx_apis/vulkan/image.rs @@ -556,8 +556,9 @@ impl GfxFramebuffer for VulkanImage { blend_buffer: Option<&Rc>, blend_cd: &Rc, ) -> Result, GfxError> { - let mut blend_buffer = - blend_buffer.map(|b| b.clone().into_vk(&self.renderer.device.device)); + let mut blend_buffer = blend_buffer + .map(|b| b.clone().into_vk(&self.renderer.device.device)) + .transpose()?; if let Some(bb) = &blend_buffer && bb.size() != self.size() { diff --git a/src/gfx_apis/vulkan/renderer.rs b/src/gfx_apis/vulkan/renderer.rs index b384af96..fd461e7c 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -627,7 +627,7 @@ impl VulkanRenderer { opts: &[GfxApiOpt], blend_cd: &ColorDescription, fb_cd: &ColorDescription, - ) { + ) -> Result<(), VulkanError> { zone!("convert_ops"); let memory = &mut *self.memory.borrow_mut(); for ops in memory.ops.values_mut() { @@ -744,7 +744,7 @@ impl VulkanRenderer { } } GfxApiOpt::CopyTexture(ct) => { - let tex = ct.tex.clone().into_vk(&self.device.device); + let tex = ct.tex.clone().into_vk(&self.device.device)?; if tex.contents_are_undefined.get() { log::warn!("Ignoring undefined texture"); continue; @@ -815,6 +815,7 @@ impl VulkanRenderer { } } sync(memory); + Ok(()) } fn create_data_buffer(&self) -> Result<(), VulkanError> { @@ -1735,7 +1736,7 @@ impl VulkanRenderer { clear: Option<&Color>, region: &Region, bb: Option<&VulkanImage>, - ) { + ) -> Result<(), VulkanError> { zone!("create_paint_regions"); let memory = &mut *self.memory.borrow_mut(); memory.regions_1.clear(); @@ -1755,7 +1756,7 @@ impl VulkanRenderer { break 'opaque false; } if !c.opaque { - let tex = c.tex.as_vk(&self.device.device); + let tex = c.tex.as_vk(&self.device.device)?; if tex.format.has_alpha { break 'opaque false; } @@ -1848,6 +1849,7 @@ impl VulkanRenderer { }); } } + Ok(()) } fn elide_blend_buffer(&self, blend_buffer: &mut Option>) { @@ -1874,11 +1876,11 @@ impl VulkanRenderer { bb_cd: &Rc, ) -> Result<(), VulkanError> { self.check_defunct()?; - self.create_regions(fb, opts, clear, region, blend_buffer.as_deref()); + self.create_regions(fb, opts, clear, region, blend_buffer.as_deref())?; self.elide_blend_buffer(&mut blend_buffer); let bb = blend_buffer.as_deref(); let buf = self.gfx_command_buffers.allocate()?; - self.convert_ops(opts, bb_cd, fb_cd); + self.convert_ops(opts, bb_cd, fb_cd)?; self.create_data_buffer()?; self.create_uniform_buffer()?; self.collect_memory(); @@ -1956,40 +1958,41 @@ impl Debug for VulkanRenderer { } impl VulkanImage { - fn assert_device(&self, device: &Device) { - assert_eq!( - self.renderer.device.device.handle(), - device.handle(), - "Mixed vulkan device use" - ); + fn assert_device(&self, device: &Device) -> Result<(), VulkanError> { + if self.renderer.device.device.handle() != device.handle() { + return Err(VulkanError::MixedVulkanDeviceUse); + } + Ok(()) } } impl dyn GfxTexture { - fn as_vk(&self, device: &Device) -> &VulkanImage { + fn as_vk(&self, device: &Device) -> Result<&VulkanImage, VulkanError> { let img: &VulkanImage = (self as &dyn Any) .downcast_ref() - .expect("Non-vulkan texture passed into vulkan"); - img.assert_device(device); - img + .ok_or(VulkanError::NonVulkanBuffer)?; + img.assert_device(device)?; + Ok(img) } - pub(super) fn into_vk(self: Rc, device: &Device) -> Rc { + pub(super) fn into_vk(self: Rc, device: &Device) -> Result, VulkanError> { let img: Rc = (self as Rc) .downcast() - .expect("Non-vulkan texture passed into vulkan"); - img.assert_device(device); - img + .ok() + .ok_or(VulkanError::NonVulkanBuffer)?; + img.assert_device(device)?; + Ok(img) } } impl dyn GfxBlendBuffer { - pub(super) fn into_vk(self: Rc, device: &Device) -> Rc { + pub(super) fn into_vk(self: Rc, device: &Device) -> Result, VulkanError> { let img: Rc = (self as Rc) .downcast() - .expect("Non-vulkan blend buffer passed into vulkan"); - img.assert_device(device); - img + .ok() + .ok_or(VulkanError::NonVulkanBuffer)?; + img.assert_device(device)?; + Ok(img) } } From 384eb80e894853b392a74710a0f0dec5283ba207 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Fri, 29 Aug 2025 13:37:53 +0200 Subject: [PATCH 2/5] opengl: make mixed device use a non-fatal error --- src/gfx_apis/gl.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/gfx_apis/gl.rs b/src/gfx_apis/gl.rs index c2440002..283ee59c 100644 --- a/src/gfx_apis/gl.rs +++ b/src/gfx_apis/gl.rs @@ -329,7 +329,10 @@ fn fill_boxes3(ctx: &GlRenderContext, boxes: &[[f32; 2]], color: &Color) { } fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) { - let texture = tex.tex.as_gl(); + let Some(texture) = tex.tex.as_gl() else { + log::error!("A non-OpenGL texture was passed into OpenGL"); + return; + }; if !texture.gl.contents_valid.get() { log::error!("Ignoring texture with invalid contents"); return; @@ -437,10 +440,8 @@ fn handle_explicit_sync(ctx: &GlRenderContext, img: Option<&Rc>, sync: } impl dyn GfxTexture { - fn as_gl(&self) -> &Texture { - (self as &dyn Any) - .downcast_ref() - .expect("Non-gl texture passed into gl") + fn as_gl(&self) -> Option<&Texture> { + (self as &dyn Any).downcast_ref() } } From 886627aecdaa0f224a53f75c34097dedfb63794b Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Fri, 29 Aug 2025 13:26:46 +0200 Subject: [PATCH 3/5] metal: mark connector as changed when connector buffers change --- src/backends/metal/transaction.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backends/metal/transaction.rs b/src/backends/metal/transaction.rs index abe1321f..19eed0b3 100644 --- a/src/backends/metal/transaction.rs +++ b/src/backends/metal/transaction.rs @@ -485,6 +485,7 @@ impl MetalDeviceTransaction { Some(b) => b.clone(), None => { let modifiers = &plane.obj.formats.get(&format.drm).unwrap().modifiers; + connector.changed.set(true); let buffers = slf .dev .dev From c1f5f306fc422901a2db22b15de39606a2839b04 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Fri, 29 Aug 2025 13:26:04 +0200 Subject: [PATCH 4/5] metal: make argument name unambiguous --- src/backends/metal/video.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index ecf24277..1401c29b 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -2581,12 +2581,12 @@ impl MetalBackend { plane_modifiers: &IndexSet, width: i32, height: i32, - ctx: &Rc, + render_ctx: &Rc, cursor: bool, ) -> Result<[RenderBuffer; N], MetalError> { let mut blend_buffer = None; if !cursor { - match ctx.gfx.acquire_blend_buffer(width, height) { + match render_ctx.gfx.acquire_blend_buffer(width, height) { Ok(bb) => blend_buffer = Some(bb), Err(e) => { log::warn!("Could not create blend buffer: {}", ErrorFmt(e)); @@ -2601,7 +2601,7 @@ impl MetalBackend { plane_modifiers, width, height, - ctx, + render_ctx, cursor, damage_queue.pop().unwrap(), blend_buffer.clone(), From ed065fb9f24cb862f9017efb32597aeaa419b2df Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Fri, 29 Aug 2025 13:27:56 +0200 Subject: [PATCH 5/5] metal: use the correct graphics context when allocating buffers --- src/backends/metal/transaction.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/backends/metal/transaction.rs b/src/backends/metal/transaction.rs index 19eed0b3..a43a288e 100644 --- a/src/backends/metal/transaction.rs +++ b/src/backends/metal/transaction.rs @@ -291,8 +291,9 @@ impl MetalDeviceTransaction { } *field = plane.obj.id; } - let render_ctx = slf.dev.dev.backend.ctx.get(); let dev_ctx = slf.dev.dev.ctx.get(); + let render_ctx = slf.dev.dev.backend.ctx.get(); + let render_ctx = render_ctx.as_ref().unwrap_or(&dev_ctx); for connector in slf.connectors.values_mut() { let state = &connector.state; let dd = &*connector.obj.display.borrow(); @@ -463,9 +464,6 @@ impl MetalDeviceTransaction { if b[0].width != width || b[0].height != height || b[0].format != format { discard!(); } - let Some(render_ctx) = &render_ctx else { - discard!(); - }; if !rc_eq(render_ctx, &b[0].render_ctx) { discard!(); } @@ -496,7 +494,7 @@ impl MetalDeviceTransaction { modifiers, width, height, - &slf.dev.dev.ctx.get(), + render_ctx, plane.obj.ty == PlaneType::Cursor, ) .map_err(|e| {