94: Update C example r=kvark a=grovesNL

- Move `winit` behind a feature in wgpu-native
- Update C example to newer wgpu-native API
- Expose `Id` as `repr(C)`
- Add clang-format configuration for C files
- Add C example to CI (we can move parts of this back into the Makefile in a follow-up PR)

Co-authored-by: Joshua Groves <josh@joshgroves.com>
This commit is contained in:
bors[bot]
2019-03-10 04:03:29 +00:00
10 changed files with 195 additions and 171 deletions

5
.clang-format Normal file
View File

@@ -0,0 +1,5 @@
IndentWidth: 4
# Reduce left indentation for nested structs
AlignOperands: false
AlignAfterOpenBracket: DontAlign

View File

@@ -1,11 +1,40 @@
language: rust
rust:
- stable
- nightly
matrix:
include:
# Linux 64bit
- os: linux
rust: stable
compiler: gcc
- os: linux
rust: nightly
compiler: gcc
# macOS 64bit
- env: MACOSX_DEPLOYMENT_TARGET=10.9
os: osx
rust: stable
osx_image: xcode9
compiler: clang
#- env: MACOSX_DEPLOYMENT_TARGET=10.9
# os: osx
# rust: nightly
# osx_image: xcode9
# compiler: clang
# iPhoneOS 64bit
#- env: TARGET=aarch64-apple-ios
# os: osx
# osx_image: xcode9
# rust: nightly
# Windows 64bit
#- os: windows
# rust: stable
branches:
except:
- staging.tmp
- staging.tmp
before_install:
# Do not run bors builds against the nightly compiler.
@@ -15,3 +44,4 @@ before_install:
script:
- cargo test
- cargo check --manifest-path wgpu-native/Cargo.toml
- if [[ $TRAVIS_OS_NAME == "osx" ]]; then (brew update && brew upgrade cmake && brew install glfw3 && cd wgpu-native && cargo build --features=local,gfx-backend-metal && cd ../examples/hello_triangle_c && mkdir build && cd build && cmake .. && make); fi

View File

@@ -10,18 +10,17 @@ if(MSVC)
target_compile_options(${TARGET_NAME} PRIVATE /W4)
add_compile_definitions(WGPU_TARGET=WGPU_TARGET_WINDOWS)
set(GLFW_LIBRARY glfw3)
elseif(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)
set(GLFW_LIBRARY glfw)
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

View File

@@ -1,13 +1,13 @@
#include <stdio.h>
#include "./../../wgpu-bindings/wgpu.h"
#include <stdio.h>
#define WGPU_TARGET_MACOS 1
#define WGPU_TARGET_LINUX 2
#define WGPU_TARGET_WINDOWS 3
#if WGPU_TARGET == WGPU_TARGET_MACOS
#include <QuartzCore/CAMetalLayer.h>
#include <Foundation/Foundation.h>
#include <QuartzCore/CAMetalLayer.h>
#endif
#include <GLFW/glfw3.h>
@@ -21,14 +21,12 @@
#endif
#include <GLFW/glfw3native.h>
#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)
{
WGPUByteArray read_file(const char *name) {
FILE *file = fopen(name, "rb");
fseek(file, 0, SEEK_END);
long length = ftell(file);
@@ -36,145 +34,121 @@ WGPUByteArray read_file(const char *name)
fseek(file, 0, SEEK_SET);
fread(bytes, 1, length, file);
fclose(file);
WGPUByteArray ret = {
return (WGPUByteArray){
.bytes = bytes,
.length = length,
};
return ret;
}
int main()
{
int main() {
WGPUInstanceId instance = wgpu_create_instance();
WGPUAdapterDescriptor adapter_desc = {
.power_preference = WGPUPowerPreference_LowPower,
};
WGPUAdapterId adapter = wgpu_instance_get_adapter(instance, &adapter_desc);
WGPUDeviceDescriptor device_desc = {
.extensions = {
.anisotropic_filtering = false,
},
};
WGPUDeviceId device = wgpu_adapter_create_device(adapter, &device_desc);
WGPUShaderModuleDescriptor vertex_shader_desc = {
.code = read_file("./../../data/hello_triangle.vert.spv"),
};
WGPUShaderModuleId vertex_shader = wgpu_device_create_shader_module(device, &vertex_shader_desc);
WGPUPipelineStageDescriptor vertex_stage = {
.module = vertex_shader,
.stage = WGPUShaderStage_Vertex,
.entry_point = "main",
};
WGPUAdapterId adapter = wgpu_instance_get_adapter(instance,
&(WGPUAdapterDescriptor){
.power_preference = WGPUPowerPreference_LowPower,
});
WGPUShaderModuleDescriptor fragment_shader_desc = {
.code = read_file("./../../data/hello_triangle.frag.spv"),
};
WGPUShaderModuleId fragment_shader = wgpu_device_create_shader_module(device, &fragment_shader_desc);
WGPUPipelineStageDescriptor fragment_stage = {
.module = fragment_shader,
.stage = WGPUShaderStage_Fragment,
.entry_point = "main",
};
WGPUDeviceId device = wgpu_adapter_create_device(adapter,
&(WGPUDeviceDescriptor){
.extensions =
{
.anisotropic_filtering = false,
},
});
WGPUPipelineStageDescriptor stages[STAGES_LENGTH] = {vertex_stage, fragment_stage};
WGPUShaderModuleId vertex_shader = wgpu_device_create_shader_module(device,
&(WGPUShaderModuleDescriptor){
.code = read_file("./../../data/hello_triangle.vert.spv"),
});
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);
WGPUShaderModuleId fragment_shader =
wgpu_device_create_shader_module(device,
&(WGPUShaderModuleDescriptor){
.code = read_file("./../../data/hello_triangle.frag.spv"),
});
WGPUBindGroupLayoutId bind_group_layouts[BIND_GROUP_LAYOUTS_LENGTH] = { bind_group_layout };
WGPUBindGroupLayoutId bind_group_layout =
wgpu_device_create_bind_group_layout(device,
&(WGPUBindGroupLayoutDescriptor){
.bindings = NULL,
.bindings_length = 0,
});
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);
WGPUPipelineLayoutId pipeline_layout =
wgpu_device_create_pipeline_layout(device,
&(WGPUPipelineLayoutDescriptor){
.bind_group_layouts = bind_group_layouts,
.bind_group_layouts_length = BIND_GROUP_LAYOUTS_LENGTH,
});
WGPUBlendDescriptor blend_alpha = {
.src_factor = WGPUBlendFactor_One,
.dst_factor = WGPUBlendFactor_Zero,
.operation = WGPUBlendOperation_Add,
};
WGPUBlendDescriptor blend_color = {
.src_factor = WGPUBlendFactor_One,
.dst_factor = WGPUBlendFactor_Zero,
.operation = WGPUBlendOperation_Add,
};
WGPUBlendStateDescriptor blend_state_0_desc = {
.blend_enabled = false,
.alpha = blend_alpha,
.color = blend_color,
.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};
WGPURenderPipelineId render_pipeline =
wgpu_device_create_render_pipeline(device,
&(WGPURenderPipelineDescriptor){
.layout = pipeline_layout,
.vertex_stage =
(WGPUPipelineStageDescriptor){
.module = vertex_shader,
.entry_point = "main",
},
.fragment_stage =
(WGPUPipelineStageDescriptor){
.module = fragment_shader,
.entry_point = "main",
},
.rasterization_state =
(WGPURasterizationStateDescriptor){
.front_face = WGPUFrontFace_Ccw,
.cull_mode = WGPUCullMode_None,
.depth_bias = 0,
.depth_bias_slope_scale = 0.0,
.depth_bias_clamp = 0.0,
},
.primitive_topology = WGPUPrimitiveTopology_TriangleList,
.color_states =
&(WGPUColorStateDescriptor){
.format = WGPUTextureFormat_Bgra8Unorm,
.alpha =
(WGPUBlendDescriptor){
.src_factor = WGPUBlendFactor_One,
.dst_factor = WGPUBlendFactor_Zero,
.operation = WGPUBlendOperation_Add,
},
.color =
(WGPUBlendDescriptor){
.src_factor = WGPUBlendFactor_One,
.dst_factor = WGPUBlendFactor_Zero,
.operation = WGPUBlendOperation_Add,
},
.write_mask = WGPUColorWriteFlags_ALL,
},
.color_states_length = 1,
.depth_stencil_state = NULL,
.vertex_buffer_state =
(WGPUVertexBufferStateDescriptor){
.index_format = WGPUIndexFormat_Uint16,
.vertex_buffers = NULL,
.vertex_buffers_count = 0,
},
.sample_count = 1,
});
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);
WGPUAttachment attachments[ATTACHMENTS_LENGTH] = {
{
.format = WGPUTextureFormat_Bgra8Unorm,
.samples = 1,
},
};
WGPUAttachmentsState attachment_state = {
.color_attachments = attachments,
.color_attachments_length = ATTACHMENTS_LENGTH,
.depth_stencil_attachment = NULL,
};
WGPURenderPipelineDescriptor render_pipeline_desc = {
.layout = pipeline_layout,
.stages = stages,
.stages_length = STAGES_LENGTH,
.primitive_topology = WGPUPrimitiveTopology_TriangleList,
.attachments_state = attachment_state,
.blend_states = blend_state,
.blend_states_length = BLEND_STATES_LENGTH,
.depth_stencil_state = depth_stencil_state,
};
WGPURenderPipelineId render_pipeline = wgpu_device_create_render_pipeline(device, &render_pipeline_desc);
if (!glfwInit())
{
if (!glfwInit()) {
printf("Cannot initialize glfw");
return 1;
}
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow *window = glfwCreateWindow(640, 480, "wgpu with glfw", NULL, NULL);
GLFWwindow *window =
glfwCreateWindow(640, 480, "wgpu with glfw", NULL, NULL);
if (!window)
{
if (!window) {
printf("Cannot create window");
return 1;
}
WGPUSurfaceId surface = NULL;
WGPUSurfaceId surface = {};
#if WGPU_TARGET == WGPU_TARGET_MACOS
{
@@ -184,53 +158,62 @@ int main()
[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);
surface = wgpu_instance_create_surface_from_macos_layer(
instance, metal_layer);
}
#elif WGPU_TARGET == WGPU_TARGET_LINUX
{
Display* x11_display = glfwGetX11Display();
Display *x11_display = glfwGetX11Display();
Window x11_window = glfwGetX11Window(window);
surface = wgpu_instance_create_surface_from_xlib(instance, (const void**)x11_display, x11_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);
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_Bgra8Unorm,
.width = 640,
.height = 480,
};
WGPUSwapChainId swap_chain = wgpu_device_create_swap_chain(device, surface, &swap_chain_desc);
WGPUSwapChainId swap_chain = wgpu_device_create_swap_chain(device, surface,
&(WGPUSwapChainDescriptor){
.usage = WGPUTextureUsageFlags_OUTPUT_ATTACHMENT,
.format = WGPUTextureFormat_Bgra8Unorm,
.width = 640,
.height = 480,
});
while (!glfwWindowShouldClose(window)) {
WGPUSwapChainOutput next_texture =
wgpu_swap_chain_get_next_texture(swap_chain);
WGPUCommandEncoderId cmd_encoder = wgpu_device_create_command_encoder(
device, &(WGPUCommandEncoderDescriptor){.todo = 0});
WGPURenderPassColorAttachmentDescriptor_TextureViewId
color_attachments[ATTACHMENTS_LENGTH] = {
{
.attachment = next_texture.view_id,
.load_op = WGPULoadOp_Clear,
.store_op = WGPUStoreOp_Store,
.clear_color = WGPUColor_GREEN,
},
};
WGPURenderPassId rpass =
wgpu_command_encoder_begin_render_pass(cmd_encoder,
(WGPURenderPassDescriptor){
.color_attachments = color_attachments,
.color_attachments_length = RENDER_PASS_ATTACHMENTS_LENGTH,
.depth_stencil_attachment = NULL,
});
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);
WGPUCommandBufferId cmd_buf = wgpu_render_pass_end_pass(rpass);
wgpu_queue_submit(queue, &cmd_buf, 1);
wgpu_swap_chain_present(swap_chain);

View File

@@ -240,7 +240,14 @@ typedef enum {
typedef struct WGPUBufferMapAsyncStatus WGPUBufferMapAsyncStatus;
typedef struct WGPUId WGPUId;
typedef uint32_t WGPUIndex;
typedef uint32_t WGPUEpoch;
typedef struct {
WGPUIndex _0;
WGPUEpoch _1;
} WGPUId;
typedef WGPUId WGPUDeviceId;
@@ -752,9 +759,6 @@ WGPUSurfaceId wgpu_instance_create_surface_from_windows_hwnd(WGPUInstanceId inst
void *hinstance,
void *hwnd);
WGPUSurfaceId wgpu_instance_create_surface_from_winit(WGPUInstanceId instance_id,
const WGPUWindow *window);
WGPUSurfaceId wgpu_instance_create_surface_from_xlib(WGPUInstanceId instance_id,
const void **display,
uint64_t window);

View File

@@ -17,9 +17,10 @@ crate-type = ["lib", "cdylib", "staticlib"]
[features]
default = []
local = ["winit", "gfx-backend-empty/winit"]
local = []
remote = ["serde"]
metal-auto-capture = ["gfx-backend-metal/auto-capture"]
window-winit = ["winit", "gfx-backend-empty/winit"]
[dependencies]
arrayvec = "0.4"

View File

@@ -18,6 +18,8 @@ use std::sync::Arc;
pub(crate) type Index = u32;
pub(crate) type Epoch = u32;
#[repr(C)]
#[derive(Clone, Copy, Debug, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Id(Index, Epoch);

View File

@@ -46,7 +46,7 @@ pub extern "C" fn wgpu_create_instance() -> InstanceId {
HUB.instances.register_local(inst)
}
#[cfg(feature = "local")]
#[cfg(all(feature = "local", feature = "window-winit"))]
#[no_mangle]
pub extern "C" fn wgpu_instance_create_surface_from_winit(
instance_id: InstanceId,

View File

@@ -1,4 +1,4 @@
#[cfg(feature = "local")]
#[cfg(all(feature = "local", feature = "window-winit"))]
pub extern crate winit;
#[cfg(feature = "gfx-backend-dx11")]

View File

@@ -23,5 +23,5 @@ dx12 = ["wgpu-native/gfx-backend-dx12"]
vulkan = ["wgpu-native/gfx-backend-vulkan"]
[dependencies]
wgpu-native = { version = "0.2", path = "../wgpu-native", features = ["local"] }
wgpu-native = { version = "0.2", path = "../wgpu-native", features = ["local", "window-winit"] }
arrayvec = "0.4"