1
0
Fork 0
forked from wry/wry

Merge pull request #581 from mahkoh/jorth/mixed-device-use

Fix mixed-device-use error
This commit is contained in:
mahkoh 2025-08-29 13:46:11 +02:00 committed by GitHub
commit a138525351
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 48 additions and 40 deletions

View file

@ -291,8 +291,9 @@ impl MetalDeviceTransaction {
} }
*field = plane.obj.id; *field = plane.obj.id;
} }
let render_ctx = slf.dev.dev.backend.ctx.get();
let dev_ctx = slf.dev.dev.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() { for connector in slf.connectors.values_mut() {
let state = &connector.state; let state = &connector.state;
let dd = &*connector.obj.display.borrow(); 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 { if b[0].width != width || b[0].height != height || b[0].format != format {
discard!(); discard!();
} }
let Some(render_ctx) = &render_ctx else {
discard!();
};
if !rc_eq(render_ctx, &b[0].render_ctx) { if !rc_eq(render_ctx, &b[0].render_ctx) {
discard!(); discard!();
} }
@ -485,6 +483,7 @@ impl MetalDeviceTransaction {
Some(b) => b.clone(), Some(b) => b.clone(),
None => { None => {
let modifiers = &plane.obj.formats.get(&format.drm).unwrap().modifiers; let modifiers = &plane.obj.formats.get(&format.drm).unwrap().modifiers;
connector.changed.set(true);
let buffers = slf let buffers = slf
.dev .dev
.dev .dev
@ -495,7 +494,7 @@ impl MetalDeviceTransaction {
modifiers, modifiers,
width, width,
height, height,
&slf.dev.dev.ctx.get(), render_ctx,
plane.obj.ty == PlaneType::Cursor, plane.obj.ty == PlaneType::Cursor,
) )
.map_err(|e| { .map_err(|e| {

View file

@ -2581,12 +2581,12 @@ impl MetalBackend {
plane_modifiers: &IndexSet<Modifier>, plane_modifiers: &IndexSet<Modifier>,
width: i32, width: i32,
height: i32, height: i32,
ctx: &Rc<MetalRenderContext>, render_ctx: &Rc<MetalRenderContext>,
cursor: bool, cursor: bool,
) -> Result<[RenderBuffer; N], MetalError> { ) -> Result<[RenderBuffer; N], MetalError> {
let mut blend_buffer = None; let mut blend_buffer = None;
if !cursor { 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), Ok(bb) => blend_buffer = Some(bb),
Err(e) => { Err(e) => {
log::warn!("Could not create blend buffer: {}", ErrorFmt(e)); log::warn!("Could not create blend buffer: {}", ErrorFmt(e));
@ -2601,7 +2601,7 @@ impl MetalBackend {
plane_modifiers, plane_modifiers,
width, width,
height, height,
ctx, render_ctx,
cursor, cursor,
damage_queue.pop().unwrap(), damage_queue.pop().unwrap(),
blend_buffer.clone(), blend_buffer.clone(),

View file

@ -329,7 +329,10 @@ fn fill_boxes3(ctx: &GlRenderContext, boxes: &[[f32; 2]], color: &Color) {
} }
fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) { 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() { if !texture.gl.contents_valid.get() {
log::error!("Ignoring texture with invalid contents"); log::error!("Ignoring texture with invalid contents");
return; return;
@ -437,10 +440,8 @@ fn handle_explicit_sync(ctx: &GlRenderContext, img: Option<&Rc<EglImage>>, sync:
} }
impl dyn GfxTexture { impl dyn GfxTexture {
fn as_gl(&self) -> &Texture { fn as_gl(&self) -> Option<&Texture> {
(self as &dyn Any) (self as &dyn Any).downcast_ref()
.downcast_ref()
.expect("Non-gl texture passed into gl")
} }
} }

View file

@ -210,6 +210,10 @@ pub enum VulkanError {
BusyInTransfer, BusyInTransfer,
#[error("Driver does not support descriptor buffers")] #[error("Driver does not support descriptor buffers")]
NoDescriptorBuffer, NoDescriptorBuffer,
#[error("A non-vulkan buffer was passed into the vulkan renderer")]
NonVulkanBuffer,
#[error("Mixed vulkan device use")]
MixedVulkanDeviceUse,
} }
impl From<VulkanError> for GfxError { impl From<VulkanError> for GfxError {
@ -284,7 +288,7 @@ impl GfxContext for Context {
damage: Option<&[Rect]>, damage: Option<&[Rect]>,
) -> Result<Rc<dyn ShmGfxTexture>, GfxError> { ) -> Result<Rc<dyn ShmGfxTexture>, GfxError> {
if let Some(old) = old { if let Some(old) = old {
let old = (old as Rc<dyn GfxTexture>).into_vk(&self.0.device.device); let old = (old as Rc<dyn GfxTexture>).into_vk(&self.0.device.device)?;
let shm = match &old.ty { let shm = match &old.ty {
VulkanImageMemory::DmaBuf(_) => unreachable!(), VulkanImageMemory::DmaBuf(_) => unreachable!(),
VulkanImageMemory::Blend(_) => unreachable!(), VulkanImageMemory::Blend(_) => unreachable!(),

View file

@ -556,8 +556,9 @@ impl GfxFramebuffer for VulkanImage {
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>, blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
blend_cd: &Rc<ColorDescription>, blend_cd: &Rc<ColorDescription>,
) -> Result<Option<SyncFile>, GfxError> { ) -> Result<Option<SyncFile>, GfxError> {
let mut blend_buffer = let mut blend_buffer = blend_buffer
blend_buffer.map(|b| b.clone().into_vk(&self.renderer.device.device)); .map(|b| b.clone().into_vk(&self.renderer.device.device))
.transpose()?;
if let Some(bb) = &blend_buffer if let Some(bb) = &blend_buffer
&& bb.size() != self.size() && bb.size() != self.size()
{ {

View file

@ -627,7 +627,7 @@ impl VulkanRenderer {
opts: &[GfxApiOpt], opts: &[GfxApiOpt],
blend_cd: &ColorDescription, blend_cd: &ColorDescription,
fb_cd: &ColorDescription, fb_cd: &ColorDescription,
) { ) -> Result<(), VulkanError> {
zone!("convert_ops"); zone!("convert_ops");
let memory = &mut *self.memory.borrow_mut(); let memory = &mut *self.memory.borrow_mut();
for ops in memory.ops.values_mut() { for ops in memory.ops.values_mut() {
@ -744,7 +744,7 @@ impl VulkanRenderer {
} }
} }
GfxApiOpt::CopyTexture(ct) => { 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() { if tex.contents_are_undefined.get() {
log::warn!("Ignoring undefined texture"); log::warn!("Ignoring undefined texture");
continue; continue;
@ -815,6 +815,7 @@ impl VulkanRenderer {
} }
} }
sync(memory); sync(memory);
Ok(())
} }
fn create_data_buffer(&self) -> Result<(), VulkanError> { fn create_data_buffer(&self) -> Result<(), VulkanError> {
@ -1735,7 +1736,7 @@ impl VulkanRenderer {
clear: Option<&Color>, clear: Option<&Color>,
region: &Region, region: &Region,
bb: Option<&VulkanImage>, bb: Option<&VulkanImage>,
) { ) -> Result<(), VulkanError> {
zone!("create_paint_regions"); zone!("create_paint_regions");
let memory = &mut *self.memory.borrow_mut(); let memory = &mut *self.memory.borrow_mut();
memory.regions_1.clear(); memory.regions_1.clear();
@ -1755,7 +1756,7 @@ impl VulkanRenderer {
break 'opaque false; break 'opaque false;
} }
if !c.opaque { 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 { if tex.format.has_alpha {
break 'opaque false; break 'opaque false;
} }
@ -1848,6 +1849,7 @@ impl VulkanRenderer {
}); });
} }
} }
Ok(())
} }
fn elide_blend_buffer(&self, blend_buffer: &mut Option<Rc<VulkanImage>>) { fn elide_blend_buffer(&self, blend_buffer: &mut Option<Rc<VulkanImage>>) {
@ -1874,11 +1876,11 @@ impl VulkanRenderer {
bb_cd: &Rc<ColorDescription>, bb_cd: &Rc<ColorDescription>,
) -> Result<(), VulkanError> { ) -> Result<(), VulkanError> {
self.check_defunct()?; 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); self.elide_blend_buffer(&mut blend_buffer);
let bb = blend_buffer.as_deref(); let bb = blend_buffer.as_deref();
let buf = self.gfx_command_buffers.allocate()?; 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_data_buffer()?;
self.create_uniform_buffer()?; self.create_uniform_buffer()?;
self.collect_memory(); self.collect_memory();
@ -1956,40 +1958,41 @@ impl Debug for VulkanRenderer {
} }
impl VulkanImage { impl VulkanImage {
fn assert_device(&self, device: &Device) { fn assert_device(&self, device: &Device) -> Result<(), VulkanError> {
assert_eq!( if self.renderer.device.device.handle() != device.handle() {
self.renderer.device.device.handle(), return Err(VulkanError::MixedVulkanDeviceUse);
device.handle(), }
"Mixed vulkan device use" Ok(())
);
} }
} }
impl dyn GfxTexture { 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) let img: &VulkanImage = (self as &dyn Any)
.downcast_ref() .downcast_ref()
.expect("Non-vulkan texture passed into vulkan"); .ok_or(VulkanError::NonVulkanBuffer)?;
img.assert_device(device); img.assert_device(device)?;
img Ok(img)
} }
pub(super) fn into_vk(self: Rc<Self>, device: &Device) -> Rc<VulkanImage> { pub(super) fn into_vk(self: Rc<Self>, device: &Device) -> Result<Rc<VulkanImage>, VulkanError> {
let img: Rc<VulkanImage> = (self as Rc<dyn Any>) let img: Rc<VulkanImage> = (self as Rc<dyn Any>)
.downcast() .downcast()
.expect("Non-vulkan texture passed into vulkan"); .ok()
img.assert_device(device); .ok_or(VulkanError::NonVulkanBuffer)?;
img img.assert_device(device)?;
Ok(img)
} }
} }
impl dyn GfxBlendBuffer { impl dyn GfxBlendBuffer {
pub(super) fn into_vk(self: Rc<Self>, device: &Device) -> Rc<VulkanImage> { pub(super) fn into_vk(self: Rc<Self>, device: &Device) -> Result<Rc<VulkanImage>, VulkanError> {
let img: Rc<VulkanImage> = (self as Rc<dyn Any>) let img: Rc<VulkanImage> = (self as Rc<dyn Any>)
.downcast() .downcast()
.expect("Non-vulkan blend buffer passed into vulkan"); .ok()
img.assert_device(device); .ok_or(VulkanError::NonVulkanBuffer)?;
img img.assert_device(device)?;
Ok(img)
} }
} }