diff --git a/crates/canvas-c/src/webgpu/enums.rs b/crates/canvas-c/src/webgpu/enums.rs index 80be345b6..ea7618f3b 100644 --- a/crates/canvas-c/src/webgpu/enums.rs +++ b/crates/canvas-c/src/webgpu/enums.rs @@ -1083,11 +1083,11 @@ pub enum CanvasCullMode { } impl From for Option { - fn from(value: GpuCullMode) -> Option { + fn from(value: CanvasCullMode) -> Option { match value { - GpuCullMode::None => None, - GpuCullMode::Front => Some(wgpu_types::Face::Front), - GpuCullMode::Back => Some(wgpu_types::Face::Back), + CanvasCullMode::None => None, + CanvasCullMode::Front => Some(wgpu_types::Face::Front), + CanvasCullMode::Back => Some(wgpu_types::Face::Back), } } } diff --git a/crates/canvas-c/src/webgpu/gpu_command_encoder.rs b/crates/canvas-c/src/webgpu/gpu_command_encoder.rs index 1b83b3b6b..c0d84f494 100644 --- a/crates/canvas-c/src/webgpu/gpu_command_encoder.rs +++ b/crates/canvas-c/src/webgpu/gpu_command_encoder.rs @@ -130,7 +130,7 @@ pub extern "C" fn canvas_native_webgpu_command_encoder_begin_render_pass( label, color_attachments: todo!(), depth_stencil_attachment: todo!(), - timestamp_writes, + timestamp_writes: timestamp_writes.as_ref(), occlusion_query_set: todo!(), }; let pass = wgpu_core::command::RenderPass::new(command_encoder_id, &desc); diff --git a/crates/canvas-c/src/webgpu/gpu_device.rs b/crates/canvas-c/src/webgpu/gpu_device.rs index 3be2eb13e..352a490e9 100644 --- a/crates/canvas-c/src/webgpu/gpu_device.rs +++ b/crates/canvas-c/src/webgpu/gpu_device.rs @@ -1,4 +1,5 @@ use std::{ + borrow::Cow, collections::HashMap, ffi::{CStr, CString}, os::raw::{c_char, c_void}, @@ -7,11 +8,17 @@ use std::{ use crate::buffers::StringBuffer; use super::{ - enums::{CanvasCompareFunction, CanvasCullMode, CanvasFrontFace, CanvasGPUTextureFormat, CanvasIndexFormat, CanvasPrimitiveTopology, CanvasStencilFaceState, CanvasTextureDimension, CanvasVertexStepMode}, + enums::{ + CanvasCompareFunction, CanvasCullMode, CanvasFrontFace, CanvasGPUTextureFormat, + CanvasIndexFormat, CanvasPrimitiveTopology, CanvasStencilFaceState, CanvasTextureDimension, + CanvasVertexStepMode, + }, gpu::CanvasWebGPUInstance, gpu_buffer::CanvasGPUBuffer, gpu_command_encoder::CanvasGPUCommandEncoder, + gpu_pipeline_layout::CanvasGPUPipelineLayout, gpu_queue::CanvasGPUQueue, + gpu_render_pipeline::CanvasGPURenderPipeline, gpu_shader_module::CanvasGPUShaderModule, gpu_supported_limits::CanvasGPUSupportedLimits, gpu_texture::CanvasGPUTexture, @@ -299,7 +306,7 @@ pub unsafe extern "C" fn canvas_native_webgpu_constants_insert( constants: *mut CanvasConstants, key: *const c_char, value: f64, -) -> *mut CanvasConstants { +) { if constants.is_null() { return; } @@ -314,7 +321,7 @@ pub unsafe extern "C" fn canvas_native_webgpu_constants_insert( #[no_mangle] pub unsafe extern "C" fn canvas_native_webgpu_constants_destroy( constants: *mut CanvasConstants, -) -> *mut CanvasConstants { +) { if constants.is_null() { return; } @@ -322,7 +329,6 @@ pub unsafe extern "C" fn canvas_native_webgpu_constants_destroy( let _ = Box::from_raw(constants); } - #[repr(C)] pub struct CanvasDepthStencilState { format: CanvasGPUTextureFormat, @@ -340,7 +346,7 @@ pub struct CanvasDepthStencilState { #[repr(C)] pub struct CanvasPrimitiveState { topology: CanvasPrimitiveTopology, - strip_index_format: *const CanvasIndexFormat, + strip_index_format: CanvasIndexFormat, front_face: CanvasFrontFace, cull_mode: CanvasCullMode, unclipped_depth: bool, @@ -351,7 +357,7 @@ pub struct CanvasVertexBufferLayout { array_stride: u64, step_mode: CanvasVertexStepMode, attributes: *const CanvasVertexAttribute, - attributes_size: usize + attributes_size: usize, } #[repr(C)] @@ -361,15 +367,14 @@ pub struct CanvasVertexState { constants: *const CanvasConstants, constants_size: usize, buffers: *const CanvasVertexBufferLayout, - buffers_size: usize + buffers_size: usize, } - #[repr(C)] struct CanvasFragmentState { targets: *const CanvasColorTargetState, targets_size: usize, - module: u32, + module: *const CanvasGPUShaderModule, entry_point: *const c_char, constants: *const CanvasConstants, } @@ -400,7 +405,7 @@ pub struct CanvasCreateRenderPipelineDescriptor { #[no_mangle] pub unsafe extern "C" fn canvas_native_webgpu_device_create_render_pipeline( device: *const CanvasGPUDevice, - descriptor: *const CanvasCreateRenderPipelineDescriptor + descriptor: *const CanvasCreateRenderPipelineDescriptor, ) -> *mut CanvasGPUBuffer { if device.is_null() || descriptor.is_null() { return std::ptr::null_mut(); @@ -414,20 +419,171 @@ pub unsafe extern "C" fn canvas_native_webgpu_device_create_render_pipeline( let descriptor = &*descriptor; + let label = if !descriptor.label.is_null() { + Some(unsafe { CStr::from_ptr(descriptor.label).to_string_lossy() }) + } else { + None + }; + + let layout = match descriptor.layout { + CanvasGPUPipelineLayoutOrGPUAutoLayoutMode::Layout(value) => { + if value.is_null() { + None + } else { + let value = &*value; + Some(value.layout) + } + } + CanvasGPUPipelineLayoutOrGPUAutoLayoutMode::Auto(CanvasGPUAutoLayoutMode::Auto) => None, + }; + + let vertex = &*descriptor.vertex; + + let vertex_shader_module = &*vertex.module; + let vertex_shader_module_id = vertex_shader_module.module; - // let desc = wgpu_core::pipeline::RenderPipelineDescriptor { - // label: todo!(), - // layout: todo!(), - // vertex: todo!(), - // primitive: todo!(), - // depth_stencil: todo!(), - // multisample: todo!(), - // fragment: todo!(), - // multiview: todo!(), - // }; + let fragment = if !descriptor.fragment.is_null() { + let frag = &*descriptor.fragment; + let module = &*frag.module; + let module_id = module.module; - // global.device_create_render_pipeline(device_id, &desc, None, None) + let entry_point = if frag.entry_point.is_null() { + None + } else { + Some(CStr::from_ptr(frag.entry_point).to_string_lossy()) + }; + + let targets = if !frag.targets.is_null() { + std::slice::from_raw_parts(frag.targets, frag.targets_size) + .iter() + .map(|target| { + Some(wgpu_types::ColorTargetState { + format: target.format.into(), + blend: target.blend.into(), + write_mask: wgpu_types::ColorWrites::from_bits_retain(target.write_mask,) + }) + }) + .collect::>>() + } else { + vec![] + }; + + if (frag.constants.is_null()) { + let constants = HashMap::default(); + Some(wgpu_core::pipeline::FragmentState { + stage: wgpu_core::pipeline::ProgrammableStageDescriptor { + module: module_id, + entry_point: entry_point, + constants: Cow::Owned(constants), + // Required to be true for WebGPU + zero_initialize_workgroup_memory: true, + }, + targets: Cow::Owned(targets), + }) + } else { + let constants = &*frag.constants; + let constants = Cow::from(&constants.0); + Some(wgpu_core::pipeline::FragmentState { + stage: wgpu_core::pipeline::ProgrammableStageDescriptor { + module: module_id, + entry_point: entry_point, + constants: constants, + // Required to be true for WebGPU + zero_initialize_workgroup_memory: true, + }, + targets: Cow::Owned(targets), + }) + } + } else { + None + }; + + let primitive = &*descriptor.primitive; + let primitive: wgpu_types::PrimitiveState = primitive.into(); + + let depth_stencil = if !descriptor.depth_stencil.is_null() { + let depth_stencil = &*descriptor.depth_stencil; + let depth_stencil: wgpu_types::DepthStencilState = depth_stencil.into(); + Some(depth_stencil) + } else { + None + }; + + let multisample = &*descriptor.multisample; + + let multisample: wgpu_types::MultisampleState = multisample.into(); + + let vertex_buffers = if !vertex.buffers.is_null() { + let buffers = std::slice::from_raw_parts(vertex.buffers, vertex.buffers_size); + buffers + .iter() + .map(|layout| { + let attributes = if !layout.attributes.is_null() { + std::slice::from_raw_parts(layout.attributes, layout.attributes_size) + .iter() + .map(|attr| attr.into()) + .collect::>() + } else { + vec![] + }; + wgpu_core::pipeline::VertexBufferLayout { + array_stride: layout.array_stride, + attributes: Cow::Owned((attributes)), + step_mode: layout.step_mode.into(), + } + }) + .collect::>() + } else { + vec![] + }; + + let entry_point = if vertex.entry_point.is_null() { + None + } else { + Some(CStr::from_ptr(vertex.entry_point).to_string_lossy()) + }; + + let constants = if !vertex.constants.is_null() { + let constants = &*vertex.constants; + Cow::Borrowed(&constants.0) + } else { + HashMap::default() + }; + + let vertex = wgpu_core::pipeline::VertexState { + stage: wgpu_core::pipeline::ProgrammableStageDescriptor { + module: vertex_shader_module_id, + entry_point: entry_point, + constants: Cow::Owned(constants), + // Required to be true for WebGPU + zero_initialize_workgroup_memory: true, + }, + buffers: Cow::Owned(vertex_buffers), + }; + + let desc = wgpu_core::pipeline::RenderPipelineDescriptor { + label: label, + layout: layout, + vertex: vertex, + primitive: primitive, + depth_stencil: depth_stencil, + multisample: multisample, + fragment: fragment, + multiview: None, + }; + + let (pipeline, error) = gfx_select!(device_id => global.device_create_render_pipeline(device_id, &desc, None, None)); + + if let Some(error) = error { + // todo handle error + return std::ptr::null_mut(); + } + + Box::into_raw(Box::new(CanvasGPURenderPipeline { + instance: device.instance.clone(), + pipeline: pipeline, + })) } #[repr(C)] diff --git a/crates/canvas-c/src/webgpu/gpu_pipeline_layout.rs b/crates/canvas-c/src/webgpu/gpu_pipeline_layout.rs index a7b7f3ef3..d0ca08bcf 100644 --- a/crates/canvas-c/src/webgpu/gpu_pipeline_layout.rs +++ b/crates/canvas-c/src/webgpu/gpu_pipeline_layout.rs @@ -1,3 +1,5 @@ +use super::gpu::CanvasWebGPUInstance; + pub struct CanvasGPUPipelineLayout { pub(crate) instance: CanvasWebGPUInstance, pub(crate) layout: wgpu_core::id::PipelineLayoutId, diff --git a/crates/canvas-c/src/webgpu/gpu_queue.rs b/crates/canvas-c/src/webgpu/gpu_queue.rs index de98e4a58..0534266db 100644 --- a/crates/canvas-c/src/webgpu/gpu_queue.rs +++ b/crates/canvas-c/src/webgpu/gpu_queue.rs @@ -249,7 +249,7 @@ pub unsafe extern "C" fn canvas_native_webgpu_queue_write_texture( let data_layout: wgpu_types::ImageDataLayout = data_layout.into(); - let buf = std::slice::from_raw_parts(buf, buf_size); + let data = std::slice::from_raw_parts(buf, buf_size); let size: wgpu_types::Extent3d = size.into(); diff --git a/crates/canvas-c/src/webgpu/gpu_texture.rs b/crates/canvas-c/src/webgpu/gpu_texture.rs index 9d05f6fef..3a27c313d 100644 --- a/crates/canvas-c/src/webgpu/gpu_texture.rs +++ b/crates/canvas-c/src/webgpu/gpu_texture.rs @@ -1,4 +1,4 @@ -use std::{ffi::CString, os::raw::c_char}; +use std::{ffi::{CStr, CString}, os::raw::c_char}; use super::{ enums::{CanvasGPUTextureFormat, CanvasTextureDimension}, diff --git a/crates/canvas-c/src/webgpu/structs.rs b/crates/canvas-c/src/webgpu/structs.rs index 709491a6f..1f26becb2 100644 --- a/crates/canvas-c/src/webgpu/structs.rs +++ b/crates/canvas-c/src/webgpu/structs.rs @@ -1,4 +1,6 @@ -use super::enums::{CanvasGPUTextureFormat, CanvasVertexFormat}; +use wgpu_core::naga::valid; + +use super::enums::{CanvasGPUTextureFormat, CanvasTextureAspect, CanvasVertexFormat}; #[repr(C)] #[derive(Clone, Copy, PartialEq, Eq, Hash)] @@ -231,8 +233,8 @@ impl From for CanvasImageSubresourceRange { } } -impl Into for CanvasImageSubresourceRange { - fn into(self) -> wgpu_core::ImageSubresourceRange { +impl Into for CanvasImageSubresourceRange { + fn into(self) -> wgpu_types::ImageSubresourceRange { wgpu_types::ImageSubresourceRange { aspect: self.aspect.into(), base_mip_level: self.base_mip_level, @@ -244,7 +246,7 @@ impl Into for CanvasImageSubresourceRange { } #[repr(C)] -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct CanvasColorTargetState { pub format: CanvasGPUTextureFormat, pub blend: CanvasOptionalBlendState, @@ -252,6 +254,7 @@ pub struct CanvasColorTargetState { } #[repr(C)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum CanvasOptionalBlendState { None, Some(CanvasBlendState), @@ -260,18 +263,36 @@ pub enum CanvasOptionalBlendState { impl From for CanvasColorTargetState { fn from(format: wgpu_types::TextureFormat) -> Self { Self { - format, - blend: None, + format: format.into(), + blend: CanvasOptionalBlendState::None, write_mask: wgpu_types::ColorWrites::ALL.bits(), } } } +impl From> for CanvasOptionalBlendState { + fn from(value: Option) -> Self { + match value { + Some(value) => Some(value.into()), + None => Self::None, + } + } +} + +impl Into> for CanvasOptionalBlendState { + fn into(self) -> Option { + match self { + CanvasOptionalBlendState::None => None, + CanvasOptionalBlendState::Some(value) => Some(value.into()), + } + } +} + impl From for CanvasColorTargetState { fn from(format: CanvasGPUTextureFormat) -> Self { Self { format, - blend: None, + blend: CanvasOptionalBlendState::None, write_mask: wgpu_types::ColorWrites::ALL.bits(), } } @@ -298,7 +319,7 @@ impl CanvasBlendState { color: CanvasBlendComponent { src_factor: CanvasBlendFactor::SrcAlpha, dst_factor: CanvasBlendFactor::OneMinusSrcAlpha, - operation: CanvasBlendFactor::Add, + operation: CanvasBlendOperation::Add, }, alpha: CanvasBlendComponent::OVER, }; diff --git a/packages/canvas/src-native/canvas-android/canvas/src/main/cpp/include/canvas_native.h b/packages/canvas/src-native/canvas-android/canvas/src/main/cpp/include/canvas_native.h index 2d4f8d380..d8819fdeb 100644 --- a/packages/canvas/src-native/canvas-android/canvas/src/main/cpp/include/canvas_native.h +++ b/packages/canvas/src-native/canvas-android/canvas/src/main/cpp/include/canvas_native.h @@ -717,7 +717,7 @@ typedef struct CanvasVertexState { typedef struct CanvasPrimitiveState { enum CanvasPrimitiveTopology topology; - const enum CanvasIndexFormat *strip_index_format; + enum CanvasIndexFormat strip_index_format; enum CanvasFrontFace front_face; enum CanvasCullMode cull_mode; bool unclipped_depth; @@ -1235,7 +1235,7 @@ typedef struct CanvasBlendState { /** * Blend mode that does standard alpha blending with non-premultiplied alpha. */ -#define CanvasBlendState_ALPHA_BLENDING (CanvasBlendState){ .color = (CanvasBlendComponent){ .src_factor = CanvasBlendFactor_SrcAlpha, .dst_factor = CanvasBlendFactor_OneMinusSrcAlpha, .operation = CanvasBlendFactor_Add }, .alpha = CanvasBlendComponent_OVER } +#define CanvasBlendState_ALPHA_BLENDING (CanvasBlendState){ .color = (CanvasBlendComponent){ .src_factor = CanvasBlendFactor_SrcAlpha, .dst_factor = CanvasBlendFactor_OneMinusSrcAlpha, .operation = CanvasBlendOperation_Add }, .alpha = CanvasBlendComponent_OVER } /** * Blend mode that does standard alpha blending with premultiplied alpha. */ @@ -1264,7 +1264,7 @@ typedef struct CanvasColorTargetState { typedef struct CanvasFragmentState { const struct CanvasColorTargetState *targets; uintptr_t targets_size; - uint32_t module; + const struct CanvasGPUShaderModule *module; const char *entry_point; const struct CanvasConstants *constants; } CanvasFragmentState; @@ -4151,11 +4151,11 @@ struct CanvasGPUBuffer *canvas_native_webgpu_device_create_buffer(const struct C struct CanvasConstants *canvas_native_webgpu_constants_create(void); -struct CanvasConstants *canvas_native_webgpu_constants_insert(struct CanvasConstants *constants, - const char *key, - double value); +void canvas_native_webgpu_constants_insert(struct CanvasConstants *constants, + const char *key, + double value); -struct CanvasConstants *canvas_native_webgpu_constants_destroy(struct CanvasConstants *constants); +void canvas_native_webgpu_constants_destroy(struct CanvasConstants *constants); struct CanvasGPUBuffer *canvas_native_webgpu_device_create_render_pipeline(const struct CanvasGPUDevice *device, const struct CanvasCreateRenderPipelineDescriptor *descriptor); diff --git a/packages/canvas/src-native/canvas-ios/CanvasNative/include/canvas_native.h b/packages/canvas/src-native/canvas-ios/CanvasNative/include/canvas_native.h index 2d4f8d380..d8819fdeb 100644 --- a/packages/canvas/src-native/canvas-ios/CanvasNative/include/canvas_native.h +++ b/packages/canvas/src-native/canvas-ios/CanvasNative/include/canvas_native.h @@ -717,7 +717,7 @@ typedef struct CanvasVertexState { typedef struct CanvasPrimitiveState { enum CanvasPrimitiveTopology topology; - const enum CanvasIndexFormat *strip_index_format; + enum CanvasIndexFormat strip_index_format; enum CanvasFrontFace front_face; enum CanvasCullMode cull_mode; bool unclipped_depth; @@ -1235,7 +1235,7 @@ typedef struct CanvasBlendState { /** * Blend mode that does standard alpha blending with non-premultiplied alpha. */ -#define CanvasBlendState_ALPHA_BLENDING (CanvasBlendState){ .color = (CanvasBlendComponent){ .src_factor = CanvasBlendFactor_SrcAlpha, .dst_factor = CanvasBlendFactor_OneMinusSrcAlpha, .operation = CanvasBlendFactor_Add }, .alpha = CanvasBlendComponent_OVER } +#define CanvasBlendState_ALPHA_BLENDING (CanvasBlendState){ .color = (CanvasBlendComponent){ .src_factor = CanvasBlendFactor_SrcAlpha, .dst_factor = CanvasBlendFactor_OneMinusSrcAlpha, .operation = CanvasBlendOperation_Add }, .alpha = CanvasBlendComponent_OVER } /** * Blend mode that does standard alpha blending with premultiplied alpha. */ @@ -1264,7 +1264,7 @@ typedef struct CanvasColorTargetState { typedef struct CanvasFragmentState { const struct CanvasColorTargetState *targets; uintptr_t targets_size; - uint32_t module; + const struct CanvasGPUShaderModule *module; const char *entry_point; const struct CanvasConstants *constants; } CanvasFragmentState; @@ -4151,11 +4151,11 @@ struct CanvasGPUBuffer *canvas_native_webgpu_device_create_buffer(const struct C struct CanvasConstants *canvas_native_webgpu_constants_create(void); -struct CanvasConstants *canvas_native_webgpu_constants_insert(struct CanvasConstants *constants, - const char *key, - double value); +void canvas_native_webgpu_constants_insert(struct CanvasConstants *constants, + const char *key, + double value); -struct CanvasConstants *canvas_native_webgpu_constants_destroy(struct CanvasConstants *constants); +void canvas_native_webgpu_constants_destroy(struct CanvasConstants *constants); struct CanvasGPUBuffer *canvas_native_webgpu_device_create_render_pipeline(const struct CanvasGPUDevice *device, const struct CanvasCreateRenderPipelineDescriptor *descriptor);