diff --git a/build.rs b/build.rs index 11404558..2b4c1551 100644 --- a/build.rs +++ b/build.rs @@ -28,7 +28,6 @@ fn main() { ("WGPUSampler", "WGPUSamplerImpl"), ("WGPUShaderModule", "WGPUShaderModuleImpl"), ("WGPUSurface", "WGPUSurfaceImpl"), - ("WGPUSwapChain", "WGPUSwapChainImpl"), ("WGPUTexture", "WGPUTextureImpl"), ("WGPUTextureView", "WGPUTextureViewImpl"), ]; diff --git a/examples/capture/main.c b/examples/capture/main.c index 4f4192e7..f3831d2c 100644 --- a/examples/capture/main.c +++ b/examples/capture/main.c @@ -3,6 +3,7 @@ #include "webgpu-headers/webgpu.h" #include "wgpu.h" #include +#include #include #include @@ -85,7 +86,7 @@ int main(int argc, char *argv[]) { frmwrk_setup_logging(WGPULogLevel_Warn); - instance = wgpuCreateInstance(&(const WGPUInstanceDescriptor){0}); + instance = wgpuCreateInstance(NULL); ASSERT_CHECK(instance); wgpuInstanceRequestAdapter(instance, NULL, handle_request_adapter, diff --git a/examples/compute/main.c b/examples/compute/main.c index 13ab8e97..cc3fb98e 100644 --- a/examples/compute/main.c +++ b/examples/compute/main.c @@ -1,5 +1,6 @@ #include "framework.h" #include "webgpu-headers/webgpu.h" +#include #include #include @@ -59,7 +60,7 @@ int main(int argc, char *argv[]) { uint32_t numbers_size = sizeof(numbers); uint32_t numbers_length = numbers_size / sizeof(uint32_t); - instance = wgpuCreateInstance(&(const WGPUInstanceDescriptor){0}); + instance = wgpuCreateInstance(NULL); ASSERT_CHECK(instance); wgpuInstanceRequestAdapter(instance, NULL, handle_request_adapter, diff --git a/examples/enumerate_adapters/main.c b/examples/enumerate_adapters/main.c index 49812e74..5d57ebde 100644 --- a/examples/enumerate_adapters/main.c +++ b/examples/enumerate_adapters/main.c @@ -9,8 +9,7 @@ int main(int argc, char *argv[]) { frmwrk_setup_logging(WGPULogLevel_Warn); - WGPUInstance instance = - wgpuCreateInstance(&(const WGPUInstanceDescriptor){0}); + WGPUInstance instance = wgpuCreateInstance(NULL); assert(instance); const size_t adapter_count = diff --git a/examples/triangle/main.c b/examples/triangle/main.c index d5539fd6..e6272ead 100644 --- a/examples/triangle/main.c +++ b/examples/triangle/main.c @@ -2,6 +2,7 @@ #include "webgpu-headers/webgpu.h" #include "wgpu.h" #include +#include #include #include #include @@ -30,9 +31,7 @@ struct demo { WGPUSurface surface; WGPUAdapter adapter; WGPUDevice device; - WGPUSwapChainDescriptor config; - WGPUSwapChain swapchain; - bool skip_curr_frame; + WGPUSurfaceConfiguration config; }; static void handle_request_adapter(WGPURequestAdapterStatus status, @@ -78,38 +77,13 @@ static void handle_glfw_framebuffer_size(GLFWwindow *window, int width, } struct demo *demo = glfwGetWindowUserPointer(window); - if (!demo || !demo->swapchain) + if (!demo) return; demo->config.width = width; demo->config.height = height; - if (demo->swapchain) - wgpuSwapChainRelease(demo->swapchain); - demo->swapchain = - wgpuDeviceCreateSwapChain(demo->device, demo->surface, &demo->config); - assert(demo->swapchain); -} -static void handle_curr_texture_error(WGPUErrorType type, char const *message, - void *userdata) { - if (type == WGPUErrorType_NoError) - return; - - printf(LOG_PREFIX " curr_texture_error type=%#.8x message=%s\n", type, - message); - - struct demo *demo = userdata; - - if (strstr(message, "Surface timed out") != NULL) { - demo->skip_curr_frame = true; - return; - } else if (strstr(message, "Surface is outdated") != NULL) { - demo->skip_curr_frame = true; - return; - } else if (strstr(message, "Surface was lost") != NULL) { - demo->skip_curr_frame = true; - return; - } + wgpuSurfaceConfigure(demo->surface, &demo->config); } int main(int argc, char *argv[]) { @@ -121,6 +95,7 @@ int main(int argc, char *argv[]) { WGPUShaderModule shader_module = NULL; WGPUPipelineLayout pipeline_layout = NULL; WGPURenderPipeline render_pipeline = NULL; + WGPUSurfaceCapabilities surface_capabilities = {0}; int ret = EXIT_SUCCESS; #define ASSERT_CHECK(expr) \ @@ -141,7 +116,7 @@ int main(int argc, char *argv[]) { ASSERT_CHECK(glfwInit()); - demo.instance = wgpuCreateInstance(&(const WGPUInstanceDescriptor){0}); + demo.instance = wgpuCreateInstance(NULL); ASSERT_CHECK(demo.instance); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); @@ -262,48 +237,49 @@ int main(int argc, char *argv[]) { }); ASSERT_CHECK(pipeline_layout); - WGPUTextureFormat surface_preferred_format = - wgpuSurfaceGetPreferredFormat(demo.surface, demo.adapter); - ASSERT_CHECK(surface_preferred_format != WGPUTextureFormat_Undefined); + wgpuSurfaceGetCapabilities(demo.surface, demo.adapter, &surface_capabilities); render_pipeline = wgpuDeviceCreateRenderPipeline( - demo.device, &(const WGPURenderPipelineDescriptor){ - .label = "render_pipeline", - .layout = pipeline_layout, - .vertex = - (const WGPUVertexState){ - .module = shader_module, - .entryPoint = "vs_main", - }, - .fragment = - &(const WGPUFragmentState){ - .module = shader_module, - .entryPoint = "fs_main", - .targetCount = 1, - .targets = - (const WGPUColorTargetState[]){ - (const WGPUColorTargetState){ - .format = surface_preferred_format, - .writeMask = WGPUColorWriteMask_All, - }, - }, - }, - .primitive = - (const WGPUPrimitiveState){ - .topology = WGPUPrimitiveTopology_TriangleList, - }, - .multisample = - (const WGPUMultisampleState){ - .count = 1, - .mask = 0xFFFFFFFF, - }, - }); + demo.device, + &(const WGPURenderPipelineDescriptor){ + .label = "render_pipeline", + .layout = pipeline_layout, + .vertex = + (const WGPUVertexState){ + .module = shader_module, + .entryPoint = "vs_main", + }, + .fragment = + &(const WGPUFragmentState){ + .module = shader_module, + .entryPoint = "fs_main", + .targetCount = 1, + .targets = + (const WGPUColorTargetState[]){ + (const WGPUColorTargetState){ + .format = surface_capabilities.formats[0], + .writeMask = WGPUColorWriteMask_All, + }, + }, + }, + .primitive = + (const WGPUPrimitiveState){ + .topology = WGPUPrimitiveTopology_TriangleList, + }, + .multisample = + (const WGPUMultisampleState){ + .count = 1, + .mask = 0xFFFFFFFF, + }, + }); ASSERT_CHECK(render_pipeline); - demo.config = (WGPUSwapChainDescriptor){ + demo.config = (const WGPUSurfaceConfiguration){ + .device = demo.device, .usage = WGPUTextureUsage_RenderAttachment, - .format = surface_preferred_format, + .format = surface_capabilities.formats[0], .presentMode = WGPUPresentMode_Fifo, + .alphaMode = surface_capabilities.alphaModes[0], }; { @@ -313,24 +289,44 @@ int main(int argc, char *argv[]) { demo.config.height = height; } - demo.swapchain = - wgpuDeviceCreateSwapChain(demo.device, demo.surface, &demo.config); - ASSERT_CHECK(demo.swapchain); + wgpuSurfaceConfigure(demo.surface, &demo.config); while (!glfwWindowShouldClose(window)) { - demo.skip_curr_frame = false; glfwPollEvents(); - wgpuDevicePushErrorScope(demo.device, WGPUErrorFilter_Validation); - WGPUTextureView next_texture = - wgpuSwapChainGetCurrentTextureView(demo.swapchain); - wgpuDevicePopErrorScope(demo.device, handle_curr_texture_error, &demo); - if (demo.skip_curr_frame) { - if (next_texture) - wgpuTextureViewRelease(next_texture); + WGPUSurfaceTexture surface_texture; + wgpuSurfaceGetCurrentTexture(demo.surface, &surface_texture); + switch (surface_texture.status) { + case WGPUSurfaceGetCurrentTextureStatus_Success: + // All good, could check for `surface_texture.suboptimal` here. + break; + case WGPUSurfaceGetCurrentTextureStatus_Timeout: + case WGPUSurfaceGetCurrentTextureStatus_Outdated: + case WGPUSurfaceGetCurrentTextureStatus_Lost: { + // Skip this frame, and re-configure surface. + wgpuTextureRelease(surface_texture.texture); + int width, height; + glfwGetWindowSize(window, &width, &height); + if (width != 0 && height != 0) { + demo.config.width = width; + demo.config.height = height; + wgpuSurfaceConfigure(demo.surface, &demo.config); + } continue; } - assert(next_texture); + case WGPUSurfaceGetCurrentTextureStatus_OutOfMemory: + case WGPUSurfaceGetCurrentTextureStatus_DeviceLost: + case WGPUSurfaceGetCurrentTextureStatus_Force32: + // Fatal error + printf(LOG_PREFIX " get_current_texture status=%#.8x\n", + surface_texture.status); + abort(); + } + assert(surface_texture.texture); + + WGPUTextureView frame = + wgpuTextureCreateView(surface_texture.texture, NULL); + assert(frame); WGPUCommandEncoder command_encoder = wgpuDeviceCreateCommandEncoder( demo.device, &(const WGPUCommandEncoderDescriptor){ @@ -346,7 +342,7 @@ int main(int argc, char *argv[]) { .colorAttachments = (const WGPURenderPassColorAttachment[]){ (const WGPURenderPassColorAttachment){ - .view = next_texture, + .view = frame, .loadOp = WGPULoadOp_Clear, .storeOp = WGPUStoreOp_Store, .clearValue = @@ -372,12 +368,13 @@ int main(int argc, char *argv[]) { assert(command_buffer); wgpuQueueSubmit(queue, 1, (const WGPUCommandBuffer[]){command_buffer}); - wgpuSwapChainPresent(demo.swapchain); + wgpuSurfacePresent(demo.surface); wgpuCommandBufferRelease(command_buffer); wgpuRenderPassEncoderRelease(render_pass_encoder); wgpuCommandEncoderRelease(command_encoder); - wgpuTextureViewRelease(next_texture); + wgpuTextureViewRelease(frame); + wgpuTextureRelease(surface_texture.texture); } cleanup_and_exit: @@ -387,8 +384,7 @@ int main(int argc, char *argv[]) { wgpuPipelineLayoutRelease(pipeline_layout); if (shader_module) wgpuShaderModuleRelease(shader_module); - if (demo.swapchain) - wgpuSwapChainRelease(demo.swapchain); + wgpuSurfaceCapabilitiesFreeMembers(surface_capabilities); if (queue) wgpuQueueRelease(queue); if (demo.device) diff --git a/ffi/webgpu-headers b/ffi/webgpu-headers index 8e9025e0..d1238857 160000 --- a/ffi/webgpu-headers +++ b/ffi/webgpu-headers @@ -1 +1 @@ -Subproject commit 8e9025e0fa4b33d5e7cc682b7604b021b29f36c6 +Subproject commit d12388575785f254b5c186667e0c1b79e4da46b1 diff --git a/ffi/wgpu.h b/ffi/wgpu.h index 6e576aea..876d464c 100644 --- a/ffi/wgpu.h +++ b/ffi/wgpu.h @@ -6,13 +6,11 @@ typedef enum WGPUNativeSType { // Start at 6 to prevent collisions with webgpu STypes WGPUSType_DeviceExtras = 0x60000001, - WGPUSType_AdapterExtras = 0x60000002, - WGPUSType_RequiredLimitsExtras = 0x60000003, - WGPUSType_PipelineLayoutExtras = 0x60000004, - WGPUSType_ShaderModuleGLSLDescriptor = 0x60000005, - WGPUSType_SupportedLimitsExtras = 0x60000003, + WGPUSType_RequiredLimitsExtras = 0x60000002, + WGPUSType_PipelineLayoutExtras = 0x60000003, + WGPUSType_ShaderModuleGLSLDescriptor = 0x60000004, + WGPUSType_SupportedLimitsExtras = 0x60000005, WGPUSType_InstanceExtras = 0x60000006, - WGPUSType_SwapChainDescriptorExtras = 0x60000007, WGPUNativeSType_Force32 = 0x7FFFFFFF } WGPUNativeSType; @@ -58,15 +56,6 @@ typedef enum WGPUDx12Compiler { WGPUDx12Compiler_Force32 = 0x7FFFFFFF } WGPUDx12Compiler; -typedef enum WGPUCompositeAlphaMode { - WGPUCompositeAlphaMode_Auto = 0x00000000, - WGPUCompositeAlphaMode_Opaque = 0x00000001, - WGPUCompositeAlphaMode_PreMultiplied = 0x00000002, - WGPUCompositeAlphaMode_PostMultiplied = 0x00000003, - WGPUCompositeAlphaMode_Inherit = 0x00000004, - WGPUCompositeAlphaMode_Force32 = 0x7FFFFFFF -} WGPUCompositeAlphaMode; - typedef struct WGPUInstanceExtras { WGPUChainedStruct chain; WGPUInstanceBackendFlags backends; @@ -157,22 +146,6 @@ typedef struct WGPUGlobalReport { WGPUHubReport gl; } WGPUGlobalReport; -typedef struct WGPUSurfaceCapabilities { - size_t formatCount; - WGPUTextureFormat * formats; - size_t presentModeCount; - WGPUPresentMode * presentModes; - size_t alphaModeCount; - WGPUCompositeAlphaMode * alphaModes; -} WGPUSurfaceCapabilities; - -typedef struct WGPUSwapChainDescriptorExtras { - WGPUChainedStruct chain; - WGPUCompositeAlphaMode alphaMode; - size_t viewFormatCount; - WGPUTextureFormat const * viewFormats; -} WGPUSwapChainDescriptorExtras; - typedef struct WGPUInstanceEnumerateAdapterOptions { WGPUChainedStruct const * nextInChain; WGPUInstanceBackendFlags backends; @@ -190,7 +163,7 @@ size_t wgpuInstanceEnumerateAdapters(WGPUInstance instance, WGPUInstanceEnumerat WGPUSubmissionIndex wgpuQueueSubmitForIndex(WGPUQueue queue, size_t commandCount, WGPUCommandBuffer const * commands); // Returns true if the queue is empty, or false if there are more queue submissions still in flight. -bool wgpuDevicePoll(WGPUDevice device, bool wait, WGPUWrappedSubmissionIndex const * wrappedSubmissionIndex); +WGPUBool wgpuDevicePoll(WGPUDevice device, WGPUBool wait, WGPUWrappedSubmissionIndex const * wrappedSubmissionIndex); void wgpuSetLogCallback(WGPULogCallback callback, void * userdata); @@ -198,8 +171,6 @@ void wgpuSetLogLevel(WGPULogLevel level); uint32_t wgpuGetVersion(void); -void wgpuSurfaceGetCapabilities(WGPUSurface surface, WGPUAdapter adapter, WGPUSurfaceCapabilities * capabilities); - void wgpuRenderPassEncoderSetPushConstants(WGPURenderPassEncoder encoder, WGPUShaderStageFlags stages, 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 1271140a..2f0fe76a 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -28,11 +28,11 @@ map_enum!( ); #[inline] pub fn map_load_op(value: native::WGPULoadOp) -> wgc::command::LoadOp { - return _raw_map_load_op(value).unwrap_or(wgc::command::LoadOp::Clear) + return _raw_map_load_op(value).unwrap_or(wgc::command::LoadOp::Clear); } #[inline] pub fn map_store_op(value: native::WGPUStoreOp) -> wgc::command::StoreOp { - return _raw_map_store_op(value).unwrap_or(wgc::command::StoreOp::Discard) + return _raw_map_store_op(value).unwrap_or(wgc::command::StoreOp::Discard); } map_enum!( map_address_mode, @@ -88,7 +88,8 @@ map_enum!( "Unknown present mode", Immediate, Mailbox, - Fifo + Fifo, + FifoRelaxed ); map_enum!( map_primitive_topology, @@ -201,11 +202,11 @@ map_enum!( map_composite_alpha_mode, WGPUCompositeAlphaMode, wgt::CompositeAlphaMode, - Auto, - Opaque, - PreMultiplied, - PostMultiplied, - Inherit + Auto: Auto, + Opaque: Opaque, + Premultiplied: PreMultiplied, + Unpremultiplied: PostMultiplied, + Inherit: Inherit ); pub const WGPU_WHOLE_SIZE: ::std::os::raw::c_ulonglong = native::WGPU_WHOLE_SIZE as _; @@ -298,7 +299,7 @@ pub fn map_device_descriptor<'a>( ( wgt::DeviceDescriptor { label: ptr_into_label(des.label), - features: map_features(make_slice(des.requiredFeatures, des.requiredFeaturesCount)), + features: map_features(make_slice(des.requiredFeatures, des.requiredFeatureCount)), limits, }, match extras { @@ -355,6 +356,8 @@ pub fn write_limits_struct( limits.maxTextureDimension3D = wgt_limits.max_texture_dimension_3d; limits.maxTextureArrayLayers = wgt_limits.max_texture_array_layers; limits.maxBindGroups = wgt_limits.max_bind_groups; + // TODO: not yet in wgt + // limits.maxBindGroupsPlusVertexBuffers = wgt_limits.max_bind_groups_plus_vertex_buffers; limits.maxBindingsPerBindGroup = wgt_limits.max_bindings_per_bind_group; limits.maxDynamicUniformBuffersPerPipelineLayout = wgt_limits.max_dynamic_uniform_buffers_per_pipeline_layout; @@ -425,6 +428,10 @@ pub fn map_required_limits( if limits.maxBindGroups != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_bind_groups = limits.maxBindGroups; } + // TODO: not yet in wgt + // if limits.maxBindGroupsPlusVertexBuffers != native::WGPU_LIMIT_U32_UNDEFINED { + // wgt_limits.max_bind_groups_plus_vertex_buffers = limits.maxBindGroupsPlusVertexBuffers; + // } if limits.maxBindingsPerBindGroup != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_bindings_per_bind_group = limits.maxBindingsPerBindGroup; } @@ -908,7 +915,7 @@ pub fn map_primitive_state( depth_clip_control: Option<&native::WGPUPrimitiveDepthClipControl>, ) -> bool { if let Some(depth_clip_control) = depth_clip_control { - return depth_clip_control.unclippedDepth; + return depth_clip_control.unclippedDepth != 0; } false @@ -1094,10 +1101,8 @@ pub fn to_native_present_mode(mode: wgt::PresentMode) -> Option Some(native::WGPUPresentMode_Fifo), wgt::PresentMode::Immediate => Some(native::WGPUPresentMode_Immediate), wgt::PresentMode::Mailbox => Some(native::WGPUPresentMode_Mailbox), - - wgt::PresentMode::AutoVsync - | wgt::PresentMode::AutoNoVsync - | wgt::PresentMode::FifoRelaxed => None, // needs to be supported in webgpu.h + wgt::PresentMode::FifoRelaxed => Some(native::WGPUPresentMode_FifoRelaxed), + wgt::PresentMode::AutoVsync | wgt::PresentMode::AutoNoVsync => None, } } @@ -1108,52 +1113,12 @@ pub fn to_native_composite_alpha_mode( match mode { wgt::CompositeAlphaMode::Auto => native::WGPUCompositeAlphaMode_Auto, wgt::CompositeAlphaMode::Opaque => native::WGPUCompositeAlphaMode_Opaque, - wgt::CompositeAlphaMode::PreMultiplied => native::WGPUCompositeAlphaMode_PreMultiplied, - wgt::CompositeAlphaMode::PostMultiplied => native::WGPUCompositeAlphaMode_PostMultiplied, + wgt::CompositeAlphaMode::PreMultiplied => native::WGPUCompositeAlphaMode_Premultiplied, + wgt::CompositeAlphaMode::PostMultiplied => native::WGPUCompositeAlphaMode_Unpremultiplied, wgt::CompositeAlphaMode::Inherit => native::WGPUCompositeAlphaMode_Inherit, } } -#[inline] -pub fn map_swapchain_descriptor( - desc: &native::WGPUSwapChainDescriptor, - extras: Option<&native::WGPUSwapChainDescriptorExtras>, -) -> wgt::SurfaceConfiguration> { - let (alpha_mode, view_formats) = match extras { - Some(extras) => ( - match extras.alphaMode { - native::WGPUCompositeAlphaMode_Auto => wgt::CompositeAlphaMode::Auto, - native::WGPUCompositeAlphaMode_Opaque => wgt::CompositeAlphaMode::Opaque, - native::WGPUCompositeAlphaMode_PreMultiplied => { - wgt::CompositeAlphaMode::PreMultiplied - } - native::WGPUCompositeAlphaMode_PostMultiplied => { - wgt::CompositeAlphaMode::PostMultiplied - } - native::WGPUCompositeAlphaMode_Inherit => wgt::CompositeAlphaMode::Inherit, - _ => panic!("invalid alpha mode for swapchain descriptor"), - }, - make_slice(extras.viewFormats, extras.viewFormatCount) - .iter() - .map(|f| { - map_texture_format(*f).expect("invalid view format for swapchain descriptor") - }) - .collect(), - ), - None => (wgt::CompositeAlphaMode::default(), Vec::new()), - }; - - wgt::SurfaceConfiguration { - usage: wgt::TextureUsages::from_bits(desc.usage).unwrap(), - format: map_texture_format(desc.format).expect("Texture format not defined"), - width: desc.width, - height: desc.height, - present_mode: map_present_mode(desc.presentMode), - alpha_mode, - view_formats, - } -} - #[inline] pub fn map_query_set_descriptor<'a>( desc: &native::WGPUQuerySetDescriptor, @@ -1167,7 +1132,7 @@ pub fn map_query_set_descriptor<'a>( native::WGPUQueryType_PipelineStatistics => { let mut types = wgt::PipelineStatisticsTypes::empty(); - make_slice(desc.pipelineStatistics, desc.pipelineStatisticsCount) + make_slice(desc.pipelineStatistics, desc.pipelineStatisticCount) .iter() .for_each(|f| { types.insert(match *f { @@ -1197,6 +1162,24 @@ pub fn map_query_set_descriptor<'a>( } } +#[inline] +pub fn map_texture_usage_flags(flags: native::WGPUTextureUsage) -> wgt::TextureUsages { + let mut temp = wgt::TextureUsages::empty(); + if (flags & native::WGPUTextureUsage_CopySrc) != 0 { + temp.insert(wgt::TextureUsages::COPY_SRC); + } + if (flags & native::WGPUTextureUsage_CopyDst) != 0 { + temp.insert(wgt::TextureUsages::COPY_DST); + } + if (flags & native::WGPUTextureUsage_TextureBinding) != 0 { + temp.insert(wgt::TextureUsages::TEXTURE_BINDING); + } + if (flags & native::WGPUTextureUsage_RenderAttachment) != 0 { + temp.insert(wgt::TextureUsages::RENDER_ATTACHMENT); + } + temp +} + pub enum CreateSurfaceParams { Raw( ( diff --git a/src/lib.rs b/src/lib.rs index 22187d27..f5d6fafd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ use conv::{ map_device_descriptor, map_instance_backend_flags, map_instance_descriptor, map_pipeline_layout_descriptor, map_primitive_state, map_shader_module, map_surface, - map_swapchain_descriptor, CreateSurfaceParams, + CreateSurfaceParams, }; use parking_lot::{Mutex, RwLock}; use smallvec::SmallVec; @@ -11,11 +11,11 @@ use std::{ error, ffi::{CStr, CString}, fmt::Display, + mem, num::NonZeroU64, sync::{atomic, Arc}, thread, }; -use thiserror::Error; use utils::{make_slice, ptr_into_label, ptr_into_path}; use wgc::{ command::{self, bundle_ffi, compute_ffi, render_ffi}, @@ -272,9 +272,18 @@ impl Drop for WGPUShaderModuleImpl { } } +struct SurfaceData { + device_id: id::DeviceId, + error_sink: ErrorSink, + texture_data: TextureData, +} + pub struct WGPUSurfaceImpl { context: Arc, id: id::SurfaceId, + data: Mutex>, + // Shared bool between Texture & Surface to track surface_present calls + has_surface_presented: Arc, } impl Drop for WGPUSurfaceImpl { fn drop(&mut self) { @@ -284,24 +293,44 @@ impl Drop for WGPUSurfaceImpl { } } -pub struct WGPUSwapChainImpl { - context: Arc, - surface_id: id::SurfaceId, - device_id: id::DeviceId, - error_sink: ErrorSink, +#[derive(Copy, Clone)] +struct TextureData { + usage: native::WGPUTextureUsageFlags, + dimension: native::WGPUTextureDimension, + size: native::WGPUExtent3D, + format: native::WGPUTextureFormat, + mip_level_count: u32, + sample_count: u32, } pub struct WGPUTextureImpl { context: Arc, id: id::TextureId, error_sink: ErrorSink, - descriptor: native::WGPUTextureDescriptor, + data: TextureData, + surface_id: Option, + // Shared bool between Texture & Surface to track surface_present calls + has_surface_presented: Arc, } impl Drop for WGPUTextureImpl { fn drop(&mut self) { - if !thread::panicking() { - let context = &self.context; - gfx_select!(self.id => context.texture_drop(self.id, false)); + if thread::panicking() { + return; + } + match self.surface_id { + Some(surface_id) => { + if !self.has_surface_presented.load(atomic::Ordering::SeqCst) { + let context = &self.context; + match gfx_select!(self.id => context.surface_texture_discard(surface_id)) { + Ok(_) => (), + Err(cause) => handle_error_fatal(context, cause, "wgpuTextureRelease"), + } + } + } + None => { + let context = &self.context; + gfx_select!(self.id => context.texture_drop(self.id, false)); + } } } } @@ -544,11 +573,13 @@ fn handle_error( pub unsafe extern "C" fn wgpuCreateInstance( descriptor: Option<&native::WGPUInstanceDescriptor>, ) -> native::WGPUInstance { - let descriptor = descriptor.expect("invalid descriptor"); - - let instance_desc = follow_chain!(map_instance_descriptor(descriptor, - WGPUSType_InstanceExtras => native::WGPUInstanceExtras - )); + let instance_desc = match descriptor { + Some(descriptor) => follow_chain!(map_instance_descriptor( + descriptor, + WGPUSType_InstanceExtras => native::WGPUInstanceExtras + )), + None => wgt::InstanceDescriptor::default(), + }; Arc::into_raw(Arc::new(WGPUInstanceImpl { context: Arc::new(Context::new( @@ -588,7 +619,7 @@ pub unsafe extern "C" fn wgpuAdapterEnumerateFeatures( pub unsafe extern "C" fn wgpuAdapterGetLimits( adapter: native::WGPUAdapter, limits: Option<&mut native::WGPUSupportedLimits>, -) -> bool { +) -> native::WGPUBool { let (adapter_id, context) = { let adapter = adapter.as_ref().expect("invalid adapter"); (adapter.id, &adapter.context) @@ -601,7 +632,7 @@ pub unsafe extern "C" fn wgpuAdapterGetLimits( Err(err) => handle_error_fatal(context, err, "wgpuAdapterGetLimits"), } - true // indicates that we can fill WGPUChainedStructOut + true as native::WGPUBool // indicates that we can fill WGPUChainedStructOut } #[no_mangle] @@ -658,7 +689,7 @@ pub unsafe extern "C" fn wgpuAdapterGetProperties( pub unsafe extern "C" fn wgpuAdapterHasFeature( adapter: native::WGPUAdapter, feature: native::WGPUFeatureName, -) -> bool { +) -> native::WGPUBool { let (adapter_id, context) = { let adapter = adapter.as_ref().expect("invalid adapter"); (adapter.id, &adapter.context) @@ -670,10 +701,10 @@ pub unsafe extern "C" fn wgpuAdapterHasFeature( let feature = match conv::map_feature(feature) { Some(feature) => feature, - None => return false, + None => return false as native::WGPUBool, }; - adapter_features.contains(feature) + adapter_features.contains(feature) as native::WGPUBool } #[no_mangle] @@ -1005,13 +1036,13 @@ pub unsafe extern "C" fn wgpuCommandEncoderBeginRenderPass( load_op: conv::map_load_op(desc.depthLoadOp), store_op: conv::map_store_op(desc.depthStoreOp), clear_value: desc.depthClearValue, - read_only: desc.depthReadOnly, + read_only: desc.depthReadOnly != 0, }, stencil: wgc::command::PassChannel { load_op: conv::map_load_op(desc.stencilLoadOp), store_op: conv::map_store_op(desc.stencilStoreOp), clear_value: desc.stencilClearValue, - read_only: desc.stencilReadOnly, + read_only: desc.stencilReadOnly != 0, }, } }); @@ -1761,7 +1792,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateBindGroupLayout( native::WGPUTextureViewDimension_3D => wgt::TextureViewDimension::D3, _ => panic!("invalid texture view dimension for texture binding layout"), }, - multisampled: entry.texture.multisampled, + multisampled: entry.texture.multisampled != 0, } } else if is_sampler { match entry.sampler.type_ { @@ -1820,7 +1851,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateBindGroupLayout( } _ => panic!("invalid buffer binding type for buffer binding layout"), }, - has_dynamic_offset: entry.buffer.hasDynamicOffset, + has_dynamic_offset: entry.buffer.hasDynamicOffset != 0, min_binding_size: { assert_ne!( entry.buffer.minBindingSize, @@ -1883,7 +1914,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateBuffer( label: ptr_into_label(descriptor.label), size: descriptor.size, usage: wgt::BufferUsages::from_bits(descriptor.usage).expect("invalid buffer usage"), - mapped_at_creation: descriptor.mappedAtCreation, + mapped_at_creation: descriptor.mappedAtCreation != 0, }; let (buffer_id, error) = @@ -2088,15 +2119,15 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderBundleEncoder( let desc = wgc::command::RenderBundleEncoderDescriptor { label: ptr_into_label(descriptor.label), - color_formats: make_slice(descriptor.colorFormats, descriptor.colorFormatsCount) + color_formats: make_slice(descriptor.colorFormats, descriptor.colorFormatCount) .iter() .map(|format| conv::map_texture_format(*format)) .collect(), depth_stencil: conv::map_texture_format(descriptor.depthStencilFormat).map(|format| { wgt::RenderBundleDepthStencil { format, - depth_read_only: descriptor.depthReadOnly, - stencil_read_only: descriptor.stencilReadOnly, + depth_read_only: descriptor.depthReadOnly != 0, + stencil_read_only: descriptor.stencilReadOnly != 0, } }), sample_count: descriptor.sampleCount, @@ -2193,7 +2224,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( .map(|desc| wgt::DepthStencilState { format: conv::map_texture_format(desc.format) .expect("invalid texture format for depth stencil state"), - depth_write_enabled: desc.depthWriteEnabled, + depth_write_enabled: desc.depthWriteEnabled != 0, depth_compare: conv::map_compare_function(desc.depthCompare) .expect("invalid depth compare function for depth stencil state"), stencil: wgt::StencilState { @@ -2211,7 +2242,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( multisample: wgt::MultisampleState { count: descriptor.multisample.count, mask: descriptor.multisample.mask as u64, - alpha_to_coverage_enabled: descriptor.multisample.alphaToCoverageEnabled, + alpha_to_coverage_enabled: descriptor.multisample.alphaToCoverageEnabled != 0, }, fragment: descriptor .fragment @@ -2388,37 +2419,6 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( })) } -#[no_mangle] -pub unsafe extern "C" fn wgpuDeviceCreateSwapChain( - device: native::WGPUDevice, - surface: native::WGPUSurface, - descriptor: Option<&native::WGPUSwapChainDescriptor>, -) -> native::WGPUSwapChain { - let (device_id, context, error_sink) = { - let device = device.as_ref().expect("invalid device"); - (device.id, &device.context, &device.error_sink) - }; - let surface_id = surface.as_ref().expect("invalid surface").id; - - let config = follow_chain!( - map_swapchain_descriptor( - descriptor.expect("invalid descriptor"), - WGPUSType_SwapChainDescriptorExtras => native::WGPUSwapChainDescriptorExtras) - ); - - let error = gfx_select!(device_id => context.surface_configure(surface_id, device_id, &config)); - if let Some(cause) = error { - handle_error_fatal(context, cause, "wgpuDeviceCreateSwapChain"); - } - - Arc::into_raw(Arc::new(WGPUSwapChainImpl { - context: context.clone(), - surface_id, - device_id, - error_sink: error_sink.clone(), - })) -} - #[no_mangle] pub unsafe extern "C" fn wgpuDeviceCreateTexture( device: native::WGPUDevice, @@ -2465,7 +2465,16 @@ pub unsafe extern "C" fn wgpuDeviceCreateTexture( context: context.clone(), id: texture_id, error_sink: error_sink.clone(), - descriptor: *descriptor, + surface_id: None, + has_surface_presented: Arc::default(), + data: TextureData { + usage: descriptor.usage, + dimension: descriptor.dimension, + size: descriptor.size, + format: descriptor.format, + mip_level_count: descriptor.mipLevelCount, + sample_count: descriptor.sampleCount, + }, })) } @@ -2501,7 +2510,7 @@ pub unsafe extern "C" fn wgpuDeviceEnumerateFeatures( pub unsafe extern "C" fn wgpuDeviceGetLimits( device: native::WGPUDevice, limits: Option<&mut native::WGPUSupportedLimits>, -) -> bool { +) -> native::WGPUBool { let (device_id, context) = { let device = device.as_ref().expect("invalid device"); (device.id, &device.context) @@ -2514,7 +2523,7 @@ pub unsafe extern "C" fn wgpuDeviceGetLimits( Err(err) => handle_error_fatal(context, err, "wgpuDeviceGetLimits"), } - true // indicates that we can fill WGPUChainedStructOut + true as native::WGPUBool // indicates that we can fill WGPUChainedStructOut } #[no_mangle] @@ -2535,7 +2544,7 @@ pub unsafe extern "C" fn wgpuDeviceGetQueue(device: native::WGPUDevice) -> nativ pub unsafe extern "C" fn wgpuDeviceHasFeature( device: native::WGPUDevice, feature: native::WGPUFeatureName, -) -> bool { +) -> native::WGPUBool { let (device_id, context) = { let device = device.as_ref().expect("invalid device"); (device.id, &device.context) @@ -2547,10 +2556,10 @@ pub unsafe extern "C" fn wgpuDeviceHasFeature( let feature = match conv::map_feature(feature) { Some(feature) => feature, - None => return false, + None => return false as native::WGPUBool, }; - device_features.contains(feature) + device_features.contains(feature) as native::WGPUBool } #[no_mangle] @@ -2655,6 +2664,8 @@ pub unsafe extern "C" fn wgpuInstanceCreateSurface( Arc::into_raw(Arc::new(WGPUSurfaceImpl { context: context.clone(), id: surface_id, + data: Mutex::default(), + has_surface_presented: Arc::default(), })) } @@ -2679,7 +2690,7 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter( } _ => wgt::PowerPreference::default(), }, - force_fallback_adapter: options.forceFallbackAdapter, + force_fallback_adapter: options.forceFallbackAdapter != 0, compatible_surface: options.compatibleSurface.as_ref().map(|surface| surface.id), }, wgc::instance::AdapterInputs::Mask( @@ -3602,6 +3613,192 @@ pub unsafe extern "C" fn wgpuShaderModuleRelease(shader_module: native::WGPUShad // Surface methods +#[no_mangle] +pub unsafe extern "C" fn wgpuSurfaceConfigure( + surface: native::WGPUSurface, + config: Option<&native::WGPUSurfaceConfiguration>, +) { + let surface = surface.as_ref().expect("invalid surface"); + let config = config.expect("invalid config"); + let device = config + .device + .as_ref() + .expect("invalid device for surface configuration"); + let context = &device.context; + + let surface_config = wgt::SurfaceConfiguration { + usage: conv::map_texture_usage_flags(config.usage as native::WGPUTextureUsage), + format: conv::map_texture_format(config.format) + .expect("invalid format for surface configuration"), + width: config.width, + height: config.height, + present_mode: conv::map_present_mode(config.presentMode), + alpha_mode: conv::map_composite_alpha_mode(config.alphaMode) + .expect("invalid alpha mode for surface configuration"), + view_formats: make_slice(config.viewFormats, config.viewFormatCount) + .iter() + .map(|f| { + conv::map_texture_format(*f).expect("invalid view format for surface configuration") + }) + .collect(), + }; + + match wgc::gfx_select!(device.id => context.surface_configure(surface.id, device.id, &surface_config)) + { + Some(cause) => handle_error_fatal(context, cause, "wgpuSurfaceConfigure"), + None => { + let mut surface_data_guard = surface.data.lock(); + *surface_data_guard = Some(SurfaceData { + device_id: device.id, + error_sink: device.error_sink.clone(), + texture_data: TextureData { + usage: config.usage, + dimension: native::WGPUTextureDimension_2D, + format: config.format, + mip_level_count: 1, + size: native::WGPUExtent3D { + width: config.width, + height: config.height, + depthOrArrayLayers: 1, + }, + sample_count: 1, + }, + }); + surface + .has_surface_presented + .store(false, atomic::Ordering::SeqCst); + } + }; +} + +#[no_mangle] +pub unsafe extern "C" fn wgpuSurfaceGetCapabilities( + surface: native::WGPUSurface, + adapter: native::WGPUAdapter, + capabilities: Option<&mut native::WGPUSurfaceCapabilities>, +) { + let (adapter_id, context) = { + let adapter = adapter.as_ref().expect("invalid adapter"); + (adapter.id, &adapter.context) + }; + let surface_id = surface.as_ref().expect("invalid surface").id; + let capabilities = capabilities.expect("invalid return pointer \"capabilities\""); + + let caps = match wgc::gfx_select!(adapter_id => context.surface_get_capabilities(surface_id, adapter_id)) + { + Ok(caps) => caps, + Err(wgc::instance::GetSurfaceSupportError::Unsupported) => { + wgt::SurfaceCapabilities::default() + } + Err(cause) => handle_error_fatal(context, cause, "wgpuSurfaceGetCapabilities"), + }; + + let formats = caps + .formats + .iter() + // some texture formats are not in webgpu.h and + // conv::to_native_texture_format returns None for them. + // so, filter them out. + .filter_map(|f| conv::to_native_texture_format(*f)) + .collect::>(); + + if !formats.is_empty() { + let mut array = formats.into_boxed_slice(); + capabilities.formats = array.as_mut_ptr(); + capabilities.formatCount = array.len(); + mem::forget(array); + } else { + capabilities.formats = std::ptr::null_mut(); + capabilities.formatCount = 0; + } + + let present_modes = caps + .present_modes + .iter() + .filter_map(|f| conv::to_native_present_mode(*f)) + .collect::>(); + + if !present_modes.is_empty() { + let mut array = present_modes.into_boxed_slice(); + capabilities.presentModes = array.as_mut_ptr(); + capabilities.presentModeCount = array.len(); + mem::forget(array); + } else { + capabilities.presentModes = std::ptr::null_mut(); + capabilities.presentModeCount = 0; + } + + let alpha_modes = caps + .alpha_modes + .iter() + .map(|f| conv::to_native_composite_alpha_mode(*f)) + .collect::>(); + + if !alpha_modes.is_empty() { + let mut array = alpha_modes.into_boxed_slice(); + capabilities.alphaModes = array.as_mut_ptr(); + capabilities.alphaModeCount = array.len(); + mem::forget(array); + } else { + capabilities.alphaModes = std::ptr::null_mut(); + capabilities.alphaModeCount = 0; + } +} + +#[no_mangle] +pub unsafe extern "C" fn wgpuSurfaceGetCurrentTexture( + surface: native::WGPUSurface, + surface_texture: Option<&mut native::WGPUSurfaceTexture>, +) { + let surface = surface.as_ref().expect("invalid surface"); + let context = &surface.context; + let surface_texture = surface_texture.expect("invalid return pointer \"surface_texture\""); + + let surface_data_guard = surface.data.lock(); + let surface_data = match surface_data_guard.as_ref() { + Some(surface_data) => surface_data, + None => handle_error_fatal( + context, + wgc::present::SurfaceError::NotConfigured, + "wgpuSurfaceGetCurrentTexture", + ), + }; + + match wgc::gfx_select!(surface_data.device_id => context.surface_get_current_texture(surface.id, ())) + { + Ok(wgc::present::SurfaceOutput { status, texture_id }) => { + surface + .has_surface_presented + .store(false, atomic::Ordering::SeqCst); + surface_texture.status = match status { + wgt::SurfaceStatus::Good => native::WGPUSurfaceGetCurrentTextureStatus_Success, + wgt::SurfaceStatus::Suboptimal => { + native::WGPUSurfaceGetCurrentTextureStatus_Success + } + 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(), + id: texture_id, + error_sink: surface_data.error_sink.clone(), + data: surface_data.texture_data, + surface_id: Some(surface.id), + has_surface_presented: surface.has_surface_presented.clone(), + })), + None => std::ptr::null_mut(), + }; + } + Err(cause) => handle_error_fatal(context, cause, "wgpuSurfaceGetCurrentTexture"), + }; +} + #[no_mangle] pub unsafe extern "C" fn wgpuSurfaceGetPreferredFormat( surface: native::WGPUSurface, @@ -3635,96 +3832,36 @@ pub unsafe extern "C" fn wgpuSurfaceGetPreferredFormat( } } -#[derive(Debug, Error)] -pub enum SurfaceError { - #[error("Surface timed out")] - Timeout, - #[error("Surface is outdated")] - Outdated, - #[error("Surface was lost")] - Lost, -} - #[no_mangle] -pub unsafe extern "C" fn wgpuSwapChainGetCurrentTextureView( - swap_chain: native::WGPUSwapChain, -) -> native::WGPUTextureView { - let (surface_id, device_id, context, error_sink) = { - let swap_chain = swap_chain.as_ref().expect("invalid swap chain"); - ( - swap_chain.surface_id, - swap_chain.device_id, - &swap_chain.context, - &swap_chain.error_sink, - ) +pub unsafe extern "C" fn wgpuSurfacePresent(surface: native::WGPUSurface) { + let surface = surface.as_ref().expect("invalid surface"); + let context = &surface.context; + let surface_data_guard = surface.data.lock(); + let surface_data = match surface_data_guard.as_ref() { + Some(surface_data) => surface_data, + None => handle_error_fatal( + context, + wgc::present::SurfaceError::NotConfigured, + "wgpuSurfacePresent", + ), }; - match gfx_select!(device_id => context.surface_get_current_texture(surface_id, ())) { - Ok(result) => match result.status { - wgt::SurfaceStatus::Good | wgt::SurfaceStatus::Suboptimal => { - let texture_id = result.texture_id.unwrap(); - let (texture_view_id, error) = gfx_select!(texture_id => context.texture_create_view( - texture_id, - &wgc::resource::TextureViewDescriptor::default(), - () - )); - gfx_select!(texture_id => context.texture_drop(texture_id, false)); - if let Some(cause) = error { - handle_error( - context, - error_sink, - cause, - "", - None, - "wgpuSwapChainGetCurrentTextureView", - ); - } - - Arc::into_raw(Arc::new(WGPUTextureViewImpl { - context: context.clone(), - id: texture_view_id, - })) - } - _ => { - if let Some(texture_id) = result.texture_id { - gfx_select!(texture_id => context.texture_drop(texture_id, false)); - } - handle_error( - context, - error_sink, - match result.status { - wgt::SurfaceStatus::Timeout => &SurfaceError::Timeout, - wgt::SurfaceStatus::Outdated => &SurfaceError::Outdated, - wgt::SurfaceStatus::Lost => &SurfaceError::Lost, - _ => unreachable!(), - }, - "", - None, - "wgpuSwapChainGetCurrentTextureView", - ); - std::ptr::null_mut() - } - }, - Err(cause) => { - handle_error_fatal(context, cause, "wgpuSwapChainGetCurrentTextureView"); - } - } + match wgc::gfx_select!(surface_data.device_id => context.surface_present(surface.id)) { + Ok(_status) => surface + .has_surface_presented + .store(true, atomic::Ordering::SeqCst), + Err(cause) => handle_error_fatal(context, cause, "wgpuSurfacePresent"), + }; } #[no_mangle] -pub unsafe extern "C" fn wgpuSwapChainPresent(swap_chain: native::WGPUSwapChain) { - let (surface_id, device_id, context) = { - let swap_chain = swap_chain.as_ref().expect("invalid swap chain"); - ( - swap_chain.surface_id, - swap_chain.device_id, - &swap_chain.context, - ) - }; - - if let Err(cause) = gfx_select!(device_id => context.surface_present(surface_id)) { - handle_error_fatal(context, cause, "wgpuSwapChainPresent"); - } +pub unsafe extern "C" fn wgpuSurfaceUnconfigure(surface: native::WGPUSurface) { + let surface = surface.as_ref().expect("invalid surface"); + let mut surface_data_guard = surface.data.lock(); + let _ = surface_data_guard.take(); // drop SurfaceData + surface + .has_surface_presented + .store(false, atomic::Ordering::SeqCst); } #[no_mangle] @@ -3738,17 +3875,33 @@ pub unsafe extern "C" fn wgpuSurfaceRelease(surface: native::WGPUSurface) { Arc::decrement_strong_count(surface); } -// SwapChain methods +// SurfaceCapabilities methods #[no_mangle] -pub unsafe extern "C" fn wgpuSwapChainReference(swap_chain: native::WGPUSwapChain) { - assert!(!swap_chain.is_null(), "invalid swap chain"); - Arc::increment_strong_count(swap_chain); -} -#[no_mangle] -pub unsafe extern "C" fn wgpuSwapChainRelease(swap_chain: native::WGPUSwapChain) { - assert!(!swap_chain.is_null(), "invalid swap chain"); - Arc::decrement_strong_count(swap_chain); +pub unsafe extern "C" fn wgpuSurfaceCapabilitiesFreeMembers( + capabilities: native::WGPUSurfaceCapabilities, +) { + if !capabilities.formats.is_null() && capabilities.formatCount > 0 { + drop(Vec::from_raw_parts( + capabilities.formats, + capabilities.formatCount, + capabilities.formatCount, + )); + } + if !capabilities.presentModes.is_null() && capabilities.presentModeCount > 0 { + drop(Vec::from_raw_parts( + capabilities.presentModes, + capabilities.presentModeCount, + capabilities.presentModeCount, + )); + } + if !capabilities.alphaModes.is_null() && capabilities.alphaModeCount > 0 { + drop(Vec::from_raw_parts( + capabilities.alphaModes, + capabilities.alphaModeCount, + capabilities.alphaModeCount, + )); + } } // Texture methods @@ -3819,56 +3972,56 @@ pub unsafe extern "C" fn wgpuTextureDestroy(texture: native::WGPUTexture) { #[no_mangle] pub unsafe extern "C" fn wgpuTextureGetDepthOrArrayLayers(texture: native::WGPUTexture) -> u32 { - let descriptor = texture.as_ref().expect("invalid texture").descriptor; - descriptor.size.depthOrArrayLayers + let texture = texture.as_ref().expect("invalid texture"); + texture.data.size.depthOrArrayLayers } #[no_mangle] pub unsafe extern "C" fn wgpuTextureGetDimension( texture: native::WGPUTexture, ) -> native::WGPUTextureDimension { - let descriptor = texture.as_ref().expect("invalid texture").descriptor; - descriptor.dimension + let texture = texture.as_ref().expect("invalid texture"); + texture.data.dimension } #[no_mangle] pub unsafe extern "C" fn wgpuTextureGetFormat( texture: native::WGPUTexture, ) -> native::WGPUTextureFormat { - let descriptor = texture.as_ref().expect("invalid texture").descriptor; - descriptor.format + let texture = texture.as_ref().expect("invalid texture"); + texture.data.format } #[no_mangle] pub unsafe extern "C" fn wgpuTextureGetHeight(texture: native::WGPUTexture) -> u32 { - let descriptor = texture.as_ref().expect("invalid texture").descriptor; - descriptor.size.height + let texture = texture.as_ref().expect("invalid texture"); + texture.data.size.height } #[no_mangle] pub unsafe extern "C" fn wgpuTextureGetMipLevelCount(texture: native::WGPUTexture) -> u32 { - let descriptor = texture.as_ref().expect("invalid texture").descriptor; - descriptor.mipLevelCount + let texture = texture.as_ref().expect("invalid texture"); + texture.data.mip_level_count } #[no_mangle] pub unsafe extern "C" fn wgpuTextureGetSampleCount(texture: native::WGPUTexture) -> u32 { - let descriptor = texture.as_ref().expect("invalid texture").descriptor; - descriptor.sampleCount + let texture = texture.as_ref().expect("invalid texture"); + texture.data.sample_count } #[no_mangle] pub unsafe extern "C" fn wgpuTextureGetUsage( texture: native::WGPUTexture, ) -> native::WGPUTextureUsageFlags { - let descriptor = texture.as_ref().expect("invalid texture").descriptor; - descriptor.usage + let texture = texture.as_ref().expect("invalid texture"); + texture.data.usage } #[no_mangle] pub unsafe extern "C" fn wgpuTextureGetWidth(texture: native::WGPUTexture) -> u32 { - let descriptor = texture.as_ref().expect("invalid texture").descriptor; - descriptor.size.width + let texture = texture.as_ref().expect("invalid texture"); + texture.data.size.width } #[no_mangle] @@ -3969,76 +4122,6 @@ pub unsafe extern "C" fn wgpuDevicePoll( } } -#[no_mangle] -pub unsafe extern "C" fn wgpuSurfaceGetCapabilities( - surface: native::WGPUSurface, - adapter: native::WGPUAdapter, - capabilities: Option<&mut native::WGPUSurfaceCapabilities>, -) { - let (adapter_id, context) = { - let adapter = adapter.as_ref().expect("invalid adapter"); - (adapter.id, &adapter.context) - }; - let surface_id = surface.as_ref().expect("invalid surface").id; - let capabilities = capabilities.expect("invalid return pointer \"capabilities\""); - - let caps = match wgc::gfx_select!(adapter_id => context.surface_get_capabilities(surface_id, adapter_id)) - { - Ok(caps) => caps, - Err(wgc::instance::GetSurfaceSupportError::Unsupported) => { - wgt::SurfaceCapabilities::default() - } - Err(cause) => handle_error_fatal(context, cause, "wgpuSurfaceGetCapabilities"), - }; - - let formats = caps - .formats - .iter() - // some texture formats are not in webgpu.h and - // conv::to_native_texture_format returns None for them. - // so, filter them out. - .filter_map(|f| conv::to_native_texture_format(*f)) - .collect::>(); - - capabilities.formatCount = formats.len(); - - if !capabilities.formats.is_null() { - std::ptr::copy_nonoverlapping(formats.as_ptr(), capabilities.formats, formats.len()); - } - - let present_modes = caps - .present_modes - .iter() - .filter_map(|f| conv::to_native_present_mode(*f)) - .collect::>(); - - capabilities.presentModeCount = present_modes.len(); - - if !capabilities.presentModes.is_null() { - std::ptr::copy_nonoverlapping( - present_modes.as_ptr(), - capabilities.presentModes, - present_modes.len(), - ); - } - - let alpha_modes = caps - .alpha_modes - .iter() - .map(|f| conv::to_native_composite_alpha_mode(*f)) - .collect::>(); - - capabilities.alphaModeCount = alpha_modes.len(); - - if !capabilities.alphaModes.is_null() { - std::ptr::copy_nonoverlapping( - alpha_modes.as_ptr(), - capabilities.alphaModes, - alpha_modes.len(), - ); - } -} - #[no_mangle] pub unsafe extern "C" fn wgpuRenderPassEncoderSetPushConstants( pass: native::WGPURenderPassEncoder,