diff --git a/Cargo.lock b/Cargo.lock index bcaa1d64..9cd70b15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1025,6 +1025,7 @@ name = "wgpu-native" version = "0.0.0" dependencies = [ "bindgen", + "bitflags 2.6.0", "log", "naga", "parking_lot", diff --git a/Cargo.toml b/Cargo.toml index bf7ebdd2..8fa64f86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -157,6 +157,7 @@ log = "0.4" thiserror = "1" parking_lot = "0.12" smallvec = "1" +bitflags = "2" [build-dependencies] bindgen = "0.70" diff --git a/build.rs b/build.rs index b26a4f19..3a3abaf6 100644 --- a/build.rs +++ b/build.rs @@ -41,7 +41,8 @@ fn main() { .prepend_enum_name(false) .size_t_is_usize(true) .ignore_functions() - .layout_tests(true); + .layout_tests(true) + .clang_macro_fallback(); for (old_name, new_name) in types_to_rename { let line = format!("pub type {old_name} = *const crate::{new_name};"); diff --git a/examples/capture/main.c b/examples/capture/main.c index e7133836..5d2a4f08 100644 --- a/examples/capture/main.c +++ b/examples/capture/main.c @@ -14,21 +14,27 @@ const size_t IMAGE_HEIGHT = 200; const size_t COPY_BYTES_PER_ROW_ALIGNMENT = 256; static void handle_request_adapter(WGPURequestAdapterStatus status, - WGPUAdapter adapter, char const *message, - void *userdata) { + WGPUAdapter adapter, WGPUStringView message, + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUAdapter *)userdata = adapter; + UNUSED(userdata2) + *(WGPUAdapter *)userdata1 = adapter; } static void handle_request_device(WGPURequestDeviceStatus status, - WGPUDevice device, char const *message, - void *userdata) { + WGPUDevice device, WGPUStringView message, + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUDevice *)userdata = device; + UNUSED(userdata2) + *(WGPUDevice *)userdata1 = device; } -static void handle_buffer_map(WGPUBufferMapAsyncStatus status, void *userdata) { - UNUSED(userdata) +static void handle_buffer_map(WGPUMapAsyncStatus status, + WGPUStringView message, + void *userdata1, void *userdata2) { + UNUSED(message) + UNUSED(userdata1) + UNUSED(userdata2) printf(LOG_PREFIX " buffer_map status=%#.8x\n", status); } @@ -67,14 +73,21 @@ int main(int argc, char *argv[]) { assert(instance); WGPUAdapter adapter = NULL; - wgpuInstanceRequestAdapter(instance, NULL, handle_request_adapter, - (void *)&adapter); + wgpuInstanceRequestAdapter(instance, NULL, + (const WGPURequestAdapterCallbackInfo){ + .callback = handle_request_adapter, + .userdata1 = &adapter + }); assert(adapter); WGPUDevice device = NULL; - wgpuAdapterRequestDevice(adapter, NULL, handle_request_device, - (void *)&device); + wgpuAdapterRequestDevice(adapter, NULL, + (const WGPURequestDeviceCallbackInfo){ + .callback = handle_request_device, + .userdata1 = &device + }); assert(device); + WGPUQueue queue = wgpuDeviceGetQueue(device); assert(queue); @@ -86,7 +99,7 @@ int main(int argc, char *argv[]) { WGPUBuffer output_buffer = wgpuDeviceCreateBuffer( device, &(const WGPUBufferDescriptor){ - .label = "output_buffer", + .label = {"output_buffer", WGPU_STRLEN}, .size = buffer_size, .usage = WGPUBufferUsage_MapRead | WGPUBufferUsage_CopyDst, .mappedAtCreation = false, @@ -102,7 +115,7 @@ int main(int argc, char *argv[]) { WGPUTexture texture = wgpuDeviceCreateTexture( device, &(const WGPUTextureDescriptor){ - .label = "texture", + .label = {"texture", WGPU_STRLEN}, .size = texture_extent, .mipLevelCount = 1, .sampleCount = 1, @@ -116,13 +129,13 @@ int main(int argc, char *argv[]) { WGPUCommandEncoder command_encoder = wgpuDeviceCreateCommandEncoder( device, &(const WGPUCommandEncoderDescriptor){ - .label = "command_encoder", + .label = {"command_encoder", WGPU_STRLEN}, }); assert(command_encoder); WGPURenderPassEncoder render_pass_encoder = wgpuCommandEncoderBeginRenderPass( command_encoder, &(const WGPURenderPassDescriptor){ - .label = "rende_pass_encoder", + .label = {"rende_pass_encoder", WGPU_STRLEN}, .colorAttachmentCount = 1, .colorAttachments = (const WGPURenderPassColorAttachment[]){ @@ -167,14 +180,16 @@ int main(int argc, char *argv[]) { WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish( command_encoder, &(const WGPUCommandBufferDescriptor){ - .label = "command_buffer", + .label = {"command_buffer", WGPU_STRLEN}, }); assert(command_buffer); wgpuQueueSubmit(queue, 1, (const WGPUCommandBuffer[]){command_buffer}); wgpuBufferMapAsync(output_buffer, WGPUMapMode_Read, 0, buffer_size, - handle_buffer_map, NULL); + (const WGPUBufferMapCallbackInfo){ + .callback = handle_buffer_map + }); wgpuDevicePoll(device, true, NULL); uint8_t *buf = diff --git a/examples/compute/main.c b/examples/compute/main.c index 03dcaeba..19f6c3a3 100644 --- a/examples/compute/main.c +++ b/examples/compute/main.c @@ -7,21 +7,26 @@ #define LOG_PREFIX "[compute]" static void handle_request_adapter(WGPURequestAdapterStatus status, - WGPUAdapter adapter, char const *message, - void *userdata) { + WGPUAdapter adapter, WGPUStringView message, + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUAdapter *)userdata = adapter; + UNUSED(userdata2) + *(WGPUAdapter *)userdata1 = adapter; } static void handle_request_device(WGPURequestDeviceStatus status, - WGPUDevice device, char const *message, - void *userdata) { + WGPUDevice device, WGPUStringView message, + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUDevice *)userdata = device; + UNUSED(userdata2) + *(WGPUDevice *)userdata1 = device; } -static void handle_buffer_map(WGPUBufferMapAsyncStatus status, void *userdata) { - UNUSED(userdata) +static void handle_buffer_map(WGPUMapAsyncStatus status, + WGPUStringView message, + void *userdata1, void *userdata2) { + UNUSED(userdata1) + UNUSED(userdata2) printf(LOG_PREFIX " buffer_map status=%#.8x\n", status); } @@ -38,13 +43,19 @@ int main(int argc, char *argv[]) { assert(instance); WGPUAdapter adapter = NULL; - wgpuInstanceRequestAdapter(instance, NULL, handle_request_adapter, - (void *)&adapter); + wgpuInstanceRequestAdapter(instance, NULL, + (const WGPURequestAdapterCallbackInfo){ + .callback = handle_request_adapter, + .userdata1 = &adapter + }); assert(adapter); WGPUDevice device = NULL; - wgpuAdapterRequestDevice(adapter, NULL, handle_request_device, - (void *)&device); + wgpuAdapterRequestDevice(adapter, NULL, + (const WGPURequestDeviceCallbackInfo){ + .callback = handle_request_device, + .userdata1 = &device + }); assert(device); WGPUQueue queue = wgpuDeviceGetQueue(device); @@ -56,7 +67,7 @@ int main(int argc, char *argv[]) { WGPUBuffer staging_buffer = wgpuDeviceCreateBuffer( device, &(const WGPUBufferDescriptor){ - .label = "staging_buffer", + .label = {"staging_buffer", WGPU_STRLEN}, .usage = WGPUBufferUsage_MapRead | WGPUBufferUsage_CopyDst, .size = numbers_size, .mappedAtCreation = false, @@ -65,7 +76,7 @@ int main(int argc, char *argv[]) { WGPUBuffer storage_buffer = wgpuDeviceCreateBuffer( device, &(const WGPUBufferDescriptor){ - .label = "storage_buffer", + .label = {"storage_buffer", WGPU_STRLEN}, .usage = WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst | WGPUBufferUsage_CopySrc, .size = numbers_size, @@ -75,11 +86,11 @@ int main(int argc, char *argv[]) { WGPUComputePipeline compute_pipeline = wgpuDeviceCreateComputePipeline( device, &(const WGPUComputePipelineDescriptor){ - .label = "compute_pipeline", + .label = {"compute_pipeline", WGPU_STRLEN}, .compute = (const WGPUProgrammableStageDescriptor){ .module = shader_module, - .entryPoint = "main", + .entryPoint = {"main", WGPU_STRLEN}, }, }); assert(compute_pipeline); @@ -90,7 +101,7 @@ int main(int argc, char *argv[]) { WGPUBindGroup bind_group = wgpuDeviceCreateBindGroup( device, &(const WGPUBindGroupDescriptor){ - .label = "bind_group", + .label = {"bind_group", WGPU_STRLEN}, .layout = bind_group_layout, .entryCount = 1, .entries = @@ -107,14 +118,14 @@ int main(int argc, char *argv[]) { WGPUCommandEncoder command_encoder = wgpuDeviceCreateCommandEncoder( device, &(const WGPUCommandEncoderDescriptor){ - .label = "command_encoder", + .label = {"command_encoder", WGPU_STRLEN}, }); assert(command_encoder); WGPUComputePassEncoder compute_pass_encoder = wgpuCommandEncoderBeginComputePass(command_encoder, &(const WGPUComputePassDescriptor){ - .label = "compute_pass", + .label = {"compute_pass", WGPU_STRLEN}, }); assert(compute_pass_encoder); @@ -131,7 +142,7 @@ int main(int argc, char *argv[]) { WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish( command_encoder, &(const WGPUCommandBufferDescriptor){ - .label = "command_buffer", + .label = {"command_buffer", WGPU_STRLEN}, }); assert(command_buffer); @@ -139,7 +150,9 @@ int main(int argc, char *argv[]) { wgpuQueueSubmit(queue, 1, &command_buffer); wgpuBufferMapAsync(staging_buffer, WGPUMapMode_Read, 0, numbers_size, - handle_buffer_map, NULL); + (const WGPUBufferMapCallbackInfo){ + .callback = handle_buffer_map + }); wgpuDevicePoll(device, true, NULL); uint32_t *buf = diff --git a/examples/enumerate_adapters/main.c b/examples/enumerate_adapters/main.c index 25b533d8..7e3db303 100644 --- a/examples/enumerate_adapters/main.c +++ b/examples/enumerate_adapters/main.c @@ -26,16 +26,17 @@ int main(int argc, char *argv[]) { wgpuAdapterGetInfo(adapter, &info); printf("WGPUAdapter: %d\n", i); printf("WGPUAdapterInfo {\n" - "\tvendor: %s\n" - "\tarchitecture: %s\n" - "\tdevice: %s\n" - "\tdescription: %s\n" + "\tvendor: %.*s\n" + "\tarchitecture: %.*s\n" + "\tdevice: %.*s\n" + "\tdescription: %.*s\n" "\tbackendType: %#.8x\n" "\tadapterType: %#.8x\n" "\tvendorID: %" PRIu32 "\n" "\tdeviceID: %" PRIu32 "\n" "}\n", - info.vendor, info.architecture, info.device, info.description, + (int) info.vendor.length, info.vendor.data, (int) info.architecture.length, info.architecture.data, + (int) info.device.length, info.device.data, (int) info.description.length, info.description.data, info.backendType, info.adapterType, info.vendorID, info.deviceID); wgpuAdapterInfoFreeMembers(info); diff --git a/examples/framework/framework.c b/examples/framework/framework.c index f0729e51..dadde215 100644 --- a/examples/framework/framework.c +++ b/examples/framework/framework.c @@ -1,6 +1,6 @@ #include "framework.h" -static void log_callback(WGPULogLevel level, char const *message, +static void log_callback(WGPULogLevel level, WGPUStringView message, void *userdata) { UNUSED(userdata) char *level_str; @@ -23,7 +23,7 @@ static void log_callback(WGPULogLevel level, char const *message, default: level_str = "unknown_level"; } - fprintf(stderr, "[wgpu] [%s] %s\n", level_str, message); + fprintf(stderr, "[wgpu] [%s] %.*s\n", level_str, (int) message.length, message.data); } void frmwrk_setup_logging(WGPULogLevel level) { @@ -64,15 +64,15 @@ WGPUShaderModule frmwrk_load_shader_module(WGPUDevice device, shader_module = wgpuDeviceCreateShaderModule( device, &(const WGPUShaderModuleDescriptor){ - .label = name, + .label = {name, WGPU_STRLEN}, .nextInChain = (const WGPUChainedStruct *)&( - const WGPUShaderModuleWGSLDescriptor){ + const WGPUShaderSourceWGSL){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_ShaderModuleWGSLDescriptor, + .sType = WGPUSType_ShaderSourceWGSL, }, - .code = buf, + .code = {buf, WGPU_STRLEN}, }, }); @@ -92,7 +92,7 @@ WGPUBuffer frmwrk_device_create_buffer_init( assert(descriptor); if (descriptor->content_size == 0) { return wgpuDeviceCreateBuffer(device, &(WGPUBufferDescriptor){ - .label = descriptor->label, + .label = {descriptor->label, WGPU_STRLEN}, .size = 0, .usage = descriptor->usage, .mappedAtCreation = false, @@ -105,7 +105,7 @@ WGPUBuffer frmwrk_device_create_buffer_init( MAX((unpadded_size + align_mask) & ~align_mask, COPY_BUFFER_ALIGNMENT); WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &(WGPUBufferDescriptor){ - .label = descriptor->label, + .label = {descriptor->label, WGPU_STRLEN}, .size = padded_size, .usage = descriptor->usage, .mappedAtCreation = true, @@ -168,10 +168,10 @@ void frmwrk_print_global_report(WGPUGlobalReport report) { void frmwrk_print_adapter_info(WGPUAdapter adapter) { struct WGPUAdapterInfo info = {0}; wgpuAdapterGetInfo(adapter, &info); - printf("description: %s\n", info.description); - printf("vendor: %s\n", info.vendor); - printf("architecture: %s\n", info.architecture); - printf("device: %s\n", info.device); + printf("description: %.*s\n", (int) info.description.length, info.description.data); + printf("vendor: %.*s\n", (int) info.vendor.length, info.vendor.data); + printf("architecture: %.*s\n", (int) info.architecture.length, info.architecture.data); + printf("device: %.*s\n", (int) info.device.length, info.device.data); printf("backend type: %u\n", info.backendType); printf("adapter type: %u\n", info.adapterType); printf("vendorID: %x\n", info.vendorID); diff --git a/examples/framework/framework.h b/examples/framework/framework.h index c10084d7..cbde32bf 100644 --- a/examples/framework/framework.h +++ b/examples/framework/framework.h @@ -12,7 +12,7 @@ typedef struct frmwrk_buffer_init_descriptor { WGPU_NULLABLE char const *label; - WGPUBufferUsageFlags usage; + WGPUBufferUsage usage; void *content; size_t content_size; } frmwrk_buffer_init_descriptor; diff --git a/examples/push_constants/main.c b/examples/push_constants/main.c index 6018eaa8..c1cbaec5 100644 --- a/examples/push_constants/main.c +++ b/examples/push_constants/main.c @@ -8,21 +8,26 @@ #define LOG_PREFIX "[push_constants]" static void handle_request_adapter(WGPURequestAdapterStatus status, - WGPUAdapter adapter, char const *message, - void *userdata) { + WGPUAdapter adapter, WGPUStringView message, + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUAdapter *)userdata = adapter; + UNUSED(userdata2) + *(WGPUAdapter *)userdata1 = adapter; } static void handle_request_device(WGPURequestDeviceStatus status, - WGPUDevice device, char const *message, - void *userdata) { + WGPUDevice device, WGPUStringView message, + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUDevice *)userdata = device; + UNUSED(userdata2) + *(WGPUDevice *)userdata1 = device; } -static void handle_buffer_map(WGPUBufferMapAsyncStatus status, void *userdata) { - UNUSED(userdata) +static void handle_buffer_map(WGPUMapAsyncStatus status, + WGPUStringView message, + void *userdata1, void *userdata2) { + UNUSED(userdata1) + UNUSED(userdata2) printf(LOG_PREFIX " buffer_map status=%#.8x\n", status); } @@ -39,50 +44,41 @@ int main(int argc, char *argv[]) { assert(instance); WGPUAdapter adapter = NULL; - wgpuInstanceRequestAdapter(instance, NULL, handle_request_adapter, - (void *)&adapter); + wgpuInstanceRequestAdapter(instance, NULL, + (const WGPURequestAdapterCallbackInfo){ + .callback = handle_request_adapter, + .userdata1 = &adapter + }); assert(adapter); - WGPUSupportedLimitsExtras supported_limits_extras = { + WGPUNativeLimits supported_limits_extras = { .chain = { - .sType = WGPUSType_SupportedLimitsExtras, - }, - .limits = - { - .maxPushConstantSize = 0, + .sType = WGPUSType_NativeLimits, }, + .maxPushConstantSize = 0, }; - WGPUSupportedLimits supported_limits = { + WGPULimits supported_limits = { .nextInChain = &supported_limits_extras.chain, }; wgpuAdapterGetLimits(adapter, &supported_limits); - WGPURequiredLimitsExtras required_limits_extras = { - .chain = - { - .sType = WGPUSType_RequiredLimitsExtras, - }, - .limits = supported_limits_extras.limits, - }; - WGPURequiredLimits required_limits = { - .nextInChain = &required_limits_extras.chain, - .limits = supported_limits.limits, - }; - WGPUFeatureName requiredFeatures[] = { WGPUNativeFeature_PushConstants, }; WGPUDeviceDescriptor device_desc = { - .label = "compute_device", + .label = {"compute_device", WGPU_STRLEN}, .requiredFeatures = requiredFeatures, .requiredFeatureCount = 1, - .requiredLimits = &required_limits, + .requiredLimits = &supported_limits, }; WGPUDevice device = NULL; - wgpuAdapterRequestDevice(adapter, &device_desc, handle_request_device, - (void *)&device); + wgpuAdapterRequestDevice(adapter, &device_desc, + (const WGPURequestDeviceCallbackInfo){ + .callback = handle_request_device, + .userdata1 = &device + }); assert(device); WGPUQueue queue = wgpuDeviceGetQueue(device); @@ -94,7 +90,7 @@ int main(int argc, char *argv[]) { WGPUBuffer storage_buffer = wgpuDeviceCreateBuffer( device, &(const WGPUBufferDescriptor){ - .label = "storage_buffer", + .label = {"storage_buffer", WGPU_STRLEN}, .usage = WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst | WGPUBufferUsage_CopySrc, .size = numbers_size, @@ -104,7 +100,7 @@ int main(int argc, char *argv[]) { WGPUBuffer staging_buffer = wgpuDeviceCreateBuffer( device, &(const WGPUBufferDescriptor){ - .label = "staging_buffer", + .label = {"staging_buffer", WGPU_STRLEN}, .usage = WGPUBufferUsage_MapRead | WGPUBufferUsage_CopyDst, .size = numbers_size, .mappedAtCreation = false, @@ -137,7 +133,7 @@ int main(int argc, char *argv[]) { }, }; WGPUBindGroupLayoutDescriptor bind_group_layout_desc = { - .label = "bind_group_layout", + .label = {"bind_group_layout", WGPU_STRLEN}, .nextInChain = NULL, .entryCount = 1, .entries = bind_group_layout_entries, @@ -147,7 +143,7 @@ int main(int argc, char *argv[]) { assert(bind_group_layout); WGPUPipelineLayoutDescriptor pipeline_layout_desc = { - .label = "pipeline_layout", + .label = {"pipeline_layout", WGPU_STRLEN}, .nextInChain = &pipeline_layout_extras.chain, .bindGroupLayouts = &bind_group_layout, .bindGroupLayoutCount = 1, @@ -158,11 +154,11 @@ int main(int argc, char *argv[]) { WGPUComputePipeline compute_pipeline = wgpuDeviceCreateComputePipeline( device, &(const WGPUComputePipelineDescriptor){ - .label = "compute_pipeline", + .label = {"compute_pipeline", WGPU_STRLEN}, .compute = (const WGPUProgrammableStageDescriptor){ .module = shader_module, - .entryPoint = "main", + .entryPoint = {"main", WGPU_STRLEN}, }, .layout = pipeline_layout, }); @@ -170,7 +166,7 @@ int main(int argc, char *argv[]) { WGPUBindGroup bind_group = wgpuDeviceCreateBindGroup( device, &(const WGPUBindGroupDescriptor){ - .label = "bind_group", + .label = {"bind_group", WGPU_STRLEN}, .layout = bind_group_layout, .entryCount = 1, .entries = @@ -187,14 +183,14 @@ int main(int argc, char *argv[]) { WGPUCommandEncoder command_encoder = wgpuDeviceCreateCommandEncoder( device, &(const WGPUCommandEncoderDescriptor){ - .label = "command_encoder", + .label = {"command_encoder", WGPU_STRLEN}, }); assert(command_encoder); WGPUComputePassEncoder compute_pass_encoder = wgpuCommandEncoderBeginComputePass(command_encoder, &(const WGPUComputePassDescriptor){ - .label = "compute_pass", + .label = {"compute_pass", WGPU_STRLEN}, }); assert(compute_pass_encoder); @@ -219,7 +215,7 @@ int main(int argc, char *argv[]) { WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish( command_encoder, &(const WGPUCommandBufferDescriptor){ - .label = "command_buffer", + .label = {"command_buffer", WGPU_STRLEN}, }); assert(command_buffer); @@ -227,7 +223,9 @@ int main(int argc, char *argv[]) { wgpuQueueSubmit(queue, 1, &command_buffer); wgpuBufferMapAsync(staging_buffer, WGPUMapMode_Read, 0, numbers_size, - handle_buffer_map, NULL); + (const WGPUBufferMapCallbackInfo){ + .callback = handle_buffer_map + }); wgpuDevicePoll(device, true, NULL); uint32_t *buf = diff --git a/examples/texture_arrays/main.c b/examples/texture_arrays/main.c index 907355f7..4a5c1a88 100644 --- a/examples/texture_arrays/main.c +++ b/examples/texture_arrays/main.c @@ -26,25 +26,27 @@ struct demo { }; static void handle_request_adapter(WGPURequestAdapterStatus status, - WGPUAdapter adapter, char const *message, - void *userdata) { + WGPUAdapter adapter, WGPUStringView message, + void *userdata1, void *userdata2) { + UNUSED(userdata2) if (status == WGPURequestAdapterStatus_Success) { - struct demo *demo = userdata; + struct demo *demo = userdata1; demo->adapter = adapter; } else { - printf(LOG_PREFIX " request_adapter status=%#.8x message=%s\n", status, - message); + printf(LOG_PREFIX " request_adapter status=%#.8x message=%.*s\n", status, + (int) message.length, message.data); } } static void handle_request_device(WGPURequestDeviceStatus status, - WGPUDevice device, char const *message, - void *userdata) { + WGPUDevice device, WGPUStringView message, + void *userdata1, void *userdata2) { + UNUSED(userdata2) if (status == WGPURequestDeviceStatus_Success) { - struct demo *demo = userdata; + struct demo *demo = userdata1; demo->device = device; } else { - printf(LOG_PREFIX " request_device status=%#.8x message=%s\n", status, - message); + printf(LOG_PREFIX " request_device status=%#.8x message=%.*s\n", status, + (int) message.length, message.data); } } static void handle_glfw_framebuffer_size(GLFWwindow *window, int width, @@ -147,10 +149,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromMetalLayer){ + const WGPUSurfaceSourceMetalLayer){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromMetalLayer, + .sType = WGPUSType_SurfaceSourceMetalLayer, }, .layer = metal_layer, }, @@ -165,10 +167,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromXlibWindow){ + const WGPUSurfaceSourceXlibWindow){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromXlibWindow, + .sType = WGPUSType_SurfaceSourceXlibWindow, }, .display = x11_display, .window = x11_window, @@ -183,11 +185,11 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromWaylandSurface){ + const WGPUSurfaceSourceWaylandSurface){ .chain = (const WGPUChainedStruct){ .sType = - WGPUSType_SurfaceDescriptorFromWaylandSurface, + WGPUSType_SurfaceSourceWaylandSurface, }, .display = wayland_display, .surface = wayland_surface, @@ -203,10 +205,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromWindowsHWND){ + const WGPUSurfaceSourceWindowsHWND){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromWindowsHWND, + .sType = WGPUSType_SurfaceSourceWindowsHWND, }, .hinstance = hinstance, .hwnd = hwnd, @@ -222,22 +224,22 @@ int main(int argc, char *argv[]) { &(const WGPURequestAdapterOptions){ .compatibleSurface = demo.surface, }, - handle_request_adapter, &demo); + (const WGPURequestAdapterCallbackInfo){ + .callback = handle_request_adapter, + .userdata1 = &demo + }); assert(demo.adapter); WGPUSurfaceCapabilities surface_capabilities = {0}; wgpuSurfaceGetCapabilities(demo.surface, demo.adapter, &surface_capabilities); - size_t adapter_feature_count = - wgpuAdapterEnumerateFeatures(demo.adapter, NULL); - WGPUFeatureName *adapter_features = (WGPUFeatureName *)malloc( - sizeof(WGPUFeatureName) * adapter_feature_count); - wgpuAdapterEnumerateFeatures(demo.adapter, adapter_features); + WGPUSupportedFeatures adapter_features = {0}; + wgpuAdapterGetFeatures(demo.adapter, &adapter_features); bool adapter_has_required_features = false; bool adapter_has_optional_features = false; - for (size_t i = 0; i < adapter_feature_count; i++) { - switch ((uint32_t)adapter_features[i]) { + for (size_t i = 0; i < adapter_features.featureCount; i++) { + switch ((uint32_t)adapter_features.features[i]) { case WGPUNativeFeature_TextureBindingArray: adapter_has_required_features = true; break; @@ -248,7 +250,7 @@ int main(int argc, char *argv[]) { } assert( adapter_has_required_features /* Adapter must support WGPUNativeFeature_TextureBindingArray feature for this example */); - free(adapter_features); + wgpuSupportedFeaturesFreeMembers(adapter_features); WGPUFeatureName required_device_features[2] = { (WGPUFeatureName)WGPUNativeFeature_TextureBindingArray, @@ -260,13 +262,15 @@ int main(int argc, char *argv[]) { required_device_feature_count++; } - wgpuAdapterRequestDevice( - demo.adapter, - &(const WGPUDeviceDescriptor){ - .requiredFeatureCount = required_device_feature_count, - .requiredFeatures = required_device_features, - }, - handle_request_device, &demo); + wgpuAdapterRequestDevice(demo.adapter, + &(const WGPUDeviceDescriptor){ + .requiredFeatureCount = required_device_feature_count, + .requiredFeatures = required_device_features, + }, + (const WGPURequestDeviceCallbackInfo){ + .callback = handle_request_device, + .userdata1 = &demo + }); assert(demo.device); WGPUQueue queue = wgpuDeviceGetQueue(demo.device); @@ -364,25 +368,25 @@ int main(int argc, char *argv[]) { WGPUTexture red_texture = wgpuDeviceCreateTexture( demo.device, &(const WGPUTextureDescriptor){ COLOR_TEXTURE_DESCRIPTOR_COMMON_FIELDS, - .label = "red", + .label = {"red", WGPU_STRLEN}, }); assert(red_texture); WGPUTexture green_texture = wgpuDeviceCreateTexture( demo.device, &(const WGPUTextureDescriptor){ COLOR_TEXTURE_DESCRIPTOR_COMMON_FIELDS, - .label = "green", + .label = {"green", WGPU_STRLEN}, }); assert(green_texture); WGPUTexture blue_texture = wgpuDeviceCreateTexture( demo.device, &(const WGPUTextureDescriptor){ COLOR_TEXTURE_DESCRIPTOR_COMMON_FIELDS, - .label = "blue", + .label = {"blue", WGPU_STRLEN}, }); assert(blue_texture); WGPUTexture white_texture = wgpuDeviceCreateTexture( demo.device, &(const WGPUTextureDescriptor){ COLOR_TEXTURE_DESCRIPTOR_COMMON_FIELDS, - .label = "white", + .label = {"white", WGPU_STRLEN}, }); assert(white_texture); @@ -512,7 +516,7 @@ int main(int argc, char *argv[]) { }; WGPUBindGroupLayout bind_group_layout = wgpuDeviceCreateBindGroupLayout( demo.device, &(const WGPUBindGroupLayoutDescriptor){ - .label = "bind group layout", + .label = {"bind group layout", WGPU_STRLEN}, .entryCount = sizeof(bind_group_layout_entries) / sizeof(bind_group_layout_entries[0]), .entries = bind_group_layout_entries, @@ -578,7 +582,7 @@ int main(int argc, char *argv[]) { WGPUBindGroup bind_group = wgpuDeviceCreateBindGroup( demo.device, &(const WGPUBindGroupDescriptor){ .layout = bind_group_layout, - .label = "bind group", + .label = {"bind group", WGPU_STRLEN}, .entryCount = sizeof(bind_group_entries) / sizeof(bind_group_entries[0]), .entries = bind_group_entries, @@ -587,7 +591,7 @@ int main(int argc, char *argv[]) { WGPUPipelineLayout pipeline_layout = wgpuDeviceCreatePipelineLayout( demo.device, &(const WGPUPipelineLayoutDescriptor){ - .label = "main", + .label = {"main", WGPU_STRLEN}, .bindGroupLayoutCount = 1, .bindGroupLayouts = (const WGPUBindGroupLayout[]){ @@ -603,7 +607,7 @@ int main(int argc, char *argv[]) { .vertex = (const WGPUVertexState){ .module = base_shader_module, - .entryPoint = "vert_main", + .entryPoint = {"vert_main", WGPU_STRLEN}, .bufferCount = 1, .buffers = (const WGPUVertexBufferLayout[]){ @@ -619,7 +623,7 @@ int main(int argc, char *argv[]) { .fragment = &(const WGPUFragmentState){ .module = fragment_shader_module, - .entryPoint = fragment_entry_point, + .entryPoint = {fragment_entry_point, WGPU_STRLEN}, .targetCount = 1, .targets = (const WGPUColorTargetState[]){ @@ -648,8 +652,9 @@ int main(int argc, char *argv[]) { WGPUSurfaceTexture surface_texture; wgpuSurfaceGetCurrentTexture(demo.surface, &surface_texture); switch (surface_texture.status) { - case WGPUSurfaceGetCurrentTextureStatus_Success: - // All good, could check for `surface_texture.suboptimal` here. + case WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal: + case WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal: + // All good, could handle suboptimal here break; case WGPUSurfaceGetCurrentTextureStatus_Timeout: case WGPUSurfaceGetCurrentTextureStatus_Outdated: @@ -683,7 +688,7 @@ int main(int argc, char *argv[]) { WGPUCommandEncoder command_encoder = wgpuDeviceCreateCommandEncoder( demo.device, &(const WGPUCommandEncoderDescriptor){ - .label = "command_encoder", + .label = {"command_encoder", WGPU_STRLEN}, }); assert(command_encoder); @@ -691,7 +696,7 @@ int main(int argc, char *argv[]) { wgpuCommandEncoderBeginRenderPass( command_encoder, &(const WGPURenderPassDescriptor){ - .label = "render_pass_encoder", + .label = {"render_pass_encoder", WGPU_STRLEN}, .colorAttachmentCount = 1, .colorAttachments = (const WGPURenderPassColorAttachment[]){ @@ -735,7 +740,7 @@ int main(int argc, char *argv[]) { WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish( command_encoder, &(const WGPUCommandBufferDescriptor){ - .label = "command_buffer", + .label = {"command_buffer", WGPU_STRLEN}, }); assert(command_buffer); diff --git a/examples/triangle/main.c b/examples/triangle/main.c index fb6eacdd..50d468d8 100644 --- a/examples/triangle/main.c +++ b/examples/triangle/main.c @@ -26,25 +26,27 @@ struct demo { }; static void handle_request_adapter(WGPURequestAdapterStatus status, - WGPUAdapter adapter, char const *message, - void *userdata) { + WGPUAdapter adapter, WGPUStringView message, + void *userdata1, void *userdata2) { + UNUSED(userdata2) if (status == WGPURequestAdapterStatus_Success) { - struct demo *demo = userdata; + struct demo *demo = userdata1; demo->adapter = adapter; } else { - printf(LOG_PREFIX " request_adapter status=%#.8x message=%s\n", status, - message); + printf(LOG_PREFIX " request_adapter status=%#.8x message=%.*s\n", status, + (int) message.length, message.data); } } static void handle_request_device(WGPURequestDeviceStatus status, - WGPUDevice device, char const *message, - void *userdata) { + WGPUDevice device, WGPUStringView message, + void *userdata1, void *userdata2) { + UNUSED(userdata2) if (status == WGPURequestDeviceStatus_Success) { - struct demo *demo = userdata; + struct demo *demo = userdata1; demo->device = device; } else { - printf(LOG_PREFIX " request_device status=%#.8x message=%s\n", status, - message); + printf(LOG_PREFIX " request_device status=%#.8x message=%.*s\n", status, + (int) message.length, message.data); } } static void handle_glfw_key(GLFWwindow *window, int key, int scancode, @@ -110,10 +112,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromMetalLayer){ + const WGPUSurfaceSourceMetalLayer){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromMetalLayer, + .sType = WGPUSType_SurfaceSourceMetalLayer, }, .layer = metal_layer, }, @@ -128,10 +130,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromXlibWindow){ + const WGPUSurfaceSourceXlibWindow){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromXlibWindow, + .sType = WGPUSType_SurfaceSourceXlibWindow, }, .display = x11_display, .window = x11_window, @@ -146,11 +148,11 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromWaylandSurface){ + const WGPUSurfaceSourceWaylandSurface){ .chain = (const WGPUChainedStruct){ .sType = - WGPUSType_SurfaceDescriptorFromWaylandSurface, + WGPUSType_SurfaceSourceWaylandSurface, }, .display = wayland_display, .surface = wayland_surface, @@ -166,10 +168,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromWindowsHWND){ + const WGPUSurfaceSourceWindowsHWND){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromWindowsHWND, + .sType = WGPUSType_SurfaceSourceWindowsHWND, }, .hinstance = hinstance, .hwnd = hwnd, @@ -185,12 +187,19 @@ int main(int argc, char *argv[]) { &(const WGPURequestAdapterOptions){ .compatibleSurface = demo.surface, }, - handle_request_adapter, &demo); + (const WGPURequestAdapterCallbackInfo){ + .callback = handle_request_adapter, + .userdata1 = &demo + }); assert(demo.adapter); frmwrk_print_adapter_info(demo.adapter); - wgpuAdapterRequestDevice(demo.adapter, NULL, handle_request_device, &demo); + wgpuAdapterRequestDevice(demo.adapter, NULL, + (const WGPURequestDeviceCallbackInfo){ + .callback = handle_request_device, + .userdata1 = &demo + }); assert(demo.device); WGPUQueue queue = wgpuDeviceGetQueue(demo.device); @@ -202,7 +211,7 @@ int main(int argc, char *argv[]) { WGPUPipelineLayout pipeline_layout = wgpuDeviceCreatePipelineLayout( demo.device, &(const WGPUPipelineLayoutDescriptor){ - .label = "pipeline_layout", + .label = {"pipeline_layout", WGPU_STRLEN}, }); assert(pipeline_layout); @@ -212,17 +221,17 @@ int main(int argc, char *argv[]) { WGPURenderPipeline render_pipeline = wgpuDeviceCreateRenderPipeline( demo.device, &(const WGPURenderPipelineDescriptor){ - .label = "render_pipeline", + .label = {"render_pipeline", WGPU_STRLEN}, .layout = pipeline_layout, .vertex = (const WGPUVertexState){ .module = shader_module, - .entryPoint = "vs_main", + .entryPoint = {"vs_main", WGPU_STRLEN}, }, .fragment = &(const WGPUFragmentState){ .module = shader_module, - .entryPoint = "fs_main", + .entryPoint = {"fs_main", WGPU_STRLEN}, .targetCount = 1, .targets = (const WGPUColorTargetState[]){ @@ -267,8 +276,9 @@ int main(int argc, char *argv[]) { WGPUSurfaceTexture surface_texture; wgpuSurfaceGetCurrentTexture(demo.surface, &surface_texture); switch (surface_texture.status) { - case WGPUSurfaceGetCurrentTextureStatus_Success: - // All good, could check for `surface_texture.suboptimal` here. + case WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal: + case WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal: + // All good, could handle suboptimal here break; case WGPUSurfaceGetCurrentTextureStatus_Timeout: case WGPUSurfaceGetCurrentTextureStatus_Outdated: @@ -302,7 +312,7 @@ int main(int argc, char *argv[]) { WGPUCommandEncoder command_encoder = wgpuDeviceCreateCommandEncoder( demo.device, &(const WGPUCommandEncoderDescriptor){ - .label = "command_encoder", + .label = {"command_encoder", WGPU_STRLEN}, }); assert(command_encoder); @@ -310,7 +320,7 @@ int main(int argc, char *argv[]) { wgpuCommandEncoderBeginRenderPass( command_encoder, &(const WGPURenderPassDescriptor){ - .label = "render_pass_encoder", + .label = {"render_pass_encoder", WGPU_STRLEN}, .colorAttachmentCount = 1, .colorAttachments = (const WGPURenderPassColorAttachment[]){ @@ -338,7 +348,7 @@ int main(int argc, char *argv[]) { WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish( command_encoder, &(const WGPUCommandBufferDescriptor){ - .label = "command_buffer", + .label = {"command_buffer", WGPU_STRLEN}, }); assert(command_buffer); diff --git a/ffi/webgpu-headers b/ffi/webgpu-headers index 043af6c7..6f549cc3 160000 --- a/ffi/webgpu-headers +++ b/ffi/webgpu-headers @@ -1 +1 @@ -Subproject commit 043af6c77e566f707db36759d9c9f161ebb616fd +Subproject commit 6f549cc3409663303b06f50483b9ebf9d1cf19dd diff --git a/ffi/wgpu.h b/ffi/wgpu.h index 7c1cf575..a490c556 100644 --- a/ffi/wgpu.h +++ b/ffi/wgpu.h @@ -6,10 +6,9 @@ typedef enum WGPUNativeSType { // Start at 0003 since that's allocated range for wgpu-native WGPUSType_DeviceExtras = 0x00030001, - WGPUSType_RequiredLimitsExtras = 0x00030002, + WGPUSType_NativeLimits = 0x00030002, WGPUSType_PipelineLayoutExtras = 0x00030003, WGPUSType_ShaderModuleGLSLDescriptor = 0x00030004, - WGPUSType_SupportedLimitsExtras = 0x00030005, WGPUSType_InstanceExtras = 0x00030006, WGPUSType_BindGroupEntryExtras = 0x00030007, WGPUSType_BindGroupLayoutEntryExtras = 0x00030008, @@ -69,30 +68,26 @@ typedef enum WGPULogLevel { WGPULogLevel_Force32 = 0x7FFFFFFF } WGPULogLevel; -typedef enum WGPUInstanceBackend { - WGPUInstanceBackend_All = 0x00000000, - WGPUInstanceBackend_Vulkan = 1 << 0, - WGPUInstanceBackend_GL = 1 << 1, - WGPUInstanceBackend_Metal = 1 << 2, - WGPUInstanceBackend_DX12 = 1 << 3, - WGPUInstanceBackend_DX11 = 1 << 4, - WGPUInstanceBackend_BrowserWebGPU = 1 << 5, - WGPUInstanceBackend_Primary = WGPUInstanceBackend_Vulkan | WGPUInstanceBackend_Metal | - WGPUInstanceBackend_DX12 | - WGPUInstanceBackend_BrowserWebGPU, - WGPUInstanceBackend_Secondary = WGPUInstanceBackend_GL | WGPUInstanceBackend_DX11, - WGPUInstanceBackend_Force32 = 0x7FFFFFFF -} WGPUInstanceBackend; -typedef WGPUFlags WGPUInstanceBackendFlags; - -typedef enum WGPUInstanceFlag { - WGPUInstanceFlag_Default = 0x00000000, - WGPUInstanceFlag_Debug = 1 << 0, - WGPUInstanceFlag_Validation = 1 << 1, - WGPUInstanceFlag_DiscardHalLabels = 1 << 2, - WGPUInstanceFlag_Force32 = 0x7FFFFFFF -} WGPUInstanceFlag; -typedef WGPUFlags WGPUInstanceFlags; +typedef WGPUFlags WGPUInstanceBackend; +static const WGPUInstanceBackend WGPUInstanceBackend_All = 0x00000000; +static const WGPUInstanceBackend WGPUInstanceBackend_Vulkan = 1 << 0; +static const WGPUInstanceBackend WGPUInstanceBackend_GL = 1 << 1; +static const WGPUInstanceBackend WGPUInstanceBackend_Metal = 1 << 2; +static const WGPUInstanceBackend WGPUInstanceBackend_DX12 = 1 << 3; +static const WGPUInstanceBackend WGPUInstanceBackend_DX11 = 1 << 4; +static const WGPUInstanceBackend WGPUInstanceBackend_BrowserWebGPU = 1 << 5; +// Vulkan, Metal, DX12 and BrowserWebGPU +static const WGPUInstanceBackend WGPUInstanceBackend_Primary = (1 << 0) | (1 << 2) | (1 << 3) | (1 << 5); +// GL and DX11 +static const WGPUInstanceBackend WGPUInstanceBackend_Secondary = (1 << 1) | (1 << 4); +static const WGPUInstanceBackend WGPUInstanceBackend_Force32 = 0x7FFFFFFF; + +typedef WGPUFlags WGPUInstanceFlag; +static const WGPUInstanceFlag WGPUInstanceFlag_Default = 0x00000000; +static const WGPUInstanceFlag WGPUInstanceFlag_Debug = 1 << 0; +static const WGPUInstanceFlag WGPUInstanceFlag_Validation = 1 << 1; +static const WGPUInstanceFlag WGPUInstanceFlag_DiscardHalLabels = 1 << 2; +static const WGPUInstanceFlag WGPUInstanceFlag_Force32 = 0x7FFFFFFF; typedef enum WGPUDx12Compiler { WGPUDx12Compiler_Undefined = 0x00000000, @@ -125,36 +120,28 @@ typedef enum WGPUNativeQueryType { typedef struct WGPUInstanceExtras { WGPUChainedStruct chain; - WGPUInstanceBackendFlags backends; - WGPUInstanceFlags flags; + WGPUInstanceBackend backends; + WGPUInstanceFlag flags; WGPUDx12Compiler dx12ShaderCompiler; WGPUGles3MinorVersion gles3MinorVersion; - const char * dxilPath; - const char * dxcPath; + WGPUStringView dxilPath; + WGPUStringView dxcPath; } WGPUInstanceExtras; typedef struct WGPUDeviceExtras { WGPUChainedStruct chain; - const char * tracePath; + WGPUStringView tracePath; } WGPUDeviceExtras; typedef struct WGPUNativeLimits { + /** This struct chain is used as mutable in some places and immutable in others. */ + WGPUChainedStructOut chain; uint32_t maxPushConstantSize; uint32_t maxNonSamplerBindings; } WGPUNativeLimits; -typedef struct WGPURequiredLimitsExtras { - WGPUChainedStruct chain; - WGPUNativeLimits limits; -} WGPURequiredLimitsExtras; - -typedef struct WGPUSupportedLimitsExtras { - WGPUChainedStructOut chain; - WGPUNativeLimits limits; -} WGPUSupportedLimitsExtras; - typedef struct WGPUPushConstantRange { - WGPUShaderStageFlags stages; + WGPUShaderStage stages; uint32_t start; uint32_t end; } WGPUPushConstantRange; @@ -173,20 +160,20 @@ typedef struct WGPUWrappedSubmissionIndex { } WGPUWrappedSubmissionIndex; typedef struct WGPUShaderDefine { - char const * name; - char const * value; + WGPUStringView name; + WGPUStringView value; } WGPUShaderDefine; typedef struct WGPUShaderModuleGLSLDescriptor { WGPUChainedStruct chain; WGPUShaderStage stage; - char const * code; + WGPUStringView code; uint32_t defineCount; WGPUShaderDefine * defines; } WGPUShaderModuleGLSLDescriptor; typedef struct WGPUShaderModuleDescriptorSpirV { - char const * label; + WGPUStringView label; uint32_t sourceSize; uint32_t const * source; } WGPUShaderModuleDescriptorSpirV; @@ -229,7 +216,7 @@ typedef struct WGPUGlobalReport { typedef struct WGPUInstanceEnumerateAdapterOptions { WGPUChainedStruct const * nextInChain; - WGPUInstanceBackendFlags backends; + WGPUInstanceBackend backends; } WGPUInstanceEnumerateAdapterOptions; typedef struct WGPUBindGroupEntryExtras { @@ -258,7 +245,7 @@ typedef struct WGPUSurfaceConfigurationExtras { uint32_t desiredMaximumFrameLatency; } WGPUSurfaceConfigurationExtras WGPU_STRUCTURE_ATTRIBUTE; -typedef void (*WGPULogCallback)(WGPULogLevel level, char const * message, void * userdata); +typedef void (*WGPULogCallback)(WGPULogLevel level, WGPUStringView message, void * userdata); typedef enum WGPUNativeTextureFormat { // From Features::TEXTURE_FORMAT_16BIT_NORM @@ -291,7 +278,7 @@ void wgpuSetLogLevel(WGPULogLevel level); uint32_t wgpuGetVersion(void); -void wgpuRenderPassEncoderSetPushConstants(WGPURenderPassEncoder encoder, WGPUShaderStageFlags stages, uint32_t offset, uint32_t sizeBytes, void const * data); +void wgpuRenderPassEncoderSetPushConstants(WGPURenderPassEncoder encoder, WGPUShaderStage stages, uint32_t offset, uint32_t sizeBytes, void const * data); void wgpuComputePassEncoderSetPushConstants(WGPUComputePassEncoder encoder, uint32_t offset, uint32_t sizeBytes, void const * data); void wgpuRenderPassEncoderMultiDrawIndirect(WGPURenderPassEncoder encoder, WGPUBuffer buffer, uint64_t offset, uint32_t count); diff --git a/src/conv.rs b/src/conv.rs index 21f4a7fb..e64bf25c 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -1,9 +1,10 @@ -use crate::utils::{make_slice, ptr_into_label, ptr_into_pathbuf}; -use crate::{follow_chain, map_enum}; +use crate::utils::{make_slice, string_view_into_label, string_view_into_str}; +use crate::{follow_chain, map_enum, map_enum_with_undefined, new_userdata}; use crate::{native, UncapturedErrorCallback}; +use std::borrow::Cow; use std::num::{NonZeroIsize, NonZeroU32, NonZeroU64}; +use std::path::PathBuf; use std::ptr::NonNull; -use std::{borrow::Cow, ffi::CStr}; map_enum!(map_load_op, WGPULoadOp, wgc::command::LoadOp, Clear, Load); map_enum!( @@ -13,7 +14,7 @@ map_enum!( Discard, Store ); -map_enum!( +map_enum_with_undefined!( map_address_mode, WGPUAddressMode, wgt::AddressMode, @@ -22,7 +23,7 @@ map_enum!( Repeat, MirrorRepeat ); -map_enum!( +map_enum_with_undefined!( map_filter_mode, WGPUFilterMode, wgt::FilterMode, @@ -30,7 +31,7 @@ map_enum!( Nearest, Linear ); -map_enum!( +map_enum_with_undefined!( map_mipmap_filter_mode, WGPUMipmapFilterMode, wgt::FilterMode, @@ -38,7 +39,7 @@ map_enum!( Nearest, Linear ); -map_enum!( +map_enum_with_undefined!( map_compare_function, WGPUCompareFunction, wgt::CompareFunction, @@ -51,7 +52,7 @@ map_enum!( GreaterEqual, Always ); -map_enum!( +map_enum_with_undefined!( map_texture_aspect, WGPUTextureAspect, wgt::TextureAspect, @@ -60,7 +61,7 @@ map_enum!( StencilOnly, DepthOnly ); -map_enum!( +map_enum_with_undefined!( map_present_mode, WGPUPresentMode, wgt::PresentMode, @@ -70,7 +71,7 @@ map_enum!( Fifo, FifoRelaxed ); -map_enum!( +map_enum_with_undefined!( map_primitive_topology, WGPUPrimitiveTopology, wgt::PrimitiveTopology, @@ -88,26 +89,30 @@ map_enum!( Uint16, Uint32 ); -map_enum!( +map_enum_with_undefined!( map_blend_factor, WGPUBlendFactor, wgt::BlendFactor, "Unknown blend factor", - Zero: Zero, - One: One, - Src: Src, - OneMinusSrc: OneMinusSrc, - SrcAlpha: SrcAlpha, - OneMinusSrcAlpha: OneMinusSrcAlpha, - Dst: Dst, - OneMinusDst: OneMinusDst, - DstAlpha: DstAlpha, - OneMinusDstAlpha: OneMinusDstAlpha, - SrcAlphaSaturated: SrcAlphaSaturated, - Constant: Constant, - OneMinusConstant: OneMinusConstant + Zero, + One, + Src, + OneMinusSrc, + SrcAlpha, + OneMinusSrcAlpha, + Dst, + OneMinusDst, + DstAlpha, + OneMinusDstAlpha, + SrcAlphaSaturated, + Constant, + OneMinusConstant, + Src1, + OneMinusSrc1, + Src1Alpha, + OneMinusSrc1Alpha ); -map_enum!( +map_enum_with_undefined!( map_blend_operation, WGPUBlendOperation, wgt::BlendOperation, @@ -118,10 +123,11 @@ map_enum!( Min, Max ); -map_enum!( +map_enum_with_undefined!( map_stencil_operation, WGPUStencilOperation, wgt::StencilOperation, + "Unknown stencil operation", Keep, Zero, Replace, @@ -164,7 +170,8 @@ map_enum!( Sint32, Sint32x2, Sint32x3, - Sint32x4 + Sint32x4, + Unorm10_10_10_2 ); #[cfg(feature = "glsl")] @@ -199,20 +206,23 @@ map_enum!( Version2 ); -map_enum!( +map_enum_with_undefined!( map_storage_texture_access, WGPUStorageTextureAccess, wgt::StorageTextureAccess, + "Unknown storage texture access", WriteOnly, ReadOnly, ReadWrite ); -pub const WGPU_WHOLE_SIZE: ::std::os::raw::c_ulonglong = native::WGPU_WHOLE_SIZE as _; -pub const WGPU_LIMIT_U64_UNDEFINED: ::std::os::raw::c_ulonglong = - native::WGPU_LIMIT_U64_UNDEFINED as _; +// These are defined as UINT64_MAX in the header, but bindgen currently can't process that define. +// See https://github.com/rust-lang/rust-bindgen/issues/2822 +pub const WGPU_WHOLE_SIZE: u64 = u64::MAX; +pub const WGPU_LIMIT_U64_UNDEFINED: u64 = u64::MAX; // it's SIZE_MAX in headers but it's not available in some compilers pub const WGPU_WHOLE_MAP_SIZE: usize = usize::MAX; +pub const WGPU_STRLEN: usize = usize::MAX; #[inline] pub fn map_extent3d(native: &native::WGPUExtent3D) -> wgt::Extent3d { @@ -273,7 +283,7 @@ pub fn map_instance_flags(flags: native::WGPUInstanceFlag) -> wgt::InstanceFlags } #[inline] -pub fn map_instance_descriptor( +pub unsafe fn map_instance_descriptor( _base: &native::WGPUInstanceDescriptor, extras: Option<&native::WGPUInstanceExtras>, ) -> wgt::InstanceDescriptor { @@ -281,8 +291,8 @@ pub fn map_instance_descriptor( let dx12_shader_compiler = match extras.dx12ShaderCompiler { native::WGPUDx12Compiler_Fxc => wgt::Dx12Compiler::Fxc, native::WGPUDx12Compiler_Dxc => wgt::Dx12Compiler::Dxc { - dxil_path: ptr_into_pathbuf(extras.dxilPath), - dxc_path: ptr_into_pathbuf(extras.dxcPath), + dxil_path: string_view_into_str(extras.dxilPath).map(PathBuf::from), + dxc_path: string_view_into_str(extras.dxcPath).map(PathBuf::from), }, _ => wgt::Dx12Compiler::default(), }; @@ -291,7 +301,7 @@ pub fn map_instance_descriptor( backends: map_instance_backend_flags(extras.backends as native::WGPUInstanceBackend), dx12_shader_compiler, gles_minor_version: map_gles3_minor_version(extras.gles3MinorVersion), - flags: match extras.flags as native::WGPUInstanceFlag { + flags: match extras.flags { native::WGPUInstanceFlag_Default => wgt::InstanceFlags::default(), flags => map_instance_flags(flags), }, @@ -302,18 +312,18 @@ pub fn map_instance_descriptor( } #[inline] -pub(crate) fn map_device_descriptor<'a>( +pub(crate) unsafe fn map_device_descriptor<'a>( des: &native::WGPUDeviceDescriptor, base_limits: wgt::Limits, extras: Option<&native::WGPUDeviceExtras>, ) -> ( wgt::DeviceDescriptor>, - *const std::ffi::c_char, + Option<&'a str>, Option, ) { ( wgt::DeviceDescriptor { - label: ptr_into_label(des.label), + label: string_view_into_label(des.label), required_features: map_features(make_slice( des.requiredFeatures, des.requiredFeatureCount, @@ -322,7 +332,7 @@ pub(crate) fn map_device_descriptor<'a>( Some(required_limits) => unsafe { follow_chain!( map_required_limits((required_limits, base_limits), - WGPUSType_RequiredLimitsExtras => native::WGPURequiredLimitsExtras) + WGPUSType_NativeLimits => native::WGPUNativeLimits) ) }, None => base_limits, @@ -330,15 +340,12 @@ pub(crate) fn map_device_descriptor<'a>( // TODO(wgpu.h) memory_hints: Default::default(), }, - match extras { - Some(extras) => extras.tracePath, - None => std::ptr::null(), - }, + extras.and_then(|extras| string_view_into_str(extras.tracePath)), match des.uncapturedErrorCallbackInfo.callback { None => None, callback => Some(UncapturedErrorCallback { callback, - userdata: des.uncapturedErrorCallbackInfo.userdata, + userdata: new_userdata!(des.uncapturedErrorCallbackInfo), }), }, ) @@ -363,7 +370,7 @@ pub unsafe fn map_pipeline_layout_descriptor<'a>( make_slice(extras.pushConstantRanges, extras.pushConstantRangeCount) .iter() .map(|range| wgt::PushConstantRange { - stages: wgt::ShaderStages::from_bits(range.stages) + stages: from_u64_bits(range.stages) .expect("invalid shader stage for push constant range"), range: range.start..range.end, }) @@ -371,18 +378,14 @@ pub unsafe fn map_pipeline_layout_descriptor<'a>( }); return wgc::binding_model::PipelineLayoutDescriptor { - label: ptr_into_label(des.label), + label: string_view_into_label(des.label), bind_group_layouts: Cow::from(bind_group_layouts), push_constant_ranges: Cow::from(push_constant_ranges), }; } #[inline] -pub fn write_limits_struct( - wgt_limits: wgt::Limits, - supported_limits: &mut native::WGPUSupportedLimits, -) { - let mut limits = supported_limits.limits; +pub fn write_limits_struct(wgt_limits: wgt::Limits, limits: &mut native::WGPULimits) { limits.maxTextureDimension1D = wgt_limits.max_texture_dimension_1d; limits.maxTextureDimension2D = wgt_limits.max_texture_dimension_2d; limits.maxTextureDimension3D = wgt_limits.max_texture_dimension_3d; @@ -408,7 +411,6 @@ pub fn write_limits_struct( limits.maxVertexBufferArrayStride = wgt_limits.max_vertex_buffer_array_stride; limits.minUniformBufferOffsetAlignment = wgt_limits.min_uniform_buffer_offset_alignment; limits.minStorageBufferOffsetAlignment = wgt_limits.min_storage_buffer_offset_alignment; - limits.maxInterStageShaderComponents = wgt_limits.max_inter_stage_shader_components; // TODO: not yet in wgt // limits.maxInterStageShaderVariables = wgt_limits.max_inter_stage_shader_variables; // TODO: not yet in wgt @@ -421,33 +423,29 @@ pub fn write_limits_struct( limits.maxComputeWorkgroupSizeY = wgt_limits.max_compute_workgroup_size_y; limits.maxComputeWorkgroupSizeZ = wgt_limits.max_compute_workgroup_size_z; limits.maxComputeWorkgroupsPerDimension = wgt_limits.max_compute_workgroups_per_dimension; - supported_limits.limits = limits; if let Some(native::WGPUChainedStructOut { - sType: native::WGPUSType_SupportedLimitsExtras, + sType: native::WGPUSType_NativeLimits, .. - }) = unsafe { supported_limits.nextInChain.as_ref() } + }) = unsafe { limits.nextInChain.as_ref() } { unsafe { - let extras = std::mem::transmute::< + let native_limits = std::mem::transmute::< *mut native::WGPUChainedStructOut, - *mut native::WGPUSupportedLimitsExtras, - >(supported_limits.nextInChain); - (*extras).limits = native::WGPUNativeLimits { - maxPushConstantSize: wgt_limits.max_push_constant_size, - maxNonSamplerBindings: wgt_limits.max_non_sampler_bindings, - }; + *mut native::WGPUNativeLimits, + >(limits.nextInChain); + (*native_limits).maxPushConstantSize = wgt_limits.max_push_constant_size; + (*native_limits).maxNonSamplerBindings = wgt_limits.max_non_sampler_bindings; } }; } #[inline] pub fn map_required_limits( - required_limits: &native::WGPURequiredLimits, + limits: &native::WGPULimits, base_limits: wgt::Limits, - extras: Option<&native::WGPURequiredLimitsExtras>, + extras: Option<&native::WGPUNativeLimits>, ) -> wgt::Limits { - let limits = required_limits.limits; let mut wgt_limits = base_limits; if limits.maxTextureDimension1D != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_texture_dimension_1d = limits.maxTextureDimension1D; @@ -494,10 +492,10 @@ pub fn map_required_limits( if limits.maxUniformBuffersPerShaderStage != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_uniform_buffers_per_shader_stage = limits.maxUniformBuffersPerShaderStage; } - if limits.maxUniformBufferBindingSize != native::WGPU_LIMIT_U64_UNDEFINED as u64 { + if limits.maxUniformBufferBindingSize != WGPU_LIMIT_U64_UNDEFINED { wgt_limits.max_uniform_buffer_binding_size = limits.maxUniformBufferBindingSize as u32; } - if limits.maxStorageBufferBindingSize != native::WGPU_LIMIT_U64_UNDEFINED as u64 { + if limits.maxStorageBufferBindingSize != WGPU_LIMIT_U64_UNDEFINED { wgt_limits.max_storage_buffer_binding_size = limits.maxStorageBufferBindingSize as u32; } if limits.minUniformBufferOffsetAlignment != native::WGPU_LIMIT_U32_UNDEFINED { @@ -509,7 +507,7 @@ pub fn map_required_limits( if limits.maxVertexBuffers != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_vertex_buffers = limits.maxVertexBuffers; } - if limits.maxBufferSize != native::WGPU_LIMIT_U64_UNDEFINED as u64 { + if limits.maxBufferSize != WGPU_LIMIT_U64_UNDEFINED { wgt_limits.max_buffer_size = limits.maxBufferSize; } if limits.maxVertexAttributes != native::WGPU_LIMIT_U32_UNDEFINED { @@ -518,9 +516,6 @@ pub fn map_required_limits( if limits.maxVertexBufferArrayStride != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_vertex_buffer_array_stride = limits.maxVertexBufferArrayStride; } - if limits.maxInterStageShaderComponents != native::WGPU_LIMIT_U32_UNDEFINED { - wgt_limits.max_inter_stage_shader_components = limits.maxInterStageShaderComponents; - } // TODO: not yet in wgt // if limits.maxInterStageShaderVariables != native::WGPU_LIMIT_U32_UNDEFINED { // wgt_limits.max_inter_stage_shader_variables = limits.maxInterStageShaderVariables; @@ -551,8 +546,7 @@ pub fn map_required_limits( if limits.maxComputeWorkgroupsPerDimension != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_compute_workgroups_per_dimension = limits.maxComputeWorkgroupsPerDimension; } - if let Some(extras) = extras { - let limits = extras.limits; + if let Some(limits) = extras { if limits.maxPushConstantSize != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_push_constant_size = limits.maxPushConstantSize; } @@ -574,16 +568,15 @@ pub enum ShaderParseError { } #[inline] -pub fn map_shader_module<'a>( +pub unsafe fn map_shader_module<'a>( _: &native::WGPUShaderModuleDescriptor, - spirv: Option<&native::WGPUShaderModuleSPIRVDescriptor>, - wgsl: Option<&native::WGPUShaderModuleWGSLDescriptor>, + spirv: Option<&native::WGPUShaderSourceSPIRV>, + wgsl: Option<&native::WGPUShaderSourceWGSL>, glsl: Option<&native::WGPUShaderModuleGLSLDescriptor>, ) -> Result, ShaderParseError> { #[cfg(feature = "wgsl")] if let Some(wgsl) = wgsl { - let c_str: &CStr = unsafe { CStr::from_ptr(wgsl.code) }; - let str_slice: &str = c_str.to_str().expect("not a valid utf-8 string"); + let str_slice: &str = string_view_into_str(wgsl.code).unwrap_or(""); return Ok(wgc::pipeline::ShaderModuleSource::Wgsl(Cow::Borrowed( str_slice, ))); @@ -607,8 +600,7 @@ pub fn map_shader_module<'a>( #[cfg(feature = "glsl")] if let Some(glsl) = glsl { - let c_str: &CStr = unsafe { CStr::from_ptr(glsl.code) }; - let str_slice: &str = c_str.to_str().expect("not a valid utf-8 string"); + let str_slice: &str = string_view_into_str(glsl.code).unwrap_or(""); let mut options = naga::front::glsl::Options::from( map_shader_stage(glsl.stage) .expect("invalid shader stage for shader module glsl descriptor"), @@ -616,11 +608,8 @@ pub fn map_shader_module<'a>( let raw_defines = make_slice(glsl.defines, glsl.defineCount as usize); for define in raw_defines { - let name_c_str: &CStr = unsafe { CStr::from_ptr(define.name) }; - let name_str_slice: &str = name_c_str.to_str().expect("not a valid utf-8 string"); - - let value_c_str: &CStr = unsafe { CStr::from_ptr(define.value) }; - let value_str_slice: &str = value_c_str.to_str().expect("not a valid utf-8 string"); + let name_str_slice: &str = string_view_into_str(define.name).unwrap_or(""); + let value_str_slice: &str = string_view_into_str(define.value).unwrap_or(""); options .defines @@ -649,7 +638,7 @@ pub unsafe fn map_image_copy_texture( .id, mip_level: native.mipLevel, origin: map_origin3d(&native.origin), - aspect: map_texture_aspect(native.aspect), + aspect: map_texture_aspect(native.aspect).unwrap_or(wgt::TextureAspect::All), } } @@ -697,9 +686,9 @@ pub fn map_color(native: &native::WGPUColor) -> wgt::Color { #[inline] pub fn map_blend_component(native: native::WGPUBlendComponent) -> wgt::BlendComponent { wgt::BlendComponent { - src_factor: map_blend_factor(native.srcFactor), - dst_factor: map_blend_factor(native.dstFactor), - operation: map_blend_operation(native.operation), + src_factor: map_blend_factor(native.srcFactor).unwrap_or(wgt::BlendFactor::One), + dst_factor: map_blend_factor(native.dstFactor).unwrap_or(wgt::BlendFactor::Zero), + operation: map_blend_operation(native.operation).unwrap_or(wgt::BlendOperation::Add), } } @@ -707,6 +696,8 @@ pub fn map_blend_component(native: native::WGPUBlendComponent) -> wgt::BlendComp pub fn map_texture_view_dimension( value: native::WGPUTextureViewDimension, ) -> Option { + // This doesn't use map_enum_with_undefined! because the enum name after the _ + // isn't a valid ident on its own for the macro. match value { native::WGPUTextureViewDimension_1D => Some(wgt::TextureViewDimension::D1), native::WGPUTextureViewDimension_2D => Some(wgt::TextureViewDimension::D2), @@ -714,16 +705,20 @@ pub fn map_texture_view_dimension( native::WGPUTextureViewDimension_Cube => Some(wgt::TextureViewDimension::Cube), native::WGPUTextureViewDimension_CubeArray => Some(wgt::TextureViewDimension::CubeArray), native::WGPUTextureViewDimension_3D => Some(wgt::TextureViewDimension::D3), - _ => None, + native::WGPUTextureDimension_Undefined => None, + _ => panic!("Unknown texture view dimension"), } } #[inline] -pub fn map_texture_dimension(value: native::WGPUTextureDimension) -> wgt::TextureDimension { +pub fn map_texture_dimension(value: native::WGPUTextureDimension) -> Option { + // This doesn't use map_enum_with_undefined! because the enum name after the _ + // isn't a valid ident on its own for the macro. match value { - native::WGPUTextureDimension_1D => wgt::TextureDimension::D1, - native::WGPUTextureDimension_2D => wgt::TextureDimension::D2, - native::WGPUTextureDimension_3D => wgt::TextureDimension::D3, + native::WGPUTextureDimension_1D => Some(wgt::TextureDimension::D1), + native::WGPUTextureDimension_2D => Some(wgt::TextureDimension::D2), + native::WGPUTextureDimension_3D => Some(wgt::TextureDimension::D3), + native::WGPUTextureDimension_Undefined => None, x => panic!("Unknown texture dimension: {x}"), } } @@ -734,6 +729,7 @@ pub fn map_texture_format(value: native::WGPUTextureFormat) -> Option None, native::WGPUTextureFormat_R8Unorm => Some(wgt::TextureFormat::R8Unorm), native::WGPUTextureFormat_R8Snorm => Some(wgt::TextureFormat::R8Snorm), native::WGPUTextureFormat_R8Uint => Some(wgt::TextureFormat::R8Uint), @@ -838,7 +834,7 @@ pub fn map_texture_format(value: native::WGPUTextureFormat) -> Option Some(wgt::TextureFormat::Rgba16Unorm), native::WGPUNativeTextureFormat_Rgba16Snorm => Some(wgt::TextureFormat::Rgba16Snorm), native::WGPUNativeTextureFormat_NV12 => Some(wgt::TextureFormat::NV12), - _ => None, + _ => panic!("Unknown texture format"), } } @@ -965,26 +961,13 @@ pub fn map_stencil_face_state( ) -> wgt::StencilFaceState { wgt::StencilFaceState { compare: map_compare_function(value.compare) - .unwrap_or_else(|_| panic!("invalid compare function for {mode} stencil face state")), - fail_op: map_stencil_operation(value.failOp) - .unwrap_or_else(|_| panic!("invalid fail op for {mode} stencil face state")), + .unwrap_or_else(|_| panic!("invalid compare function for {mode} stencil face state")) + .unwrap_or(wgt::CompareFunction::Always), + fail_op: map_stencil_operation(value.failOp).unwrap_or(wgt::StencilOperation::Keep), depth_fail_op: map_stencil_operation(value.depthFailOp) - .unwrap_or_else(|_| panic!("invalid depth fail op for {mode} stencil face state")), - pass_op: map_stencil_operation(value.passOp) - .unwrap_or_else(|_| panic!("invalid pass op for {mode} stencil face state")), - } -} - -#[inline] -pub fn map_primitive_state( - _: &native::WGPUPrimitiveState, - depth_clip_control: Option<&native::WGPUPrimitiveDepthClipControl>, -) -> bool { - if let Some(depth_clip_control) = depth_clip_control { - return depth_clip_control.unclippedDepth != 0; + .unwrap_or(wgt::StencilOperation::Keep), + pass_op: map_stencil_operation(value.passOp).unwrap_or(wgt::StencilOperation::Keep), } - - false } #[inline] @@ -1113,7 +1096,9 @@ pub fn features_to_native(features: wgt::Features) -> Vec Option { native::WGPUFeatureName_DepthClipControl => Some(Features::DEPTH_CLIP_CONTROL), native::WGPUFeatureName_Depth32FloatStencil8 => Some(Features::DEPTH32FLOAT_STENCIL8), native::WGPUFeatureName_TextureCompressionBC => Some(Features::TEXTURE_COMPRESSION_BC), + // TODO: WGPUFeatureName_TextureCompressionBCSliced3D native::WGPUFeatureName_TextureCompressionETC2 => Some(Features::TEXTURE_COMPRESSION_ETC2), native::WGPUFeatureName_TextureCompressionASTC => Some(Features::TEXTURE_COMPRESSION_ASTC), + // TODO: WGPUFeatureName_TextureCompressionASTCSliced3D native::WGPUFeatureName_TimestampQuery => Some(Features::TIMESTAMP_QUERY), native::WGPUFeatureName_IndirectFirstInstance => Some(Features::INDIRECT_FIRST_INSTANCE), native::WGPUFeatureName_ShaderF16 => Some(Features::SHADER_F16), native::WGPUFeatureName_RG11B10UfloatRenderable => Some(Features::RG11B10UFLOAT_RENDERABLE), native::WGPUFeatureName_BGRA8UnormStorage => Some(Features::BGRA8UNORM_STORAGE), + // TODO: WGPUFeatureName_ClipDistances + // TODO: WGPUFeatureName_Float32Blendable native::WGPUFeatureName_Float32Filterable => Some(Features::FLOAT32_FILTERABLE), + native::WGPUFeatureName_DualSourceBlending => Some(Features::DUAL_SOURCE_BLENDING), // wgpu-rs only features native::WGPUNativeFeature_PushConstants => Some(Features::PUSH_CONSTANTS), @@ -1399,16 +1389,16 @@ pub fn map_bind_group_layout_entry( entry: &native::WGPUBindGroupLayoutEntry, extras: Option<&native::WGPUBindGroupLayoutEntryExtras>, ) -> wgt::BindGroupLayoutEntry { - let is_buffer = entry.buffer.type_ != native::WGPUBufferBindingType_Undefined; - let is_sampler = entry.sampler.type_ != native::WGPUSamplerBindingType_Undefined; - let is_texture = entry.texture.sampleType != native::WGPUTextureSampleType_Undefined; + let is_buffer = entry.buffer.type_ != native::WGPUBufferBindingType_BindingNotUsed; + let is_sampler = entry.sampler.type_ != native::WGPUSamplerBindingType_BindingNotUsed; + let is_texture = entry.texture.sampleType != native::WGPUTextureSampleType_BindingNotUsed; let is_storage_texture = - entry.storageTexture.access != native::WGPUStorageTextureAccess_Undefined; + entry.storageTexture.access != native::WGPUStorageTextureAccess_BindingNotUsed; let ty = if is_texture { wgt::BindingType::Texture { sample_type: match entry.texture.sampleType { - native::WGPUTextureSampleType_Float => { + native::WGPUTextureSampleType_Float | native::WGPUTextureSampleType_Undefined => { wgt::TextureSampleType::Float { filterable: true } } native::WGPUTextureSampleType_UnfilterableFloat => { @@ -1432,7 +1422,7 @@ pub fn map_bind_group_layout_entry( } } else if is_sampler { match entry.sampler.type_ { - native::WGPUSamplerBindingType_Filtering => { + native::WGPUSamplerBindingType_Filtering | native::WGPUSamplerBindingType_Undefined => { wgt::BindingType::Sampler(wgt::SamplerBindingType::Filtering) } native::WGPUSamplerBindingType_NonFiltering => { @@ -1446,7 +1436,7 @@ pub fn map_bind_group_layout_entry( } else if is_storage_texture { wgt::BindingType::StorageTexture { access: map_storage_texture_access(entry.storageTexture.access) - .expect("invalid storage texture access for storage texture binding layout"), + .unwrap_or(wgt::StorageTextureAccess::WriteOnly), format: map_texture_format(entry.storageTexture.format) .expect("invalid texture format for storage texture binding layout"), view_dimension: match entry.storageTexture.viewDimension { @@ -1464,7 +1454,9 @@ pub fn map_bind_group_layout_entry( } else if is_buffer { wgt::BindingType::Buffer { ty: match entry.buffer.type_ { - native::WGPUBufferBindingType_Uniform => wgt::BufferBindingType::Uniform, + native::WGPUBufferBindingType_Uniform | native::WGPUBufferBindingType_Undefined => { + wgt::BufferBindingType::Uniform + } native::WGPUBufferBindingType_Storage => { wgt::BufferBindingType::Storage { read_only: false } } @@ -1490,7 +1482,7 @@ pub fn map_bind_group_layout_entry( wgt::BindGroupLayoutEntry { ty, binding: entry.binding, - visibility: wgt::ShaderStages::from_bits(entry.visibility) + visibility: from_u64_bits(entry.visibility) .expect("invalid visibility for bind group layout entry"), count: extras.and_then(|v| NonZeroU32::new(v.count)), } @@ -1504,12 +1496,12 @@ pub fn map_query_set_index(index: u32) -> Option { } #[inline] -pub fn map_query_set_descriptor<'a>( +pub unsafe fn map_query_set_descriptor<'a>( desc: &native::WGPUQuerySetDescriptor, extras: Option<&native::WGPUQuerySetDescriptorExtras>, ) -> wgt::QuerySetDescriptor> { wgt::QuerySetDescriptor { - label: ptr_into_label(desc.label), + label: string_view_into_label(desc.label), count: desc.count, ty: match (desc.type_, extras) { (native::WGPUQueryType_Occlusion, _) => wgt::QueryType::Occlusion, @@ -1596,12 +1588,12 @@ pub enum CreateSurfaceParams { pub unsafe fn map_surface( _: &native::WGPUSurfaceDescriptor, - win: Option<&native::WGPUSurfaceDescriptorFromWindowsHWND>, - xcb: Option<&native::WGPUSurfaceDescriptorFromXcbWindow>, - xlib: Option<&native::WGPUSurfaceDescriptorFromXlibWindow>, - wl: Option<&native::WGPUSurfaceDescriptorFromWaylandSurface>, - _metal: Option<&native::WGPUSurfaceDescriptorFromMetalLayer>, - android: Option<&native::WGPUSurfaceDescriptorFromAndroidNativeWindow>, + win: Option<&native::WGPUSurfaceSourceWindowsHWND>, + xcb: Option<&native::WGPUSurfaceSourceXCBWindow>, + xlib: Option<&native::WGPUSurfaceSourceXlibWindow>, + wl: Option<&native::WGPUSurfaceSourceWaylandSurface>, + _metal: Option<&native::WGPUSurfaceSourceMetalLayer>, + android: Option<&native::WGPUSurfaceSourceAndroidNativeWindow>, ) -> CreateSurfaceParams { if let Some(win) = win { let display_handle = raw_window_handle::WindowsDisplayHandle::new(); @@ -1680,7 +1672,7 @@ pub fn map_surface_configuration( .expect("invalid format for surface configuration"), width: config.width, height: config.height, - present_mode: map_present_mode(config.presentMode), + present_mode: map_present_mode(config.presentMode).unwrap_or(wgt::PresentMode::Fifo), alpha_mode: map_composite_alpha_mode(config.alphaMode) .expect("invalid alpha mode for surface configuration"), view_formats: make_slice(config.viewFormats, config.viewFormatCount) @@ -1715,3 +1707,11 @@ pub fn map_adapter_type(device_type: wgt::DeviceType) -> native::WGPUAdapterType wgt::DeviceType::Cpu => native::WGPUAdapterType_CPU, } } + +pub fn from_u64_bits>(value: u64) -> Option { + if value > u32::MAX.into() { + return None; + } + + T::from_bits(value as u32) +} diff --git a/src/lib.rs b/src/lib.rs index 3b585fc6..8c45627b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,16 +1,16 @@ use conv::{ - map_adapter_type, map_backend_type, map_bind_group_entry, map_bind_group_layout_entry, - map_device_descriptor, map_instance_backend_flags, map_instance_descriptor, - map_pipeline_layout_descriptor, map_primitive_state, map_query_set_descriptor, + from_u64_bits, map_adapter_type, map_backend_type, map_bind_group_entry, + map_bind_group_layout_entry, map_device_descriptor, map_instance_backend_flags, + map_instance_descriptor, map_pipeline_layout_descriptor, map_query_set_descriptor, map_query_set_index, map_shader_module, map_surface, map_surface_configuration, CreateSurfaceParams, }; +use core::slice; use parking_lot::Mutex; use smallvec::SmallVec; use std::{ borrow::Cow, error, - ffi::{CStr, CString}, fmt::Display, mem, num::NonZeroU64, @@ -18,7 +18,8 @@ use std::{ thread, }; use utils::{ - get_base_device_limits_from_adapter_limits, make_slice, ptr_into_label, ptr_into_path, + get_base_device_limits_from_adapter_limits, make_slice, str_into_string_view, + string_view_into_label, string_view_into_str, texture_format_has_depth, }; use wgc::{ command::{bundle_ffi, DynComputePass, DynRenderPass}, @@ -80,7 +81,7 @@ impl Drop for WGPUBindGroupLayoutImpl { } struct BufferData { - usage: native::WGPUBufferUsageFlags, + usage: native::WGPUBufferUsage, size: u64, } pub struct WGPUBufferImpl { @@ -343,7 +344,7 @@ impl Drop for WGPUSurfaceImpl { #[derive(Copy, Clone)] struct TextureData { - usage: native::WGPUTextureUsageFlags, + usage: native::WGPUTextureUsage, dimension: native::WGPUTextureDimension, size: native::WGPUExtent3D, format: native::WGPUTextureFormat, @@ -396,41 +397,51 @@ impl Drop for WGPUTextureViewImpl { } } +const NULL_FUTURE: native::WGPUFuture = native::WGPUFuture { id: 0 }; +const EMPTY_STRING: native::WGPUStringView = native::WGPUStringView { + length: 0, + data: std::ptr::null(), +}; + struct DeviceCallback { callback: T, - userdata: *mut std::os::raw::c_void, + userdata: utils::Userdata, } unsafe impl Send for DeviceCallback {} -type UncapturedErrorCallback = DeviceCallback; +type UncapturedErrorCallback = DeviceCallback; type DeviceLostCallback = DeviceCallback; unsafe extern "C" fn default_uncaptured_error_handler( + _device: *const native::WGPUDevice, _typ: native::WGPUErrorType, - message: *const ::std::os::raw::c_char, - _userdata: *mut ::std::os::raw::c_void, + message: native::WGPUStringView, + _userdata1: *mut ::std::os::raw::c_void, + _userdata2: *mut ::std::os::raw::c_void, ) { - let message = unsafe { CStr::from_ptr(message) }.to_str().unwrap(); + let message = string_view_into_str(message).unwrap_or(""); log::warn!("Handling wgpu uncaptured errors as fatal by default"); panic!("wgpu uncaptured error:\n{message}\n"); } const DEFAULT_UNCAPTURED_ERROR_HANDLER: UncapturedErrorCallback = UncapturedErrorCallback { callback: Some(default_uncaptured_error_handler), - userdata: std::ptr::null_mut(), + userdata: utils::Userdata::NULL, }; unsafe extern "C" fn default_device_lost_handler( + _device: *const native::WGPUDevice, _reason: native::WGPUDeviceLostReason, - message: *const ::std::os::raw::c_char, - _userdata: *mut ::std::os::raw::c_void, + message: native::WGPUStringView, + _userdata1: *mut ::std::os::raw::c_void, + _userdata2: *mut ::std::os::raw::c_void, ) { - let message = unsafe { CStr::from_ptr(message) }.to_str().unwrap(); + let message = string_view_into_str(message).unwrap_or(""); log::warn!("Handling wgpu device lost errors as fatal by default"); panic!("wgpu device lost error:\n{message}\n"); } const DEFAULT_DEVICE_LOST_HANDLER: DeviceLostCallback = DeviceLostCallback { callback: Some(default_device_lost_handler), - userdata: std::ptr::null_mut(), + userdata: utils::Userdata::NULL, }; #[derive(Debug)] @@ -486,6 +497,7 @@ struct ErrorSinkRaw { scopes: Vec, uncaptured_handler: UncapturedErrorCallback, device_lost_handler: DeviceLostCallback, + device: Option, } impl ErrorSinkRaw { @@ -494,6 +506,7 @@ impl ErrorSinkRaw { scopes: Vec::new(), uncaptured_handler: DEFAULT_UNCAPTURED_ERROR_HANDLER, device_lost_handler, + device: None, } } @@ -502,13 +515,15 @@ impl ErrorSinkRaw { crate::Error::DeviceLost { .. } => { // handle device lost error early if let Some(callback) = self.device_lost_handler.callback { - let userdata = self.device_lost_handler.userdata; - let msg = CString::new(err.to_string()).unwrap(); + let userdata = &self.device_lost_handler.userdata; + let msg = err.to_string(); unsafe { callback( + &self.device.unwrap(), native::WGPUDeviceLostReason_Destroyed, - msg.as_ptr(), - userdata, + str_into_string_view(&msg), + userdata.get_1(), + userdata.get_2(), ); }; } @@ -537,9 +552,17 @@ impl ErrorSinkRaw { } None => { if let Some(callback) = self.uncaptured_handler.callback { - let userdata = self.uncaptured_handler.userdata; - let msg = CString::new(err.to_string()).unwrap(); - unsafe { callback(typ, msg.as_ptr(), userdata) }; + let userdata = &self.uncaptured_handler.userdata; + let msg = err.to_string(); + unsafe { + callback( + &self.device.unwrap(), + typ, + str_into_string_view(&msg), + userdata.get_1(), + userdata.get_2(), + ) + }; } } } @@ -626,10 +649,18 @@ pub unsafe extern "C" fn wgpuCreateInstance( descriptor: Option<&native::WGPUInstanceDescriptor>, ) -> native::WGPUInstance { let instance_desc = match descriptor { - Some(descriptor) => follow_chain!(map_instance_descriptor( - (descriptor), - WGPUSType_InstanceExtras => native::WGPUInstanceExtras - )), + Some(descriptor) => { + if descriptor.features.timedWaitAnyEnable != 0 + || descriptor.features.timedWaitAnyMaxCount > 0 + { + panic!("Unsupported timed WaitAny features specified"); + } + + follow_chain!(map_instance_descriptor( + (descriptor), + WGPUSType_InstanceExtras => native::WGPUInstanceExtras + )) + } None => wgt::InstanceDescriptor::default(), }; @@ -638,35 +669,53 @@ pub unsafe extern "C" fn wgpuCreateInstance( })) } +#[no_mangle] +pub unsafe extern "C" fn wgpuGetInstanceFeatures( + features: Option<&mut native::WGPUInstanceFeatures>, +) { + let features = features.expect("invalid return pointer \"features\""); + // WaitAny is currently completely unsupported, so... + features.timedWaitAnyEnable = false as native::WGPUBool; + features.timedWaitAnyMaxCount = 0; +} + // Adapter methods #[no_mangle] -pub unsafe extern "C" fn wgpuAdapterEnumerateFeatures( +pub unsafe extern "C" fn wgpuAdapterGetFeatures( adapter: native::WGPUAdapter, - features: *mut native::WGPUFeatureName, -) -> usize { + features: Option<&mut native::WGPUSupportedFeatures>, +) -> native::WGPUStatus { let (adapter_id, context) = { let adapter = adapter.as_ref().expect("invalid adapter"); (adapter.id, &adapter.context) }; + let features = features.expect("invalid return pointer \"features\""); + let adapter_features = match gfx_select!(adapter_id => context.adapter_features(adapter_id)) { Ok(features) => features, Err(err) => handle_error_fatal(err, "wgpuAdapterEnumerateFeatures"), }; - let temp = conv::features_to_native(adapter_features); + return_features(features, adapter_features); - if !features.is_null() { - std::ptr::copy_nonoverlapping(temp.as_ptr(), features, temp.len()); - } + native::WGPUStatus_Success +} + +fn return_features(native: &mut native::WGPUSupportedFeatures, features: wgt::Features) { + let temp = conv::features_to_native(features); + let mut temp = temp.into_boxed_slice(); + + native.featureCount = temp.len(); + native.features = temp.as_mut_ptr(); - temp.len() + mem::forget(temp); } #[no_mangle] pub unsafe extern "C" fn wgpuAdapterGetLimits( adapter: native::WGPUAdapter, - limits: Option<&mut native::WGPUSupportedLimits>, + limits: Option<&mut native::WGPULimits>, ) -> native::WGPUBool { let (adapter_id, context) = { let adapter = adapter.as_ref().expect("invalid adapter"); @@ -699,10 +748,10 @@ pub unsafe extern "C" fn wgpuAdapterGetInfo( Err(err) => handle_error_fatal(err, "wgpuAdapterGetInfo"), }; - info.vendor = CString::new(result.driver).unwrap().into_raw(); - info.architecture = CString::default().into_raw(); // TODO(webgpu.h) - info.device = CString::new(result.name).unwrap().into_raw(); - info.description = CString::new(result.driver_info).unwrap().into_raw(); + info.vendor = utils::str_into_owned_string_view(&result.driver); + info.architecture = EMPTY_STRING; // TODO(webgpu.h) + info.device = utils::str_into_owned_string_view(&result.name); + info.description = utils::str_into_owned_string_view(&result.driver_info); info.backendType = map_backend_type(result.backend); info.adapterType = map_adapter_type(result.device_type); info.vendorID = result.vendor; @@ -733,44 +782,36 @@ pub unsafe extern "C" fn wgpuAdapterHasFeature( #[no_mangle] pub unsafe extern "C" fn wgpuAdapterInfoFreeMembers(adapter_info: native::WGPUAdapterInfo) { - drop(CString::from_raw( - adapter_info.vendor as *mut std::ffi::c_char, - )); - drop(CString::from_raw( - adapter_info.architecture as *mut std::ffi::c_char, - )); - drop(CString::from_raw( - adapter_info.device as *mut std::ffi::c_char, - )); - drop(CString::from_raw( - adapter_info.description as *mut std::ffi::c_char, - )); + utils::drop_string_view(adapter_info.vendor); + utils::drop_string_view(adapter_info.architecture); + utils::drop_string_view(adapter_info.device); + utils::drop_string_view(adapter_info.description); } #[no_mangle] pub unsafe extern "C" fn wgpuAdapterRequestDevice( adapter: native::WGPUAdapter, descriptor: Option<&native::WGPUDeviceDescriptor>, - callback: native::WGPUAdapterRequestDeviceCallback, - userdata: *mut std::os::raw::c_void, -) { + callback_info: native::WGPURequestDeviceCallbackInfo, +) -> native::WGPUFuture { let (adapter_id, context) = { let adapter = adapter.as_ref().expect("invalid adapter"); (adapter.id, &adapter.context) }; - let callback = callback.expect("invalid callback"); + let callback = callback_info.callback.expect("invalid callback"); let adapter_limits = match gfx_select!(adapter_id => context.adapter_limits(adapter_id)) { Ok(adapter_limits) => adapter_limits, Err(cause) => { - let msg = CString::new(format_error(&cause)).unwrap(); + let msg = format_error(&cause); callback( native::WGPURequestDeviceStatus_Error, std::ptr::null(), - msg.as_ptr(), - userdata, + str_into_string_view(&msg), + callback_info.userdata1, + callback_info.userdata2, ); - return; + return NULL_FUTURE; } }; let base_limits = get_base_device_limits_from_adapter_limits(&adapter_limits); @@ -782,8 +823,8 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( WGPUSType_DeviceExtras => native::WGPUDeviceExtras) ); let device_lost_handler = DeviceLostCallback { - callback: descriptor.deviceLostCallback, - userdata: descriptor.deviceLostUserdata, + callback: descriptor.deviceLostCallbackInfo.callback, + userdata: new_userdata!(descriptor.deviceLostCallbackInfo), }; (desc, trace_str, device_lost_handler, error_callback) } @@ -792,7 +833,7 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( required_limits: base_limits, ..Default::default() }, - std::ptr::null(), + None, DEFAULT_DEVICE_LOST_HANDLER, None, ), @@ -802,48 +843,55 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( context.adapter_request_device( adapter_id, &desc, - ptr_into_path(trace_str), + trace_str.map(std::path::Path::new), None, None ) ); match err { None => { - let message = CString::default(); let mut error_sink = ErrorSinkRaw::new(device_lost_handler); if let Some(error_callback) = error_callback { error_sink.uncaptured_handler = error_callback; } + let error_sink = Arc::new(Mutex::new(error_sink)); + let device = Arc::into_raw(Arc::new(WGPUDeviceImpl { + context: context.clone(), + id: device_id, + queue: Arc::new(QueueId { + context: context.clone(), + id: queue_id, + }), + error_sink: error_sink.clone(), + })); + error_sink.lock().device = Some(device); + callback( native::WGPURequestDeviceStatus_Success, - Arc::into_raw(Arc::new(WGPUDeviceImpl { - context: context.clone(), - id: device_id, - queue: Arc::new(QueueId { - context: context.clone(), - id: queue_id, - }), - error_sink: Arc::new(Mutex::new(error_sink)), - })), - message.as_ptr(), - userdata, + device, + EMPTY_STRING, + callback_info.userdata1, + callback_info.userdata2, ); } Some(err) => { - let message = CString::new(format_error(&err)).unwrap(); + let message = format_error(&err); callback( native::WGPURequestDeviceStatus_Error, std::ptr::null_mut(), - message.as_ptr(), - userdata, + str_into_string_view(&message), + callback_info.userdata1, + callback_info.userdata2, ); } - } + }; + + return NULL_FUTURE; } #[no_mangle] -pub unsafe extern "C" fn wgpuAdapterReference(adapter: native::WGPUAdapter) { +pub unsafe extern "C" fn wgpuAdapterAddRef(adapter: native::WGPUAdapter) { assert!(!adapter.is_null(), "invalid adapter"); Arc::increment_strong_count(adapter); } @@ -856,7 +904,7 @@ pub unsafe extern "C" fn wgpuAdapterRelease(adapter: native::WGPUAdapter) { // BindGroup methods #[no_mangle] -pub unsafe extern "C" fn wgpuBindGroupReference(bind_group: native::WGPUBindGroup) { +pub unsafe extern "C" fn wgpuBindGroupAddRef(bind_group: native::WGPUBindGroup) { assert!(!bind_group.is_null(), "invalid bind group"); Arc::increment_strong_count(bind_group); } @@ -869,9 +917,7 @@ pub unsafe extern "C" fn wgpuBindGroupRelease(bind_group: native::WGPUBindGroup) // BindGroupLayout methods #[no_mangle] -pub unsafe extern "C" fn wgpuBindGroupLayoutReference( - bind_group_layout: native::WGPUBindGroupLayout, -) { +pub unsafe extern "C" fn wgpuBindGroupLayoutAddRef(bind_group_layout: native::WGPUBindGroupLayout) { assert!(!bind_group_layout.is_null(), "invalid bind group layout"); Arc::increment_strong_count(bind_group_layout); } @@ -954,9 +1000,7 @@ pub unsafe extern "C" fn wgpuBufferGetSize(buffer: native::WGPUBuffer) -> u64 { } #[no_mangle] -pub unsafe extern "C" fn wgpuBufferGetUsage( - buffer: native::WGPUBuffer, -) -> native::WGPUBufferUsageFlags { +pub unsafe extern "C" fn wgpuBufferGetUsage(buffer: native::WGPUBuffer) -> native::WGPUBufferUsage { let buffer = buffer.as_ref().expect("invalid buffer"); buffer.data.usage } @@ -964,18 +1008,17 @@ pub unsafe extern "C" fn wgpuBufferGetUsage( #[no_mangle] pub unsafe extern "C" fn wgpuBufferMapAsync( buffer: native::WGPUBuffer, - mode: native::WGPUMapModeFlags, + mode: native::WGPUMapMode, offset: usize, size: usize, - callback: native::WGPUBufferMapAsyncCallback, - userdata: *mut std::ffi::c_void, -) { + callback_info: native::WGPUBufferMapCallbackInfo, +) -> native::WGPUFuture { let (buffer_id, context, error_sink) = { let buffer = buffer.as_ref().expect("invalid buffer"); (buffer.id, &buffer.context, &buffer.error_sink) }; - let callback = callback.expect("invalid callback"); - let userdata = utils::Userdata::new(userdata); + let callback = callback_info.callback.expect("invalid callback"); + let userdata = new_userdata!(callback_info); let operation = wgc::resource::BufferMapOperation { host: match mode as native::WGPUMapMode { @@ -985,24 +1028,26 @@ pub unsafe extern "C" fn wgpuBufferMapAsync( }, callback: Some(wgc::resource::BufferMapCallback::from_rust(Box::new( move |result: resource::BufferAccessResult| { - let status = match result { - Ok(()) => native::WGPUBufferMapAsyncStatus_Success, - Err(resource::BufferAccessError::Device(_)) => { - native::WGPUBufferMapAsyncStatus_DeviceLost - } - Err(resource::BufferAccessError::MapAlreadyPending) => { - native::WGPUBufferMapAsyncStatus_MappingAlreadyPending + let (status, message) = match result { + Ok(()) => (native::WGPUMapAsyncStatus_Success, String::default()), + Err(cause) => { + let code = match cause { + resource::BufferAccessError::MapAborted => { + native::WGPUMapAsyncStatus_Aborted + } + _ => native::WGPUMapAsyncStatus_Error, + }; + + (code, format_error(&cause)) } - Err(resource::BufferAccessError::InvalidBufferId(_)) - | Err(resource::BufferAccessError::DestroyedResource(_)) => { - native::WGPUBufferMapAsyncStatus_DestroyedBeforeCallback - } - Err(_) => native::WGPUBufferMapAsyncStatus_ValidationError, - // TODO: WGPUBufferMapAsyncStatus_OffsetOutOfRange - // TODO: WGPUBufferMapAsyncStatus_SizeOutOfRange }; - callback(status, userdata.as_ptr()); + callback( + status, + str_into_string_view(&message), + userdata.get_1(), + userdata.get_2(), + ); }, ))), }; @@ -1015,6 +1060,9 @@ pub unsafe extern "C" fn wgpuBufferMapAsync( )) { handle_error(error_sink, cause, None, "wgpuBufferMapAsync"); }; + + // TODO: Properly handle futures. + return NULL_FUTURE; } #[no_mangle] @@ -1030,7 +1078,7 @@ pub unsafe extern "C" fn wgpuBufferUnmap(buffer: native::WGPUBuffer) { } #[no_mangle] -pub unsafe extern "C" fn wgpuBufferReference(buffer: native::WGPUBuffer) { +pub unsafe extern "C" fn wgpuBufferAddRef(buffer: native::WGPUBuffer) { assert!(!buffer.is_null(), "invalid buffer"); Arc::increment_strong_count(buffer); } @@ -1043,7 +1091,7 @@ pub unsafe extern "C" fn wgpuBufferRelease(buffer: native::WGPUBuffer) { // CommandBuffer methods #[no_mangle] -pub unsafe extern "C" fn wgpuCommandBufferReference(command_buffer: native::WGPUCommandBuffer) { +pub unsafe extern "C" fn wgpuCommandBufferAddRef(command_buffer: native::WGPUCommandBuffer) { assert!(!command_buffer.is_null(), "invalid command buffer"); Arc::increment_strong_count(command_buffer); } @@ -1087,7 +1135,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderBeginComputePass( let desc = match descriptor { Some(descriptor) => wgc::command::ComputePassDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), timestamp_writes: timestamp_writes.as_ref(), }, None => wgc::command::ComputePassDescriptor::default(), @@ -1164,7 +1212,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderBeginRenderPass( }); let desc = wgc::command::RenderPassDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), color_attachments: Cow::Owned( make_slice(descriptor.colorAttachments, descriptor.colorAttachmentCount) .iter() @@ -1387,7 +1435,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderFinish( let desc = match descriptor { Some(descriptor) => wgt::CommandBufferDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), }, None => wgt::CommandBufferDescriptor::default(), }; @@ -1407,7 +1455,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderFinish( #[no_mangle] pub unsafe extern "C" fn wgpuCommandEncoderInsertDebugMarker( command_encoder: native::WGPUCommandEncoder, - marker_label: *const std::ffi::c_char, + marker_label: native::WGPUStringView, ) { let (command_encoder_id, context, error_sink) = { let command_encoder = command_encoder.as_ref().expect("invalid command encoder"); @@ -1418,7 +1466,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderInsertDebugMarker( ) }; - if let Err(cause) = gfx_select!(command_encoder_id => context.command_encoder_insert_debug_marker(command_encoder_id, CStr::from_ptr(marker_label).to_str().unwrap())) + if let Err(cause) = gfx_select!(command_encoder_id => context.command_encoder_insert_debug_marker(command_encoder_id, string_view_into_str(marker_label).unwrap_or(""))) { handle_error( error_sink, @@ -1451,7 +1499,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderPopDebugGroup( #[no_mangle] pub unsafe extern "C" fn wgpuCommandEncoderPushDebugGroup( command_encoder: native::WGPUCommandEncoder, - group_label: *const std::ffi::c_char, + group_label: native::WGPUStringView, ) { let (command_encoder_id, context, error_sink) = { let command_encoder = command_encoder.as_ref().expect("invalid command encoder"); @@ -1462,7 +1510,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderPushDebugGroup( ) }; - if let Err(cause) = gfx_select!(command_encoder_id => context.command_encoder_push_debug_group(command_encoder_id, CStr::from_ptr(group_label).to_str().unwrap())) + if let Err(cause) = gfx_select!(command_encoder_id => context.command_encoder_push_debug_group(command_encoder_id, string_view_into_str(group_label).unwrap_or(""))) { handle_error(error_sink, cause, None, "wgpuCommandEncoderPushDebugGroup"); } @@ -1526,7 +1574,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderWriteTimestamp( } #[no_mangle] -pub unsafe extern "C" fn wgpuCommandEncoderReference(command_encoder: native::WGPUCommandEncoder) { +pub unsafe extern "C" fn wgpuCommandEncoderAddRef(command_encoder: native::WGPUCommandEncoder) { assert!(!command_encoder.is_null(), "invalid command encoder"); Arc::increment_strong_count(command_encoder); } @@ -1603,14 +1651,14 @@ pub unsafe extern "C" fn wgpuComputePassEncoderEnd(pass: native::WGPUComputePass #[no_mangle] pub unsafe extern "C" fn wgpuComputePassEncoderInsertDebugMarker( pass: native::WGPUComputePassEncoder, - marker_label: *const std::ffi::c_char, + marker_label: native::WGPUStringView, ) { let pass = pass.as_ref().expect("invalid compute pass"); let encoder = pass.encoder.as_mut().unwrap(); match encoder.insert_debug_marker( &pass.context, - CStr::from_ptr(marker_label).to_str().unwrap(), + string_view_into_str(marker_label).unwrap_or(""), 0, ) { Ok(()) => (), @@ -1642,14 +1690,14 @@ pub unsafe extern "C" fn wgpuComputePassEncoderPopDebugGroup(pass: native::WGPUC #[no_mangle] pub unsafe extern "C" fn wgpuComputePassEncoderPushDebugGroup( pass: native::WGPUComputePassEncoder, - group_label: *const std::ffi::c_char, + group_label: native::WGPUStringView, ) { let pass = pass.as_ref().expect("invalid compute pass"); let encoder = pass.encoder.as_mut().unwrap(); match encoder.push_debug_group( &pass.context, - CStr::from_ptr(group_label).to_str().unwrap(), + string_view_into_str(group_label).unwrap_or(""), 0, ) { Ok(()) => (), @@ -1715,7 +1763,7 @@ pub unsafe extern "C" fn wgpuComputePassEncoderSetPipeline( } #[no_mangle] -pub unsafe extern "C" fn wgpuComputePassEncoderReference( +pub unsafe extern "C" fn wgpuComputePassEncoderAddRef( compute_pass_encoder: native::WGPUComputePassEncoder, ) { assert!( @@ -1764,9 +1812,7 @@ pub unsafe extern "C" fn wgpuComputePipelineGetBindGroupLayout( } #[no_mangle] -pub unsafe extern "C" fn wgpuComputePipelineReference( - compute_pipeline: native::WGPUComputePipeline, -) { +pub unsafe extern "C" fn wgpuComputePipelineAddRef(compute_pipeline: native::WGPUComputePipeline) { assert!(!compute_pipeline.is_null(), "invalid command pipeline"); Arc::increment_strong_count(compute_pipeline); } @@ -1804,7 +1850,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateBindGroup( .collect::>(); let desc = wgc::binding_model::BindGroupDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), layout: bind_group_layout_id, entries: Cow::Borrowed(&entries), }; @@ -1841,7 +1887,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateBindGroupLayout( .collect::>(); let desc = wgc::binding_model::BindGroupLayoutDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), entries: Cow::Borrowed(&entries), }; let (bind_group_layout_id, error) = @@ -1873,9 +1919,9 @@ pub unsafe extern "C" fn wgpuDeviceCreateBuffer( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgt::BufferDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), size: descriptor.size, - usage: wgt::BufferUsages::from_bits(descriptor.usage).expect("invalid buffer usage"), + usage: from_u64_bits(descriptor.usage).expect("invalid buffer usage"), mapped_at_creation: descriptor.mappedAtCreation != 0, }; @@ -1907,7 +1953,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateCommandEncoder( }; let desc = match descriptor { Some(descriptor) => wgt::CommandEncoderDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), }, None => wgt::CommandEncoderDescriptor::default(), }; @@ -1942,7 +1988,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateComputePipeline( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::pipeline::ComputePipelineDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), layout: descriptor.layout.as_ref().map(|v| v.id), stage: wgc::pipeline::ProgrammableStageDescriptor { module: descriptor @@ -1952,7 +1998,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateComputePipeline( .expect("invalid fragment shader module for render pipeline descriptor") .id .expect("invalid fragment shader module for render pipeline descriptor"), - entry_point: ptr_into_label(descriptor.compute.entryPoint), + entry_point: string_view_into_label(descriptor.compute.entryPoint), constants: Cow::Owned( make_slice( descriptor.compute.constants, @@ -1961,7 +2007,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateComputePipeline( .iter() .map(|entry| { ( - CStr::from_ptr(entry.key).to_str().unwrap().to_string(), + string_view_into_str(entry.key).unwrap_or("").to_string(), entry.value, ) }) @@ -2084,7 +2130,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderBundleEncoder( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::command::RenderBundleEncoderDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), color_formats: make_slice(descriptor.colorFormats, descriptor.colorFormatCount) .iter() .map(|format| conv::map_texture_format(*format)) @@ -2123,7 +2169,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::pipeline::RenderPipelineDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), layout: descriptor.layout.as_ref().map(|v| v.id), vertex: wgc::pipeline::VertexState { stage: wgc::pipeline::ProgrammableStageDescriptor { @@ -2134,13 +2180,13 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( .expect("invalid vertex shader module for vertex state") .id .expect("invalid vertex shader module for vertex state"), - entry_point: ptr_into_label(descriptor.vertex.entryPoint), + entry_point: string_view_into_label(descriptor.vertex.entryPoint), constants: Cow::Owned( make_slice(descriptor.vertex.constants, descriptor.vertex.constantCount) .iter() .map(|entry| { ( - CStr::from_ptr(entry.key).to_str().unwrap().to_string(), + string_view_into_str(entry.key).unwrap_or("").to_string(), entry.value, ) }) @@ -2177,37 +2223,46 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( ), }, primitive: wgt::PrimitiveState { - topology: conv::map_primitive_topology(descriptor.primitive.topology), + topology: conv::map_primitive_topology(descriptor.primitive.topology) + .unwrap_or(wgt::PrimitiveTopology::TriangleList), strip_index_format: conv::map_index_format(descriptor.primitive.stripIndexFormat).ok(), front_face: match descriptor.primitive.frontFace { - native::WGPUFrontFace_CCW => wgt::FrontFace::Ccw, + native::WGPUFrontFace_CCW | native::WGPUFrontFace_Undefined => wgt::FrontFace::Ccw, native::WGPUFrontFace_CW => wgt::FrontFace::Cw, _ => panic!("invalid front face for primitive state"), }, cull_mode: match descriptor.primitive.cullMode { - native::WGPUCullMode_None => None, + native::WGPUCullMode_None | native::WGPUCullMode_Undefined => None, native::WGPUCullMode_Front => Some(wgt::Face::Front), native::WGPUCullMode_Back => Some(wgt::Face::Back), _ => panic!("invalid cull mode for primitive state"), }, - unclipped_depth: follow_chain!( - map_primitive_state( - (&descriptor.primitive), - WGPUSType_PrimitiveDepthClipControl => native::WGPUPrimitiveDepthClipControl - ) - ), + unclipped_depth: descriptor.primitive.unclippedDepth != 0, polygon_mode: wgt::PolygonMode::Fill, conservative: false, }, - depth_stencil: descriptor - .depthStencil - .as_ref() - .map(|desc| wgt::DepthStencilState { - format: conv::map_texture_format(desc.format) - .expect("invalid texture format for depth stencil state"), - depth_write_enabled: desc.depthWriteEnabled != 0, + depth_stencil: descriptor.depthStencil.as_ref().map(|desc| { + let format = conv::map_texture_format(desc.format) + .expect("invalid texture format for depth stencil state"); + + // Validation per spec. + if texture_format_has_depth(format) { + if desc.depthWriteEnabled == native::WGPUOptionalBool_Undefined { + panic!("Depth write not specified for depth format") + } + } else { + if desc.depthWriteEnabled == native::WGPUOptionalBool_True { + panic!("Depth write enabled for non-depth format") + } + } + + wgt::DepthStencilState { + format, + depth_write_enabled: desc.depthWriteEnabled == native::WGPUOptionalBool_True, + // TODO: Is validation correct if we return always for undefined depth compare? depth_compare: conv::map_compare_function(desc.depthCompare) - .expect("invalid depth compare function for depth stencil state"), + .expect("invalid depth compare function for depth stencil state") + .unwrap_or(wgt::CompareFunction::Always), stencil: wgt::StencilState { front: conv::map_stencil_face_state(desc.stencilFront, "front"), back: conv::map_stencil_face_state(desc.stencilBack, "back"), @@ -2219,7 +2274,8 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( slope_scale: desc.depthBiasSlopeScale, clamp: desc.depthBiasClamp, }, - }), + } + }), multisample: wgt::MultisampleState { count: descriptor.multisample.count, mask: descriptor.multisample.mask as u64, @@ -2236,13 +2292,13 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( .expect("invalid fragment shader module for render pipeline descriptor") .id .expect("invalid fragment shader module for render pipeline descriptor"), - entry_point: ptr_into_label(fragment.entryPoint), + entry_point: string_view_into_label(fragment.entryPoint), constants: Cow::Owned( make_slice(fragment.constants, fragment.constantCount) .iter() .map(|entry| { ( - CStr::from_ptr(entry.key).to_str().unwrap().to_string(), + string_view_into_str(entry.key).unwrap_or("").to_string(), entry.value, ) }) @@ -2266,8 +2322,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( alpha: conv::map_blend_component(blend.alpha), } }), - write_mask: wgt::ColorWrites::from_bits(color_target.writeMask) - .unwrap(), + write_mask: from_u64_bits(color_target.writeMask).unwrap(), } }) }) @@ -2313,18 +2368,25 @@ pub unsafe extern "C" fn wgpuDeviceCreateSampler( let desc = match descriptor { Some(descriptor) => wgc::resource::SamplerDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), address_modes: [ - conv::map_address_mode(descriptor.addressModeU), - conv::map_address_mode(descriptor.addressModeV), - conv::map_address_mode(descriptor.addressModeW), + conv::map_address_mode(descriptor.addressModeU) + .unwrap_or(wgt::AddressMode::ClampToEdge), + conv::map_address_mode(descriptor.addressModeV) + .unwrap_or(wgt::AddressMode::ClampToEdge), + conv::map_address_mode(descriptor.addressModeW) + .unwrap_or(wgt::AddressMode::ClampToEdge), ], - mag_filter: conv::map_filter_mode(descriptor.magFilter), - min_filter: conv::map_filter_mode(descriptor.minFilter), - mipmap_filter: conv::map_mipmap_filter_mode(descriptor.mipmapFilter), + mag_filter: conv::map_filter_mode(descriptor.magFilter) + .unwrap_or(wgt::FilterMode::Nearest), + min_filter: conv::map_filter_mode(descriptor.minFilter) + .unwrap_or(wgt::FilterMode::Nearest), + mipmap_filter: conv::map_mipmap_filter_mode(descriptor.mipmapFilter) + .unwrap_or(wgt::FilterMode::Nearest), lod_min_clamp: descriptor.lodMinClamp, lod_max_clamp: descriptor.lodMaxClamp, - compare: conv::map_compare_function(descriptor.compare).ok(), + compare: conv::map_compare_function(descriptor.compare) + .expect("Invalid compare function"), anisotropy_clamp: descriptor.maxAnisotropy, // TODO(wgpu.h) border_color: None, @@ -2374,14 +2436,14 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::pipeline::ShaderModuleDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), shader_bound_checks: wgt::ShaderBoundChecks::default(), }; let source = match follow_chain!( map_shader_module((descriptor), - WGPUSType_ShaderModuleSPIRVDescriptor => native::WGPUShaderModuleSPIRVDescriptor, - WGPUSType_ShaderModuleWGSLDescriptor => native::WGPUShaderModuleWGSLDescriptor, + WGPUSType_ShaderSourceSPIRV => native::WGPUShaderSourceSPIRV, + WGPUSType_ShaderSourceWGSL => native::WGPUShaderSourceWGSL, WGPUSType_ShaderModuleGLSLDescriptor => native::WGPUShaderModuleGLSLDescriptor) ) { Ok(source) => source, @@ -2428,14 +2490,15 @@ pub unsafe extern "C" fn wgpuDeviceCreateTexture( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgt::TextureDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), size: conv::map_extent3d(&descriptor.size), mip_level_count: descriptor.mipLevelCount, sample_count: descriptor.sampleCount, - dimension: conv::map_texture_dimension(descriptor.dimension), + dimension: conv::map_texture_dimension(descriptor.dimension) + .unwrap_or(wgt::TextureDimension::D2), format: conv::map_texture_format(descriptor.format) .expect("invalid texture format for texture descriptor"), - usage: wgt::TextureUsages::from_bits(descriptor.usage) + usage: from_u64_bits(descriptor.usage) .expect("invalid texture usage for texture descriptor"), view_formats: make_slice(descriptor.viewFormats, descriptor.viewFormatCount) .iter() @@ -2474,32 +2537,42 @@ pub extern "C" fn wgpuDeviceDestroy(_device: native::WGPUDevice) { } #[no_mangle] -pub unsafe extern "C" fn wgpuDeviceEnumerateFeatures( +pub unsafe extern "C" fn wgpuDeviceGetFeatures( device: native::WGPUDevice, - features: *mut native::WGPUFeatureName, -) -> usize { + features: Option<&mut native::WGPUSupportedFeatures>, +) -> native::WGPUStatus { let (device_id, context) = { let device = device.as_ref().expect("invalid device"); (device.id, &device.context) }; + let features = features.expect("invalid return pointer \"features\""); + let device_features = match gfx_select!(device_id => context.device_features(device_id)) { Ok(features) => features, Err(err) => handle_error_fatal(err, "wgpuDeviceEnumerateFeatures"), }; - let temp = conv::features_to_native(device_features); + return_features(features, device_features); - if !features.is_null() { - std::ptr::copy_nonoverlapping(temp.as_ptr(), features, temp.len()); - } + native::WGPUStatus_Success +} - temp.len() +#[no_mangle] +pub unsafe extern "C" fn wgpuSupportedFeaturesFreeMembers( + supported_features: native::WGPUSupportedFeatures, +) { + if !supported_features.features.is_null() && supported_features.featureCount > 0 { + drop(Box::from_raw(slice::from_raw_parts_mut( + supported_features.features as *mut native::WGPUFeatureName, + supported_features.featureCount, + ))) + } } #[no_mangle] pub unsafe extern "C" fn wgpuDeviceGetLimits( device: native::WGPUDevice, - limits: Option<&mut native::WGPUSupportedLimits>, + limits: Option<&mut native::WGPULimits>, ) -> native::WGPUBool { let (device_id, context) = { let device = device.as_ref().expect("invalid device"); @@ -2554,11 +2627,10 @@ pub unsafe extern "C" fn wgpuDeviceHasFeature( #[no_mangle] pub unsafe extern "C" fn wgpuDevicePopErrorScope( device: native::WGPUDevice, - callback: native::WGPUErrorCallback, - userdata: *mut ::std::os::raw::c_void, -) { + callback_info: native::WGPUPopErrorScopeCallbackInfo, +) -> native::WGPUFuture { let device = device.as_ref().expect("invalid device"); - let callback = callback.expect("invalid callback"); + let callback = callback_info.callback.expect("invalid callback"); let mut error_sink = device.error_sink.lock(); let scope = error_sink.scopes.pop().unwrap(); @@ -2572,18 +2644,31 @@ pub unsafe extern "C" fn wgpuDevicePopErrorScope( crate::Error::DeviceLost { .. } => unreachable!(), }; - let msg = CString::new(error.to_string()).unwrap(); + let msg = error.to_string(); unsafe { - callback(typ, msg.as_ptr(), userdata); + callback( + native::WGPUPopErrorScopeStatus_Success, + typ, + str_into_string_view(&msg), + callback_info.userdata1, + callback_info.userdata2, + ); }; } None => { - let msg = CString::default(); unsafe { - callback(native::WGPUErrorType_NoError, msg.as_ptr(), userdata); + callback( + native::WGPUPopErrorScopeStatus_Success, + native::WGPUErrorType_NoError, + EMPTY_STRING, + callback_info.userdata1, + callback_info.userdata2, + ); }; } }; + + return NULL_FUTURE; } #[no_mangle] @@ -2604,7 +2689,7 @@ pub unsafe extern "C" fn wgpuDevicePushErrorScope( } #[no_mangle] -pub unsafe extern "C" fn wgpuDeviceReference(device: native::WGPUDevice) { +pub unsafe extern "C" fn wgpuDeviceAddRef(device: native::WGPUDevice) { assert!(!device.is_null(), "invalid device"); Arc::increment_strong_count(device); } @@ -2626,12 +2711,12 @@ pub unsafe extern "C" fn wgpuInstanceCreateSurface( let create_surface_params = follow_chain!( map_surface((descriptor), - WGPUSType_SurfaceDescriptorFromWindowsHWND => native::WGPUSurfaceDescriptorFromWindowsHWND, - WGPUSType_SurfaceDescriptorFromXcbWindow => native::WGPUSurfaceDescriptorFromXcbWindow, - WGPUSType_SurfaceDescriptorFromXlibWindow => native::WGPUSurfaceDescriptorFromXlibWindow, - WGPUSType_SurfaceDescriptorFromWaylandSurface => native::WGPUSurfaceDescriptorFromWaylandSurface, - WGPUSType_SurfaceDescriptorFromMetalLayer => native::WGPUSurfaceDescriptorFromMetalLayer, - WGPUSType_SurfaceDescriptorFromAndroidNativeWindow => native::WGPUSurfaceDescriptorFromAndroidNativeWindow) + WGPUSType_SurfaceSourceWindowsHWND => native::WGPUSurfaceSourceWindowsHWND, + WGPUSType_SurfaceSourceXCBWindow => native::WGPUSurfaceSourceXCBWindow, + WGPUSType_SurfaceSourceXlibWindow => native::WGPUSurfaceSourceXlibWindow, + WGPUSType_SurfaceSourceWaylandSurface => native::WGPUSurfaceSourceWaylandSurface, + WGPUSType_SurfaceSourceMetalLayer => native::WGPUSurfaceSourceMetalLayer, + WGPUSType_SurfaceSourceAndroidNativeWindow => native::WGPUSurfaceSourceAndroidNativeWindow) ); let surface_id = match create_surface_params { @@ -2662,12 +2747,11 @@ pub unsafe extern "C" fn wgpuInstanceCreateSurface( pub unsafe extern "C" fn wgpuInstanceRequestAdapter( instance: native::WGPUInstance, options: Option<&native::WGPURequestAdapterOptions>, - callback: native::WGPUInstanceRequestAdapterCallback, - userdata: *mut std::os::raw::c_void, -) { + callback_info: native::WGPURequestAdapterCallbackInfo, +) -> native::WGPUFuture { let instance = instance.as_ref().expect("invalid instance"); let context = &instance.context; - let callback = callback.expect("invalid callback"); + let callback = callback_info.callback.expect("invalid callback"); let (desc, inputs) = match options { Some(options) => ( @@ -2696,10 +2780,12 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter( callback( native::WGPURequestAdapterStatus_Error, std::ptr::null_mut(), - "unsupported backend type: d3d11".as_ptr() as _, - userdata, + str_into_string_view("unsupported backend type: d3d11"), + callback_info.userdata1, + callback_info.userdata2, ); - return; + + return NULL_FUTURE; } backend_type => panic!("invalid backend type: 0x{backend_type:08X}"), }, @@ -2714,19 +2800,19 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter( match context.request_adapter(&desc, inputs) { Ok(adapter_id) => { - let message = CString::default(); callback( native::WGPURequestAdapterStatus_Success, Arc::into_raw(Arc::new(WGPUAdapterImpl { context: context.clone(), id: adapter_id, })), - message.as_ptr(), - userdata, + EMPTY_STRING, + callback_info.userdata1, + callback_info.userdata2, ); } Err(err) => { - let message = CString::new(format_error(&err)).unwrap(); + let message = format_error(&err); callback( match err { wgc::instance::RequestAdapterError::NotFound => { @@ -2738,11 +2824,14 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter( _ => native::WGPURequestAdapterStatus_Unknown, }, std::ptr::null_mut(), - message.as_ptr(), - userdata, + str_into_string_view(&message), + callback_info.userdata1, + callback_info.userdata2, ); } }; + + return NULL_FUTURE; } #[no_mangle] @@ -2789,7 +2878,7 @@ pub unsafe extern "C" fn wgpuInstanceEnumerateAdapters( } #[no_mangle] -pub unsafe extern "C" fn wgpuInstanceReference(instance: native::WGPUInstance) { +pub unsafe extern "C" fn wgpuInstanceAddRef(instance: native::WGPUInstance) { assert!(!instance.is_null(), "invalid instance"); Arc::increment_strong_count(instance); } @@ -2802,7 +2891,7 @@ pub unsafe extern "C" fn wgpuInstanceRelease(instance: native::WGPUInstance) { // PipelineLayout methods #[no_mangle] -pub unsafe extern "C" fn wgpuPipelineLayoutReference(pipeline_layout: native::WGPUPipelineLayout) { +pub unsafe extern "C" fn wgpuPipelineLayoutAddRef(pipeline_layout: native::WGPUPipelineLayout) { assert!(!pipeline_layout.is_null(), "invalid pipeline layout"); Arc::increment_strong_count(pipeline_layout); } @@ -2834,7 +2923,7 @@ pub unsafe extern "C" fn wgpuQuerySetGetType( } #[no_mangle] -pub unsafe extern "C" fn wgpuQuerySetReference(query_set: native::WGPUQuerySet) { +pub unsafe extern "C" fn wgpuQuerySetAddRef(query_set: native::WGPUQuerySet) { assert!(!query_set.is_null(), "invalid query set"); Arc::increment_strong_count(query_set); } @@ -2849,18 +2938,21 @@ pub unsafe extern "C" fn wgpuQuerySetRelease(query_set: native::WGPUQuerySet) { #[no_mangle] pub unsafe extern "C" fn wgpuQueueOnSubmittedWorkDone( queue: native::WGPUQueue, - callback: native::WGPUQueueOnSubmittedWorkDoneCallback, - userdata: *mut ::std::os::raw::c_void, -) { + callback_info: native::WGPUQueueWorkDoneCallbackInfo, +) -> native::WGPUFuture { let (queue_id, context) = { let queue = queue.as_ref().expect("invalid queue"); (queue.queue.id, &queue.queue.context) }; - let callback = callback.expect("invalid callback"); - let userdata = utils::Userdata::new(userdata); + let callback = callback_info.callback.expect("invalid callback"); + let userdata = new_userdata!(callback_info); let closure = wgc::device::queue::SubmittedWorkDoneClosure::from_rust(Box::new(move || { - callback(native::WGPUQueueWorkDoneStatus_Success, userdata.as_ptr()); + callback( + native::WGPUQueueWorkDoneStatus_Success, + userdata.get_1(), + userdata.get_2(), + ); })); if let Err(cause) = @@ -2868,6 +2960,9 @@ pub unsafe extern "C" fn wgpuQueueOnSubmittedWorkDone( { handle_error_fatal(cause, "wgpuQueueOnSubmittedWorkDone"); }; + + // TODO: Properly handle futures. + return NULL_FUTURE; } #[no_mangle] @@ -2945,7 +3040,7 @@ pub unsafe extern "C" fn wgpuQueueWriteTexture( } #[no_mangle] -pub unsafe extern "C" fn wgpuQueueReference(queue: native::WGPUQueue) { +pub unsafe extern "C" fn wgpuQueueAddRef(queue: native::WGPUQueue) { assert!(!queue.is_null(), "invalid queue"); Arc::increment_strong_count(queue); } @@ -2958,7 +3053,7 @@ pub unsafe extern "C" fn wgpuQueueRelease(queue: native::WGPUQueue) { // RenderBundle methods #[no_mangle] -pub unsafe extern "C" fn wgpuRenderBundleReference(render_bundle: native::WGPURenderBundle) { +pub unsafe extern "C" fn wgpuRenderBundleAddRef(render_bundle: native::WGPURenderBundle) { assert!(!render_bundle.is_null(), "invalid render bundle"); Arc::increment_strong_count(render_bundle); } @@ -3069,7 +3164,7 @@ pub unsafe extern "C" fn wgpuRenderBundleEncoderFinish( let desc = match descriptor { Some(descriptor) => wgt::RenderBundleDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), }, None => wgt::RenderBundleDescriptor::default(), }; @@ -3087,40 +3182,49 @@ pub unsafe extern "C" fn wgpuRenderBundleEncoderFinish( #[no_mangle] pub unsafe extern "C" fn wgpuRenderBundleEncoderInsertDebugMarker( - bundle: native::WGPURenderBundleEncoder, - marker_label: *const std::ffi::c_char, + _bundle: native::WGPURenderBundleEncoder, + _marker_label: native::WGPUStringView, ) { - let bundle = bundle.as_ref().expect("invalid render bundle"); - let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); - let encoder = encoder.expect("invalid render bundle"); - let encoder = encoder.as_mut().unwrap(); + // These functions are not implemented in wgpu-core, and the API is incompatible with the new WGPUStringView. + // Commenting out until it's actually implemented. + + // let bundle = bundle.as_ref().expect("invalid render bundle"); + // let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); + // let encoder = encoder.expect("invalid render bundle"); + // let encoder = encoder.as_mut().unwrap(); - bundle_ffi::wgpu_render_bundle_insert_debug_marker(encoder, marker_label); + // bundle_ffi::wgpu_render_bundle_insert_debug_marker(encoder, marker_label); } #[no_mangle] pub unsafe extern "C" fn wgpuRenderBundleEncoderPopDebugGroup( - bundle: native::WGPURenderBundleEncoder, + _bundle: native::WGPURenderBundleEncoder, ) { - let bundle = bundle.as_ref().expect("invalid render bundle"); - let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); - let encoder = encoder.expect("invalid render bundle"); - let encoder = encoder.as_mut().unwrap(); + // These functions are not implemented in wgpu-core, and the API is incompatible with the new WGPUStringView. + // Commenting out until it's actually implemented. - bundle_ffi::wgpu_render_bundle_pop_debug_group(encoder); + // let bundle = bundle.as_ref().expect("invalid render bundle"); + // let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); + // let encoder = encoder.expect("invalid render bundle"); + // let encoder = encoder.as_mut().unwrap(); + + // bundle_ffi::wgpu_render_bundle_pop_debug_group(encoder); } #[no_mangle] pub unsafe extern "C" fn wgpuRenderBundleEncoderPushDebugGroup( - bundle: native::WGPURenderBundleEncoder, - group_label: *const std::ffi::c_char, + _bundle: native::WGPURenderBundleEncoder, + _group_label: native::WGPUStringView, ) { - let bundle = bundle.as_ref().expect("invalid render bundle"); - let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); - let encoder = encoder.expect("invalid render bundle"); - let encoder = encoder.as_mut().unwrap(); + // These functions are not implemented in wgpu-core, and the API is incompatible with the new WGPUStringView. + // Commenting out until it's actually implemented. - bundle_ffi::wgpu_render_bundle_push_debug_group(encoder, group_label); + // let bundle = bundle.as_ref().expect("invalid render bundle"); + // let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); + // let encoder = encoder.expect("invalid render bundle"); + // let encoder = encoder.as_mut().unwrap(); + + // bundle_ffi::wgpu_render_bundle_push_debug_group(encoder, group_label); } #[no_mangle] @@ -3217,7 +3321,7 @@ pub unsafe extern "C" fn wgpuRenderBundleEncoderSetVertexBuffer( } #[no_mangle] -pub unsafe extern "C" fn wgpuRenderBundleEncoderReference( +pub unsafe extern "C" fn wgpuRenderBundleEncoderAddRef( render_bundle_encoder: native::WGPURenderBundleEncoder, ) { assert!( @@ -3415,14 +3519,14 @@ pub unsafe extern "C" fn wgpuRenderPassEncoderExecuteBundles( #[no_mangle] pub unsafe extern "C" fn wgpuRenderPassEncoderInsertDebugMarker( pass: native::WGPURenderPassEncoder, - marker_label: *const std::ffi::c_char, + marker_label: native::WGPUStringView, ) { let pass = pass.as_ref().expect("invalid render pass"); let encoder = pass.encoder.as_mut().unwrap(); match encoder.insert_debug_marker( &pass.context, - CStr::from_ptr(marker_label).to_str().unwrap(), + string_view_into_str(marker_label).unwrap_or(""), 0, ) { Ok(()) => (), @@ -3454,14 +3558,14 @@ pub unsafe extern "C" fn wgpuRenderPassEncoderPopDebugGroup(pass: native::WGPURe #[no_mangle] pub unsafe extern "C" fn wgpuRenderPassEncoderPushDebugGroup( pass: native::WGPURenderPassEncoder, - group_label: *const std::ffi::c_char, + group_label: native::WGPUStringView, ) { let pass = pass.as_ref().expect("invalid render pass"); let encoder = pass.encoder.as_mut().unwrap(); match encoder.push_debug_group( &pass.context, - CStr::from_ptr(group_label).to_str().unwrap(), + string_view_into_str(group_label).unwrap_or(""), 0, ) { Ok(()) => (), @@ -3681,7 +3785,7 @@ pub unsafe extern "C" fn wgpuRenderPassEncoderSetViewport( } #[no_mangle] -pub unsafe extern "C" fn wgpuRenderPassEncoderReference( +pub unsafe extern "C" fn wgpuRenderPassEncoderAddRef( render_pass_encoder: native::WGPURenderPassEncoder, ) { assert!( @@ -3733,7 +3837,7 @@ pub unsafe extern "C" fn wgpuRenderPipelineGetBindGroupLayout( } #[no_mangle] -pub unsafe extern "C" fn wgpuRenderPipelineReference(render_pipeline: native::WGPURenderPipeline) { +pub unsafe extern "C" fn wgpuRenderPipelineAddRef(render_pipeline: native::WGPURenderPipeline) { assert!(!render_pipeline.is_null(), "invalid render pipeline"); Arc::increment_strong_count(render_pipeline); } @@ -3746,7 +3850,7 @@ pub unsafe extern "C" fn wgpuRenderPipelineRelease(render_pipeline: native::WGPU // Sampler methods #[no_mangle] -pub unsafe extern "C" fn wgpuSamplerReference(sampler: native::WGPUSampler) { +pub unsafe extern "C" fn wgpuSamplerAddRef(sampler: native::WGPUSampler) { assert!(!sampler.is_null(), "invalid sampler"); Arc::increment_strong_count(sampler); } @@ -3759,7 +3863,7 @@ pub unsafe extern "C" fn wgpuSamplerRelease(sampler: native::WGPUSampler) { // ShaderModule methods #[no_mangle] -pub unsafe extern "C" fn wgpuShaderModuleReference(shader_module: native::WGPUShaderModule) { +pub unsafe extern "C" fn wgpuShaderModuleAddRef(shader_module: native::WGPUShaderModule) { assert!(!shader_module.is_null(), "invalid shader module"); Arc::increment_strong_count(shader_module); } @@ -3840,7 +3944,7 @@ pub unsafe extern "C" fn wgpuSurfaceGetCapabilities( }; capabilities.usages = - conv::to_native_texture_usage_flags(caps.usages) as native::WGPUTextureUsageFlags; + conv::to_native_texture_usage_flags(caps.usages) as native::WGPUTextureUsage; let formats = caps .formats @@ -3919,18 +4023,16 @@ pub unsafe extern "C" fn wgpuSurfaceGetCurrentTexture( .has_surface_presented .store(false, atomic::Ordering::SeqCst); surface_texture.status = match status { - wgt::SurfaceStatus::Good => native::WGPUSurfaceGetCurrentTextureStatus_Success, + wgt::SurfaceStatus::Good => { + native::WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal + } wgt::SurfaceStatus::Suboptimal => { - native::WGPUSurfaceGetCurrentTextureStatus_Success + native::WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal } wgt::SurfaceStatus::Timeout => native::WGPUSurfaceGetCurrentTextureStatus_Timeout, wgt::SurfaceStatus::Outdated => native::WGPUSurfaceGetCurrentTextureStatus_Outdated, wgt::SurfaceStatus::Lost => native::WGPUSurfaceGetCurrentTextureStatus_Lost, }; - surface_texture.suboptimal = match status { - wgt::SurfaceStatus::Suboptimal => true as native::WGPUBool, - _ => false as native::WGPUBool, - }; surface_texture.texture = match texture_id { Some(texture_id) => Arc::into_raw(Arc::new(WGPUTextureImpl { context: context.clone(), @@ -3979,7 +4081,7 @@ pub unsafe extern "C" fn wgpuSurfaceUnconfigure(surface: native::WGPUSurface) { } #[no_mangle] -pub unsafe extern "C" fn wgpuSurfaceReference(surface: native::WGPUSurface) { +pub unsafe extern "C" fn wgpuSurfaceAddRef(surface: native::WGPUSurface) { assert!(!surface.is_null(), "invalid surface"); Arc::increment_strong_count(surface); } @@ -4025,32 +4127,45 @@ pub unsafe extern "C" fn wgpuTextureCreateView( texture: native::WGPUTexture, descriptor: Option<&native::WGPUTextureViewDescriptor>, ) -> native::WGPUTextureView { - let (texture_id, context, error_sink) = { + let (texture_id, context, error_sink, texture_usage) = { let texture = texture.as_ref().expect("invalid texture"); - (texture.id, &texture.context, &texture.error_sink) + ( + texture.id, + &texture.context, + &texture.error_sink, + texture.data.usage, + ) }; let desc = match descriptor { - Some(descriptor) => wgc::resource::TextureViewDescriptor { - label: ptr_into_label(descriptor.label), - format: conv::map_texture_format(descriptor.format), - dimension: conv::map_texture_view_dimension(descriptor.dimension), - range: wgt::ImageSubresourceRange { - aspect: conv::map_texture_aspect(descriptor.aspect), - base_mip_level: descriptor.baseMipLevel, - mip_level_count: match descriptor.mipLevelCount { - 0 => panic!("invalid mipLevelCount"), - native::WGPU_MIP_LEVEL_COUNT_UNDEFINED => None, - _ => Some(descriptor.mipLevelCount), - }, - base_array_layer: descriptor.baseArrayLayer, - array_layer_count: match descriptor.arrayLayerCount { - 0 => panic!("invalid arrayLayerCount"), - native::WGPU_ARRAY_LAYER_COUNT_UNDEFINED => None, - _ => Some(descriptor.arrayLayerCount), + Some(descriptor) => { + // TODO: Pass usage to texture view creation when wgpu-core supports it. + if descriptor.usage != 0 && (descriptor.usage & texture_usage) != descriptor.usage { + panic!("Texture view usage must be subset of texture's usage") + } + + wgc::resource::TextureViewDescriptor { + label: string_view_into_label(descriptor.label), + format: conv::map_texture_format(descriptor.format), + dimension: conv::map_texture_view_dimension(descriptor.dimension), + range: wgt::ImageSubresourceRange { + aspect: conv::map_texture_aspect(descriptor.aspect) + .unwrap_or(wgt::TextureAspect::All), + base_mip_level: descriptor.baseMipLevel, + mip_level_count: match descriptor.mipLevelCount { + 0 => panic!("invalid mipLevelCount"), + native::WGPU_MIP_LEVEL_COUNT_UNDEFINED => None, + _ => Some(descriptor.mipLevelCount), + }, + base_array_layer: descriptor.baseArrayLayer, + array_layer_count: match descriptor.arrayLayerCount { + 0 => panic!("invalid arrayLayerCount"), + native::WGPU_ARRAY_LAYER_COUNT_UNDEFINED => None, + _ => Some(descriptor.arrayLayerCount), + }, }, - }, - }, + } + } None => wgc::resource::TextureViewDescriptor::default(), }; @@ -4120,7 +4235,7 @@ pub unsafe extern "C" fn wgpuTextureGetSampleCount(texture: native::WGPUTexture) #[no_mangle] pub unsafe extern "C" fn wgpuTextureGetUsage( texture: native::WGPUTexture, -) -> native::WGPUTextureUsageFlags { +) -> native::WGPUTextureUsage { let texture = texture.as_ref().expect("invalid texture"); texture.data.usage } @@ -4132,7 +4247,7 @@ pub unsafe extern "C" fn wgpuTextureGetWidth(texture: native::WGPUTexture) -> u3 } #[no_mangle] -pub unsafe extern "C" fn wgpuTextureReference(texture: native::WGPUTexture) { +pub unsafe extern "C" fn wgpuTextureAddRef(texture: native::WGPUTexture) { assert!(!texture.is_null(), "invalid texture"); Arc::increment_strong_count(texture); } @@ -4145,7 +4260,7 @@ pub unsafe extern "C" fn wgpuTextureRelease(texture: native::WGPUTexture) { // TextureView methods #[no_mangle] -pub unsafe extern "C" fn wgpuTextureViewReference(texture_view: native::WGPUTextureView) { +pub unsafe extern "C" fn wgpuTextureViewAddRef(texture_view: native::WGPUTextureView) { assert!(!texture_view.is_null(), "invalid texture"); Arc::increment_strong_count(texture_view); } @@ -4242,7 +4357,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModuleSpirV( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::pipeline::ShaderModuleDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), shader_bound_checks: unsafe { wgt::ShaderBoundChecks::unchecked() }, }; @@ -4269,7 +4384,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModuleSpirV( #[no_mangle] pub unsafe extern "C" fn wgpuRenderPassEncoderSetPushConstants( pass: native::WGPURenderPassEncoder, - stages: native::WGPUShaderStageFlags, + stages: native::WGPUShaderStage, offset: u32, size_bytes: u32, data: *const u8, @@ -4279,7 +4394,7 @@ pub unsafe extern "C" fn wgpuRenderPassEncoderSetPushConstants( match encoder.set_push_constants( &pass.context, - wgt::ShaderStages::from_bits(stages).expect("invalid shader stage"), + from_u64_bits(stages).expect("invalid shader stage"), offset, make_slice(data, size_bytes as usize), ) { diff --git a/src/logging.rs b/src/logging.rs index f5c31e78..1b71147c 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -1,7 +1,6 @@ -use crate::{map_enum, native}; +use crate::{map_enum, native, utils}; use log::{Level, LevelFilter, Metadata, Record}; use parking_lot::RwLock; -use std::ffi::CString; #[no_mangle] pub extern "C" fn wgpuGetVersion() -> std::os::raw::c_uint { @@ -40,7 +39,6 @@ impl log::Log for Logger { if let Some(callback) = logger.callback { let msg = record.args().to_string(); - let msg_c = CString::new(msg).unwrap(); let level = match record.level() { Level::Error => native::WGPULogLevel_Error, Level::Warn => native::WGPULogLevel_Warn, @@ -50,7 +48,7 @@ impl log::Log for Logger { }; unsafe { - callback(level, msg_c.as_ptr(), logger.userdata); + callback(level, utils::str_into_string_view(&msg), logger.userdata); } // We do not use std::mem::forget(msg_c), so Rust will reclaim the memory diff --git a/src/unimplemented.rs b/src/unimplemented.rs index f58045f8..8f56ab25 100644 --- a/src/unimplemented.rs +++ b/src/unimplemented.rs @@ -1,17 +1,14 @@ use crate::native; #[no_mangle] -pub extern "C" fn wgpuGetProcAddress( - _device: native::WGPUDevice, - _proc_name: *const ::std::os::raw::c_char, -) -> native::WGPUProc { +pub extern "C" fn wgpuGetProcAddress(_proc_name: native::WGPUStringView) -> native::WGPUProc { unimplemented!(); } #[no_mangle] pub extern "C" fn wgpuBindGroupSetLabel( _bind_group: native::WGPUBindGroup, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -19,7 +16,7 @@ pub extern "C" fn wgpuBindGroupSetLabel( #[no_mangle] pub extern "C" fn wgpuBindGroupLayoutSetLabel( _bind_group_layout: native::WGPUBindGroupLayout, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -30,17 +27,14 @@ pub extern "C" fn wgpuBufferGetMapState(_buffer: native::WGPUBuffer) -> native:: } #[no_mangle] -pub extern "C" fn wgpuBufferSetLabel( - _buffer: native::WGPUBuffer, - _label: *const ::std::os::raw::c_char, -) { +pub extern "C" fn wgpuBufferSetLabel(_buffer: native::WGPUBuffer, _label: native::WGPUStringView) { unimplemented!(); } #[no_mangle] pub extern "C" fn wgpuCommandBufferSetLabel( _command_buffer: native::WGPUCommandBuffer, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -48,7 +42,7 @@ pub extern "C" fn wgpuCommandBufferSetLabel( #[no_mangle] pub extern "C" fn wgpuCommandEncoderSetLabel( _command_encoder: native::WGPUCommandEncoder, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -56,7 +50,7 @@ pub extern "C" fn wgpuCommandEncoderSetLabel( #[no_mangle] pub extern "C" fn wgpuComputePassEncoderSetLabel( _compute_pass_encoder: native::WGPUComputePassEncoder, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -64,7 +58,7 @@ pub extern "C" fn wgpuComputePassEncoderSetLabel( #[no_mangle] pub extern "C" fn wgpuComputePipelineSetLabel( _compute_pipeline: native::WGPUComputePipeline, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -73,9 +67,8 @@ pub extern "C" fn wgpuComputePipelineSetLabel( pub extern "C" fn wgpuDeviceCreateComputePipelineAsync( _device: native::WGPUDevice, _descriptor: *const native::WGPUComputePipelineDescriptor, - _callback: native::WGPUDeviceCreateComputePipelineAsyncCallback, - _userdata: *mut ::std::os::raw::c_void, -) { + _callback: native::WGPUCreateComputePipelineAsyncCallbackInfo, +) -> native::WGPUFuture { unimplemented!(); } @@ -83,17 +76,13 @@ pub extern "C" fn wgpuDeviceCreateComputePipelineAsync( pub extern "C" fn wgpuDeviceCreateRenderPipelineAsync( _device: native::WGPUDevice, _descriptor: *const native::WGPURenderPipelineDescriptor, - _callback: native::WGPUDeviceCreateRenderPipelineAsyncCallback, - _userdata: *mut ::std::os::raw::c_void, -) { + _callback: native::WGPUCreateRenderPipelineAsyncCallbackInfo, +) -> native::WGPUFuture { unimplemented!(); } #[no_mangle] -pub extern "C" fn wgpuDeviceSetLabel( - _device: native::WGPUDevice, - _label: *const ::std::os::raw::c_char, -) { +pub extern "C" fn wgpuDeviceSetLabel(_device: native::WGPUDevice, _label: native::WGPUStringView) { unimplemented!(); } @@ -113,7 +102,7 @@ pub extern "C" fn wgpuInstanceProcessEvents(_instance: native::WGPUInstance) { #[no_mangle] pub extern "C" fn wgpuPipelineLayoutSetLabel( _pipeline_layout: native::WGPUPipelineLayout, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -121,23 +110,20 @@ pub extern "C" fn wgpuPipelineLayoutSetLabel( #[no_mangle] pub extern "C" fn wgpuQuerySetSetLabel( _query_set: native::WGPUQuerySet, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } #[no_mangle] -pub extern "C" fn wgpuQueueSetLabel( - _queue: native::WGPUQueue, - _label: *const ::std::os::raw::c_char, -) { +pub extern "C" fn wgpuQueueSetLabel(_queue: native::WGPUQueue, _label: native::WGPUStringView) { unimplemented!(); } #[no_mangle] pub extern "C" fn wgpuRenderBundleSetLabel( _render_bundle: native::WGPURenderBundle, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -145,7 +131,7 @@ pub extern "C" fn wgpuRenderBundleSetLabel( #[no_mangle] pub extern "C" fn wgpuRenderBundleEncoderSetLabel( _render_bundle_encoder: native::WGPURenderBundleEncoder, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -153,7 +139,7 @@ pub extern "C" fn wgpuRenderBundleEncoderSetLabel( #[no_mangle] pub extern "C" fn wgpuRenderPassEncoderSetLabel( _render_pass_encoder: native::WGPURenderPassEncoder, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -161,7 +147,7 @@ pub extern "C" fn wgpuRenderPassEncoderSetLabel( #[no_mangle] pub extern "C" fn wgpuRenderPipelineSetLabel( _render_pipeline: native::WGPURenderPipeline, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -169,7 +155,7 @@ pub extern "C" fn wgpuRenderPipelineSetLabel( #[no_mangle] pub extern "C" fn wgpuSamplerSetLabel( _sampler: native::WGPUSampler, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -177,16 +163,15 @@ pub extern "C" fn wgpuSamplerSetLabel( #[no_mangle] pub extern "C" fn wgpuShaderModuleGetCompilationInfo( _shader_module: native::WGPUShaderModule, - _callback: native::WGPUShaderModuleGetCompilationInfoCallback, - _userdata: *mut ::std::os::raw::c_void, -) { + _callback: native::WGPUCompilationInfoCallbackInfo, +) -> native::WGPUFuture { unimplemented!(); } #[no_mangle] pub extern "C" fn wgpuShaderModuleSetLabel( _shader_module: native::WGPUShaderModule, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -194,7 +179,7 @@ pub extern "C" fn wgpuShaderModuleSetLabel( #[no_mangle] pub extern "C" fn wgpuSurfaceSetLabel( _surface: native::WGPUSurface, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -202,7 +187,7 @@ pub extern "C" fn wgpuSurfaceSetLabel( #[no_mangle] pub extern "C" fn wgpuTextureSetLabel( _texture: native::WGPUTexture, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -210,7 +195,17 @@ pub extern "C" fn wgpuTextureSetLabel( #[no_mangle] pub extern "C" fn wgpuTextureViewSetLabel( _texture_view: native::WGPUTextureView, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } + +#[no_mangle] +pub extern "C" fn wgpuInstanceWaitAny( + _instance: native::WGPUInstance, + _future_count: usize, + _futures: *mut native::WGPUFutureWaitInfo, + _timeout_ns: u64, +) -> native::WGPUWaitStatus { + unimplemented!(); +} diff --git a/src/utils.rs b/src/utils.rs index 8b65f115..0793b39e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,48 +1,42 @@ -use std::{ - borrow::Cow, - ffi::CStr, - path::{Path, PathBuf}, -}; +use std::{borrow::Cow, ffi::CStr}; + +use crate::native; // A dummy wrapper that is `Send` + `Sync` to store userdata pointer // to be usable across Rust callbacks. -pub(crate) struct Userdata(*mut std::ffi::c_void); +pub(crate) struct Userdata(*mut std::ffi::c_void, *mut std::ffi::c_void); impl Userdata { + pub(crate) const NULL: Userdata = Userdata::new(std::ptr::null_mut(), std::ptr::null_mut()); + #[inline] - pub(crate) const fn new(userdata: *mut std::ffi::c_void) -> Userdata { - Userdata(userdata) + pub(crate) const fn new( + userdata1: *mut std::ffi::c_void, + userdata2: *mut std::ffi::c_void, + ) -> Userdata { + Userdata(userdata1, userdata2) } #[inline] - pub(crate) fn as_ptr(&self) -> *mut std::ffi::c_void { + pub(crate) fn get_1(&self) -> *mut std::ffi::c_void { self.0 } -} -unsafe impl Send for Userdata {} -unsafe impl Sync for Userdata {} -#[inline] -pub(crate) fn ptr_into_label<'a>(ptr: *const std::ffi::c_char) -> wgc::Label<'a> { - unsafe { ptr.as_ref() }.and_then(|ptr| { - unsafe { CStr::from_ptr(ptr) } - .to_str() - .ok() - .map(Cow::Borrowed) - }) -} -#[inline] -pub(crate) fn ptr_into_path<'a>(ptr: *const std::ffi::c_char) -> Option<&'a std::path::Path> { - unsafe { ptr.as_ref() } - .and_then(|v| unsafe { CStr::from_ptr(v) }.to_str().ok()) - .map(Path::new) + #[inline] + pub(crate) fn get_2(&self) -> *mut std::ffi::c_void { + self.1 + } } -#[inline] -pub(crate) fn ptr_into_pathbuf(ptr: *const std::ffi::c_char) -> Option { - unsafe { ptr.as_ref() } - .and_then(|v| unsafe { CStr::from_ptr(v) }.to_str().ok()) - .map(PathBuf::from) + +#[macro_export] +macro_rules! new_userdata { + ($var:expr) => { + crate::utils::Userdata::new($var.userdata1, $var.userdata2) + }; } +unsafe impl Send for Userdata {} +unsafe impl Sync for Userdata {} + // Safer wrapper around `slice::from_raw_parts` to handle // invalid `ptr` when `len` is zero. #[inline] @@ -98,6 +92,14 @@ pub fn get_base_device_limits_from_adapter_limits(adapter_limits: &wgt::Limits) } } +pub fn texture_format_has_depth(format: wgt::TextureFormat) -> bool { + return format == wgt::TextureFormat::Depth16Unorm + || format == wgt::TextureFormat::Depth24Plus + || format == wgt::TextureFormat::Depth24PlusStencil8 + || format == wgt::TextureFormat::Depth32Float + || format == wgt::TextureFormat::Depth32FloatStencil8; +} + /// Follow a chain of next pointers and automatically resolve them to the underlying structs. /// /// # Syntax: @@ -164,7 +166,7 @@ macro_rules! follow_chain { $( let mut $stype: Option<&$ty> = None; )* - let mut chain_opt: Option<&$crate::native::WGPUChainedStruct> = $base1.nextInChain.as_ref(); + let mut chain_opt: Option<&$crate::native::WGPUChainedStruct> = ($base1.nextInChain as *const $crate::native::WGPUChainedStruct).as_ref(); while let Some(next_in_chain) = chain_opt { match next_in_chain.sType { $( @@ -268,6 +270,110 @@ macro_rules! map_enum { }; } +/// Equivalent to [map_enum], but it returns [Option] and "undefined" values are converted to [None]. +#[macro_export] +macro_rules! map_enum_with_undefined { + ($name:ident, $c_name:ident, $rs_type:ty, $($variant:ident),+) => { + #[inline] + pub fn $name(value: native::$c_name) -> Result, native::$c_name> { + match value { + paste::paste!(native::[<$c_name _ Undefined>]) => Ok(None), + $(paste::paste!(native::[<$c_name _ $variant>]) => Ok(Some(<$rs_type>::$variant))),+, + x => Err(x), + } + } + }; + ($name:ident, $c_name:ident, $rs_type:ty, $err_msg:literal, $($variant:ident),+) => { + #[inline] + pub fn $name(value: native::$c_name) -> Option<$rs_type> { + map_enum_with_undefined!(map_fn, $c_name, $rs_type, $($variant),+); + + map_fn(value).expect($err_msg) + } + }; + ($name:ident, $c_name:ident, $rs_type:ty, $($native_variant:ident:$variant2:ident),+) => { + #[inline] + pub fn $name(value: native::$c_name) -> Result, native::$c_name> { + match value { + paste::paste!(native::[<$c_name _ Undefined>]) => Ok(None), + $(paste::paste!(native::[<$c_name _ $native_variant>]) => Ok(Some(<$rs_type>::$variant2))),+, + x => Err(x), + } + } + }; + ($name:ident, $c_name:ident, $rs_type:ty, $err_msg:literal, $($native_variant:ident:$variant2:ident),+) => { + #[inline] + pub fn $name(value: native::$c_name) -> Option<$rs_type> { + map_enum_with_undefined!(map_fn, $c_name, $rs_type, $($native_variant:$variant2),+); + + map_fn(value).expect($err_msg) + } + }; +} + +pub unsafe fn string_view_into_str<'a>(string_view: native::WGPUStringView) -> Option<&'a str> { + if string_view.data.is_null() { + match string_view.length { + crate::conv::WGPU_STRLEN => None, + 0 => Some(""), + _ => panic!("Null address to WGPUStringView!"), + } + } else { + let bytes = match string_view.length { + crate::conv::WGPU_STRLEN => CStr::from_ptr(string_view.data).to_bytes(), + _ => make_slice(string_view.data as *const u8, string_view.length), + }; + + Some(std::str::from_utf8_unchecked(bytes)) + } +} + +pub unsafe fn string_view_into_label<'a>(string_view: native::WGPUStringView) -> wgc::Label<'a> { + string_view_into_str(string_view).map(Cow::Borrowed) +} + +pub const fn str_into_string_view(str: &str) -> native::WGPUStringView { + native::WGPUStringView { + data: str.as_ptr() as *const std::os::raw::c_char, + length: str.len(), + } +} + +/// Create a string view that "owns" its memory, so it can be later dropped with [drop_string_view]. +pub fn str_into_owned_string_view(str: &str) -> native::WGPUStringView { + let boxed = String::from(str).into_boxed_str(); + + let result = native::WGPUStringView { + data: boxed.as_ptr() as *const std::os::raw::c_char, + length: boxed.len(), + }; + + std::mem::forget(boxed); + + result +} + +/// Drop a string view created by [str_into_owned_string_view]. +pub unsafe fn drop_string_view(view: native::WGPUStringView) { + if view.data.is_null() { + return; + } + + drop(Box::from_raw(std::slice::from_raw_parts_mut( + view.data as *mut u8, + view.length, + ))) +} + +#[test] +pub fn test_string_view_into_str() { + let str = "Hello, world!"; + let string_view = str_into_string_view(str); + let str_2 = unsafe { string_view_into_str(string_view) }.unwrap(); + + assert_eq!(str, str_2) +} + #[test] pub fn test_get_base_device_limits_from_adapter_limits() { fn expected_limits_with_default_resolution(