mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-01-10 04:08:33 -05:00
[deno] Fix dropping of command encoders/buffers, and an enum typo (#7808)
Fixes #7797
This commit is contained in:
@@ -9,6 +9,11 @@ webgpu:api,operation,compute,basic:memcpy:*
|
||||
//FAIL: webgpu:api,operation,compute,basic:large_dispatch:*
|
||||
webgpu:api,operation,compute_pipeline,overrides:*
|
||||
webgpu:api,operation,device,lost:*
|
||||
webgpu:api,validation,queue,submit:command_buffer,device_mismatch:*
|
||||
webgpu:api,validation,queue,submit:command_buffer,duplicate_buffers:*
|
||||
webgpu:api,validation,queue,submit:command_buffer,submit_invalidates:*
|
||||
//FAIL: webgpu:api,validation,queue,submit:command_buffer,invalid_submit_invalidates:*
|
||||
// https://github.com/gfx-rs/wgpu/issues/3911#issuecomment-2972995675
|
||||
webgpu:api,operation,render_pipeline,overrides:*
|
||||
webgpu:api,operation,rendering,basic:clear:*
|
||||
webgpu:api,operation,rendering,basic:fullscreen_quad:*
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use std::cell::OnceCell;
|
||||
|
||||
use deno_core::op2;
|
||||
use deno_core::GarbageCollected;
|
||||
use deno_core::WebIDL;
|
||||
@@ -12,15 +10,11 @@ pub struct GPUCommandBuffer {
|
||||
pub instance: Instance,
|
||||
pub id: wgpu_core::id::CommandBufferId,
|
||||
pub label: String,
|
||||
|
||||
pub consumed: OnceCell<()>,
|
||||
}
|
||||
|
||||
impl Drop for GPUCommandBuffer {
|
||||
fn drop(&mut self) {
|
||||
if self.consumed.get().is_none() {
|
||||
self.instance.command_buffer_drop(self.id);
|
||||
}
|
||||
self.instance.command_buffer_drop(self.id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use deno_core::cppgc::Ptr;
|
||||
use deno_core::op2;
|
||||
@@ -28,11 +29,19 @@ pub struct GPUCommandEncoder {
|
||||
|
||||
pub id: wgpu_core::id::CommandEncoderId,
|
||||
pub label: String,
|
||||
|
||||
pub finished: AtomicBool,
|
||||
}
|
||||
|
||||
impl Drop for GPUCommandEncoder {
|
||||
fn drop(&mut self) {
|
||||
self.instance.command_encoder_drop(self.id);
|
||||
// Command encoders and command buffers are both the same wgpu object.
|
||||
// At the time `finished` is set, ownership of the id (and
|
||||
// responsibility for dropping it) transfers from the encoder to the
|
||||
// buffer.
|
||||
if !self.finished.load(Ordering::SeqCst) {
|
||||
self.instance.command_encoder_drop(self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,23 +416,34 @@ impl GPUCommandEncoder {
|
||||
fn finish(
|
||||
&self,
|
||||
#[webidl] descriptor: crate::command_buffer::GPUCommandBufferDescriptor,
|
||||
) -> GPUCommandBuffer {
|
||||
) -> Result<GPUCommandBuffer, JsErrorBox> {
|
||||
let wgpu_descriptor = wgpu_types::CommandBufferDescriptor {
|
||||
label: crate::transform_label(descriptor.label.clone()),
|
||||
};
|
||||
|
||||
// TODO(https://github.com/gfx-rs/wgpu/issues/7812): This is not right,
|
||||
// it should be a validation error, and it would be nice if we can just
|
||||
// let wgpu generate it for us. The problem is that if the encoder was
|
||||
// already finished, we transferred ownership of the id to a command
|
||||
// buffer, so we have to bail out before we mint a duplicate command
|
||||
// buffer with the same id below.
|
||||
if self.finished.fetch_or(true, Ordering::SeqCst) {
|
||||
return Err(JsErrorBox::type_error(
|
||||
"The command encoder has already finished.",
|
||||
));
|
||||
}
|
||||
|
||||
let (id, err) = self
|
||||
.instance
|
||||
.command_encoder_finish(self.id, &wgpu_descriptor);
|
||||
|
||||
self.error_handler.push_error(err);
|
||||
|
||||
GPUCommandBuffer {
|
||||
Ok(GPUCommandBuffer {
|
||||
instance: self.instance.clone(),
|
||||
id,
|
||||
label: descriptor.label,
|
||||
consumed: Default::default(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn push_debug_group(&self, #[webidl] group_label: String) {
|
||||
|
||||
@@ -498,6 +498,7 @@ impl GPUDevice {
|
||||
error_handler: self.error_handler.clone(),
|
||||
id,
|
||||
label,
|
||||
finished: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,17 +59,8 @@ impl GPUQueue {
|
||||
) -> Result<v8::Local<v8::Value>, JsErrorBox> {
|
||||
let ids = command_buffers
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, cb)| {
|
||||
if cb.consumed.set(()).is_err() {
|
||||
Err(JsErrorBox::type_error(format!(
|
||||
"The command buffer at position {i} has already been submitted."
|
||||
)))
|
||||
} else {
|
||||
Ok(cb.id)
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
.map(|cb| cb.id)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let err = self.instance.queue_submit(self.id, &ids).err();
|
||||
|
||||
|
||||
@@ -550,7 +550,7 @@ impl From<GPUTextureFormat> for TextureFormat {
|
||||
channel: AstcChannel::Unorm,
|
||||
},
|
||||
GPUTextureFormat::Astc4x4UnormSrgb => Self::Astc {
|
||||
block: AstcBlock::B5x4,
|
||||
block: AstcBlock::B4x4,
|
||||
channel: AstcChannel::UnormSrgb,
|
||||
},
|
||||
GPUTextureFormat::Astc5x4Unorm => Self::Astc {
|
||||
|
||||
Reference in New Issue
Block a user