diff --git a/examples/hello_triangle_c/main.c b/examples/hello_triangle_c/main.c index 59e81e055..fa0a02ce4 100644 --- a/examples/hello_triangle_c/main.c +++ b/examples/hello_triangle_c/main.c @@ -30,19 +30,115 @@ int main() }, }; WGPUDeviceId device = wgpu_adapter_create_device(adapter, device_desc); - WGPUShaderModuleDescriptor vs_desc = { + + /* + WGPUBindGroupLayoutDescriptor bind_group_layout_desc = { + .bindings = NULL, + .bindings_length = 0, + }; + WGPUBindGroupLayoutId _bind_group_layout = wgpu_device_create_bind_group_layout(device, bind_group_layout_desc); + */ + + WGPUPipelineLayoutDescriptor pipeline_layout_desc = { + .bind_group_layouts = NULL, + .bind_group_layouts_length = 0, + }; + WGPUPipelineLayoutId layout = wgpu_device_create_pipeline_layout(device, pipeline_layout_desc); + + WGPUShaderModuleDescriptor vertex_shader_desc = { .code = read_file("./../data/hello_triangle.vert.spv"), }; - WGPUShaderModuleId _vs = wgpu_device_create_shader_module(device, vs_desc); - WGPUShaderModuleDescriptor fs_desc = { + WGPUShaderModuleId vertex_shader = wgpu_device_create_shader_module(device, vertex_shader_desc); + WGPUPipelineStageDescriptor vertex_stage = { + .module = vertex_shader, + .stage = WGPUShaderStage_Vertex, + .entry_point = "main", + }; + + WGPUShaderModuleDescriptor fragment_shader_desc = { .code = read_file("./../data/hello_triangle.frag.spv"), }; - WGPUShaderModuleId _fs = wgpu_device_create_shader_module(device, fs_desc); - - WGPUCommandBufferDescriptor cmd_buf_desc = { + WGPUShaderModuleId fragment_shader = wgpu_device_create_shader_module(device, fragment_shader_desc); + WGPUPipelineStageDescriptor fragment_stage = { + .module = fragment_shader, + .stage = WGPUShaderStage_Fragment, + .entry_point = "main", }; + + const unsigned int STAGES_LENGTH = 2; + WGPUPipelineStageDescriptor *stages = malloc(STAGES_LENGTH); + stages[0] = vertex_stage; + stages[1] = fragment_stage; + + WGPUBlendDescriptor blend_alpha = { + .src_factor = WGPUBlendFactor_Zero, + .dst_factor = WGPUBlendFactor_Zero, + .operation = WGPUBlendOperation_Add, + }; + WGPUBlendDescriptor blend_color = { + .src_factor = WGPUBlendFactor_Zero, + .dst_factor = WGPUBlendFactor_Zero, + .operation = WGPUBlendOperation_Add, + }; + WGPUBlendStateDescriptor blend_state_0_desc = { + .blend_enabled = false, + .alpha = blend_alpha, + .color = blend_color, + .write_mask = 0, + }; + WGPUBlendStateId blend_state_0 = wgpu_device_create_blend_state(device, blend_state_0_desc); + const unsigned int BLEND_STATE_LENGTH = 1; + WGPUBlendStateId *blend_state = malloc(BLEND_STATE_LENGTH); + blend_state[0] = blend_state_0; + + WGPUStencilStateFaceDescriptor stencil_state_front = { + .compare = WGPUCompareFunction_Never, + .stencil_fail_op = WGPUStencilOperation_Keep, + .depth_fail_op = WGPUStencilOperation_Keep, + .pass_op = WGPUStencilOperation_Keep, + }; + WGPUStencilStateFaceDescriptor stencil_state_back = { + .compare = WGPUCompareFunction_Never, + .stencil_fail_op = WGPUStencilOperation_Keep, + .depth_fail_op = WGPUStencilOperation_Keep, + .pass_op = WGPUStencilOperation_Keep, + }; + WGPUDepthStencilStateDescriptor depth_stencil_state_desc = { + .depth_write_enabled = false, + .depth_compare = WGPUCompareFunction_Never, + .front = stencil_state_front, + .back = stencil_state_back, + .stencil_read_mask = 0, + .stencil_write_mask = 0, + }; + WGPUDepthStencilStateId depth_stencil_state = wgpu_device_create_depth_stencil_state(device, depth_stencil_state_desc); + + const unsigned int FORMATS_LENGTH = 1; + WGPUTextureFormat *formats = malloc(FORMATS_LENGTH); + formats[0] = WGPUTextureFormat_R8g8b8a8Unorm; + WGPUAttachmentStateDescriptor attachment_state_desc = { + .formats = formats, + .formats_length = FORMATS_LENGTH, + }; + WGPUAttachmentStateId attachment_state = wgpu_device_create_attachment_state(device, attachment_state_desc); + + WGPURenderPipelineDescriptor render_pipeline_desc = { + .layout = layout, + .stages = stages, + .stages_length = STAGES_LENGTH, + .primitive_topology = WGPUPrimitiveTopology_TriangleList, + .blend_state = blend_state, + .blend_state_length = BLEND_STATE_LENGTH, + .depth_stencil_state = depth_stencil_state, + .attachment_state = attachment_state, + }; + + WGPURenderPipelineId render_pipeline = wgpu_device_create_render_pipeline(device, render_pipeline_desc); + + WGPUCommandBufferDescriptor cmd_buf_desc = { }; WGPUCommandBufferId cmd_buf = wgpu_device_create_command_buffer(device, cmd_buf_desc); WGPUQueueId queue = wgpu_device_get_queue(device); wgpu_queue_submit(queue, &cmd_buf, 1); + return 0; } diff --git a/wgpu-bindings/wgpu.h b/wgpu-bindings/wgpu.h index e01267d11..bad2c2e05 100644 --- a/wgpu-bindings/wgpu.h +++ b/wgpu-bindings/wgpu.h @@ -8,6 +8,18 @@ #include #include +#define WGPUColorWriteFlags_ALL 15 + +#define WGPUColorWriteFlags_ALPHA 8 + +#define WGPUColorWriteFlags_BLUE 4 + +#define WGPUColorWriteFlags_GREEN 2 + +#define WGPUColorWriteFlags_NONE 0 + +#define WGPUColorWriteFlags_RED 1 + #define WGPUShaderStageFlags_COMPUTE 4 #define WGPUShaderStageFlags_FRAGMENT 2 @@ -23,6 +35,41 @@ typedef enum { WGPUBindingType_StorageBuffer = 3, } WGPUBindingType; +typedef enum { + WGPUBlendFactor_Zero = 0, + WGPUBlendFactor_One = 1, + WGPUBlendFactor_SrcColor = 2, + WGPUBlendFactor_OneMinusSrcColor = 3, + WGPUBlendFactor_SrcAlpha = 4, + WGPUBlendFactor_OneMinusSrcAlpha = 5, + WGPUBlendFactor_DstColor = 6, + WGPUBlendFactor_OneMinusDstColor = 7, + WGPUBlendFactor_DstAlpha = 8, + WGPUBlendFactor_OneMinusDstAlpha = 9, + WGPUBlendFactor_SrcAlphaSaturated = 10, + WGPUBlendFactor_BlendColor = 11, + WGPUBlendFactor_OneMinusBlendColor = 12, +} WGPUBlendFactor; + +typedef enum { + WGPUBlendOperation_Add = 0, + WGPUBlendOperation_Subtract = 1, + WGPUBlendOperation_ReverseSubtract = 2, + WGPUBlendOperation_Min = 3, + WGPUBlendOperation_Max = 4, +} WGPUBlendOperation; + +typedef enum { + WGPUCompareFunction_Never = 0, + WGPUCompareFunction_Less = 1, + WGPUCompareFunction_Equal = 2, + WGPUCompareFunction_LessEqual = 3, + WGPUCompareFunction_Greater = 4, + WGPUCompareFunction_NotEqual = 5, + WGPUCompareFunction_GreaterEqual = 6, + WGPUCompareFunction_Always = 7, +} WGPUCompareFunction; + typedef enum { WGPUPowerPreference_Default = 0, WGPUPowerPreference_LowPower = 1, @@ -43,6 +90,24 @@ typedef enum { WGPUShaderStage_Compute = 2, } WGPUShaderStage; +typedef enum { + WGPUStencilOperation_Keep = 0, + WGPUStencilOperation_Zero = 1, + WGPUStencilOperation_Replace = 2, + WGPUStencilOperation_Invert = 3, + WGPUStencilOperation_IncrementClamp = 4, + WGPUStencilOperation_DecrementClamp = 5, + WGPUStencilOperation_IncrementWrap = 6, + WGPUStencilOperation_DecrementWrap = 7, +} WGPUStencilOperation; + +typedef enum { + WGPUTextureFormat_R8g8b8a8Unorm = 0, + WGPUTextureFormat_R8g8b8a8Uint = 1, + WGPUTextureFormat_B8g8r8a8Unorm = 2, + WGPUTextureFormat_D32FloatS8Uint = 3, +} WGPUTextureFormat; + typedef WGPUId WGPUDeviceId; typedef WGPUId WGPUAdapterId; @@ -66,6 +131,13 @@ typedef WGPUId WGPUInstanceId; typedef struct { } WGPUCommandBufferDescriptor; +typedef WGPUId WGPUAttachmentStateId; + +typedef struct { + const WGPUTextureFormat *formats; + uintptr_t formats_length; +} WGPUAttachmentStateDescriptor; + typedef WGPUId WGPUBindGroupLayoutId; typedef uint32_t WGPUShaderStageFlags; @@ -81,6 +153,41 @@ typedef struct { uintptr_t bindings_length; } WGPUBindGroupLayoutDescriptor; +typedef WGPUId WGPUBlendStateId; + +typedef struct { + WGPUBlendFactor src_factor; + WGPUBlendFactor dst_factor; + WGPUBlendOperation operation; +} WGPUBlendDescriptor; + +typedef uint32_t WGPUColorWriteFlags; + +typedef struct { + bool blend_enabled; + WGPUBlendDescriptor alpha; + WGPUBlendDescriptor color; + WGPUColorWriteFlags write_mask; +} WGPUBlendStateDescriptor; + +typedef WGPUId WGPUDepthStencilStateId; + +typedef struct { + WGPUCompareFunction compare; + WGPUStencilOperation stencil_fail_op; + WGPUStencilOperation depth_fail_op; + WGPUStencilOperation pass_op; +} WGPUStencilStateFaceDescriptor; + +typedef struct { + bool depth_write_enabled; + WGPUCompareFunction depth_compare; + WGPUStencilStateFaceDescriptor front; + WGPUStencilStateFaceDescriptor back; + uint32_t stencil_read_mask; + uint32_t stencil_write_mask; +} WGPUDepthStencilStateDescriptor; + typedef WGPUId WGPUPipelineLayoutId; typedef struct { @@ -98,12 +205,6 @@ typedef struct { const char *entry_point; } WGPUPipelineStageDescriptor; -typedef WGPUId WGPUBlendStateId; - -typedef WGPUId WGPUDepthStencilStateId; - -typedef WGPUId WGPUAttachmentStateId; - typedef struct { WGPUPipelineLayoutId layout; const WGPUPipelineStageDescriptor *stages; @@ -140,9 +241,18 @@ WGPUInstanceId wgpu_create_instance(void); WGPUCommandBufferId wgpu_device_create_command_buffer(WGPUDeviceId device_id, WGPUCommandBufferDescriptor desc); +WGPUAttachmentStateId wgpu_device_create_attachment_state(WGPUDeviceId device_id, + WGPUAttachmentStateDescriptor desc); + WGPUBindGroupLayoutId wgpu_device_create_bind_group_layout(WGPUDeviceId device_id, WGPUBindGroupLayoutDescriptor desc); +WGPUBlendStateId wgpu_device_create_blend_state(WGPUDeviceId _device_id, + WGPUBlendStateDescriptor desc); + +WGPUDepthStencilStateId wgpu_device_create_depth_stencil_state(WGPUDeviceId device_id, + WGPUDepthStencilStateDescriptor desc); + WGPUPipelineLayoutId wgpu_device_create_pipeline_layout(WGPUDeviceId device_id, WGPUPipelineLayoutDescriptor desc); diff --git a/wgpu-native/src/binding_model.rs b/wgpu-native/src/binding_model.rs index 3e1a4d8d0..a25c0b41d 100644 --- a/wgpu-native/src/binding_model.rs +++ b/wgpu-native/src/binding_model.rs @@ -14,6 +14,7 @@ pub const ShaderStageFlags_FRAGMENT: u32 = 2; pub const ShaderStageFlags_COMPUTE: u32 = 4; #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum BindingType { UniformBuffer = 0, Sampler = 1, @@ -44,8 +45,8 @@ pub struct PipelineLayoutDescriptor { pub bind_group_layouts_length: usize, } -pub struct PipelineLayout { - raw: B::PipelineLayout, +pub(crate) struct PipelineLayout { + pub raw: B::PipelineLayout, } #[repr(C)] diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 73abf9a83..ee81ce088 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -17,12 +17,14 @@ use std::thread::ThreadId; #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum LoadOp { Clear = 0, Load = 1, } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum StoreOp { Store = 0, } diff --git a/wgpu-native/src/conv.rs b/wgpu-native/src/conv.rs index e5e0f0962..fe1345124 100644 --- a/wgpu-native/src/conv.rs +++ b/wgpu-native/src/conv.rs @@ -1,6 +1,6 @@ use hal; -use {binding_model, resource}; +use {binding_model, pipeline, resource}; pub(crate) fn map_buffer_usage( usage: resource::BufferUsageFlags, @@ -72,3 +72,167 @@ pub(crate) fn map_shader_stage_flags( } value } + +pub(crate) fn map_primitive_topology( + primitive_topology: pipeline::PrimitiveTopology, +) -> hal::Primitive { + use pipeline::PrimitiveTopology::*; + use hal::Primitive as H; + match primitive_topology { + PointList => H::PointList, + LineList => H::LineList, + LineStrip => H::LineStrip, + TriangleList => H::TriangleList, + TriangleStrip => H::TriangleStrip, + } +} + +pub(crate) fn map_blend_state_descriptor( + desc: pipeline::BlendStateDescriptor, +) -> hal::pso::ColorBlendDesc { + let color_mask = desc.write_mask; + let blend_state = match desc.blend_enabled { + true => hal::pso::BlendState::On { + color: map_blend_descriptor(desc.color), + alpha: map_blend_descriptor(desc.alpha), + }, + false => hal::pso::BlendState::Off, + }; + hal::pso::ColorBlendDesc(map_color_write_flags(color_mask), blend_state) +} + +fn map_color_write_flags(flags: u32) -> hal::pso::ColorMask { + use pipeline::{ColorWriteFlags_RED, ColorWriteFlags_GREEN, ColorWriteFlags_BLUE, ColorWriteFlags_ALPHA}; + use hal::pso::ColorMask as H; + let mut value = H::empty(); + if 0 != flags & ColorWriteFlags_RED { + value |= H::RED; + } + if 0 != flags & ColorWriteFlags_GREEN { + value |= H::GREEN; + } + if 0 != flags & ColorWriteFlags_BLUE { + value |= H::BLUE; + } + if 0 != flags & ColorWriteFlags_ALPHA { + value |= H::ALPHA; + } + value +} + +fn map_blend_descriptor( + blend_desc: pipeline::BlendDescriptor, +) -> hal::pso::BlendOp { + use pipeline::BlendOperation::*; + use hal::pso::BlendOp as H; + match blend_desc.operation { + Add => H::Add { src: map_blend_factor(blend_desc.src_factor), dst: map_blend_factor(blend_desc.dst_factor) }, + Subtract => H::Sub { src: map_blend_factor(blend_desc.src_factor), dst: map_blend_factor(blend_desc.dst_factor) }, + ReverseSubtract => H::RevSub { src: map_blend_factor(blend_desc.src_factor), dst: map_blend_factor(blend_desc.dst_factor) }, + Min => H::Min, + Max => H::Max, + } +} + +fn map_blend_factor( + blend_factor: pipeline::BlendFactor, +) -> hal::pso::Factor { + use pipeline::BlendFactor::*; + use hal::pso::Factor as H; + match blend_factor { + Zero => H::Zero, + One => H::One, + SrcColor => H::SrcColor, + OneMinusSrcColor => H::OneMinusSrcColor, + SrcAlpha => H::SrcAlpha, + OneMinusSrcAlpha => H::OneMinusSrcAlpha, + DstColor => H::DstColor, + OneMinusDstColor => H::OneMinusDstColor, + DstAlpha => H::DstAlpha, + OneMinusDstAlpha => H::OneMinusDstAlpha, + SrcAlphaSaturated => H::SrcAlphaSaturate, + BlendColor => H::ConstColor, + OneMinusBlendColor => H::OneMinusConstColor, + } +} + +pub(crate) fn map_depth_stencil_state( + desc: pipeline::DepthStencilStateDescriptor, +) -> hal::pso::DepthStencilDesc { + hal::pso::DepthStencilDesc { + // TODO DepthTest::Off? + depth: hal::pso::DepthTest:: On { + fun: map_compare_function(desc.depth_compare), + write: desc.depth_write_enabled, + }, + depth_bounds: false, // TODO + // TODO StencilTest::Off? + stencil: hal::pso::StencilTest::On { + front: map_stencil_face(desc.front, desc.stencil_read_mask, desc.stencil_write_mask), + back: map_stencil_face(desc.back, desc.stencil_read_mask, desc.stencil_write_mask), + }, + } +} + +fn map_stencil_face( + stencil_state_face_desc: pipeline::StencilStateFaceDescriptor, + stencil_read_mask: u32, + stencil_write_mask: u32, +) -> hal::pso::StencilFace { + hal::pso::StencilFace { + fun: map_compare_function(stencil_state_face_desc.compare), + mask_read: hal::pso::State::Static(stencil_read_mask), // TODO dynamic? + mask_write: hal::pso::State::Static(stencil_read_mask), // TODO dynamic? + op_fail: map_stencil_operation(stencil_state_face_desc.stencil_fail_op), + op_depth_fail: map_stencil_operation(stencil_state_face_desc.depth_fail_op), + op_pass: map_stencil_operation(stencil_state_face_desc.pass_op), + reference: hal::pso::State::Static(0), // TODO can this be set? + } +} + +fn map_compare_function( + compare_function: resource::CompareFunction +) -> hal::pso::Comparison { + use resource::CompareFunction::*; + use hal::pso::Comparison as H; + match compare_function { + Never => H::Never, + Less => H::Less, + Equal => H::Equal, + LessEqual => H::LessEqual, + Greater => H::Greater, + NotEqual => H::NotEqual, + GreaterEqual => H::GreaterEqual, + Always => H::Always + } +} + +fn map_stencil_operation( + stencil_operation: pipeline::StencilOperation, +) -> hal::pso::StencilOp { + use pipeline::StencilOperation::*; + use hal::pso::StencilOp as H; + match stencil_operation { + Keep => H::Keep, + Zero => H::Zero, + Replace => H::Replace, + Invert => H::Invert, + IncrementClamp => H::IncrementClamp, + DecrementClamp => H::DecrementClamp, + IncrementWrap => H::IncrementWrap, + DecrementWrap => H::DecrementWrap, + } +} + +pub(crate) fn map_texture_format( + texture_format: resource::TextureFormat, +) -> hal::format::Format { + use resource::TextureFormat::*; + use hal::format::Format as H; + match texture_format { + R8g8b8a8Unorm => H::Rgba8Unorm, + R8g8b8a8Uint => H::Rgba8Uint, + B8g8r8a8Unorm => H::Bgra8Unorm, + D32FloatS8Uint => H::D32FloatS8Uint, + } +} diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index c7ee4d5a5..d4c692ef8 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -3,8 +3,9 @@ use hal::queue::RawCommandQueue; use {binding_model, command, conv, memory, pipeline, resource}; use registry::{self, Registry}; -use {BindGroupLayoutId, DeviceId, PipelineLayoutId, RenderPipelineId, , BufferId, CommandBufferId, DeviceId, QueueId, ShaderModuleId}; use std::{iter, slice}; +use {binding_model, conv, memory, pipeline}; +use {AttachmentStateId, BindGroupLayoutId, BlendStateId, BufferId, CommandBufferId, DepthStencilStateId, DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId}; pub struct Device { @@ -39,8 +40,8 @@ pub extern "C" fn wgpu_device_create_bind_group_layout( desc: binding_model::BindGroupLayoutDescriptor, ) -> BindGroupLayoutId { let bindings = unsafe { slice::from_raw_parts(desc.bindings, desc.bindings_length) }; - let device = registry::DEVICE_REGISTRY.get_mut(device_id); - let descriptor_set_layout = device.device.create_descriptor_set_layout( + let device = &mut registry::DEVICE_REGISTRY.get_mut(device_id).device; + let descriptor_set_layout = device.create_descriptor_set_layout( bindings.iter().map(|binding| { hal::pso::DescriptorSetLayoutBinding { binding: binding.binding, @@ -62,7 +63,34 @@ pub extern "C" fn wgpu_device_create_pipeline_layout( device_id: DeviceId, desc: binding_model::PipelineLayoutDescriptor, ) -> PipelineLayoutId { - unimplemented!() + let bind_group_layout_ids = unsafe { slice::from_raw_parts(desc.bind_group_layouts, desc.bind_group_layouts_length) }; + // TODO: only lock mutex once? + let descriptor_set_layouts = bind_group_layout_ids.iter().map(|id| registry::BIND_GROUP_LAYOUT_REGISTRY.get_mut(*id)).collect::>(); + let device = &mut registry::DEVICE_REGISTRY.get_mut(device_id).device; + let pipeline_layout = device.create_pipeline_layout(descriptor_set_layouts.iter().map(|d| &d.raw), &[]); // TODO: push constants + registry::PIPELINE_LAYOUT_REGISTRY.register(binding_model::PipelineLayout { + raw: pipeline_layout, + }) +} + +#[no_mangle] +pub extern "C" fn wgpu_device_create_blend_state( + _device_id: DeviceId, + desc: pipeline::BlendStateDescriptor +) -> BlendStateId { + registry::BLEND_STATE_REGISTRY.register(pipeline::BlendState { + raw: conv::map_blend_state_descriptor(desc), + }) +} + +#[no_mangle] +pub extern "C" fn wgpu_device_create_depth_stencil_state( + device_id: DeviceId, + desc: pipeline::DepthStencilStateDescriptor, +) -> DepthStencilStateId { + registry::DEPTH_STENCIL_STATE_REGISTRY.register(pipeline::DepthStencilState { + raw: conv::map_depth_stencil_state(desc) + }) } #[no_mangle] @@ -70,12 +98,10 @@ pub extern "C" fn wgpu_device_create_shader_module( device_id: DeviceId, desc: pipeline::ShaderModuleDescriptor, ) -> ShaderModuleId { - let device = registry::DEVICE_REGISTRY.get_mut(device_id); + let device = &mut registry::DEVICE_REGISTRY.get_mut(device_id).device; let shader = device - .device - .create_shader_module(unsafe { - slice::from_raw_parts(desc.code.bytes, desc.code.length) - }).unwrap(); + .create_shader_module(unsafe { slice::from_raw_parts(desc.code.bytes, desc.code.length) }) + .unwrap(); registry::SHADER_MODULE_REGISTRY.register(ShaderModule { raw: shader }) } @@ -123,12 +149,45 @@ pub extern "C" fn wgpu_queue_submit( } device.com_allocator.submit(cmd_buf); } +pub extern "C" fn wgpu_device_create_attachment_state( + device_id: DeviceId, + desc: pipeline::AttachmentStateDescriptor, +) -> AttachmentStateId { + // TODO: Either formats should be changed to a single format, + // or its assumed that `AttachmentStateDescriptor` contains multiple attachments. + // Assume the latter for now. + let attachments = unsafe { slice::from_raw_parts(desc.formats, desc.formats_length) }.iter().map(|format| { + hal::pass::Attachment { + // TODO: either formats should be changed to format, + // or return multiple attachments here + format: Some(conv::map_texture_format(*format)), + samples: 1, // TODO map + ops: hal::pass::AttachmentOps { // TODO map + load: hal::pass::AttachmentLoadOp::Clear, + store: hal::pass::AttachmentStoreOp::Store, + }, + stencil_ops: hal::pass::AttachmentOps { // TODO map + load: hal::pass::AttachmentLoadOp::DontCare, + store: hal::pass::AttachmentStoreOp::DontCare, + }, + layouts: hal::image::Layout::Undefined..hal::image::Layout::Present, // TODO map + } + }).collect(); + registry::ATTACHMENT_STATE_REGISTRY.register(pipeline::AttachmentState { raw: attachments }) +} + +#[no_mangle] pub extern "C" fn wgpu_device_create_render_pipeline( device_id: DeviceId, desc: pipeline::RenderPipelineDescriptor, ) -> RenderPipelineId { - let device = registry::DEVICE_REGISTRY.get_mut(device_id); - // TODO: layout, primitive_topology, blend_state, depth_stencil_state, attachment_state + // TODO + let extent = hal::window::Extent2D { width: 100, height: 100 }; + + let device = ®istry::DEVICE_REGISTRY.get_mut(device_id).device; + + let layout = ®istry::PIPELINE_LAYOUT_REGISTRY.get_mut(desc.layout).raw; + let pipeline_stages = unsafe { slice::from_raw_parts(desc.stages, desc.stages_length) }; // TODO: avoid allocation @@ -172,10 +231,111 @@ pub extern "C" fn wgpu_device_create_render_pipeline( } }; - /* - let pipeline = device - .device - .create_graphics_pipeline(pipeline_desc); - */ - unimplemented!(); + // TODO + let rasterizer = hal::pso::Rasterizer { + depth_clamping: false, + polygon_mode: hal::pso::PolygonMode::Fill, + cull_face: hal::pso::Face::BACK, + front_face: hal::pso::FrontFace::Clockwise, + depth_bias: None, + conservative: false, + }; + + // TODO + let vertex_buffers: Vec = Vec::new(); + + // TODO + let attributes: Vec = Vec::new(); + + let input_assembler = hal::pso::InputAssemblerDesc { + primitive: conv::map_primitive_topology(desc.primitive_topology), + primitive_restart: hal::pso::PrimitiveRestart::Disabled, // TODO + }; + + let blender = hal::pso::BlendDesc { + logic_op: None, // TODO + targets: unsafe { slice::from_raw_parts(desc.blend_state, desc.blend_state_length) } + .iter() + .map(|id| registry::BLEND_STATE_REGISTRY.get_mut(*id).raw) + .collect() + }; + + let depth_stencil = registry::DEPTH_STENCIL_STATE_REGISTRY.get_mut(desc.depth_stencil_state).raw; + + // TODO + let multisampling: Option = None; + + // TODO + let baked_states = hal::pso::BakedStates { + viewport: Some(hal::pso::Viewport { + rect: hal::pso::Rect { + x: 0, + y: 0, + w: extent.width as i16, + h: extent.height as i16, + }, + depth: (0.0..1.0), + }), + scissor: Some(hal::pso::Rect { + x: 0, + y: 0, + w: extent.width as i16, + h: extent.height as i16, + }), + blend_color: None, + depth_bounds: None, + }; + + let attachments = ®istry::ATTACHMENT_STATE_REGISTRY.get_mut(desc.attachment_state).raw; + + // TODO + let subpass = hal::pass::SubpassDesc { + colors: &[(0, hal::image::Layout::ColorAttachmentOptimal)], + depth_stencil: None, + inputs: &[], + resolves: &[], + preserves: &[], + }; + + // TODO + let subpass_dependency = hal::pass::SubpassDependency { + passes: hal::pass::SubpassRef::External..hal::pass::SubpassRef::Pass(0), + stages: hal::pso::PipelineStage::COLOR_ATTACHMENT_OUTPUT..hal::pso::PipelineStage::COLOR_ATTACHMENT_OUTPUT, + accesses: hal::image::Access::empty()..(hal::image::Access::COLOR_ATTACHMENT_READ | hal::image::Access::COLOR_ATTACHMENT_WRITE), + }; + + let main_pass = &device.create_render_pass(&attachments[..], &[subpass], &[subpass_dependency]); + + // TODO + let subpass = hal::pass::Subpass { + index: 0, + main_pass, + }; + + // TODO + let flags = hal::pso::PipelineCreationFlags::empty(); + + // TODO + let parent = hal::pso::BasePipeline::None; + + let pipeline_desc = hal::pso::GraphicsPipelineDesc { + shaders, + rasterizer, + vertex_buffers, + attributes, + input_assembler, + blender, + depth_stencil, + multisampling, + baked_states, + layout, + subpass, + flags, + parent, + }; + + // TODO: cache + let pipeline = device.create_graphics_pipeline(&pipeline_desc, None).unwrap(); + + registry::RENDER_PIPELINE_REGISTRY.register(pipeline::RenderPipeline { raw: pipeline }) } diff --git a/wgpu-native/src/instance.rs b/wgpu-native/src/instance.rs index 5e4f79fe6..0f43da91d 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -4,6 +4,7 @@ use registry::{self, Registry}; use {AdapterId, Device, DeviceId, InstanceId}; #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum PowerPreference { Default = 0, LowPower = 1, diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index e53126a3f..d065a0e83 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -85,18 +85,23 @@ pub type SamplerId = Id; // Binding model pub type BindGroupLayoutId = Id; -pub(crate) type BindGroupLayoutHandle = BindGroupLayout; +type BindGroupLayoutHandle = BindGroupLayout; pub type PipelineLayoutId = Id; +type PipelineLayoutHandle = PipelineLayout; // Pipeline pub type BlendStateId = Id; +type BlendStateHandle = BlendState; pub type DepthStencilStateId = Id; +type DepthStencilStateHandle = DepthStencilState; pub type InputStateId = Id; pub type ShaderModuleId = Id; type ShaderModuleHandle = ShaderModule; pub type AttachmentStateId = Id; +type AttachmentStateHandle = AttachmentState; pub type ComputePipelineId = Id; pub type RenderPipelineId = Id; +type RenderPipelineHandle = RenderPipeline; pub type CommandBufferId = Id; type CommandBufferHandle = CommandBuffer; diff --git a/wgpu-native/src/pipeline.rs b/wgpu-native/src/pipeline.rs index 955a1bbb8..c57175cd6 100644 --- a/wgpu-native/src/pipeline.rs +++ b/wgpu-native/src/pipeline.rs @@ -7,6 +7,7 @@ use { }; #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum BlendFactor { Zero = 0, One = 1, @@ -24,6 +25,7 @@ pub enum BlendFactor { } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum BlendOperation { Add = 0, Subtract = 1, @@ -32,17 +34,20 @@ pub enum BlendOperation { Max = 4, } -bitflags! { - #[repr(transparent)] - pub struct ColorWriteFlags: u32 { - const NONE = 0; - const RED = 1; - const GREEN = 2; - const BLUE = 4; - const ALPHA = 8; - const ALL = 15; - } -} +// TODO: bitflags +pub type ColorWriteFlags = u32; +#[allow(non_upper_case_globals)] +pub const ColorWriteFlags_NONE: u32 = 0; +#[allow(non_upper_case_globals)] +pub const ColorWriteFlags_RED: u32 = 1; +#[allow(non_upper_case_globals)] +pub const ColorWriteFlags_GREEN: u32 = 2; +#[allow(non_upper_case_globals)] +pub const ColorWriteFlags_BLUE: u32 = 4; +#[allow(non_upper_case_globals)] +pub const ColorWriteFlags_ALPHA: u32 = 8; +#[allow(non_upper_case_globals)] +pub const ColorWriteFlags_ALL: u32 = 15; #[repr(C)] pub struct BlendDescriptor { @@ -59,11 +64,12 @@ pub struct BlendStateDescriptor { pub write_mask: ColorWriteFlags, } -pub struct BlendState { - raw: hal::pso::BlendState, +pub(crate) struct BlendState { + pub raw: hal::pso::ColorBlendDesc, } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum StencilOperation { Keep = 0, Zero = 1, @@ -93,17 +99,19 @@ pub struct DepthStencilStateDescriptor { pub stencil_write_mask: u32, } -pub struct DepthStencilState { - raw: hal::pso::DepthStencilDesc, +pub(crate) struct DepthStencilState { + pub raw: hal::pso::DepthStencilDesc, } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum IndexFormat { Uint16 = 0, Uint32 = 1, } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum VertexFormat { FloatR32G32B32A32 = 0, FloatR32G32B32 = 1, @@ -112,6 +120,7 @@ pub enum VertexFormat { } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum InputStepMode { Vertex = 0, Instance = 1, @@ -154,11 +163,12 @@ pub struct AttachmentStateDescriptor { pub formats_length: usize, } -pub struct AttachmentState { - raw: hal::pass::Attachment, +pub(crate) struct AttachmentState { + pub raw: Vec, } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum ShaderStage { Vertex = 0, Fragment = 1, @@ -183,6 +193,7 @@ pub struct ComputePipeline { } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum PrimitiveTopology { PointList = 0, LineList = 1, @@ -203,6 +214,6 @@ pub struct RenderPipelineDescriptor { pub attachment_state: AttachmentStateId, } -pub struct RenderPipeline { - // TODO +pub(crate) struct RenderPipeline { + pub raw: B::GraphicsPipeline, } diff --git a/wgpu-native/src/registry.rs b/wgpu-native/src/registry.rs index 6ed5056d7..3d2d801e1 100644 --- a/wgpu-native/src/registry.rs +++ b/wgpu-native/src/registry.rs @@ -11,7 +11,7 @@ use std::sync::Arc; #[cfg(feature = "remote")] use hal::backend::FastHashMap; -use {AdapterHandle, BindGroupLayoutHandle, CommandBufferHandle, DeviceHandle, InstanceHandle, ShaderModuleHandle}; +use {AdapterHandle, AttachmentStateHandle, BindGroupLayoutHandle, BlendStateHandle, CommandBufferHandle, DepthStencilStateHandle, DeviceHandle, InstanceHandle, PipelineLayoutHandle, RenderPipelineHandle, ShaderModuleHandle}; #[cfg(not(feature = "remote"))] pub(crate) type Id = *mut c_void; @@ -123,10 +123,22 @@ type ConcreteRegistry = RemoteRegistry; lazy_static! { pub(crate) static ref ADAPTER_REGISTRY: ConcreteRegistry = ConcreteRegistry::new(); + pub(crate) static ref ATTACHMENT_STATE_REGISTRY: ConcreteRegistry = + ConcreteRegistry::new(); pub(crate) static ref BIND_GROUP_LAYOUT_REGISTRY: ConcreteRegistry = ConcreteRegistry::new(); + pub(crate) static ref BLEND_STATE_REGISTRY: ConcreteRegistry = + ConcreteRegistry::new(); + pub(crate) static ref DEPTH_STENCIL_STATE_REGISTRY: ConcreteRegistry = + ConcreteRegistry::new(); pub(crate) static ref DEVICE_REGISTRY: ConcreteRegistry = ConcreteRegistry::new(); - pub(crate) static ref INSTANCE_REGISTRY: ConcreteRegistry = ConcreteRegistry::new(); - pub(crate) static ref SHADER_MODULE_REGISTRY: ConcreteRegistry = ConcreteRegistry::new(); pub(crate) static ref COMMAND_BUFFER_REGISTRY: ConcreteRegistry = ConcreteRegistry::new(); + pub(crate) static ref INSTANCE_REGISTRY: ConcreteRegistry = + ConcreteRegistry::new(); + pub(crate) static ref PIPELINE_LAYOUT_REGISTRY: ConcreteRegistry = + ConcreteRegistry::new(); + pub(crate) static ref RENDER_PIPELINE_REGISTRY: ConcreteRegistry = + ConcreteRegistry::new(); + pub(crate) static ref SHADER_MODULE_REGISTRY: ConcreteRegistry = + ConcreteRegistry::new(); } diff --git a/wgpu-native/src/resource.rs b/wgpu-native/src/resource.rs index 6913af100..ac4486aee 100644 --- a/wgpu-native/src/resource.rs +++ b/wgpu-native/src/resource.rs @@ -34,6 +34,7 @@ pub struct TextureView { } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum TextureDimension { D1, D2, @@ -41,6 +42,7 @@ pub enum TextureDimension { } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum TextureFormat { R8g8b8a8Unorm = 0, R8g8b8a8Uint = 1, @@ -75,6 +77,7 @@ pub struct Texture { } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum AddressMode { ClampToEdge = 0, Repeat = 1, @@ -83,12 +86,14 @@ pub enum AddressMode { } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum FilterMode { Nearest = 0, Linear = 1, } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum CompareFunction { Never = 0, Less = 1, @@ -101,6 +106,7 @@ pub enum CompareFunction { } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum BorderColor { TransparentBlack = 0, OpaqueBlack = 1,