0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-04 09:57:11 -05:00
deno/ext/webgpu/queue.rs
Leo Kettmeir 7253820764
refactor: object wrap WebGPU (#27665)
Fixes #25874
Fixes #26760
Fixes #24288
Fixes #24798
Fixes #25627
Fixes #25915
Fixes #26769
2025-02-12 13:45:41 +00:00

165 lines
3.9 KiB
Rust

// Copyright 2018-2025 the Deno authors. MIT license.
use deno_core::cppgc::Ptr;
use deno_core::op2;
use deno_core::GarbageCollected;
use deno_core::WebIDL;
use deno_error::JsErrorBox;
use crate::buffer::GPUBuffer;
use crate::command_buffer::GPUCommandBuffer;
use crate::texture::GPUTexture;
use crate::texture::GPUTextureAspect;
use crate::webidl::GPUExtent3D;
use crate::webidl::GPUOrigin3D;
use crate::Instance;
pub struct GPUQueue {
pub instance: Instance,
pub error_handler: super::error::ErrorHandler,
pub label: String,
pub id: wgpu_core::id::QueueId,
}
impl Drop for GPUQueue {
fn drop(&mut self) {
self.instance.queue_drop(self.id);
}
}
impl GarbageCollected for GPUQueue {}
#[op2]
impl GPUQueue {
#[getter]
#[string]
fn label(&self) -> String {
self.label.clone()
}
#[setter]
#[string]
fn label(&self, #[webidl] _label: String) {
// TODO(@crowlKats): no-op, needs wpgu to implement changing the label
}
#[required(1)]
fn submit(
&self,
#[webidl] command_buffers: Vec<Ptr<GPUCommandBuffer>>,
) -> Result<(), 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<_>, _>>()?;
let err = self.instance.queue_submit(self.id, &ids).err();
if let Some((_, err)) = err {
self.error_handler.push_error(Some(err));
}
Ok(())
}
#[async_method]
async fn on_submitted_work_done(&self) -> Result<(), JsErrorBox> {
Err(JsErrorBox::generic(
"This operation is currently not supported",
))
}
#[required(3)]
fn write_buffer(
&self,
#[webidl] buffer: Ptr<GPUBuffer>,
#[webidl(options(enforce_range = true))] buffer_offset: u64,
#[anybuffer] buf: &[u8],
#[webidl(default = 0, options(enforce_range = true))] data_offset: u64,
#[webidl(options(enforce_range = true))] size: Option<u64>,
) {
let data = match size {
Some(size) => {
&buf[(data_offset as usize)..((data_offset + size) as usize)]
}
None => &buf[(data_offset as usize)..],
};
let err = self
.instance
.queue_write_buffer(self.id, buffer.id, buffer_offset, data)
.err();
self.error_handler.push_error(err);
}
#[required(4)]
fn write_texture(
&self,
#[webidl] destination: GPUTexelCopyTextureInfo,
#[anybuffer] buf: &[u8],
#[webidl] data_layout: GPUTexelCopyBufferLayout,
#[webidl] size: GPUExtent3D,
) {
let destination = wgpu_core::command::TexelCopyTextureInfo {
texture: destination.texture.id,
mip_level: destination.mip_level,
origin: destination.origin.into(),
aspect: destination.aspect.into(),
};
let data_layout = wgpu_types::TexelCopyBufferLayout {
offset: data_layout.offset,
bytes_per_row: data_layout.bytes_per_row,
rows_per_image: data_layout.rows_per_image,
};
let err = self
.instance
.queue_write_texture(
self.id,
&destination,
buf,
&data_layout,
&size.into(),
)
.err();
self.error_handler.push_error(err);
}
}
#[derive(WebIDL)]
#[webidl(dictionary)]
pub(crate) struct GPUTexelCopyTextureInfo {
pub texture: Ptr<GPUTexture>,
#[webidl(default = 0)]
#[options(enforce_range = true)]
pub mip_level: u32,
#[webidl(default = Default::default())]
pub origin: GPUOrigin3D,
#[webidl(default = GPUTextureAspect::All)]
pub aspect: GPUTextureAspect,
}
#[derive(WebIDL)]
#[webidl(dictionary)]
struct GPUTexelCopyBufferLayout {
#[webidl(default = 0)]
#[options(enforce_range = true)]
offset: u64,
#[options(enforce_range = true)]
bytes_per_row: Option<u32>,
#[options(enforce_range = true)]
rows_per_image: Option<u32>,
}