11: Add render pipeline creation r=kvark a=grovesNL

~~WIP~~

~~Let me know if you have any ideas to address my `TODO`s as I work through it 😃~~

- Added render pipeline creation
- Updated example
- Reworked how mutex guard is managed for registries

Co-authored-by: Joshua Groves <josh@joshgroves.com>
This commit is contained in:
bors[bot] 2018-09-28 14:46:18 +00:00
commit e5d4f9e04d
16 changed files with 1045 additions and 200 deletions

26
Cargo.lock generated
View File

@ -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"

View File

@ -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

View File

@ -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;
}

View File

@ -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]);
}

View File

@ -1,12 +1,75 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#define WGPU_REMOTE 1
#ifdef WGPU_REMOTE
typedef uint32_t WGPUId;
#else
typedef void *WGPUId;
#endif
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#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);

View File

@ -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<B: hal::Backend> {
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<B: hal::Backend> {
raw: B::PipelineLayout,
pub(crate) struct PipelineLayout<B: hal::Backend> {
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 {

View File

@ -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<B: hal::Backend> {
raw: B::CommandPool,
available: Vec<CommandBuffer<B>>,
@ -39,15 +38,13 @@ impl<B: hal::Backend> CommandAllocator<B> {
pub fn allocate(&self, device: &B::Device) -> CommandBuffer<B> {
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<B: hal::Backend> CommandAllocator<B> {
}
pub fn submit(&self, cmd_buf: CommandBuffer<B>) {
self.inner
.lock()
.unwrap()
.pending
.push(cmd_buf);
self.inner.lock().unwrap().pending.push(cmd_buf);
}
pub fn recycle(&self, mut cmd_buf: CommandBuffer<B>) {
@ -86,7 +79,7 @@ impl<B: hal::Backend> CommandAllocator<B> {
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

View File

@ -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,
}

View File

@ -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,
}
}

View File

@ -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<B: hal::Backend> {
device: B::Device,
@ -30,22 +31,96 @@ impl<B: hal::Backend> Device<B> {
}
}
pub struct ShaderModule<B: hal::Backend> {
pub(crate) struct ShaderModule<B: hal::Backend> {
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::<Vec<_>>();
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::<back::Backend> {
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<hal::pso::VertexBufferDesc> = Vec::new();
// TODO
let attributes: Vec<hal::pso::AttributeDesc> = 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<hal::pso::Multisampling> = 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 })
}

View File

@ -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))
}

View File

@ -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<B>;
pub type PipelineLayoutId = Id;
type PipelineLayoutHandle = PipelineLayout<B>;
// 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<B>;
pub type AttachmentStateId = Id;
type AttachmentStateHandle = AttachmentState;
pub type ComputePipelineId = Id;
pub type RenderPipelineId = Id;
type RenderPipelineHandle = RenderPipeline<B>;
pub type CommandBufferId = Id;
type CommandBufferHandle = CommandBuffer<B>;

View File

@ -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<hal::pass::Attachment>,
}
#[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<B: hal::Backend> {
pub raw: B::GraphicsPipeline,
}

View File

@ -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<T>;
#[cfg(feature = "remote")]
type RegistryItem<'a, T> = MappedMutexGuard<'a, T>;
type ItemsGuard<'a, T> = MutexGuard<'a, RemoteItems<T>>;
pub(crate) trait Registry<T> {
fn new() -> Self;
fn register(&self, handle: T) -> Id;
fn get_mut(&self, id: Id) -> RegistryItem<T>;
fn take(&self, id: Id) -> T;
fn lock(&self) -> ItemsGuard<T>;
}
pub(crate) trait Items<T> {
fn register(&mut self, handle: T) -> Id;
fn get(&self, id: Id) -> Item<T>;
fn get_mut(&mut self, id: Id) -> ItemMut<T>;
fn take(&mut self, id: Id) -> T;
}
#[cfg(not(feature = "remote"))]
pub(crate) struct LocalItems<T> {
marker: PhantomData<T>,
}
#[cfg(not(feature = "remote"))]
impl<T> Items<T> for LocalItems<T> {
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<T> {
unsafe { (id as *mut T).as_ref() }.unwrap()
}
fn get_mut(&mut self, id: Id) -> ItemMut<T> {
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<T> Registry<T> for LocalRegistry<T> {
}
}
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<T> {
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<T> {
LocalItems {
marker: PhantomData,
}
}
}
#[cfg(feature = "remote")]
struct Registrations<T> {
pub(crate) struct RemoteItems<T> {
next_id: Id,
tracked: FastHashMap<Id, T>,
free: Vec<Id>,
}
#[cfg(feature = "remote")]
impl<T> Registrations<T> {
impl<T> RemoteItems<T> {
fn new() -> Self {
Registrations {
RemoteItems {
next_id: 0,
tracked: FastHashMap::default(),
free: Vec::new(),
@ -77,40 +102,49 @@ impl<T> Registrations<T> {
}
}
#[cfg(feature = "remote")]
impl<T> Items<T> for RemoteItems<T> {
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<T> {
self.tracked.get(&id).unwrap()
}
fn get_mut(&mut self, id: Id) -> ItemMut<T> {
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<T> {
registrations: Arc<Mutex<Registrations<T>>>,
items: Arc<Mutex<RemoteItems<T>>>,
}
#[cfg(feature = "remote")]
impl<T> Registry<T> for RemoteRegistry<T> {
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<T> {
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<T> {
self.items.lock()
}
}
@ -120,9 +154,25 @@ type ConcreteRegistry<T> = LocalRegistry<T>;
type ConcreteRegistry<T> = RemoteRegistry<T>;
lazy_static! {
pub(crate) static ref ADAPTER_REGISTRY: ConcreteRegistry<AdapterHandle> = ConcreteRegistry::new();
pub(crate) static ref ADAPTER_REGISTRY: ConcreteRegistry<AdapterHandle> =
ConcreteRegistry::new();
pub(crate) static ref ATTACHMENT_STATE_REGISTRY: ConcreteRegistry<AttachmentStateHandle> =
ConcreteRegistry::new();
pub(crate) static ref BIND_GROUP_LAYOUT_REGISTRY: ConcreteRegistry<BindGroupLayoutHandle> =
ConcreteRegistry::new();
pub(crate) static ref BLEND_STATE_REGISTRY: ConcreteRegistry<BlendStateHandle> =
ConcreteRegistry::new();
pub(crate) static ref DEPTH_STENCIL_STATE_REGISTRY: ConcreteRegistry<DepthStencilStateHandle> =
ConcreteRegistry::new();
pub(crate) static ref DEVICE_REGISTRY: ConcreteRegistry<DeviceHandle> = ConcreteRegistry::new();
pub(crate) static ref INSTANCE_REGISTRY: ConcreteRegistry<InstanceHandle> = ConcreteRegistry::new();
pub(crate) static ref SHADER_MODULE_REGISTRY: ConcreteRegistry<ShaderModuleHandle> = ConcreteRegistry::new();
pub(crate) static ref COMMAND_BUFFER_REGISTRY: ConcreteRegistry<CommandBufferHandle> = ConcreteRegistry::new();
pub(crate) static ref COMMAND_BUFFER_REGISTRY: ConcreteRegistry<CommandBufferHandle> =
ConcreteRegistry::new();
pub(crate) static ref INSTANCE_REGISTRY: ConcreteRegistry<InstanceHandle> =
ConcreteRegistry::new();
pub(crate) static ref PIPELINE_LAYOUT_REGISTRY: ConcreteRegistry<PipelineLayoutHandle> =
ConcreteRegistry::new();
pub(crate) static ref RENDER_PIPELINE_REGISTRY: ConcreteRegistry<RenderPipelineHandle> =
ConcreteRegistry::new();
pub(crate) static ref SHADER_MODULE_REGISTRY: ConcreteRegistry<ShaderModuleHandle> =
ConcreteRegistry::new();
}

View File

@ -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,

View File

@ -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(),