use dom_struct::dom_struct;
use js::context::{JSContext, NoGC};
use script_bindings::cell::DomRefCell;
use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
use webgpu_traits::{WebGPU, WebGPUComputePass, WebGPURequest};
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUComputePassEncoderMethods;
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::USVString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::webgpu::gpubindgroup::GPUBindGroup;
use crate::dom::webgpu::gpubuffer::GPUBuffer;
use crate::dom::webgpu::gpucommandencoder::GPUCommandEncoder;
use crate::dom::webgpu::gpucomputepipeline::GPUComputePipeline;
#[derive(JSTraceable, MallocSizeOf)]
struct DroppableGPUComputePassEncoder {
#[no_trace]
channel: WebGPU,
#[no_trace]
compute_pass: WebGPUComputePass,
}
impl Drop for DroppableGPUComputePassEncoder {
fn drop(&mut self) {
if let Err(e) = self
.channel
.0
.send(WebGPURequest::DropComputePass(self.compute_pass.0))
{
warn!("Failed to send WebGPURequest::DropComputePass with {e:?}");
}
}
}
#[dom_struct]
pub(crate) struct GPUComputePassEncoder {
reflector_: Reflector,
label: DomRefCell<USVString>,
command_encoder: Dom<GPUCommandEncoder>,
droppable: DroppableGPUComputePassEncoder,
}
impl GPUComputePassEncoder {
fn new_inherited(
channel: WebGPU,
parent: &GPUCommandEncoder,
compute_pass: WebGPUComputePass,
label: USVString,
) -> Self {
Self {
reflector_: Reflector::new(),
label: DomRefCell::new(label),
command_encoder: Dom::from_ref(parent),
droppable: DroppableGPUComputePassEncoder {
channel,
compute_pass,
},
}
}
pub(crate) fn new(
cx: &mut JSContext,
global: &GlobalScope,
channel: WebGPU,
parent: &GPUCommandEncoder,
compute_pass: WebGPUComputePass,
label: USVString,
) -> DomRoot<Self> {
reflect_dom_object_with_cx(
Box::new(GPUComputePassEncoder::new_inherited(
channel,
parent,
compute_pass,
label,
)),
global,
cx,
)
}
}
impl GPUComputePassEncoderMethods<crate::DomTypeHolder> for GPUComputePassEncoder {
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
fn SetLabel(&self, no_gc: &NoGC, value: USVString) {
*self.label.safe_borrow_mut(no_gc) = value;
}
fn DispatchWorkgroups(&self, x: u32, y: u32, z: u32) {
if let Err(e) =
self.droppable
.channel
.0
.send(WebGPURequest::ComputePassDispatchWorkgroups {
compute_pass_id: self.droppable.compute_pass.0,
x,
y,
z,
device_id: self.command_encoder.device_id().0,
})
{
warn!("Error sending WebGPURequest::ComputePassDispatchWorkgroups: {e:?}")
}
}
fn DispatchWorkgroupsIndirect(&self, buffer: &GPUBuffer, offset: u64) {
if let Err(e) =
self.droppable
.channel
.0
.send(WebGPURequest::ComputePassDispatchWorkgroupsIndirect {
compute_pass_id: self.droppable.compute_pass.0,
buffer_id: buffer.id().0,
offset,
device_id: self.command_encoder.device_id().0,
})
{
warn!("Error sending WebGPURequest::ComputePassDispatchWorkgroupsIndirect: {e:?}")
}
}
fn End(&self) {
if let Err(e) = self
.droppable
.channel
.0
.send(WebGPURequest::EndComputePass {
compute_pass_id: self.droppable.compute_pass.0,
device_id: self.command_encoder.device_id().0,
})
{
warn!("Failed to send WebGPURequest::EndComputePass: {e:?}");
}
}
fn SetBindGroup(&self, index: u32, bind_group: &GPUBindGroup, offsets: Vec<u32>) {
if let Err(e) = self
.droppable
.channel
.0
.send(WebGPURequest::ComputePassSetBindGroup {
compute_pass_id: self.droppable.compute_pass.0,
index,
bind_group_id: bind_group.id().0,
offsets,
device_id: self.command_encoder.device_id().0,
})
{
warn!("Error sending WebGPURequest::ComputePassSetBindGroup: {e:?}")
}
}
fn SetPipeline(&self, pipeline: &GPUComputePipeline) {
if let Err(e) = self
.droppable
.channel
.0
.send(WebGPURequest::ComputePassSetPipeline {
compute_pass_id: self.droppable.compute_pass.0,
pipeline_id: pipeline.id().0,
device_id: self.command_encoder.device_id().0,
})
{
warn!("Error sending WebGPURequest::ComputePassSetPipeline: {e:?}")
}
}
fn PushDebugGroup(&self, group_label: USVString) {
if let Err(e) = self
.droppable
.channel
.0
.send(WebGPURequest::ComputePassPushDebugGroup {
compute_pass_id: self.droppable.compute_pass.0,
label: group_label.to_string(),
device_id: self.command_encoder.device_id().0,
})
{
warn!("Error sending WebGPURequest::ComputePassPushDebugGroup: {e:?}")
}
}
fn PopDebugGroup(&self) {
if let Err(e) = self
.droppable
.channel
.0
.send(WebGPURequest::ComputePassPopDebugGroup {
compute_pass_id: self.droppable.compute_pass.0,
device_id: self.command_encoder.device_id().0,
})
{
warn!("Error sending WebGPURequest::ComputePassPopDebugGroup: {e:?}")
}
}
fn InsertDebugMarker(&self, marker_label: USVString) {
if let Err(e) = self
.droppable
.channel
.0
.send(WebGPURequest::ComputePassInsertDebugMarker {
compute_pass_id: self.droppable.compute_pass.0,
label: marker_label.to_string(),
device_id: self.command_encoder.device_id().0,
})
{
warn!("Error sending WebGPURequest::ComputePassInsertDebugMarker: {e:?}")
}
}
}