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<wgc::Label<'a>>,
-    *const std::ffi::c_char,
+    Option<&'a str>,
     Option<UncapturedErrorCallback>,
 ) {
     (
         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<wgc::pipeline::ShaderModuleSource<'a>, 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<wgt::TextureViewDimension> {
+    // 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<wgt::TextureDimension> {
+    // 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<wgt::Textu
     use wgt::{AstcBlock, AstcChannel};
 
     match value {
+        native::WGPUTextureFormat_Undefined => 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<wgt::Textu
         native::WGPUNativeTextureFormat_Rgba16Unorm => 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<native::WGPUFeatureNam
     if features.contains(wgt::Features::FLOAT32_FILTERABLE) {
         temp.push(native::WGPUFeatureName_Float32Filterable);
     }
-
+    if features.contains(wgt::Features::DUAL_SOURCE_BLENDING) {
+        temp.push(native::WGPUFeatureName_DualSourceBlending);
+    }
     // wgpu-rs only features
     if features.contains(wgt::Features::PUSH_CONSTANTS) {
         temp.push(native::WGPUNativeFeature_PushConstants);
@@ -1241,14 +1226,19 @@ pub fn map_feature(feature: native::WGPUFeatureName) -> Option<wgt::Features> {
         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<u32> {
 }
 
 #[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<wgc::Label<'a>> {
     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<T: bitflags::Flags<Bits = u32>>(value: u64) -> Option<T> {
+    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<T> {
     callback: T,
-    userdata: *mut std::os::raw::c_void,
+    userdata: utils::Userdata,
 }
 unsafe impl<T> Send for DeviceCallback<T> {}
 
-type UncapturedErrorCallback = DeviceCallback<native::WGPUErrorCallback>;
+type UncapturedErrorCallback = DeviceCallback<native::WGPUUncapturedErrorCallback>;
 type DeviceLostCallback = DeviceCallback<native::WGPUDeviceLostCallback>;
 
 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<ErrorScope>,
     uncaptured_handler: UncapturedErrorCallback,
     device_lost_handler: DeviceLostCallback,
+    device: Option<native::WGPUDevice>,
 }
 
 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::<Vec<_>>();
 
     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::<Vec<_>>();
 
     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<std::path::PathBuf> {
-    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<T>] 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<Option<$rs_type>, 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<Option<$rs_type>, 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(