diff --git a/Cargo.lock b/Cargo.lock index 3e156bc1fd..0eadaa04d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,10 +76,10 @@ dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -376,7 +376,7 @@ name = "lazy_static" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -395,7 +395,7 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -504,7 +504,7 @@ name = "parking_lot" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -659,7 +659,7 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.28" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -726,7 +726,7 @@ name = "storage-map" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -815,7 +815,7 @@ dependencies = [ [[package]] name = "toml" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", @@ -851,7 +851,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "version_check" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1067,7 +1067,7 @@ dependencies = [ "checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" -"checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" +"checksum lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775751a3e69bde4df9b38dd00a1b5d6ac13791e4223d4a0506577f0dd27cfb7a" "checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" "checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" @@ -1100,7 +1100,7 @@ dependencies = [ "checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" "checksum serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "652bc323d694dc925829725ec6c890156d8e70ae5202919869cb00fe2eff3788" "checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab" -"checksum serde_json 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "d30ec34ac923489285d24688c7a9c0898d16edff27fc1f1bd854edeff6ca3b7f" +"checksum serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "bb47a3d5c84320222f66d7db21157c4a7407755de41798f9b4c1c40593397b1a" "checksum shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" "checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" "checksum smithay-client-toolkit 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1609083d6bca3991a3c648d80ae16e1764d70881c3321bee1c915149073d605" @@ -1117,13 +1117,13 @@ dependencies = [ "checksum tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "55c1195ef8513f3273d55ff59fe5da6940287a0d7a98331254397f464833675b" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" -"checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" +"checksum toml 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b7e7d59d55f36979a9dd86d71ae54657a5e9c7fdb4fa2212f4064e2d32f9dcda" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wayland-client 0.20.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e7516a23419a55bd2e6d466c75a6a52c85718e5013660603289c2b8bee794b12" "checksum wayland-commons 0.20.12 (registry+https://github.com/rust-lang/crates.io-index)" = "d8609d59b95bf198bae4f3b064d55a712f2d529eec6aac98cc1f6e9cc911d47a" diff --git a/examples/Makefile b/examples/Makefile index c78b661b4b..bdb489dc4b 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,5 +1,3 @@ -all: hello_world_c - CC=gcc CFLAGS=-I. DEPS=./../wgpu-bindings/wgpu.h @@ -9,6 +7,10 @@ LINK_ARGS=-L ./../target/debug -lwgpu_native %.o: %.c $(DEPS) $(CC) $(LINK_ARGS) -c -o $(OUTDIR)/$@ $< $(CFLAGS) -hello_world_c: hello_triangle_c/main.c +hello_triangle_c: hello_triangle_c/main.c mkdir -p $(OUTDIR) $(CC) $(LINK_ARGS) -o $(OUTDIR)/$@ $^ $(CFLAGS) + +.PHONY: all + +all: hello_triangle_c diff --git a/examples/hello_triangle_c/main.c b/examples/hello_triangle_c/main.c index 59e81e055c..d3ad4c54c4 100644 --- a/examples/hello_triangle_c/main.c +++ b/examples/hello_triangle_c/main.c @@ -30,19 +30,109 @@ 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[STAGES_LENGTH] = { vertex_stage, 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[BLEND_STATE_LENGTH] = { 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[FORMATS_LENGTH] = { 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); + /*wgpu_queue_submit(queue, &cmd_buf, 1);*/ + return 0; } diff --git a/examples/hello_triangle_rust/main.rs b/examples/hello_triangle_rust/main.rs index 125771c30c..9985304b33 100644 --- a/examples/hello_triangle_rust/main.rs +++ b/examples/hello_triangle_rust/main.rs @@ -1,25 +1,20 @@ extern crate wgpu; fn main() { let instance = wgpu::Instance::new(); - let adapter = instance.get_adapter( - wgpu::AdapterDescriptor { - power_preference: wgpu::PowerPreference::LowPower, + let adapter = instance.get_adapter(wgpu::AdapterDescriptor { + power_preference: wgpu::PowerPreference::LowPower, + }); + let device = adapter.create_device(wgpu::DeviceDescriptor { + extensions: wgpu::Extensions { + anisotropic_filtering: false, }, - ); - let device = adapter.create_device( - wgpu::DeviceDescriptor { - extensions: wgpu::Extensions { - anisotropic_filtering: false, - }, - }, - ); + }); let vs_bytes = include_bytes!("./../data/hello_triangle.vert.spv"); let _vs = device.create_shader_module(vs_bytes); let fs_bytes = include_bytes!("./../data/hello_triangle.frag.spv"); let _fs = device.create_shader_module(fs_bytes); - let cmd_buf = device.create_command_buffer(wgpu::CommandBufferDescriptor { - }); + let cmd_buf = device.create_command_buffer(wgpu::CommandBufferDescriptor {}); let queue = device.get_queue(); queue.submit(&[cmd_buf]); } diff --git a/wgpu-bindings/wgpu.h b/wgpu-bindings/wgpu.h index ff5151a13c..b0cad59a23 100644 --- a/wgpu-bindings/wgpu.h +++ b/wgpu-bindings/wgpu.h @@ -1,12 +1,75 @@ +#include +#include +#include + +#define WGPU_REMOTE 1 #ifdef WGPU_REMOTE typedef uint32_t WGPUId; #else typedef void *WGPUId; #endif -#include -#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 + +#define WGPUShaderStageFlags_NONE 0 + +#define WGPUShaderStageFlags_VERTEX 1 + +typedef enum { + WGPUBindingType_UniformBuffer = 0, + WGPUBindingType_Sampler = 1, + WGPUBindingType_SampledTexture = 2, + 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, @@ -14,6 +77,38 @@ typedef enum { WGPUPowerPreference_HighPerformance = 2, } WGPUPowerPreference; +typedef enum { + WGPUPrimitiveTopology_PointList = 0, + WGPUPrimitiveTopology_LineList = 1, + WGPUPrimitiveTopology_LineStrip = 2, + WGPUPrimitiveTopology_TriangleList = 3, + WGPUPrimitiveTopology_TriangleStrip = 4, +} WGPUPrimitiveTopology; + +typedef enum { + WGPUShaderStage_Vertex = 0, + WGPUShaderStage_Fragment = 1, + 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; @@ -34,12 +129,95 @@ typedef WGPUId WGPUCommandBufferId; typedef WGPUId WGPUInstanceId; +typedef WGPUId WGPUAttachmentStateId; + +typedef struct { + const WGPUTextureFormat *formats; + uintptr_t formats_length; +} WGPUAttachmentStateDescriptor; + +typedef WGPUId WGPUBindGroupLayoutId; + +typedef uint32_t WGPUShaderStageFlags; + +typedef struct { + uint32_t binding; + WGPUShaderStageFlags visibility; + WGPUBindingType ty; +} WGPUBindGroupLayoutBinding; + +typedef struct { + const WGPUBindGroupLayoutBinding *bindings; + 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 struct { } WGPUCommandBufferDescriptor; +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 { + const WGPUBindGroupLayoutId *bind_group_layouts; + uintptr_t bind_group_layouts_length; +} WGPUPipelineLayoutDescriptor; + +typedef WGPUId WGPURenderPipelineId; + typedef WGPUId WGPUShaderModuleId; +typedef struct { + WGPUShaderModuleId module; + WGPUShaderStage stage; + const char *entry_point; +} WGPUPipelineStageDescriptor; + +typedef struct { + WGPUPipelineLayoutId layout; + const WGPUPipelineStageDescriptor *stages; + uintptr_t stages_length; + WGPUPrimitiveTopology primitive_topology; + const WGPUBlendStateId *blend_state; + uintptr_t blend_state_length; + WGPUDepthStencilStateId depth_stencil_state; + WGPUAttachmentStateId attachment_state; +} WGPURenderPipelineDescriptor; + typedef struct { const uint8_t *bytes; uintptr_t length; @@ -63,8 +241,26 @@ WGPURenderPassId wgpu_command_buffer_begin_render_pass(WGPUCommandBufferId _comm WGPUInstanceId wgpu_create_instance(void); +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); + WGPUCommandBufferId wgpu_device_create_command_buffer(WGPUDeviceId device_id, - WGPUCommandBufferDescriptor desc); + WGPUCommandBufferDescriptor _desc); + +WGPUDepthStencilStateId wgpu_device_create_depth_stencil_state(WGPUDeviceId device_id, + WGPUDepthStencilStateDescriptor desc); + +WGPUPipelineLayoutId wgpu_device_create_pipeline_layout(WGPUDeviceId device_id, + WGPUPipelineLayoutDescriptor desc); + +WGPURenderPipelineId wgpu_device_create_render_pipeline(WGPUDeviceId device_id, + WGPURenderPipelineDescriptor desc); WGPUShaderModuleId wgpu_device_create_shader_module(WGPUDeviceId device_id, WGPUShaderModuleDescriptor desc); diff --git a/wgpu-native/src/binding_model.rs b/wgpu-native/src/binding_model.rs index ca8df90529..a25c0b41d0 100644 --- a/wgpu-native/src/binding_model.rs +++ b/wgpu-native/src/binding_model.rs @@ -2,17 +2,19 @@ use hal; use {BindGroupLayoutId, BufferId, SamplerId, TextureViewId}; -bitflags! { - #[repr(transparent)] - pub struct ShaderStageFlags: u32 { - const NONE = 0; - const VERTEX = 1; - const FRAGMENT = 2; - const COMPUTE = 4; - } -} +// TODO: bitflags +pub type ShaderStageFlags = u32; +#[allow(non_upper_case_globals)] +pub const ShaderStageFlags_NONE: u32 = 0; +#[allow(non_upper_case_globals)] +pub const ShaderStageFlags_VERTEX: u32 = 1; +#[allow(non_upper_case_globals)] +pub const ShaderStageFlags_FRAGMENT: u32 = 2; +#[allow(non_upper_case_globals)] +pub const ShaderStageFlags_COMPUTE: u32 = 4; #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum BindingType { UniformBuffer = 0, Sampler = 1, @@ -28,21 +30,23 @@ pub struct BindGroupLayoutBinding { } #[repr(C)] -pub struct BindGroupLayoutDescriptor<'a> { - pub bindings: &'a [BindGroupLayoutBinding], +pub struct BindGroupLayoutDescriptor { + pub bindings: *const BindGroupLayoutBinding, + pub bindings_length: usize, } -pub struct BindGroupLayout { - // TODO +pub(crate) struct BindGroupLayout { + pub raw: B::DescriptorSetLayout, } #[repr(C)] -pub struct PipelineLayoutDescriptor<'a> { - pub bind_group_layouts: &'a [BindGroupLayoutId], +pub struct PipelineLayoutDescriptor { + pub bind_group_layouts: *const BindGroupLayoutId, + pub bind_group_layouts_length: usize, } -pub struct PipelineLayout { - raw: B::PipelineLayout, +pub(crate) struct PipelineLayout { + pub raw: B::PipelineLayout, } #[repr(C)] @@ -66,9 +70,10 @@ pub struct Binding { } #[repr(C)] -pub struct BindGroupDescriptor<'a> { - pub layout: BindGroupLayout, - pub bindings: &'a [Binding], +pub struct BindGroupDescriptor { + pub layout: BindGroupLayoutId, + pub bindings: *const Binding, + pub bindings_length: usize, } pub struct BindGroup { diff --git a/wgpu-native/src/command/allocator.rs b/wgpu-native/src/command/allocator.rs index ec5adbe348..cf7b05adf6 100644 --- a/wgpu-native/src/command/allocator.rs +++ b/wgpu-native/src/command/allocator.rs @@ -1,15 +1,14 @@ use super::CommandBuffer; -use hal::{self, Device}; use hal::command::RawCommandBuffer; use hal::pool::RawCommandPool; +use hal::{self, Device}; use std::collections::HashMap; //TODO: use `parking_lot::Mutex`? use std::sync::Mutex; use std::thread; - struct CommandPool { raw: B::CommandPool, available: Vec>, @@ -39,15 +38,13 @@ impl CommandAllocator { pub fn allocate(&self, device: &B::Device) -> CommandBuffer { let thread_id = thread::current().id(); let mut inner = self.inner.lock().unwrap(); - let pool = inner.pools - .entry(thread_id) - .or_insert_with(|| CommandPool { - raw: device.create_command_pool( - self.queue_family, - hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL, - ), - available: Vec::new(), - }); + let pool = inner.pools.entry(thread_id).or_insert_with(|| CommandPool { + raw: device.create_command_pool( + self.queue_family, + hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL, + ), + available: Vec::new(), + }); if let Some(cmd_buf) = pool.available.pop() { device.reset_fence(&cmd_buf.fence); @@ -65,11 +62,7 @@ impl CommandAllocator { } pub fn submit(&self, cmd_buf: CommandBuffer) { - self.inner - .lock() - .unwrap() - .pending - .push(cmd_buf); + self.inner.lock().unwrap().pending.push(cmd_buf); } pub fn recycle(&self, mut cmd_buf: CommandBuffer) { @@ -86,7 +79,7 @@ impl CommandAllocator { pub fn maintain(&self, device: &B::Device) { let mut inner = self.inner.lock().unwrap(); - for i in (0 .. inner.pending.len()).rev() { + for i in (0..inner.pending.len()).rev() { if device.get_fence_status(&inner.pending[i].fence) { let cmd_buf = inner.pending.swap_remove(i); inner diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 73abf9a837..b0501094b6 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -15,14 +15,15 @@ use { 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 238d6a8f06..8c2cae0ce8 100644 --- a/wgpu-native/src/conv.rs +++ b/wgpu-native/src/conv.rs @@ -1,6 +1,6 @@ use hal; -use resource; +use {binding_model, pipeline, resource}; pub(crate) fn map_buffer_usage( usage: resource::BufferUsageFlags, @@ -39,3 +39,201 @@ pub(crate) fn map_buffer_usage( (hal_usage, hal_memory) } + +pub(crate) fn map_binding_type( + binding_ty: &binding_model::BindingType, +) -> hal::pso::DescriptorType { + use binding_model::BindingType::*; + use hal::pso::DescriptorType as H; + match binding_ty { + UniformBuffer => H::UniformBuffer, + Sampler => H::Sampler, + SampledTexture => H::SampledImage, + StorageBuffer => H::StorageBuffer, + } +} + +pub(crate) fn map_shader_stage_flags( + shader_stage_flags: binding_model::ShaderStageFlags, +) -> hal::pso::ShaderStageFlags { + use binding_model::{ + ShaderStageFlags_COMPUTE, ShaderStageFlags_FRAGMENT, ShaderStageFlags_VERTEX, + }; + use hal::pso::ShaderStageFlags as H; + let mut value = H::empty(); + if 0 != shader_stage_flags & ShaderStageFlags_VERTEX { + value |= H::VERTEX; + } + if 0 != shader_stage_flags & ShaderStageFlags_FRAGMENT { + value |= H::FRAGMENT; + } + if 0 != shader_stage_flags & ShaderStageFlags_COMPUTE { + value |= H::COMPUTE; + } + value +} + +pub(crate) fn map_primitive_topology( + primitive_topology: pipeline::PrimitiveTopology, +) -> hal::Primitive { + use hal::Primitive as H; + use pipeline::PrimitiveTopology::*; + 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 hal::pso::ColorMask as H; + use pipeline::{ + ColorWriteFlags_ALPHA, ColorWriteFlags_BLUE, ColorWriteFlags_GREEN, ColorWriteFlags_RED, + }; + 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 hal::pso::BlendOp as H; + use pipeline::BlendOperation::*; + 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 hal::pso::Factor as H; + use pipeline::BlendFactor::*; + 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 hal::pso::Comparison as H; + use resource::CompareFunction::*; + 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 hal::pso::StencilOp as H; + use pipeline::StencilOperation::*; + 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 hal::format::Format as H; + use resource::TextureFormat::*; + 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 3e881a793e..5b60aac87e 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -1,12 +1,13 @@ -use hal::{self, Device as _Device}; use hal::queue::RawCommandQueue; -use {command, conv, memory, pipeline, resource}; - -use registry::{self, Registry}; -use {BufferId, CommandBufferId, DeviceId, QueueId, ShaderModuleId}; - -use std::{iter, slice}; +use hal::{self, Device as _Device}; +use {back, binding_model, command, conv, memory, pipeline}; +use registry::{self, Items, Registry}; +use std::{ffi, iter, slice}; +use { + AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId, + DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, +}; pub struct Device { device: B::Device, @@ -30,22 +31,96 @@ impl Device { } } -pub struct ShaderModule { +pub(crate) struct ShaderModule { pub raw: B::ShaderModule, } +#[no_mangle] +pub extern "C" fn wgpu_device_create_bind_group_layout( + device_id: DeviceId, + desc: binding_model::BindGroupLayoutDescriptor, +) -> BindGroupLayoutId { + let bindings = unsafe { slice::from_raw_parts(desc.bindings, desc.bindings_length) }; + let device_guard = registry::DEVICE_REGISTRY.lock(); + let device = device_guard.get(device_id); + let descriptor_set_layout = device.device.create_descriptor_set_layout( + bindings.iter().map(|binding| { + hal::pso::DescriptorSetLayoutBinding { + binding: binding.binding, + ty: conv::map_binding_type(&binding.ty), + count: bindings.len(), + stage_flags: conv::map_shader_stage_flags(binding.visibility), + immutable_samplers: false, // TODO + } + }), + &[], + ); + registry::BIND_GROUP_LAYOUT_REGISTRY + .lock() + .register(binding_model::BindGroupLayout { + raw: descriptor_set_layout, + }) +} + +#[no_mangle] +pub extern "C" fn wgpu_device_create_pipeline_layout( + device_id: DeviceId, + desc: binding_model::PipelineLayoutDescriptor, +) -> PipelineLayoutId { + let bind_group_layout_guard = registry::BIND_GROUP_LAYOUT_REGISTRY.lock(); + let descriptor_set_layouts = + unsafe { slice::from_raw_parts(desc.bind_group_layouts, desc.bind_group_layouts_length) } + .iter() + .map(|id| bind_group_layout_guard.get(id.clone())) + .collect::>(); + let device_guard = registry::DEVICE_REGISTRY.lock(); + let device = &device_guard.get(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 + .lock() + .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 + .lock() + .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 + .lock() + .register(pipeline::DepthStencilState { + raw: conv::map_depth_stencil_state(desc), + }) +} + #[no_mangle] 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_guard = registry::DEVICE_REGISTRY.lock(); + let device = &device_guard.get(device_id).device; let shader = device - .device - .create_shader_module(unsafe { - slice::from_raw_parts(desc.code.bytes, desc.code.length) - }).unwrap(); - registry::SHADER_MODULE_REGISTRY.register(ShaderModule { raw: shader }) + .create_shader_module(unsafe { slice::from_raw_parts(desc.code.bytes, desc.code.length) }) + .unwrap(); + registry::SHADER_MODULE_REGISTRY + .lock() + .register(ShaderModule { raw: shader }) } #[no_mangle] @@ -53,16 +128,15 @@ pub extern "C" fn wgpu_device_create_command_buffer( device_id: DeviceId, _desc: command::CommandBufferDescriptor, ) -> CommandBufferId { - let device = registry::DEVICE_REGISTRY.get_mut(device_id); + let mut device_guard = registry::DEVICE_REGISTRY.lock(); + let device = device_guard.get_mut(device_id); let cmd_buf = device.com_allocator.allocate(&device.device); - registry::COMMAND_BUFFER_REGISTRY.register(cmd_buf) + registry::COMMAND_BUFFER_REGISTRY.lock().register(cmd_buf) } #[no_mangle] -pub extern "C" fn wgpu_device_get_queue( - device_id: DeviceId, -) -> QueueId { - device_id +pub extern "C" fn wgpu_device_get_queue(device_id: DeviceId) -> QueueId { + device_id } #[no_mangle] @@ -71,13 +145,14 @@ pub extern "C" fn wgpu_queue_submit( command_buffer_ptr: *const CommandBufferId, command_buffer_count: usize, ) { - let mut device = registry::DEVICE_REGISTRY.get_mut(queue_id); - let command_buffer_ids = unsafe { - slice::from_raw_parts(command_buffer_ptr, command_buffer_count) - }; + let mut device_guard = registry::DEVICE_REGISTRY.lock(); + let device = device_guard.get_mut(queue_id); + let command_buffer_ids = + unsafe { slice::from_raw_parts(command_buffer_ptr, command_buffer_count) }; //TODO: submit at once, requires `get_all()` + let mut command_buffer_guard = registry::COMMAND_BUFFER_REGISTRY.lock(); for &cmb_id in command_buffer_ids { - let cmd_buf = registry::COMMAND_BUFFER_REGISTRY.take(cmb_id); + let cmd_buf = command_buffer_guard.take(cmb_id); { let submission = hal::queue::RawSubmission { cmd_buffers: iter::once(&cmd_buf.raw), @@ -93,3 +168,211 @@ pub extern "C" fn wgpu_queue_submit( device.com_allocator.submit(cmd_buf); } } + +#[no_mangle] +pub extern "C" fn wgpu_device_create_attachment_state( + device_id: DeviceId, + desc: pipeline::AttachmentStateDescriptor, +) -> AttachmentStateId { + // TODO: Assume that `AttachmentStateDescriptor` contains multiple attachments. + let attachments = unsafe { slice::from_raw_parts(desc.formats, desc.formats_length) } + .iter() + .map(|format| { + hal::pass::Attachment { + 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 + .lock() + .register(pipeline::AttachmentState { raw: attachments }) +} + +#[no_mangle] +pub extern "C" fn wgpu_device_create_render_pipeline( + device_id: DeviceId, + desc: pipeline::RenderPipelineDescriptor, +) -> RenderPipelineId { + // TODO + let extent = hal::window::Extent2D { + width: 100, + height: 100, + }; + + let device_guard = registry::DEVICE_REGISTRY.lock(); + let device = &device_guard.get(device_id).device; + let pipeline_layout_guard = registry::PIPELINE_LAYOUT_REGISTRY.lock(); + let layout = &pipeline_layout_guard.get(desc.layout).raw; + let pipeline_stages = unsafe { slice::from_raw_parts(desc.stages, desc.stages_length) }; + let shader_module_guard = registry::SHADER_MODULE_REGISTRY.lock(); + let shaders = { + let mut vertex = None; + let mut fragment = None; + for pipeline_stage in pipeline_stages.iter() { + let entry_name = unsafe { ffi::CStr::from_ptr(pipeline_stage.entry_point) } + .to_str() + .to_owned() + .unwrap(); + let entry = hal::pso::EntryPoint:: { + entry: unsafe { ffi::CStr::from_ptr(pipeline_stage.entry_point) } + .to_str() + .to_owned() + .unwrap(), // TODO + module: &shader_module_guard.get(pipeline_stage.module).raw, + specialization: hal::pso::Specialization { + // TODO + constants: &[], + data: &[], + }, + }; + match pipeline_stage.stage { + pipeline::ShaderStage::Vertex => { + vertex = Some(entry); + } + pipeline::ShaderStage::Fragment => { + fragment = Some(entry); + } + pipeline::ShaderStage::Compute => unimplemented!(), // TODO + } + } + + hal::pso::GraphicsShaderSet { + vertex: vertex.unwrap(), // TODO + hull: None, + domain: None, + geometry: None, + fragment, + } + }; + + // 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 blend_state_guard = registry::BLEND_STATE_REGISTRY.lock(); + let blend_state = unsafe { slice::from_raw_parts(desc.blend_state, desc.blend_state_length) } + .iter() + .map(|id| blend_state_guard.get(id.clone()).raw) + .collect(); + + let blender = hal::pso::BlendDesc { + logic_op: None, // TODO + targets: blend_state, + }; + + let depth_stencil_state_guard = registry::DEPTH_STENCIL_STATE_REGISTRY.lock(); + let depth_stencil = depth_stencil_state_guard.get(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 attachment_state_guard = registry::ATTACHMENT_STATE_REGISTRY.lock(); + let attachments = &attachment_state_guard.get(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 + .lock() + .register(pipeline::RenderPipeline { raw: pipeline }) +} diff --git a/wgpu-native/src/instance.rs b/wgpu-native/src/instance.rs index 5e4f79fe62..e534e47850 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -1,9 +1,10 @@ use hal::{self, Instance as _Instance, PhysicalDevice as _PhysicalDevice}; -use registry::{self, Registry}; +use registry::{self, Items, Registry}; use {AdapterId, Device, DeviceId, InstanceId}; #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum PowerPreference { Default = 0, LowPower = 1, @@ -34,7 +35,7 @@ pub extern "C" fn wgpu_create_instance() -> InstanceId { ))] { let inst = ::back::Instance::create("wgpu", 1); - registry::INSTANCE_REGISTRY.register(inst) + registry::INSTANCE_REGISTRY.lock().register(inst) } #[cfg(not(any( feature = "gfx-backend-vulkan", @@ -51,7 +52,8 @@ pub extern "C" fn wgpu_instance_get_adapter( instance_id: InstanceId, desc: AdapterDescriptor, ) -> AdapterId { - let instance = registry::INSTANCE_REGISTRY.get_mut(instance_id); + let instance_guard = registry::INSTANCE_REGISTRY.lock(); + let instance = instance_guard.get(instance_id); let (mut low, mut high, mut other) = (None, None, None); for adapter in instance.enumerate_adapters() { match adapter.info.device_type { @@ -65,7 +67,9 @@ pub extern "C" fn wgpu_instance_get_adapter( PowerPreference::LowPower => low.or(high), PowerPreference::HighPerformance | PowerPreference::Default => high.or(low), }; - registry::ADAPTER_REGISTRY.register(some.or(other).unwrap()) + registry::ADAPTER_REGISTRY + .lock() + .register(some.or(other).unwrap()) } #[no_mangle] @@ -73,8 +77,11 @@ pub extern "C" fn wgpu_adapter_create_device( adapter_id: AdapterId, _desc: DeviceDescriptor, ) -> DeviceId { - let mut adapter = registry::ADAPTER_REGISTRY.get_mut(adapter_id); + let mut adapter_guard = registry::ADAPTER_REGISTRY.lock(); + let adapter = adapter_guard.get_mut(adapter_id); let (device, queue_group) = adapter.open_with::<_, hal::General>(1, |_qf| true).unwrap(); let mem_props = adapter.physical_device.memory_properties(); - registry::DEVICE_REGISTRY.register(Device::new(device, queue_group, mem_props)) + registry::DEVICE_REGISTRY + .lock() + .register(Device::new(device, queue_group, mem_props)) } diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index bbae752c25..7046536423 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -40,7 +40,6 @@ pub use self::resource::*; use back::Backend as B; use registry::Id; - #[repr(C)] pub struct Color { pub r: f32, @@ -85,17 +84,23 @@ pub type SamplerId = Id; // Binding model pub type BindGroupLayoutId = Id; +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 0d94aa2ace..c57175cd6b 100644 --- a/wgpu-native/src/pipeline.rs +++ b/wgpu-native/src/pipeline.rs @@ -1,9 +1,13 @@ use hal; use resource; -use {BlendStateId, ByteArray, DepthStencilStateId, PipelineLayoutId}; +use { + AttachmentStateId, BlendStateId, ByteArray, DepthStencilStateId, PipelineLayoutId, + ShaderModuleId, +}; #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum BlendFactor { Zero = 0, One = 1, @@ -21,6 +25,7 @@ pub enum BlendFactor { } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum BlendOperation { Add = 0, Subtract = 1, @@ -29,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 { @@ -56,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, @@ -90,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, @@ -109,6 +120,7 @@ pub enum VertexFormat { } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum InputStepMode { Vertex = 0, Instance = 1, @@ -146,15 +158,17 @@ pub struct ShaderModuleDescriptor { } #[repr(C)] -pub struct AttachmentStateDescriptor<'a> { - pub formats: &'a [resource::TextureFormat], +pub struct AttachmentStateDescriptor { + pub formats: *const resource::TextureFormat, + 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, @@ -163,15 +177,15 @@ pub enum ShaderStage { #[repr(C)] pub struct PipelineStageDescriptor { - pub module: ShaderModuleDescriptor, + pub module: ShaderModuleId, pub stage: ShaderStage, pub entry_point: *const ::std::os::raw::c_char, } #[repr(C)] -pub struct ComputePipelineDescriptor<'a> { +pub struct ComputePipelineDescriptor { pub layout: PipelineLayoutId, - pub stages: &'a [PipelineStageDescriptor], + pub stages: *const PipelineStageDescriptor, } pub struct ComputePipeline { @@ -179,6 +193,7 @@ pub struct ComputePipeline { } #[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum PrimitiveTopology { PointList = 0, LineList = 1, @@ -188,15 +203,17 @@ pub enum PrimitiveTopology { } #[repr(C)] -pub struct RenderPipelineDescriptor<'a> { +pub struct RenderPipelineDescriptor { pub layout: PipelineLayoutId, - pub stages: &'a [PipelineStageDescriptor], + pub stages: *const PipelineStageDescriptor, + pub stages_length: usize, pub primitive_topology: PrimitiveTopology, - pub blend_state: &'a [BlendStateId], + pub blend_state: *const BlendStateId, + pub blend_state_length: usize, pub depth_stencil_state: DepthStencilStateId, - pub attachment_state: AttachmentState, + 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 a57bb6f08d..eb56750dff 100644 --- a/wgpu-native/src/registry.rs +++ b/wgpu-native/src/registry.rs @@ -1,34 +1,67 @@ +#[cfg(feature = "remote")] +use hal::backend::FastHashMap; +#[cfg(feature = "remote")] +use parking_lot::{Mutex, MutexGuard}; #[cfg(not(feature = "remote"))] use std::marker::PhantomData; #[cfg(not(feature = "remote"))] use std::os::raw::c_void; - #[cfg(feature = "remote")] use std::sync::Arc; -#[cfg(feature = "remote")] -use parking_lot::{Mutex, MutexGuard, MappedMutexGuard}; - -#[cfg(feature = "remote")] -use hal::backend::FastHashMap; - -use {AdapterHandle, 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; #[cfg(feature = "remote")] pub(crate) type Id = u32; +type Item<'a, T> = &'a T; +type ItemMut<'a, T> = &'a mut T; + #[cfg(not(feature = "remote"))] -type RegistryItem<'a, T> = &'a mut T; +type ItemsGuard<'a, T> = LocalItems; #[cfg(feature = "remote")] -type RegistryItem<'a, T> = MappedMutexGuard<'a, T>; +type ItemsGuard<'a, T> = MutexGuard<'a, RemoteItems>; pub(crate) trait Registry { fn new() -> Self; - fn register(&self, handle: T) -> Id; - fn get_mut(&self, id: Id) -> RegistryItem; - fn take(&self, id: Id) -> T; + fn lock(&self) -> ItemsGuard; +} + +pub(crate) trait Items { + fn register(&mut self, handle: T) -> Id; + fn get(&self, id: Id) -> Item; + fn get_mut(&mut self, id: Id) -> ItemMut; + fn take(&mut self, id: Id) -> T; +} + +#[cfg(not(feature = "remote"))] +pub(crate) struct LocalItems { + marker: PhantomData, +} + +#[cfg(not(feature = "remote"))] +impl Items for LocalItems { + fn register(&mut self, handle: T) -> Id { + Box::into_raw(Box::new(handle)) as *mut _ as *mut c_void + } + + fn get(&self, id: Id) -> Item { + unsafe { (id as *mut T).as_ref() }.unwrap() + } + + fn get_mut(&mut self, id: Id) -> ItemMut { + unsafe { (id as *mut T).as_mut() }.unwrap() + } + + fn take(&mut self, id: Id) -> T { + unsafe { *Box::from_raw(id as *mut T) } + } } #[cfg(not(feature = "remote"))] @@ -44,32 +77,24 @@ impl Registry for LocalRegistry { } } - fn register(&self, handle: T) -> Id { - Box::into_raw(Box::new(handle)) as *mut _ as *mut c_void - } - - fn get_mut(&self, id: Id) -> RegistryItem { - unsafe { (id as *mut T).as_mut() }.unwrap() - } - - fn take(&self, id: Id) -> T { - unsafe { - *Box::from_raw(id as *mut T) + fn lock(&self) -> ItemsGuard { + LocalItems { + marker: PhantomData, } } } #[cfg(feature = "remote")] -struct Registrations { +pub(crate) struct RemoteItems { next_id: Id, tracked: FastHashMap, free: Vec, } #[cfg(feature = "remote")] -impl Registrations { +impl RemoteItems { fn new() -> Self { - Registrations { + RemoteItems { next_id: 0, tracked: FastHashMap::default(), free: Vec::new(), @@ -77,40 +102,49 @@ impl Registrations { } } +#[cfg(feature = "remote")] +impl Items for RemoteItems { + fn register(&mut self, handle: T) -> Id { + let id = match self.free.pop() { + Some(id) => id, + None => { + self.next_id += 1; + self.next_id - 1 + } + }; + self.tracked.insert(id, handle); + id + } + + fn get(&self, id: Id) -> Item { + self.tracked.get(&id).unwrap() + } + + fn get_mut(&mut self, id: Id) -> ItemMut { + self.tracked.get_mut(&id).unwrap() + } + + fn take(&mut self, id: Id) -> T { + self.free.push(id); + self.tracked.remove(&id).unwrap() + } +} + #[cfg(feature = "remote")] pub(crate) struct RemoteRegistry { - registrations: Arc>>, + items: Arc>>, } #[cfg(feature = "remote")] impl Registry for RemoteRegistry { fn new() -> Self { RemoteRegistry { - registrations: Arc::new(Mutex::new(Registrations::new())), + items: Arc::new(Mutex::new(RemoteItems::new())), } } - fn register(&self, handle: T) -> Id { - let mut registrations = self.registrations.lock(); - let id = match registrations.free.pop() { - Some(id) => id, - None => { - registrations.next_id += 1; - registrations.next_id - 1 - } - }; - registrations.tracked.insert(id, handle); - id - } - - fn get_mut(&self, id: Id) -> RegistryItem { - MutexGuard::map(self.registrations.lock(), |r| r.tracked.get_mut(&id).unwrap()) - } - - fn take(&self, id: Id) -> T { - let mut registrations = self.registrations.lock(); - registrations.free.push(id); - registrations.tracked.remove(&id).unwrap() + fn lock(&self) -> ItemsGuard { + self.items.lock() } } @@ -120,9 +154,25 @@ type ConcreteRegistry = LocalRegistry; type ConcreteRegistry = RemoteRegistry; lazy_static! { - pub(crate) static ref ADAPTER_REGISTRY: ConcreteRegistry = ConcreteRegistry::new(); + 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 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 6913af1009..ac4486aee9 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, diff --git a/wgpu-rs/src/lib.rs b/wgpu-rs/src/lib.rs index b9b448092f..0497e52aaa 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -1,12 +1,10 @@ extern crate wgpu_native as wgn; pub use wgn::{ - Color, Origin3d, Extent3d, - AdapterDescriptor, Extensions, DeviceDescriptor, PowerPreference, - ShaderModuleDescriptor, CommandBufferDescriptor, + AdapterDescriptor, Color, CommandBufferDescriptor, DeviceDescriptor, Extensions, Extent3d, + Origin3d, PowerPreference, ShaderModuleDescriptor, }; - pub struct Instance { id: wgn::InstanceId, } @@ -31,7 +29,6 @@ pub struct Queue { id: wgn::QueueId, } - impl Instance { pub fn new() -> Self { Instance { @@ -56,7 +53,7 @@ impl Adapter { impl Device { pub fn create_shader_module(&self, spv: &[u8]) -> ShaderModule { - let desc = wgn::ShaderModuleDescriptor{ + let desc = wgn::ShaderModuleDescriptor { code: wgn::ByteArray { bytes: spv.as_ptr(), length: spv.len(),