1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 04:52:26 -05:00
This commit is contained in:
crowlkats 2025-01-14 11:19:14 +01:00
parent d4c6bf56c3
commit 6f497f414d
No known key found for this signature in database
GPG key ID: A82C9D461FC483E8
23 changed files with 487 additions and 249 deletions

View file

@ -213,6 +213,7 @@ ObjectDefineProperty(GPUSupportedFeatures, customInspect, {
}, },
}); });
const GPUSupportedFeaturesPrototype = GPUSupportedFeatures.prototype; const GPUSupportedFeaturesPrototype = GPUSupportedFeatures.prototype;
webidl.setlike(GPUSupportedFeatures, GPUSupportedFeaturesPrototype, true);
ObjectDefineProperty(GPUDeviceLostInfo, customInspect, { ObjectDefineProperty(GPUDeviceLostInfo, customInspect, {
value(inspect, inspectOptions) { value(inspect, inspectOptions) {
@ -689,6 +690,7 @@ ObjectDefineProperty(GPUQuerySet, customInspect, {
const GPUQuerySetPrototype = GPUQuerySet.prototype; const GPUQuerySetPrototype = GPUQuerySet.prototype;
// Converters // Converters
/*
// DICTIONARY: GPUPipelineErrorInit // DICTIONARY: GPUPipelineErrorInit
webidl.converters["GPUPipelineErrorInit"] = webidl.createDictionaryConverter( webidl.converters["GPUPipelineErrorInit"] = webidl.createDictionaryConverter(
@ -712,7 +714,7 @@ webidl.converters["GPUPipelineErrorReason"] = webidl.createEnumConverter(
); );
// TYPEDEF: GPUError // TYPEDEF: GPUError
webidl.converters["GPUError"] = webidl.converters.any /** put union here! **/; webidl.converters["GPUError"] = webidl.converters.any /!** put union here! **!/;
// // INTERFACE: GPUUncapturedErrorEvent // // INTERFACE: GPUUncapturedErrorEvent
// webidl.converters.GPUUncapturedErrorEvent = webidl.createInterfaceConverter( // webidl.converters.GPUUncapturedErrorEvent = webidl.createInterfaceConverter(
@ -794,6 +796,7 @@ webidl.converters["GPUCanvasConfiguration"] = webidl
"GPUCanvasConfiguration", "GPUCanvasConfiguration",
dictMembersGPUCanvasConfiguration, dictMembersGPUCanvasConfiguration,
); );
*/
let gpu; let gpu;
function initGPU() { function initGPU() {

View file

@ -2,7 +2,6 @@
#![cfg(not(target_arch = "wasm32"))] #![cfg(not(target_arch = "wasm32"))]
#![warn(unsafe_op_in_unsafe_fn)] #![warn(unsafe_op_in_unsafe_fn)]
use deno_core::GarbageCollected;
pub use wgpu_core; pub use wgpu_core;
pub use wgpu_types; pub use wgpu_types;
@ -40,7 +39,7 @@ deno_core::extension!(
wrap::render_pipeline::GPURenderPipeline, wrap::render_pipeline::GPURenderPipeline,
wrap::sampler::GPUSampler, wrap::sampler::GPUSampler,
wrap::shader::GPUShaderModule, wrap::shader::GPUShaderModule,
GPUSupportedFeatures, wrap::adapter::GPUSupportedFeatures,
wrap::adapter::GPUSupportedLimits, wrap::adapter::GPUSupportedLimits,
wrap::texture::GPUTexture, wrap::texture::GPUTexture,
wrap::texture::GPUTextureView, wrap::texture::GPUTextureView,
@ -48,10 +47,3 @@ deno_core::extension!(
esm = ["00_init.js"], esm = ["00_init.js"],
lazy_loaded_esm = ["01_webgpu.js"], lazy_loaded_esm = ["01_webgpu.js"],
); );
struct GPUSupportedFeatures {}
impl GarbageCollected for GPUSupportedFeatures {}
#[deno_core::op2]
impl GPUSupportedFeatures {}

View file

@ -9,9 +9,11 @@ use deno_core::op2;
use deno_core::v8; use deno_core::v8;
use deno_core::GarbageCollected; use deno_core::GarbageCollected;
use deno_core::WebIDL; use deno_core::WebIDL;
use tokio::sync::Mutex;
use super::device::GPUDevice; use super::device::GPUDevice;
use crate::wrap::webidl::features_to_feature_names; use crate::wrap::webidl::features_to_feature_names;
use crate::wrap::webidl::GPUFeatureName;
use crate::Instance; use crate::Instance;
#[derive(WebIDL)] #[derive(WebIDL)]
@ -36,7 +38,7 @@ struct GPUDeviceDescriptor {
label: String, label: String,
#[webidl(default = vec![])] #[webidl(default = vec![])]
required_features: Vec<super::webidl::GPUFeatureName>, required_features: Vec<GPUFeatureName>,
#[webidl(default = Default::default())] #[webidl(default = Default::default())]
#[options(enforce_range = true)] #[options(enforce_range = true)]
required_limits: indexmap::IndexMap<String, u64>, required_limits: indexmap::IndexMap<String, u64>,
@ -46,11 +48,17 @@ pub struct GPUAdapter {
pub instance: Instance, pub instance: Instance,
pub id: wgpu_core::id::AdapterId, pub id: wgpu_core::id::AdapterId,
pub features: SameObject<GPUAdapter>, pub features: SameObject<GPUSupportedFeatures>,
pub limits: SameObject<GPUSupportedLimits>, pub limits: SameObject<GPUSupportedLimits>,
pub info: Rc<SameObject<GPUAdapterInfo>>, pub info: Rc<SameObject<GPUAdapterInfo>>,
} }
impl Drop for GPUAdapter {
fn drop(&mut self) {
self.instance.adapter_drop(self.id);
}
}
impl GarbageCollected for GPUAdapter {} impl GarbageCollected for GPUAdapter {}
#[op2] #[op2]
@ -58,7 +66,7 @@ impl GPUAdapter {
#[getter] #[getter]
#[global] #[global]
fn info(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> { fn info(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
self.info.get(scope, || { self.info.get(scope, |_| {
let info = self.instance.adapter_get_info(self.id); let info = self.instance.adapter_get_info(self.id);
GPUAdapterInfo(info) GPUAdapterInfo(info)
}) })
@ -67,32 +75,16 @@ impl GPUAdapter {
#[getter] #[getter]
#[global] #[global]
fn features(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> { fn features(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
self.features.get(scope, || { self.features.get(scope, |scope| {
let features = self.instance.adapter_features(self.id); let features = self.instance.adapter_features(self.id);
let features = features_to_feature_names(features); let features = features_to_feature_names(features);
GPUSupportedFeatures::new(scope, features)
/*
#[symbol("[[set]]")]
function createGPUSupportedFeatures(features) {
/** @type {GPUSupportedFeatures} */
const supportedFeatures = webidl.createBranded(GPUSupportedFeatures);
supportedFeatures[webidl.setlikeInner] = new SafeSet(features);
webidl.setlike(
supportedFeatures,
GPUSupportedFeaturesPrototype,
true,
);
return supportedFeatures;
}
*/
todo!()
}) })
} }
#[getter] #[getter]
#[global] #[global]
fn limits(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> { fn limits(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
self.limits.get(scope, || { self.limits.get(scope, |_| {
let adapter_limits = self.instance.adapter_limits(self.id); let adapter_limits = self.instance.adapter_limits(self.id);
GPUSupportedLimits(adapter_limits) GPUSupportedLimits(adapter_limits)
}) })
@ -156,7 +148,7 @@ impl GPUAdapter {
adapter_info: self.info.clone(), adapter_info: self.info.clone(),
error_handler: Arc::new(super::error::DeviceErrorHandler::new(sender)), error_handler: Arc::new(super::error::DeviceErrorHandler::new(sender)),
adapter: self.id, adapter: self.id,
lost_receiver: receiver, lost_receiver: Mutex::new(Some(receiver)),
limits: SameObject::new(), limits: SameObject::new(),
features: SameObject::new(), features: SameObject::new(),
}) })
@ -333,6 +325,35 @@ impl GPUSupportedLimits {
} }
} }
pub struct GPUSupportedFeatures(v8::Global<v8::Value>);
impl GarbageCollected for GPUSupportedFeatures {}
impl GPUSupportedFeatures {
pub fn new(
scope: &mut v8::HandleScope,
features: HashSet<GPUFeatureName>,
) -> Self {
let set = v8::Set::new(scope);
for feature in features {
let key = v8::String::new(scope, feature.as_str()).unwrap();
set.add(scope, key.into());
}
Self(v8::Global::new(scope, <v8::Local<v8::Value>>::from(set)))
}
}
#[op2]
impl GPUSupportedFeatures {
#[global]
#[symbol("setlike_set")]
fn set(&self) -> v8::Global<v8::Value> {
self.0.clone()
}
}
pub struct GPUAdapterInfo(pub wgpu_types::AdapterInfo); pub struct GPUAdapterInfo(pub wgpu_types::AdapterInfo);
impl GarbageCollected for GPUAdapterInfo {} impl GarbageCollected for GPUAdapterInfo {}

View file

@ -17,12 +17,20 @@ use deno_core::WebIDL;
use crate::wrap::buffer::GPUBuffer; use crate::wrap::buffer::GPUBuffer;
use crate::wrap::sampler::GPUSampler; use crate::wrap::sampler::GPUSampler;
use crate::wrap::texture::GPUTextureView; use crate::wrap::texture::GPUTextureView;
use crate::Instance;
pub struct GPUBindGroup { pub struct GPUBindGroup {
pub instance: Instance,
pub id: wgpu_core::id::BindGroupId, pub id: wgpu_core::id::BindGroupId,
pub label: String, pub label: String,
} }
impl Drop for GPUBindGroup {
fn drop(&mut self) {
self.instance.bind_group_drop(self.id);
}
}
impl WebIdlInterfaceConverter for GPUBindGroup { impl WebIdlInterfaceConverter for GPUBindGroup {
const NAME: &'static str = "GPUBindGroup"; const NAME: &'static str = "GPUBindGroup";
} }
@ -31,7 +39,16 @@ impl GarbageCollected for GPUBindGroup {}
#[op2] #[op2]
impl GPUBindGroup { impl GPUBindGroup {
crate::with_label!(); #[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
}
} }
#[derive(WebIDL)] #[derive(WebIDL)]

View file

@ -5,12 +5,20 @@ use deno_core::GarbageCollected;
use deno_core::WebIDL; use deno_core::WebIDL;
use crate::wrap::texture::GPUTextureViewDimension; use crate::wrap::texture::GPUTextureViewDimension;
use crate::Instance;
pub struct GPUBindGroupLayout { pub struct GPUBindGroupLayout {
pub instance: Instance,
pub id: wgpu_core::id::BindGroupLayoutId, pub id: wgpu_core::id::BindGroupLayoutId,
pub label: String, pub label: String,
} }
impl Drop for GPUBindGroupLayout {
fn drop(&mut self) {
self.instance.bind_group_layout_drop(self.id);
}
}
impl deno_core::webidl::WebIdlInterfaceConverter for GPUBindGroupLayout { impl deno_core::webidl::WebIdlInterfaceConverter for GPUBindGroupLayout {
const NAME: &'static str = "GPUBindGroupLayout"; const NAME: &'static str = "GPUBindGroupLayout";
} }
@ -19,7 +27,16 @@ impl GarbageCollected for GPUBindGroupLayout {}
#[op2] #[op2]
impl GPUBindGroupLayout { impl GPUBindGroupLayout {
crate::with_label!(); #[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
}
} }
#[derive(WebIDL)] #[derive(WebIDL)]

View file

@ -37,6 +37,9 @@ pub enum BufferError {
#[class("DOMExceptionOperationError")] #[class("DOMExceptionOperationError")]
#[error(transparent)] #[error(transparent)]
Access(#[from] wgpu_core::resource::BufferAccessError), Access(#[from] wgpu_core::resource::BufferAccessError),
#[class("DOMExceptionOperationError")]
#[error("{0}")]
Operation(&'static str),
#[class(inherit)] #[class(inherit)]
#[error(transparent)] #[error(transparent)]
Other(#[from] JsErrorBox), Other(#[from] JsErrorBox),
@ -60,6 +63,12 @@ pub struct GPUBuffer {
pub mapped_js_buffers: RefCell<Vec<v8::Global<v8::ArrayBuffer>>>, pub mapped_js_buffers: RefCell<Vec<v8::Global<v8::ArrayBuffer>>>,
} }
impl Drop for GPUBuffer {
fn drop(&mut self) {
self.instance.buffer_drop(self.id);
}
}
impl WebIdlInterfaceConverter for GPUBuffer { impl WebIdlInterfaceConverter for GPUBuffer {
const NAME: &'static str = "GPUBuffer"; const NAME: &'static str = "GPUBuffer";
} }
@ -68,7 +77,16 @@ impl GarbageCollected for GPUBuffer {}
#[op2] #[op2]
impl GPUBuffer { impl GPUBuffer {
crate::with_label!(); #[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
}
#[getter] #[getter]
#[number] #[number]
@ -89,67 +107,16 @@ impl GPUBuffer {
#[async_method] #[async_method]
async fn map_async( async fn map_async(
&self, &self,
#[webidl/*(options(enforce_range = true))*/] mode: u32, #[webidl(options(enforce_range = true))] mode: u32,
#[webidl/*(default = 0)*/] offset: u64, #[webidl(default = 0)] offset: u64,
#[webidl] size: Option<u64>, #[webidl] size: Option<u64>,
) -> Result<(), BufferError> { ) -> Result<(), BufferError> {
let range_size = size.unwrap_or_else(|| self.size.saturating_sub(offset));
if (offset % 8) != 0 {
/*
throw new DOMException(
`${prefix}: offset must be a multiple of 8, received ${offset}`,
"OperationError",
);
*/
}
if (range_size % 4) != 0 {
/*
throw new DOMException(
`${prefix}: rangeSize must be a multiple of 4, received ${rangeSize}`,
"OperationError",
);
*/
}
if (offset + range_size) > self.size {
/*
throw new DOMException(
`${prefix}: offset + rangeSize must be less than or equal to buffer size`,
"OperationError",
);
*/
}
let read_mode = (mode & 0x0001) == 0x0001; let read_mode = (mode & 0x0001) == 0x0001;
let write_mode = (mode & 0x0002) == 0x0002; let write_mode = (mode & 0x0002) == 0x0002;
if (read_mode && write_mode) || (!read_mode && !write_mode) { if (read_mode && write_mode) || (!read_mode && !write_mode) {
/* return Err(BufferError::Operation(
throw new DOMException( "exactly one of READ or WRITE map mode must be set",
`${prefix}: exactly one of READ or WRITE map mode must be set`, ));
"OperationError",
);
*/
}
if read_mode && !(self.usage & 0x0001) == 0x0001 {
/*
throw new DOMException(
`${prefix}: READ map mode not valid because buffer does not have MAP_READ usage`,
"OperationError",
);
*/
}
if write_mode && !(self.usage & 0x0002) == 0x0002 {
/*
throw new DOMException(
`${prefix}: WRITE map mode not valid because buffer does not have MAP_WRITE usage`,
"OperationError",
);
*/
}
{
*self.map_state.borrow_mut() = "pending";
} }
let mode = if read_mode { let mode = if read_mode {
@ -159,6 +126,10 @@ impl GPUBuffer {
MapMode::Write MapMode::Write
}; };
{
*self.map_state.borrow_mut() = "pending";
}
let (sender, receiver) = let (sender, receiver) =
oneshot::channel::<wgpu_core::resource::BufferAccessResult>(); oneshot::channel::<wgpu_core::resource::BufferAccessResult>();
@ -167,13 +138,12 @@ impl GPUBuffer {
sender.send(status).unwrap(); sender.send(status).unwrap();
}); });
// TODO(lucacasonato): error handling
let err = self let err = self
.instance .instance
.buffer_map_async( .buffer_map_async(
self.id, self.id,
offset, offset,
Some(range_size), size,
wgpu_core::resource::BufferMapOperation { wgpu_core::resource::BufferMapOperation {
host: mode, host: mode,
callback: Some(BufferMapCallback::from_rust(callback)), callback: Some(BufferMapCallback::from_rust(callback)),
@ -183,13 +153,7 @@ impl GPUBuffer {
if err.is_some() { if err.is_some() {
self.error_handler.push_error(err); self.error_handler.push_error(err);
return Err( return Err(BufferError::Operation("validation error occurred"));
JsErrorBox::new(
"DOMExceptionOperationError",
"validation error occurred",
)
.into(),
);
} }
} }
@ -226,7 +190,7 @@ impl GPUBuffer {
fn get_mapped_range<'s>( fn get_mapped_range<'s>(
&self, &self,
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
#[webidl/*(default = 0)*/] offset: u64, #[webidl(default = 0)] offset: u64,
#[webidl] size: Option<u64>, #[webidl] size: Option<u64>,
) -> Result<v8::Local<'s, v8::Uint8Array>, BufferError> { ) -> Result<v8::Local<'s, v8::Uint8Array>, BufferError> {
let size = size.unwrap_or_else(|| self.size.saturating_sub(offset)); let size = size.unwrap_or_else(|| self.size.saturating_sub(offset));
@ -247,6 +211,7 @@ impl GPUBuffer {
) { ) {
} }
// SAFETY: creating a backing store from the pointer and length provided by wgpu
unsafe { unsafe {
v8::ArrayBuffer::new_backing_store_from_ptr( v8::ArrayBuffer::new_backing_store_from_ptr(
slice_pointer.as_ptr() as _, slice_pointer.as_ptr() as _,
@ -256,6 +221,7 @@ impl GPUBuffer {
) )
} }
} else { } else {
// SAFETY: creating a vector from the pointer and length provided by wgpu
let slice = unsafe { let slice = unsafe {
std::slice::from_raw_parts(slice_pointer.as_ptr(), range_size as usize) std::slice::from_raw_parts(slice_pointer.as_ptr(), range_size as usize)
}; };

View file

@ -4,11 +4,20 @@ use deno_core::op2;
use deno_core::GarbageCollected; use deno_core::GarbageCollected;
use deno_core::WebIDL; use deno_core::WebIDL;
use crate::Instance;
pub struct GPUCommandBuffer { pub struct GPUCommandBuffer {
pub instance: Instance,
pub id: wgpu_core::id::CommandBufferId, pub id: wgpu_core::id::CommandBufferId,
pub label: String, pub label: String,
} }
impl Drop for GPUCommandBuffer {
fn drop(&mut self) {
self.instance.command_buffer_drop(self.id);
}
}
impl deno_core::webidl::WebIdlInterfaceConverter for GPUCommandBuffer { impl deno_core::webidl::WebIdlInterfaceConverter for GPUCommandBuffer {
const NAME: &'static str = "GPUCommandBuffer"; const NAME: &'static str = "GPUCommandBuffer";
} }
@ -17,7 +26,16 @@ impl GarbageCollected for GPUCommandBuffer {}
#[op2] #[op2]
impl GPUCommandBuffer { impl GPUCommandBuffer {
crate::with_label!(); #[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
}
} }
#[derive(WebIDL)] #[derive(WebIDL)]

View file

@ -29,11 +29,26 @@ pub struct GPUCommandEncoder {
pub label: String, pub label: String,
} }
impl Drop for GPUCommandEncoder {
fn drop(&mut self) {
self.instance.command_encoder_drop(self.id);
}
}
impl GarbageCollected for GPUCommandEncoder {} impl GarbageCollected for GPUCommandEncoder {}
#[op2] #[op2]
impl GPUCommandEncoder { impl GPUCommandEncoder {
crate::with_label!(); #[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)] #[required(1)]
#[cppgc] #[cppgc]
@ -80,7 +95,7 @@ impl GPUCommandEncoder {
.unwrap_or(GPUStoreOp::Store) .unwrap_or(GPUStoreOp::Store)
.into(), .into(),
clear_value: attachment.depth_clear_value.unwrap_or_default(), clear_value: attachment.depth_clear_value.unwrap_or_default(),
read_only: false, read_only: attachment.depth_read_only,
}, },
stencil: PassChannel { stencil: PassChannel {
load_op: attachment load_op: attachment
@ -92,7 +107,7 @@ impl GPUCommandEncoder {
.unwrap_or(GPUStoreOp::Store) .unwrap_or(GPUStoreOp::Store)
.into(), .into(),
clear_value: attachment.stencil_clear_value, clear_value: attachment.stencil_clear_value,
read_only: false, read_only: attachment.stencil_read_only,
}, },
}) })
}).transpose()?; }).transpose()?;
@ -169,10 +184,10 @@ impl GPUCommandEncoder {
fn copy_buffer_to_buffer( fn copy_buffer_to_buffer(
&self, &self,
#[webidl] source: Ptr<GPUBuffer>, #[webidl] source: Ptr<GPUBuffer>,
#[webidl/*(options(enforce_range = true))*/] source_offset: u64, #[webidl(options(enforce_range = true))] source_offset: u64,
#[webidl] destination: Ptr<GPUBuffer>, #[webidl] destination: Ptr<GPUBuffer>,
#[webidl/*(options(enforce_range = true))*/] destination_offset: u64, #[webidl(options(enforce_range = true))] destination_offset: u64,
#[webidl/*(options(enforce_range = true))*/] size: u64, #[webidl(options(enforce_range = true))] size: u64,
) { ) {
let err = self let err = self
.instance .instance
@ -296,8 +311,8 @@ impl GPUCommandEncoder {
fn clear_buffer( fn clear_buffer(
&self, &self,
#[webidl] buffer: Ptr<GPUBuffer>, #[webidl] buffer: Ptr<GPUBuffer>,
#[webidl/*(default = 0, options(enforce_range = true))*/] offset: u64, #[webidl(default = 0, options(enforce_range = true))] offset: u64,
#[webidl/*(options(enforce_range = true))*/] size: Option<u64>, #[webidl(options(enforce_range = true))] size: Option<u64>,
) { ) {
let err = self let err = self
.instance .instance
@ -310,10 +325,10 @@ impl GPUCommandEncoder {
fn resolve_query_set( fn resolve_query_set(
&self, &self,
#[webidl] query_set: Ptr<super::query_set::GPUQuerySet>, #[webidl] query_set: Ptr<super::query_set::GPUQuerySet>,
#[webidl/*(options(enforce_range = true))*/] first_query: u32, #[webidl(options(enforce_range = true))] first_query: u32,
#[webidl/*(options(enforce_range = true))*/] query_count: u32, #[webidl(options(enforce_range = true))] query_count: u32,
#[webidl] destination: Ptr<GPUBuffer>, #[webidl] destination: Ptr<GPUBuffer>,
#[webidl/*(options(enforce_range = true))*/] destination_offset: u64, #[webidl(options(enforce_range = true))] destination_offset: u64,
) { ) {
let err = self let err = self
.instance .instance
@ -347,6 +362,7 @@ impl GPUCommandEncoder {
self.error_handler.push_error(err); self.error_handler.push_error(err);
GPUCommandBuffer { GPUCommandBuffer {
instance: self.instance.clone(),
id, id,
label: descriptor.label, label: descriptor.label,
} }

View file

@ -27,7 +27,16 @@ impl GarbageCollected for GPUComputePassEncoder {}
#[op2] #[op2]
impl GPUComputePassEncoder { impl GPUComputePassEncoder {
crate::with_label!(); #[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
}
fn set_pipeline( fn set_pipeline(
&self, &self,
@ -45,10 +54,10 @@ impl GPUComputePassEncoder {
fn dispatch_workgroups( fn dispatch_workgroups(
&self, &self,
#[webidl/*(options(enforce_range = true))*/] work_group_count_x: u32, #[webidl(options(enforce_range = true))] work_group_count_x: u32,
#[webidl/*(default = 1, options(enforce_range = true))*/] #[webidl(default = 1, options(enforce_range = true))]
work_group_count_y: u32, work_group_count_y: u32,
#[webidl/*(default = 1, options(enforce_range = true))*/] #[webidl(default = 1, options(enforce_range = true))]
work_group_count_z: u32, work_group_count_z: u32,
) { ) {
let err = self let err = self
@ -66,7 +75,7 @@ impl GPUComputePassEncoder {
fn dispatch_workgroups_indirect( fn dispatch_workgroups_indirect(
&self, &self,
#[webidl] indirect_buffer: Ptr<crate::wrap::buffer::GPUBuffer>, #[webidl] indirect_buffer: Ptr<crate::wrap::buffer::GPUBuffer>,
#[webidl/*(options(enforce_range = true))*/] indirect_offset: u64, #[webidl(options(enforce_range = true))] indirect_offset: u64,
) { ) {
let err = self let err = self
.instance .instance
@ -124,7 +133,7 @@ impl GPUComputePassEncoder {
fn set_bind_group<'a>( fn set_bind_group<'a>(
&self, &self,
scope: &mut v8::HandleScope<'a>, scope: &mut v8::HandleScope<'a>,
#[webidl/*(options(enforce_range = true))*/] index: u32, #[webidl(options(enforce_range = true))] index: u32,
#[webidl] bind_group: Nullable<Ptr<crate::wrap::bind_group::GPUBindGroup>>, #[webidl] bind_group: Nullable<Ptr<crate::wrap::bind_group::GPUBindGroup>>,
dynamic_offsets: v8::Local<'a, v8::Value>, dynamic_offsets: v8::Local<'a, v8::Value>,
dynamic_offsets_data_start: v8::Local<'a, v8::Value>, dynamic_offsets_data_start: v8::Local<'a, v8::Value>,
@ -159,6 +168,7 @@ impl GPUComputePassEncoder {
let ptr = ab.data().unwrap(); let ptr = ab.data().unwrap();
let ab_len = ab.byte_length() / 4; let ab_len = ab.byte_length() / 4;
// SAFETY: compute_pass_set_bind_group internally calls extend_from_slice with this slice
let data = let data =
unsafe { std::slice::from_raw_parts(ptr.as_ptr() as _, ab_len) }; unsafe { std::slice::from_raw_parts(ptr.as_ptr() as _, ab_len) };

View file

@ -20,6 +20,12 @@ pub struct GPUComputePipeline {
pub label: String, pub label: String,
} }
impl Drop for GPUComputePipeline {
fn drop(&mut self) {
self.instance.compute_pipeline_drop(self.id);
}
}
impl WebIdlInterfaceConverter for GPUComputePipeline { impl WebIdlInterfaceConverter for GPUComputePipeline {
const NAME: &'static str = "GPUComputePipeline"; const NAME: &'static str = "GPUComputePipeline";
} }
@ -28,7 +34,16 @@ impl GarbageCollected for GPUComputePipeline {}
#[op2] #[op2]
impl GPUComputePipeline { impl GPUComputePipeline {
crate::with_label!(); #[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
}
#[cppgc] #[cppgc]
fn get_bind_group_layout(&self, #[webidl] index: u32) -> GPUBindGroupLayout { fn get_bind_group_layout(&self, #[webidl] index: u32) -> GPUBindGroupLayout {
@ -40,6 +55,7 @@ impl GPUComputePipeline {
// TODO: wgpu needs to support retrieving the label // TODO: wgpu needs to support retrieving the label
GPUBindGroupLayout { GPUBindGroupLayout {
instance: self.instance.clone(),
id, id,
label: "".to_string(), label: "".to_string(),
} }

View file

@ -23,11 +23,13 @@ use super::sampler::GPUSampler;
use super::shader::GPUShaderModule; use super::shader::GPUShaderModule;
use super::texture::GPUTexture; use super::texture::GPUTexture;
use crate::wrap::adapter::GPUAdapterInfo; use crate::wrap::adapter::GPUAdapterInfo;
use crate::wrap::adapter::GPUSupportedFeatures;
use crate::wrap::adapter::GPUSupportedLimits; use crate::wrap::adapter::GPUSupportedLimits;
use crate::wrap::command_encoder::GPUCommandEncoder; use crate::wrap::command_encoder::GPUCommandEncoder;
use crate::wrap::query_set::GPUQuerySet; use crate::wrap::query_set::GPUQuerySet;
use crate::wrap::render_bundle::GPURenderBundleEncoder; use crate::wrap::render_bundle::GPURenderBundleEncoder;
use crate::wrap::render_pipeline::GPURenderPipeline; use crate::wrap::render_pipeline::GPURenderPipeline;
use crate::wrap::webidl::features_to_feature_names;
use crate::Instance; use crate::Instance;
pub struct GPUDevice { pub struct GPUDevice {
@ -38,14 +40,21 @@ pub struct GPUDevice {
pub label: String, pub label: String,
pub features: SameObject<GPUDevice>, pub features: SameObject<GPUSupportedFeatures>,
pub limits: SameObject<GPUSupportedLimits>, pub limits: SameObject<GPUSupportedLimits>,
pub adapter_info: Rc<SameObject<GPUAdapterInfo>>, pub adapter_info: Rc<SameObject<GPUAdapterInfo>>,
pub queue_obj: SameObject<GPUQueue>, pub queue_obj: SameObject<GPUQueue>,
pub error_handler: super::error::ErrorHandler, pub error_handler: super::error::ErrorHandler,
pub lost_receiver: tokio::sync::oneshot::Receiver<()>, pub lost_receiver:
tokio::sync::Mutex<Option<tokio::sync::oneshot::Receiver<()>>>,
}
impl Drop for GPUDevice {
fn drop(&mut self) {
self.instance.device_drop(self.id);
}
} }
impl GarbageCollected for GPUDevice {} impl GarbageCollected for GPUDevice {}
@ -54,19 +63,33 @@ impl GarbageCollected for GPUDevice {}
// TODO: setEventTargetData on instance // TODO: setEventTargetData on instance
#[op2] #[op2]
impl GPUDevice { impl GPUDevice {
crate::with_label!(); #[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
}
#[getter] #[getter]
fn features(&self) { #[global]
todo!() fn features(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
self.features.get(scope, |scope| {
let features = self.instance.device_features(self.id);
let features = features_to_feature_names(features);
GPUSupportedFeatures::new(scope, features)
})
} }
#[getter] #[getter]
#[global] #[global]
fn limits(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> { fn limits(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
self.limits.get(scope, || { self.limits.get(scope, |_| {
let adapter_limits = self.instance.device_limits(self.id); let limits = self.instance.device_limits(self.id);
GPUSupportedLimits(adapter_limits) GPUSupportedLimits(limits)
}) })
} }
@ -76,7 +99,7 @@ impl GPUDevice {
&self, &self,
scope: &mut v8::HandleScope, scope: &mut v8::HandleScope,
) -> v8::Global<v8::Object> { ) -> v8::Global<v8::Object> {
self.adapter_info.get(scope, || { self.adapter_info.get(scope, |_| {
let info = self.instance.adapter_get_info(self.adapter); let info = self.instance.adapter_get_info(self.adapter);
GPUAdapterInfo(info) GPUAdapterInfo(info)
}) })
@ -85,7 +108,7 @@ impl GPUDevice {
#[getter] #[getter]
#[global] #[global]
fn queue(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> { fn queue(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
self.queue_obj.get(scope, || GPUQueue { self.queue_obj.get(scope, |_| GPUQueue {
id: self.queue, id: self.queue,
error_handler: self.error_handler.clone(), error_handler: self.error_handler.clone(),
instance: self.instance.clone(), instance: self.instance.clone(),
@ -287,6 +310,7 @@ impl GPUDevice {
self.error_handler.push_error(err); self.error_handler.push_error(err);
Ok(GPUBindGroupLayout { Ok(GPUBindGroupLayout {
instance: self.instance.clone(),
id, id,
label: descriptor.label, label: descriptor.label,
}) })
@ -328,6 +352,7 @@ impl GPUDevice {
self.error_handler.push_error(err); self.error_handler.push_error(err);
Ok(GPUPipelineLayout { Ok(GPUPipelineLayout {
instance: self.instance.clone(),
id, id,
label: descriptor.label, label: descriptor.label,
}) })
@ -376,6 +401,7 @@ impl GPUDevice {
self.error_handler.push_error(err); self.error_handler.push_error(err);
GPUBindGroup { GPUBindGroup {
instance: self.instance.clone(),
id, id,
label: descriptor.label, label: descriptor.label,
} }
@ -404,6 +430,7 @@ impl GPUDevice {
self.error_handler.push_error(err); self.error_handler.push_error(err);
GPUShaderModule { GPUShaderModule {
instance: self.instance.clone(),
id, id,
label: descriptor.label, label: descriptor.label,
} }
@ -543,6 +570,7 @@ impl GPUDevice {
self.error_handler.push_error(err); self.error_handler.push_error(err);
GPUQuerySet { GPUQuerySet {
instance: self.instance.clone(),
id, id,
r#type: descriptor.r#type, r#type: descriptor.r#type,
count: descriptor.count, count: descriptor.count,
@ -550,12 +578,14 @@ impl GPUDevice {
} }
} }
// TODO: return same promise // TODO: support returning same promise
#[async_method] #[async_method]
#[getter] #[getter]
#[cppgc] #[cppgc]
async fn lost(&self) -> GPUDeviceLostInfo { async fn lost(&self) -> GPUDeviceLostInfo {
// TODO: self.lost_receiver.await.unwrap(); if let Some(lost_receiver) = self.lost_receiver.lock().await.take() {
let _ = lost_receiver.await;
}
GPUDeviceLostInfo GPUDeviceLostInfo
} }
@ -565,7 +595,8 @@ impl GPUDevice {
self self
.error_handler .error_handler
.scopes .scopes
.borrow_mut() .lock()
.unwrap()
.push((filter, vec![])); .push((filter, vec![]));
} }
@ -591,10 +622,7 @@ impl GPUDevice {
Ok(v8::null(scope).into()) Ok(v8::null(scope).into())
}*/ }*/
Err(JsErrorBox::new( todo!()
"DOMExceptionOperationError",
"There are no error scopes on the error scope stack",
))
} }
} }

View file

@ -1,10 +1,9 @@
// Copyright 2018-2025 the Deno authors. MIT license. // Copyright 2018-2025 the Deno authors. MIT license.
use std::cell::OnceCell;
use std::cell::RefCell;
use std::fmt::Display; use std::fmt::Display;
use std::fmt::Formatter; use std::fmt::Formatter;
use std::sync::Mutex; use std::sync::Mutex;
use std::sync::OnceLock;
use wgpu_core::binding_model::CreateBindGroupError; use wgpu_core::binding_model::CreateBindGroupError;
use wgpu_core::binding_model::CreateBindGroupLayoutError; use wgpu_core::binding_model::CreateBindGroupLayoutError;
@ -35,10 +34,10 @@ use wgpu_core::resource::CreateTextureViewError;
pub type ErrorHandler = std::sync::Arc<DeviceErrorHandler>; pub type ErrorHandler = std::sync::Arc<DeviceErrorHandler>;
pub struct DeviceErrorHandler { pub struct DeviceErrorHandler {
pub is_lost: OnceCell<()>, pub is_lost: OnceLock<()>,
lost_sender: Mutex<Option<tokio::sync::oneshot::Sender<()>>>, lost_sender: Mutex<Option<tokio::sync::oneshot::Sender<()>>>,
pub scopes: RefCell<Vec<(GPUErrorFilter, Vec<GPUError>)>>, pub scopes: Mutex<Vec<(GPUErrorFilter, Vec<GPUError>)>>,
} }
impl DeviceErrorHandler { impl DeviceErrorHandler {
@ -46,7 +45,7 @@ impl DeviceErrorHandler {
Self { Self {
is_lost: Default::default(), is_lost: Default::default(),
lost_sender: Mutex::new(Some(sender)), lost_sender: Mutex::new(Some(sender)),
scopes: RefCell::new(vec![]), scopes: Mutex::new(vec![]),
} }
} }
@ -77,7 +76,7 @@ impl DeviceErrorHandler {
GPUError::Internal => GPUErrorFilter::Internal, GPUError::Internal => GPUErrorFilter::Internal,
}; };
let mut scopes = self.scopes.borrow_mut(); let mut scopes = self.scopes.lock().unwrap();
let scope = scopes let scope = scopes
.iter_mut() .iter_mut()
.rfind(|(filter, _)| filter == &error_filter); .rfind(|(filter, _)| filter == &error_filter);
@ -106,7 +105,8 @@ pub enum GPUErrorFilter {
#[derive(Debug, deno_error::JsError)] #[derive(Debug, deno_error::JsError)]
pub enum GPUError { pub enum GPUError {
#[class("UNREACHABLE")] // TODO // TODO(@crowlKats): consider adding an unreachable value that uses unreachable!()
#[class("UNREACHABLE")]
Lost, Lost,
#[class("GPUValidationError")] #[class("GPUValidationError")]
Validation(String), Validation(String),

View file

@ -107,19 +107,3 @@ impl GPU {
} }
} }
} }
#[macro_export]
macro_rules! with_label {
() => {
#[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
}
};
}

View file

@ -7,11 +7,20 @@ use deno_core::webidl::WebIdlInterfaceConverter;
use deno_core::GarbageCollected; use deno_core::GarbageCollected;
use deno_core::WebIDL; use deno_core::WebIDL;
use crate::Instance;
pub struct GPUPipelineLayout { pub struct GPUPipelineLayout {
pub instance: Instance,
pub id: wgpu_core::id::PipelineLayoutId, pub id: wgpu_core::id::PipelineLayoutId,
pub label: String, pub label: String,
} }
impl Drop for GPUPipelineLayout {
fn drop(&mut self) {
self.instance.pipeline_layout_drop(self.id);
}
}
impl WebIdlInterfaceConverter for GPUPipelineLayout { impl WebIdlInterfaceConverter for GPUPipelineLayout {
const NAME: &'static str = "GPUPipelineLayout"; const NAME: &'static str = "GPUPipelineLayout";
} }
@ -20,7 +29,16 @@ impl GarbageCollected for GPUPipelineLayout {}
#[op2] #[op2]
impl GPUPipelineLayout { impl GPUPipelineLayout {
crate::with_label!(); #[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
}
} }
#[derive(WebIDL)] #[derive(WebIDL)]

View file

@ -6,13 +6,22 @@ use deno_core::GarbageCollected;
use deno_core::WebIDL; use deno_core::WebIDL;
use deno_error::JsErrorBox; use deno_error::JsErrorBox;
use crate::Instance;
pub struct GPUQuerySet { pub struct GPUQuerySet {
pub instance: Instance,
pub id: wgpu_core::id::QuerySetId, pub id: wgpu_core::id::QuerySetId,
pub r#type: GPUQueryType, pub r#type: GPUQueryType,
pub count: u32, pub count: u32,
pub label: String, pub label: String,
} }
impl Drop for GPUQuerySet {
fn drop(&mut self) {
self.instance.query_set_drop(self.id);
}
}
impl WebIdlInterfaceConverter for GPUQuerySet { impl WebIdlInterfaceConverter for GPUQuerySet {
const NAME: &'static str = "GPUQuerySet"; const NAME: &'static str = "GPUQuerySet";
} }
@ -21,7 +30,16 @@ impl GarbageCollected for GPUQuerySet {}
#[op2] #[op2]
impl GPUQuerySet { impl GPUQuerySet {
crate::with_label!(); #[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
}
#[fast] #[fast]
fn destroy(&self) -> Result<(), JsErrorBox> { fn destroy(&self) -> Result<(), JsErrorBox> {

View file

@ -22,11 +22,27 @@ pub struct GPUQueue {
pub id: wgpu_core::id::QueueId, pub id: wgpu_core::id::QueueId,
} }
impl Drop for GPUQueue {
fn drop(&mut self) {
self.instance.queue_drop(self.id);
}
}
impl GarbageCollected for GPUQueue {} impl GarbageCollected for GPUQueue {}
#[op2] #[op2]
impl GPUQueue { impl GPUQueue {
crate::with_label!(); #[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)] #[required(1)]
fn submit(&self, #[webidl] command_buffers: Vec<Ptr<GPUCommandBuffer>>) { fn submit(&self, #[webidl] command_buffers: Vec<Ptr<GPUCommandBuffer>>) {
@ -53,10 +69,10 @@ impl GPUQueue {
fn write_buffer( fn write_buffer(
&self, &self,
#[webidl] buffer: Ptr<GPUBuffer>, #[webidl] buffer: Ptr<GPUBuffer>,
#[webidl/*(options(enforce_range = true))*/] buffer_offset: u64, #[webidl(options(enforce_range = true))] buffer_offset: u64,
#[anybuffer] buf: &[u8], // TODO: AllowSharedBufferSource #[anybuffer] buf: &[u8],
#[webidl/*(default = 0, options(enforce_range = true))*/] data_offset: u64, #[webidl(default = 0, options(enforce_range = true))] data_offset: u64,
#[webidl/*(options(enforce_range = true))*/] size: Option<u64>, #[webidl(options(enforce_range = true))] size: Option<u64>,
) { ) {
let data = match size { let data = match size {
Some(size) => { Some(size) => {
@ -77,7 +93,7 @@ impl GPUQueue {
fn write_texture( fn write_texture(
&self, &self,
#[webidl] destination: GPUTexelCopyTextureInfo, #[webidl] destination: GPUTexelCopyTextureInfo,
#[anybuffer] buf: &[u8], // TODO: AllowSharedBufferSource #[anybuffer] buf: &[u8],
#[webidl] data_layout: GPUTexelCopyBufferLayout, #[webidl] data_layout: GPUTexelCopyBufferLayout,
#[webidl] size: GPUExtent3D, #[webidl] size: GPUExtent3D,
) { ) {

View file

@ -32,7 +32,16 @@ impl GarbageCollected for GPURenderBundleEncoder {}
#[op2] #[op2]
impl GPURenderBundleEncoder { impl GPURenderBundleEncoder {
crate::with_label!(); #[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
}
#[cppgc] #[cppgc]
fn finish( fn finish(
@ -52,6 +61,7 @@ impl GPURenderBundleEncoder {
self.error_handler.push_error(err); self.error_handler.push_error(err);
GPURenderBundle { GPURenderBundle {
instance: self.instance.clone(),
id, id,
label: descriptor.label.clone(), label: descriptor.label.clone(),
} }
@ -110,7 +120,7 @@ impl GPURenderBundleEncoder {
fn set_bind_group<'a>( fn set_bind_group<'a>(
&self, &self,
scope: &mut v8::HandleScope<'a>, scope: &mut v8::HandleScope<'a>,
#[webidl/*(options(enforce_range = true))*/] index: u32, #[webidl(options(enforce_range = true))] index: u32,
#[webidl] bind_group: Nullable<Ptr<crate::wrap::bind_group::GPUBindGroup>>, #[webidl] bind_group: Nullable<Ptr<crate::wrap::bind_group::GPUBindGroup>>,
dynamic_offsets: v8::Local<'a, v8::Value>, dynamic_offsets: v8::Local<'a, v8::Value>,
dynamic_offsets_data_start: v8::Local<'a, v8::Value>, dynamic_offsets_data_start: v8::Local<'a, v8::Value>,
@ -211,8 +221,8 @@ impl GPURenderBundleEncoder {
&self, &self,
#[webidl] buffer: Ptr<GPUBuffer>, #[webidl] buffer: Ptr<GPUBuffer>,
#[webidl] index_format: crate::wrap::render_pipeline::GPUIndexFormat, #[webidl] index_format: crate::wrap::render_pipeline::GPUIndexFormat,
#[webidl/*(default = 0, options(enforce_range = true))*/] offset: u64, #[webidl(default = 0, options(enforce_range = true))] offset: u64,
#[webidl/*(options(enforce_range = true))*/] size: Option<u64>, #[webidl(options(enforce_range = true))] size: Option<u64>,
) -> Result<(), JsErrorBox> { ) -> Result<(), JsErrorBox> {
let mut encoder = self.encoder.borrow_mut(); let mut encoder = self.encoder.borrow_mut();
let encoder = encoder.as_mut().ok_or_else(|| { let encoder = encoder.as_mut().ok_or_else(|| {
@ -231,10 +241,10 @@ impl GPURenderBundleEncoder {
#[required(2)] #[required(2)]
fn set_vertex_buffer( fn set_vertex_buffer(
&self, &self,
#[webidl/*(options(enforce_range = true))*/] slot: u32, #[webidl(options(enforce_range = true))] slot: u32,
#[webidl] buffer: Ptr<GPUBuffer>, // TODO: support nullable buffer #[webidl] buffer: Ptr<GPUBuffer>, // TODO: support nullable buffer
#[webidl/*(default = 0, options(enforce_range = true))*/] offset: u64, #[webidl(default = 0, options(enforce_range = true))] offset: u64,
#[webidl/*(options(enforce_range = true))*/] size: Option<u64>, #[webidl(options(enforce_range = true))] size: Option<u64>,
) -> Result<(), JsErrorBox> { ) -> Result<(), JsErrorBox> {
let mut encoder = self.encoder.borrow_mut(); let mut encoder = self.encoder.borrow_mut();
let encoder = encoder.as_mut().ok_or_else(|| { let encoder = encoder.as_mut().ok_or_else(|| {
@ -254,12 +264,10 @@ impl GPURenderBundleEncoder {
#[required(1)] #[required(1)]
fn draw( fn draw(
&self, &self,
#[webidl/*(options(enforce_range = true))*/] vertex_count: u32, #[webidl(options(enforce_range = true))] vertex_count: u32,
#[webidl/*(default = 1, options(enforce_range = true))*/] #[webidl(default = 1, options(enforce_range = true))] instance_count: u32,
instance_count: u32, #[webidl(default = 0, options(enforce_range = true))] first_vertex: u32,
#[webidl/*(default = 0, options(enforce_range = true))*/] first_vertex: u32, #[webidl(default = 0, options(enforce_range = true))] first_instance: u32,
#[webidl/*(default = 0, options(enforce_range = true))*/]
first_instance: u32,
) -> Result<(), JsErrorBox> { ) -> Result<(), JsErrorBox> {
let mut encoder = self.encoder.borrow_mut(); let mut encoder = self.encoder.borrow_mut();
let encoder = encoder.as_mut().ok_or_else(|| { let encoder = encoder.as_mut().ok_or_else(|| {
@ -279,13 +287,11 @@ impl GPURenderBundleEncoder {
#[required(1)] #[required(1)]
fn draw_indexed( fn draw_indexed(
&self, &self,
#[webidl/*(options(enforce_range = true))*/] index_count: u32, #[webidl(options(enforce_range = true))] index_count: u32,
#[webidl/*(default = 1, options(enforce_range = true))*/] #[webidl(default = 1, options(enforce_range = true))] instance_count: u32,
instance_count: u32, #[webidl(default = 0, options(enforce_range = true))] first_index: u32,
#[webidl/*(default = 0, options(enforce_range = true))*/] first_index: u32, #[webidl(default = 0, options(enforce_range = true))] base_vertex: i32,
#[webidl/*(default = 0, options(enforce_range = true))*/] base_vertex: i32, #[webidl(default = 0, options(enforce_range = true))] first_instance: u32,
#[webidl/*(default = 0, options(enforce_range = true))*/]
first_instance: u32,
) -> Result<(), JsErrorBox> { ) -> Result<(), JsErrorBox> {
let mut encoder = self.encoder.borrow_mut(); let mut encoder = self.encoder.borrow_mut();
let encoder = encoder.as_mut().ok_or_else(|| { let encoder = encoder.as_mut().ok_or_else(|| {
@ -307,7 +313,7 @@ impl GPURenderBundleEncoder {
fn draw_indirect( fn draw_indirect(
&self, &self,
#[webidl] indirect_buffer: Ptr<GPUBuffer>, #[webidl] indirect_buffer: Ptr<GPUBuffer>,
#[webidl/*(options(enforce_range = true))*/] indirect_offset: u64, #[webidl(options(enforce_range = true))] indirect_offset: u64,
) -> Result<(), JsErrorBox> { ) -> Result<(), JsErrorBox> {
let mut encoder = self.encoder.borrow_mut(); let mut encoder = self.encoder.borrow_mut();
let encoder = encoder.as_mut().ok_or_else(|| { let encoder = encoder.as_mut().ok_or_else(|| {
@ -326,7 +332,7 @@ impl GPURenderBundleEncoder {
fn draw_indexed_indirect( fn draw_indexed_indirect(
&self, &self,
#[webidl] indirect_buffer: Ptr<GPUBuffer>, #[webidl] indirect_buffer: Ptr<GPUBuffer>,
#[webidl/*(options(enforce_range = true))*/] indirect_offset: u64, #[webidl(options(enforce_range = true))] indirect_offset: u64,
) -> Result<(), JsErrorBox> { ) -> Result<(), JsErrorBox> {
let mut encoder = self.encoder.borrow_mut(); let mut encoder = self.encoder.borrow_mut();
let encoder = encoder.as_mut().ok_or_else(|| { let encoder = encoder.as_mut().ok_or_else(|| {
@ -371,10 +377,17 @@ enum SetBindGroupError {
} }
pub struct GPURenderBundle { pub struct GPURenderBundle {
pub instance: Instance,
pub id: wgpu_core::id::RenderBundleId, pub id: wgpu_core::id::RenderBundleId,
pub label: String, pub label: String,
} }
impl Drop for GPURenderBundle {
fn drop(&mut self) {
self.instance.render_bundle_drop(self.id);
}
}
impl WebIdlInterfaceConverter for GPURenderBundle { impl WebIdlInterfaceConverter for GPURenderBundle {
const NAME: &'static str = "GPURenderBundle"; const NAME: &'static str = "GPURenderBundle";
} }
@ -383,7 +396,16 @@ impl GarbageCollected for GPURenderBundle {}
#[op2] #[op2]
impl GPURenderBundle { impl GPURenderBundle {
crate::with_label!(); #[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
}
} }
#[derive(WebIDL)] #[derive(WebIDL)]

View file

@ -32,7 +32,16 @@ impl GarbageCollected for GPURenderPassEncoder {}
#[op2] #[op2]
impl GPURenderPassEncoder { impl GPURenderPassEncoder {
crate::with_label!(); #[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(6)] #[required(6)]
fn set_viewport( fn set_viewport(
@ -62,10 +71,10 @@ impl GPURenderPassEncoder {
#[required(4)] #[required(4)]
fn set_scissor_rect( fn set_scissor_rect(
&self, &self,
#[webidl/*(options(enforce_range = true))*/] x: u32, #[webidl(options(enforce_range = true))] x: u32,
#[webidl/*(options(enforce_range = true))*/] y: u32, #[webidl(options(enforce_range = true))] y: u32,
#[webidl/*(options(enforce_range = true))*/] width: u32, #[webidl(options(enforce_range = true))] width: u32,
#[webidl/*(options(enforce_range = true))*/] height: u32, #[webidl(options(enforce_range = true))] height: u32,
) { ) {
let err = self let err = self
.instance .instance
@ -95,7 +104,7 @@ impl GPURenderPassEncoder {
#[required(1)] #[required(1)]
fn set_stencil_reference( fn set_stencil_reference(
&self, &self,
#[webidl/*(options(enforce_range = true))*/] reference: u32, #[webidl(options(enforce_range = true))] reference: u32,
) { ) {
let err = self let err = self
.instance .instance
@ -110,7 +119,7 @@ impl GPURenderPassEncoder {
#[required(1)] #[required(1)]
fn begin_occlusion_query( fn begin_occlusion_query(
&self, &self,
#[webidl/*(options(enforce_range = true))*/] query_index: u32, #[webidl(options(enforce_range = true))] query_index: u32,
) { ) {
let err = self let err = self
.instance .instance
@ -191,7 +200,7 @@ impl GPURenderPassEncoder {
fn set_bind_group<'a>( fn set_bind_group<'a>(
&self, &self,
scope: &mut v8::HandleScope<'a>, scope: &mut v8::HandleScope<'a>,
#[webidl/*(options(enforce_range = true))*/] index: u32, #[webidl(options(enforce_range = true))] index: u32,
#[webidl] bind_group: Nullable<Ptr<crate::wrap::bind_group::GPUBindGroup>>, #[webidl] bind_group: Nullable<Ptr<crate::wrap::bind_group::GPUBindGroup>>,
dynamic_offsets: v8::Local<'a, v8::Value>, dynamic_offsets: v8::Local<'a, v8::Value>,
dynamic_offsets_data_start: v8::Local<'a, v8::Value>, dynamic_offsets_data_start: v8::Local<'a, v8::Value>,
@ -286,8 +295,8 @@ impl GPURenderPassEncoder {
&self, &self,
#[webidl] buffer: Ptr<GPUBuffer>, #[webidl] buffer: Ptr<GPUBuffer>,
#[webidl] index_format: crate::wrap::render_pipeline::GPUIndexFormat, #[webidl] index_format: crate::wrap::render_pipeline::GPUIndexFormat,
#[webidl/*(default = 0, options(enforce_range = true))*/] offset: u64, #[webidl(default = 0, options(enforce_range = true))] offset: u64,
#[webidl/*(options(enforce_range = true))*/] size: Option<u64>, #[webidl(options(enforce_range = true))] size: Option<u64>,
) { ) {
let err = self let err = self
.instance .instance
@ -305,10 +314,10 @@ impl GPURenderPassEncoder {
#[required(2)] #[required(2)]
fn set_vertex_buffer( fn set_vertex_buffer(
&self, &self,
#[webidl/*(options(enforce_range = true))*/] slot: u32, #[webidl(options(enforce_range = true))] slot: u32,
#[webidl] buffer: Ptr<GPUBuffer>, // TODO: support nullable buffer #[webidl] buffer: Ptr<GPUBuffer>, // TODO: support nullable buffer
#[webidl/*(default = 0, options(enforce_range = true))*/] offset: u64, #[webidl(default = 0, options(enforce_range = true))] offset: u64,
#[webidl/*(options(enforce_range = true))*/] size: Option<u64>, #[webidl(options(enforce_range = true))] size: Option<u64>,
) { ) {
let err = self let err = self
.instance .instance
@ -326,12 +335,10 @@ impl GPURenderPassEncoder {
#[required(1)] #[required(1)]
fn draw( fn draw(
&self, &self,
#[webidl/*(options(enforce_range = true))*/] vertex_count: u32, #[webidl(options(enforce_range = true))] vertex_count: u32,
#[webidl/*(default = 1, options(enforce_range = true))*/] #[webidl(default = 1, options(enforce_range = true))] instance_count: u32,
instance_count: u32, #[webidl(default = 0, options(enforce_range = true))] first_vertex: u32,
#[webidl/*(default = 0, options(enforce_range = true))*/] first_vertex: u32, #[webidl(default = 0, options(enforce_range = true))] first_instance: u32,
#[webidl/*(default = 0, options(enforce_range = true))*/]
first_instance: u32,
) { ) {
let err = self let err = self
.instance .instance
@ -349,13 +356,11 @@ impl GPURenderPassEncoder {
#[required(1)] #[required(1)]
fn draw_indexed( fn draw_indexed(
&self, &self,
#[webidl/*(options(enforce_range = true))*/] index_count: u32, #[webidl(options(enforce_range = true))] index_count: u32,
#[webidl/*(default = 1, options(enforce_range = true))*/] #[webidl(default = 1, options(enforce_range = true))] instance_count: u32,
instance_count: u32, #[webidl(default = 0, options(enforce_range = true))] first_index: u32,
#[webidl/*(default = 0, options(enforce_range = true))*/] first_index: u32, #[webidl(default = 0, options(enforce_range = true))] base_vertex: i32,
#[webidl/*(default = 0, options(enforce_range = true))*/] base_vertex: i32, #[webidl(default = 0, options(enforce_range = true))] first_instance: u32,
#[webidl/*(default = 0, options(enforce_range = true))*/]
first_instance: u32,
) { ) {
let err = self let err = self
.instance .instance
@ -375,7 +380,7 @@ impl GPURenderPassEncoder {
fn draw_indirect( fn draw_indirect(
&self, &self,
#[webidl] indirect_buffer: Ptr<GPUBuffer>, #[webidl] indirect_buffer: Ptr<GPUBuffer>,
#[webidl/*(options(enforce_range = true))*/] indirect_offset: u64, #[webidl(options(enforce_range = true))] indirect_offset: u64,
) { ) {
let err = self let err = self
.instance .instance
@ -392,7 +397,7 @@ impl GPURenderPassEncoder {
fn draw_indexed_indirect( fn draw_indexed_indirect(
&self, &self,
#[webidl] indirect_buffer: Ptr<GPUBuffer>, #[webidl] indirect_buffer: Ptr<GPUBuffer>,
#[webidl/*(options(enforce_range = true))*/] indirect_offset: u64, #[webidl(options(enforce_range = true))] indirect_offset: u64,
) { ) {
let err = self let err = self
.instance .instance

View file

@ -23,6 +23,12 @@ pub struct GPURenderPipeline {
pub label: String, pub label: String,
} }
impl Drop for GPURenderPipeline {
fn drop(&mut self) {
self.instance.render_pipeline_drop(self.id);
}
}
impl WebIdlInterfaceConverter for GPURenderPipeline { impl WebIdlInterfaceConverter for GPURenderPipeline {
const NAME: &'static str = "GPURenderPipeline"; const NAME: &'static str = "GPURenderPipeline";
} }
@ -31,7 +37,16 @@ impl GarbageCollected for GPURenderPipeline {}
#[op2] #[op2]
impl GPURenderPipeline { impl GPURenderPipeline {
crate::with_label!(); #[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
}
#[cppgc] #[cppgc]
fn get_bind_group_layout(&self, #[webidl] index: u32) -> GPUBindGroupLayout { fn get_bind_group_layout(&self, #[webidl] index: u32) -> GPUBindGroupLayout {
@ -43,6 +58,7 @@ impl GPURenderPipeline {
// TODO: wgpu needs to add a way to retrieve the label // TODO: wgpu needs to add a way to retrieve the label
GPUBindGroupLayout { GPUBindGroupLayout {
instance: self.instance.clone(),
id, id,
label: "".to_string(), label: "".to_string(),
} }

View file

@ -13,6 +13,12 @@ pub struct GPUSampler {
pub label: String, pub label: String,
} }
impl Drop for GPUSampler {
fn drop(&mut self) {
self.instance.sampler_drop(self.id);
}
}
impl WebIdlInterfaceConverter for GPUSampler { impl WebIdlInterfaceConverter for GPUSampler {
const NAME: &'static str = "GPUSampler"; const NAME: &'static str = "GPUSampler";
} }
@ -21,7 +27,16 @@ impl GarbageCollected for GPUSampler {}
#[op2] #[op2]
impl GPUSampler { impl GPUSampler {
crate::with_label!(); #[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
}
} }
#[derive(WebIDL)] #[derive(WebIDL)]

View file

@ -5,11 +5,20 @@ use deno_core::webidl::WebIdlInterfaceConverter;
use deno_core::GarbageCollected; use deno_core::GarbageCollected;
use deno_core::WebIDL; use deno_core::WebIDL;
use crate::Instance;
pub struct GPUShaderModule { pub struct GPUShaderModule {
pub instance: Instance,
pub id: wgpu_core::id::ShaderModuleId, pub id: wgpu_core::id::ShaderModuleId,
pub label: String, pub label: String,
} }
impl Drop for GPUShaderModule {
fn drop(&mut self) {
self.instance.shader_module_drop(self.id);
}
}
impl WebIdlInterfaceConverter for GPUShaderModule { impl WebIdlInterfaceConverter for GPUShaderModule {
const NAME: &'static str = "GPUShaderModule"; const NAME: &'static str = "GPUShaderModule";
} }
@ -18,7 +27,16 @@ impl GarbageCollected for GPUShaderModule {}
#[op2] #[op2]
impl GPUShaderModule { impl GPUShaderModule {
crate::with_label!(); #[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
}
} }
#[derive(WebIDL)] #[derive(WebIDL)]

View file

@ -55,6 +55,12 @@ pub struct GPUTexture {
pub usage: u32, pub usage: u32,
} }
impl Drop for GPUTexture {
fn drop(&mut self) {
self.instance.texture_drop(self.id);
}
}
impl WebIdlInterfaceConverter for GPUTexture { impl WebIdlInterfaceConverter for GPUTexture {
const NAME: &'static str = "GPUTexture"; const NAME: &'static str = "GPUTexture";
} }
@ -63,7 +69,16 @@ impl GarbageCollected for GPUTexture {}
#[op2] #[op2]
impl GPUTexture { impl GPUTexture {
crate::with_label!(); #[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
}
#[getter] #[getter]
fn width(&self) -> u32 { fn width(&self) -> u32 {
@ -133,6 +148,7 @@ impl GPUTexture {
self.error_handler.push_error(err); self.error_handler.push_error(err);
Ok(GPUTextureView { Ok(GPUTextureView {
instance: self.instance.clone(),
id, id,
label: descriptor.label, label: descriptor.label,
}) })
@ -209,11 +225,18 @@ impl From<GPUTextureAspect> for TextureAspect {
} }
} }
pub(crate) struct GPUTextureView { pub struct GPUTextureView {
pub instance: Instance,
pub id: wgpu_core::id::TextureViewId, pub id: wgpu_core::id::TextureViewId,
pub label: String, pub label: String,
} }
impl Drop for GPUTextureView {
fn drop(&mut self) {
let _ = self.instance.texture_view_drop(self.id);
}
}
impl WebIdlInterfaceConverter for GPUTextureView { impl WebIdlInterfaceConverter for GPUTextureView {
const NAME: &'static str = "GPUTextureView"; const NAME: &'static str = "GPUTextureView";
} }
@ -223,7 +246,16 @@ impl GarbageCollected for GPUTextureView {}
#[op2] #[op2]
impl GPUTextureView { impl GPUTextureView {
crate::with_label!(); #[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
}
} }
#[derive(WebIDL, Clone)] #[derive(WebIDL, Clone)]

View file

@ -1312,18 +1312,17 @@ function configureProperties(obj) {
} }
} }
const setlikeInner = SymbolFor("[[set]]"); const setlikeInner = SymbolFor("setlike_set");
// Ref: https://webidl.spec.whatwg.org/#es-setlike // Ref: https://webidl.spec.whatwg.org/#es-setlike
function setlike(obj, objPrototype, readonly) { function setlike(obj, objPrototype, readonly) {
ObjectDefineProperties(obj, { ObjectDefineProperties(objPrototype, {
size: { size: {
__proto__: null, __proto__: null,
configurable: true, configurable: true,
enumerable: true, enumerable: true,
get() { get() {
assertBranded(this, objPrototype); return this[setlikeInner].size;
return obj[setlikeInner].size;
}, },
}, },
[SymbolIterator]: { [SymbolIterator]: {
@ -1332,8 +1331,7 @@ function setlike(obj, objPrototype, readonly) {
enumerable: false, enumerable: false,
writable: true, writable: true,
value() { value() {
assertBranded(this, objPrototype); return this[setlikeInner][SymbolIterator]();
return obj[setlikeInner][SymbolIterator]();
}, },
}, },
entries: { entries: {
@ -1342,8 +1340,7 @@ function setlike(obj, objPrototype, readonly) {
enumerable: true, enumerable: true,
writable: true, writable: true,
value() { value() {
assertBranded(this, objPrototype); return SetPrototypeEntries(this[setlikeInner]);
return SetPrototypeEntries(obj[setlikeInner]);
}, },
}, },
keys: { keys: {
@ -1352,8 +1349,7 @@ function setlike(obj, objPrototype, readonly) {
enumerable: true, enumerable: true,
writable: true, writable: true,
value() { value() {
assertBranded(this, objPrototype); return SetPrototypeKeys(this[setlikeInner]);
return SetPrototypeKeys(obj[setlikeInner]);
}, },
}, },
values: { values: {
@ -1362,8 +1358,7 @@ function setlike(obj, objPrototype, readonly) {
enumerable: true, enumerable: true,
writable: true, writable: true,
value() { value() {
assertBranded(this, objPrototype); return SetPrototypeValues(this[setlikeInner]);
return SetPrototypeValues(obj[setlikeInner]);
}, },
}, },
forEach: { forEach: {
@ -1372,8 +1367,7 @@ function setlike(obj, objPrototype, readonly) {
enumerable: true, enumerable: true,
writable: true, writable: true,
value(callbackfn, thisArg) { value(callbackfn, thisArg) {
assertBranded(this, objPrototype); return SetPrototypeForEach(this[setlikeInner], callbackfn, thisArg);
return SetPrototypeForEach(obj[setlikeInner], callbackfn, thisArg);
}, },
}, },
has: { has: {
@ -1382,22 +1376,20 @@ function setlike(obj, objPrototype, readonly) {
enumerable: true, enumerable: true,
writable: true, writable: true,
value(value) { value(value) {
assertBranded(this, objPrototype); return SetPrototypeHas(this[setlikeInner], value);
return SetPrototypeHas(obj[setlikeInner], value);
}, },
}, },
}); });
if (!readonly) { if (!readonly) {
ObjectDefineProperties(obj, { ObjectDefineProperties(objPrototype, {
add: { add: {
__proto__: null, __proto__: null,
configurable: true, configurable: true,
enumerable: true, enumerable: true,
writable: true, writable: true,
value(value) { value(value) {
assertBranded(this, objPrototype); return SetPrototypeAdd(this[setlikeInner], value);
return SetPrototypeAdd(obj[setlikeInner], value);
}, },
}, },
delete: { delete: {
@ -1406,8 +1398,7 @@ function setlike(obj, objPrototype, readonly) {
enumerable: true, enumerable: true,
writable: true, writable: true,
value(value) { value(value) {
assertBranded(this, objPrototype); return SetPrototypeDelete(this[setlikeInner], value);
return SetPrototypeDelete(obj[setlikeInner], value);
}, },
}, },
clear: { clear: {
@ -1416,8 +1407,7 @@ function setlike(obj, objPrototype, readonly) {
enumerable: true, enumerable: true,
writable: true, writable: true,
value() { value() {
assertBranded(this, objPrototype); return SetPrototypeClear(this[setlikeInner]);
return SetPrototypeClear(obj[setlikeInner]);
}, },
}, },
}); });