diff --git a/.travis.yml b/.travis.yml index f6bd0c41d..2e6d9b797 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,4 +16,3 @@ script: - cargo test - cargo build --manifest-path wgpu-native/Cargo.toml --features remote - cargo build - - (cd examples && make) #TODO diff --git a/Makefile b/Makefile index fb30ee84c..16ca7442c 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,7 @@ lib-rust: Cargo.lock wgpu-rs/Cargo.toml $(wildcard wgpu-rs/**/*.rs) cargo build --manifest-path wgpu-rs/Cargo.toml --features $(FEATURE_RUST) wgpu-bindings/wgpu.h: Cargo.lock wgpu-bindings/src/*.rs lib-native - cargo run --manifest-path wgpu-bindings/Cargo.toml + cargo +nightly-2018-12-27 run --manifest-path wgpu-bindings/Cargo.toml examples-native: lib-native wgpu-bindings/wgpu.h $(wildcard wgpu-native/**/*.c) $(MAKE) -C examples diff --git a/examples/Makefile b/examples/Makefile deleted file mode 100644 index 154076175..000000000 --- a/examples/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -CC=gcc -CFLAGS=-I. -DEPS=./wgpu-bindings/wgpu.h -OUTDIR=./build -LINK_ARGS=-L ../target/debug -lwgpu_native - -%.o: %.c $(DEPS) - $(CC) $(LINK_ARGS) -c -o $(OUTDIR)/$@ $< $(CFLAGS) - -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/CMakeLists.txt b/examples/hello_triangle_c/CMakeLists.txt new file mode 100644 index 000000000..204b0c468 --- /dev/null +++ b/examples/hello_triangle_c/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.11b) + +project(hello_triangle) + +set(TARGET_NAME hello_triangle) + +add_executable(hello_triangle main.c) + +if(MSVC) + target_compile_options(${TARGET_NAME} PRIVATE /W4) + add_compile_definitions(WGPU_TARGET=WGPU_TARGET_WINDOWS) + set(GLFW_LIBRARY glfw3) +else(MSVC) + target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic) + add_compile_definitions(WGPU_TARGET=WGPU_TARGET_LINUX) + set(GLFW_LIBRARY glfw) +endif(MSVC) + +if(APPLE) + add_compile_definitions(WGPU_TARGET=WGPU_TARGET_MACOS) + set(OS_LIBRARIES "-framework Cocoa" "-framework CoreVideo" "-framework IOKit" "-framework QuartzCore") + target_compile_options(${TARGET_NAME} PRIVATE -x objective-c) +endif(APPLE) + +find_package(glfw3) + +find_library(WGPU_LIBRARY wgpu_native + HINTS "${CMAKE_CURRENT_SOURCE_DIR}/../../target/debug" +) + +target_link_libraries(${TARGET_NAME} ${GLFW_LIBRARY} ${WGPU_LIBRARY} ${OS_LIBRARIES}) diff --git a/examples/hello_triangle_c/main.c b/examples/hello_triangle_c/main.c index f63a44774..4a130ff41 100644 --- a/examples/hello_triangle_c/main.c +++ b/examples/hello_triangle_c/main.c @@ -1,9 +1,31 @@ #include #include "./../../wgpu-bindings/wgpu.h" -#define STAGES_LENGTH (2) -#define BLEND_STATES_LENGTH (1) -#define ATTACHMENTS_LENGTH (1) +#define WGPU_TARGET_MACOS 1 +#define WGPU_TARGET_LINUX 2 +#define WGPU_TARGET_WINDOWS 3 + +#if WGPU_TARGET == WGPU_TARGET_MACOS +#include +#include +#endif + +#include +#if WGPU_TARGET == WGPU_TARGET_MACOS +#define GLFW_EXPOSE_NATIVE_COCOA +#elif WGPU_TARGET == WGPU_TARGET_LINUX +#define GLFW_EXPOSE_NATIVE_X11 +#define GLFW_EXPOSE_NATIVE_WAYLAND +#elif WGPU_TARGET == WGPU_TARGET_WINDOWS +#define GLFW_EXPOSE_NATIVE_WIN32 +#endif +#include + +#define STAGES_LENGTH (2) +#define BLEND_STATES_LENGTH (1) +#define ATTACHMENTS_LENGTH (1) +#define RENDER_PASS_ATTACHMENTS_LENGTH (1) +#define BIND_GROUP_LAYOUTS_LENGTH (1) WGPUByteArray read_file(const char *name) { @@ -35,20 +57,8 @@ int main() }; WGPUDeviceId device = wgpu_adapter_create_device(adapter, &device_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"), + .code = read_file("./../../data/hello_triangle.vert.spv"), }; WGPUShaderModuleId vertex_shader = wgpu_device_create_shader_module(device, &vertex_shader_desc); WGPUPipelineStageDescriptor vertex_stage = { @@ -58,7 +68,7 @@ int main() }; WGPUShaderModuleDescriptor fragment_shader_desc = { - .code = read_file("./../data/hello_triangle.frag.spv"), + .code = read_file("./../../data/hello_triangle.frag.spv"), }; WGPUShaderModuleId fragment_shader = wgpu_device_create_shader_module(device, &fragment_shader_desc); WGPUPipelineStageDescriptor fragment_stage = { @@ -67,15 +77,29 @@ int main() .entry_point = "main", }; - WGPUPipelineStageDescriptor stages[STAGES_LENGTH] = { vertex_stage, fragment_stage }; + WGPUPipelineStageDescriptor stages[STAGES_LENGTH] = {vertex_stage, fragment_stage}; + + 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); + + WGPUBindGroupLayoutId bind_group_layouts[BIND_GROUP_LAYOUTS_LENGTH] = { bind_group_layout }; + + WGPUPipelineLayoutDescriptor pipeline_layout_desc = { + .bind_group_layouts = bind_group_layouts, + .bind_group_layouts_length = BIND_GROUP_LAYOUTS_LENGTH, + }; + WGPUPipelineLayoutId pipeline_layout = wgpu_device_create_pipeline_layout(device, &pipeline_layout_desc); WGPUBlendDescriptor blend_alpha = { - .src_factor = WGPUBlendFactor_Zero, + .src_factor = WGPUBlendFactor_One, .dst_factor = WGPUBlendFactor_Zero, .operation = WGPUBlendOperation_Add, }; WGPUBlendDescriptor blend_color = { - .src_factor = WGPUBlendFactor_Zero, + .src_factor = WGPUBlendFactor_One, .dst_factor = WGPUBlendFactor_Zero, .operation = WGPUBlendOperation_Add, }; @@ -83,10 +107,10 @@ int main() .blend_enabled = false, .alpha = blend_alpha, .color = blend_color, - .write_mask = 0, + .write_mask = WGPUColorWriteFlags_ALL, }; WGPUBlendStateId blend_state_0 = wgpu_device_create_blend_state(device, &blend_state_0_desc); - WGPUBlendStateId blend_state[BLEND_STATES_LENGTH] = { blend_state_0 }; + WGPUBlendStateId blend_state[BLEND_STATES_LENGTH] = {blend_state_0}; WGPUStencilStateFaceDescriptor stencil_state_front = { .compare = WGPUCompareFunction_Never, @@ -112,7 +136,7 @@ int main() WGPUAttachment attachments[ATTACHMENTS_LENGTH] = { { - .format = WGPUTextureFormat_R8g8b8a8Unorm, + .format = WGPUTextureFormat_B8g8r8a8Unorm, .samples = 1, }, }; @@ -123,7 +147,7 @@ int main() }; WGPURenderPipelineDescriptor render_pipeline_desc = { - .layout = layout, + .layout = pipeline_layout, .stages = stages, .stages_length = STAGES_LENGTH, .primitive_topology = WGPUPrimitiveTopology_TriangleList, @@ -135,32 +159,86 @@ int main() 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); + if (!glfwInit()) + { + printf("Cannot initialize glfw"); + return 1; + } - const uint32_t TEXTURE_WIDTH = 800; - const uint32_t TEXTURE_HEIGHT = 600; + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + GLFWwindow *window = glfwCreateWindow(640, 480, "wgpu with glfw", NULL, NULL); - WGPUExtent3d texture_size = { - .width = TEXTURE_WIDTH, - .height = TEXTURE_HEIGHT, - .depth = 1, + if (!window) + { + printf("Cannot create window"); + return 1; + } + + WGPUSurfaceId surface = NULL; + +#if WGPU_TARGET == WGPU_TARGET_MACOS + { + id metal_layer = NULL; + NSWindow *ns_window = glfwGetCocoaWindow(window); + CALayer *layer = ns_window.contentView.layer; + [ns_window.contentView setWantsLayer:YES]; + metal_layer = [CAMetalLayer layer]; + [ns_window.contentView setLayer:metal_layer]; + surface = wgpu_instance_create_surface_from_macos_layer(instance, metal_layer); + } +#elif WGPU_TARGET == WGPU_TARGET_LINUX + { + Display* x11_display = glfwGetX11Display(); + Window x11_window = glfwGetX11Window(window); + surface = wgpu_instance_create_surface_from_xlib(instance, (const void**)x11_display, x11_window); + } +#elif WGPU_TARGET == WGPU_TARGET_WINDOWS + { + HWND hwnd = glfwGetWin32Window(window); + HINSTANCE hinstance = GetModuleHandle(NULL); + surface = wgpu_instance_create_surface_from_windows_hwnd(instance, hinstance, hwnd); + } +#endif + + WGPUSwapChainDescriptor swap_chain_desc = { + .usage = WGPUTextureUsageFlags_OUTPUT_ATTACHMENT | WGPUTextureUsageFlags_PRESENT, + .format = WGPUTextureFormat_B8g8r8a8Unorm, + .width = 640, + .height = 480, }; + WGPUSwapChainId swap_chain = wgpu_device_create_swap_chain(device, surface, &swap_chain_desc); - const WGPUTextureFormat texture_format = WGPUTextureFormat_R8g8b8a8Unorm; - const WGPUTextureUsageFlags texture_usage = WGPUTextureUsageFlags_TRANSFER_DST | WGPUTextureUsageFlags_SAMPLED; + while (!glfwWindowShouldClose(window)) + { + WGPUSwapChainOutput next_texture = wgpu_swap_chain_get_next_texture(swap_chain); + WGPUCommandBufferDescriptor cmd_buf_desc = { .todo = 0 }; + WGPUCommandBufferId cmd_buf = wgpu_device_create_command_buffer(device, &cmd_buf_desc); + WGPURenderPassColorAttachmentDescriptor_TextureViewId color_attachments[ATTACHMENTS_LENGTH] = { + { + .attachment = next_texture.view_id, + .load_op = WGPULoadOp_Clear, + .store_op = WGPUStoreOp_Store, + .clear_color = WGPUColor_GREEN, + }, + }; + WGPURenderPassDescriptor rpass_desc = { + .color_attachments = color_attachments, + .color_attachments_length = RENDER_PASS_ATTACHMENTS_LENGTH, + .depth_stencil_attachment = NULL, + }; + WGPURenderPassId rpass = wgpu_command_buffer_begin_render_pass(cmd_buf, rpass_desc); + wgpu_render_pass_set_pipeline(rpass, render_pipeline); + wgpu_render_pass_draw(rpass, 3, 1, 0, 0); + wgpu_render_pass_end_pass(rpass); + WGPUQueueId queue = wgpu_device_get_queue(device); + wgpu_queue_submit(queue, &cmd_buf, 1); + wgpu_swap_chain_present(swap_chain); - WGPUTextureDescriptor texture_desc = { - .size = texture_size, - .array_size = 1, - .dimension = WGPUTextureDimension_D2, - .format = texture_format, - .usage = texture_usage, - }; + glfwPollEvents(); + } - WGPUTextureId texture = wgpu_device_create_texture(device, &texture_desc); + glfwDestroyWindow(window); + glfwTerminate(); return 0; } diff --git a/examples/hello_triangle_rust/main.rs b/examples/hello_triangle_rust/main.rs index 2568bb67b..30890d92b 100644 --- a/examples/hello_triangle_rust/main.rs +++ b/examples/hello_triangle_rust/main.rs @@ -93,7 +93,7 @@ fn main() { } let (_, view) = swap_chain.get_next_texture(); - let mut cmd_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor {}); + let mut cmd_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor { todo: 0 }); { let mut rpass = cmd_buf.begin_render_pass(&wgpu::RenderPassDescriptor { color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { diff --git a/wgpu-bindings/wgpu.h b/wgpu-bindings/wgpu.h index 2b8dc7c93..15b1a4604 100644 --- a/wgpu-bindings/wgpu.h +++ b/wgpu-bindings/wgpu.h @@ -125,6 +125,8 @@ typedef struct { WGPUExtensions extensions; } WGPUDeviceDescriptor; +typedef WGPUId WGPUBufferId; + typedef WGPUId WGPUComputePassId; typedef WGPUId WGPUCommandBufferId; @@ -171,6 +173,52 @@ typedef WGPUId WGPUInstanceId; typedef WGPUId WGPUBindGroupLayoutId; +typedef struct { + WGPUBufferId buffer; + uint32_t offset; + uint32_t size; +} WGPUBufferBinding; + +typedef WGPUId WGPUSamplerId; + +typedef enum { + WGPUBindingResource_Buffer, + WGPUBindingResource_Sampler, + WGPUBindingResource_TextureView, +} WGPUBindingResource_Tag; + +typedef struct { + WGPUBufferBinding _0; +} WGPUBindingResource_WGPUBuffer_Body; + +typedef struct { + WGPUSamplerId _0; +} WGPUBindingResource_WGPUSampler_Body; + +typedef struct { + WGPUTextureViewId _0; +} WGPUBindingResource_WGPUTextureView_Body; + +typedef struct { + WGPUBindingResource_Tag tag; + union { + WGPUBindingResource_WGPUBuffer_Body buffer; + WGPUBindingResource_WGPUSampler_Body sampler; + WGPUBindingResource_WGPUTextureView_Body texture_view; + }; +} WGPUBindingResource; + +typedef struct { + uint32_t binding; + WGPUBindingResource resource; +} WGPUBinding; + +typedef struct { + WGPUBindGroupLayoutId layout; + const WGPUBinding *bindings; + uintptr_t bindings_length; +} WGPUBindGroupDescriptor; + typedef uint32_t WGPUShaderStageFlags; typedef struct { @@ -201,8 +249,15 @@ typedef struct { WGPUColorWriteFlags write_mask; } WGPUBlendStateDescriptor; -typedef struct { +typedef uint32_t WGPUBufferUsageFlags; +typedef struct { + uint32_t size; + WGPUBufferUsageFlags usage; +} WGPUBufferDescriptor; + +typedef struct { + uint32_t todo; } WGPUCommandBufferDescriptor; typedef WGPUId WGPUDepthStencilStateId; @@ -398,6 +453,8 @@ typedef struct { WGPUDeviceId wgpu_adapter_create_device(WGPUAdapterId adapter_id, const WGPUDeviceDescriptor *_desc); +void wgpu_buffer_destroy(WGPUBufferId buffer_id); + WGPUComputePassId wgpu_command_buffer_begin_compute_pass(WGPUCommandBufferId command_buffer_id); WGPURenderPassId wgpu_command_buffer_begin_render_pass(WGPUCommandBufferId command_buffer_id, @@ -415,12 +472,17 @@ void wgpu_compute_pass_set_pipeline(WGPUComputePassId pass_id, WGPUComputePipeli WGPUInstanceId wgpu_create_instance(void); +WGPUBindGroupId wgpu_device_create_bind_group(WGPUDeviceId device_id, + const WGPUBindGroupDescriptor *desc); + WGPUBindGroupLayoutId wgpu_device_create_bind_group_layout(WGPUDeviceId device_id, const WGPUBindGroupLayoutDescriptor *desc); WGPUBlendStateId wgpu_device_create_blend_state(WGPUDeviceId _device_id, const WGPUBlendStateDescriptor *desc); +WGPUBufferId wgpu_device_create_buffer(WGPUDeviceId device_id, const WGPUBufferDescriptor *desc); + WGPUCommandBufferId wgpu_device_create_command_buffer(WGPUDeviceId device_id, const WGPUCommandBufferDescriptor *_desc); @@ -444,6 +506,17 @@ WGPUTextureId wgpu_device_create_texture(WGPUDeviceId device_id, const WGPUTextu WGPUQueueId wgpu_device_get_queue(WGPUDeviceId device_id); +WGPUSurfaceId wgpu_instance_create_surface_from_macos_layer(WGPUInstanceId instance_id, + void *layer); + +WGPUSurfaceId wgpu_instance_create_surface_from_windows_hwnd(WGPUInstanceId instance_id, + void *hinstance, + void *hwnd); + +WGPUSurfaceId wgpu_instance_create_surface_from_xlib(WGPUInstanceId instance_id, + const void **display, + uint64_t window); + WGPUAdapterId wgpu_instance_get_adapter(WGPUInstanceId instance_id, const WGPUAdapterDescriptor *desc); @@ -451,8 +524,31 @@ void wgpu_queue_submit(WGPUQueueId queue_id, const WGPUCommandBufferId *command_buffer_ptr, uintptr_t command_buffer_count); +void wgpu_render_pass_draw(WGPURenderPassId pass_id, + uint32_t vertex_count, + uint32_t instance_count, + uint32_t first_vertex, + uint32_t first_instance); + +void wgpu_render_pass_draw_indexed(WGPURenderPassId pass_id, + uint32_t index_count, + uint32_t instance_count, + uint32_t first_index, + int32_t base_vertex, + uint32_t first_instance); + WGPUCommandBufferId wgpu_render_pass_end_pass(WGPURenderPassId pass_id); +void wgpu_render_pass_set_bind_group(WGPURenderPassId pass_id, + uint32_t index, + WGPUBindGroupId bind_group_id); + +void wgpu_render_pass_set_index_buffer(WGPURenderPassId pass_id, + WGPUBufferId buffer_id, + uint32_t offset); + +void wgpu_render_pass_set_pipeline(WGPURenderPassId pass_id, WGPURenderPipelineId pipeline_id); + WGPUSwapChainOutput wgpu_swap_chain_get_next_texture(WGPUSwapChainId swap_chain_id); void wgpu_swap_chain_present(WGPUSwapChainId swap_chain_id); diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 6ee037a19..cff0871e9 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -145,7 +145,11 @@ impl CommandBuffer { } #[repr(C)] -pub struct CommandBufferDescriptor {} +pub struct CommandBufferDescriptor { + // MSVC doesn't allow zero-sized structs + // We can remove this when we actually have a field + pub todo: u32, +} #[no_mangle] pub extern "C" fn wgpu_command_buffer_begin_render_pass( diff --git a/wgpu-native/src/instance.rs b/wgpu-native/src/instance.rs index 6b8159984..79f7ad1a6 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -1,9 +1,5 @@ use crate::registry::{HUB, Items}; -use crate::{WeaklyStored, Device, - AdapterId, DeviceId, InstanceId, -}; -#[cfg(feature = "winit")] -use crate::{Surface, SurfaceId}; +use crate::{AdapterId, Device, DeviceId, InstanceId, Surface, SurfaceId, WeaklyStored}; use hal::{self, Instance as _Instance, PhysicalDevice as _PhysicalDevice}; @@ -67,6 +63,100 @@ pub extern "C" fn wgpu_instance_create_surface_from_winit( .register(surface) } +#[allow(unused)] +#[no_mangle] +pub extern "C" fn wgpu_instance_create_surface_from_xlib( + instance_id: InstanceId, + display: *mut *const std::ffi::c_void, + window: u64, +) -> SurfaceId { + #[cfg(not(feature = "gfx-backend-vulkan"))] + unimplemented!(); + + #[cfg(feature = "gfx-backend-vulkan")] + { + let raw = HUB.instances + .read() + .get(instance_id) + .create_surface_from_xlib(display, window); + let surface = Surface { + raw, + }; + + HUB.surfaces + .write() + .register(surface) + } +} + +#[allow(unused)] +#[no_mangle] +pub extern "C" fn wgpu_instance_create_surface_from_macos_layer( + instance_id: InstanceId, + layer: *mut std::ffi::c_void, +) -> SurfaceId { + #[cfg(not(feature = "gfx-backend-metal"))] + unimplemented!(); + + #[cfg(feature = "gfx-backend-metal")] + { + let raw = HUB.instances + .read() + .get(instance_id) + .create_surface_from_layer(layer as *mut _); + let surface = Surface { + raw, + }; + + HUB.surfaces + .write() + .register(surface) + } +} + +#[allow(unused)] +#[no_mangle] +pub extern "C" fn wgpu_instance_create_surface_from_windows_hwnd( + instance_id: InstanceId, + hinstance: *mut std::ffi::c_void, + hwnd: *mut std::ffi::c_void, +) -> SurfaceId { + #[cfg(not(target_os = "windows"))] + unimplemented!(); + + #[cfg(any(feature = "gfx-backend-dx11", feature = "gfx-backend-dx12"))] + { + let raw = HUB.instances + .read() + .get(instance_id) + .create_surface_from_hwnd(hwnd); + + let surface = Surface { + raw, + }; + + HUB.surfaces + .write() + .register(surface) + } + + #[cfg(all(target_os = "windows", feature = "gfx-backend-vulkan"))] + { + let raw = HUB.instances + .read() + .get(instance_id) + .create_surface_from_hwnd(hinstance, hwnd); + + let surface = Surface { + raw, + }; + + HUB.surfaces + .write() + .register(surface) + } +} + #[no_mangle] pub extern "C" fn wgpu_instance_get_adapter( instance_id: InstanceId,