dawn_node: Use IDL default parameter values

If the IDL provides a default value for a interface method parameter, then use that default value if no argument is provided.

Removes a bunch of std::optional<T>'s from the C++ interfaces, and simplifies binding implementations.

Also fix some defaults of buffer size from 0 to kWholeSize. This was partially done in an earlier CL, but it seems I missed a few.

Bug: dawn:1143
Change-Id: Ifc1bb29a5e7ead42dd015d2333c743165f2459a6
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/65663
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_node/README.md b/src/dawn_node/README.md
index 1273c85..fe2b6f1 100644
--- a/src/dawn_node/README.md
+++ b/src/dawn_node/README.md
@@ -64,7 +64,6 @@
 
 ## Remaining work
 
-- Have the IDL interop generator produce default values for parameters (instead of std::optional). [discussion](https://dawn-review.googlesource.com/c/dawn/+/64912/5/src/dawn_node/binding/GPURenderBundleEncoder.cpp#166)
 - Investigate CTS failures that are not expected to fail.
 - Generated includes live in `src/` for `dawn_node`, but outside for Dawn. [discussion](https://dawn-review.googlesource.com/c/dawn/+/64903/9/src/dawn_node/interop/CMakeLists.txt#56)
 - Hook up to presubmit bots (CQ / Kokoro)
diff --git a/src/dawn_node/binding/Converter.h b/src/dawn_node/binding/Converter.h
index 812d405..e499e4f 100644
--- a/src/dawn_node/binding/Converter.h
+++ b/src/dawn_node/binding/Converter.h
@@ -328,6 +328,11 @@
         // vector -> raw pointer + count
         template <typename OUT, typename IN>
         inline bool Convert(OUT*& out_els, uint32_t& out_count, const std::vector<IN>& in) {
+            if (in.size() == 0) {
+                out_els = nullptr;
+                out_count = 0;
+                return true;
+            }
             auto* els = Allocate<std::remove_const_t<OUT>>(in.size());
             for (size_t i = 0; i < in.size(); i++) {
                 if (!Convert(els[i], in[i])) {
diff --git a/src/dawn_node/binding/GPU.cpp b/src/dawn_node/binding/GPU.cpp
index cf22465..2f64978 100644
--- a/src/dawn_node/binding/GPU.cpp
+++ b/src/dawn_node/binding/GPU.cpp
@@ -54,11 +54,11 @@
 
     interop::Promise<std::optional<interop::Interface<interop::GPUAdapter>>> GPU::requestAdapter(
         Napi::Env env,
-        std::optional<interop::GPURequestAdapterOptions> options) {
+        interop::GPURequestAdapterOptions options) {
         auto promise =
             interop::Promise<std::optional<interop::Interface<interop::GPUAdapter>>>(env);
 
-        if (options.has_value() && options->forceFallbackAdapter) {
+        if (options.forceFallbackAdapter) {
             // Software adapters are not currently supported.
             promise.Resolve({});
             return promise;
diff --git a/src/dawn_node/binding/GPU.h b/src/dawn_node/binding/GPU.h
index 55264b2..131ce42 100644
--- a/src/dawn_node/binding/GPU.h
+++ b/src/dawn_node/binding/GPU.h
@@ -30,7 +30,7 @@
         // interop::GPU interface compliance
         interop::Promise<std::optional<interop::Interface<interop::GPUAdapter>>> requestAdapter(
             Napi::Env env,
-            std::optional<interop::GPURequestAdapterOptions> options) override;
+            interop::GPURequestAdapterOptions options) override;
 
       private:
         dawn_native::Instance instance_;
diff --git a/src/dawn_node/binding/GPUAdapter.cpp b/src/dawn_node/binding/GPUAdapter.cpp
index 81a95e1..d7b1d14 100644
--- a/src/dawn_node/binding/GPUAdapter.cpp
+++ b/src/dawn_node/binding/GPUAdapter.cpp
@@ -101,32 +101,30 @@
 
     interop::Promise<interop::Interface<interop::GPUDevice>> GPUAdapter::requestDevice(
         Napi::Env env,
-        std::optional<interop::GPUDeviceDescriptor> descriptor) {
+        interop::GPUDeviceDescriptor descriptor) {
         dawn_native::DeviceDescriptor desc{};  // TODO(crbug.com/dawn/1133): Fill in.
         interop::Promise<interop::Interface<interop::GPUDevice>> promise(env);
 
-        if (descriptor.has_value()) {
-            // See src/dawn_native/Features.cpp for enum <-> string mappings.
-            for (auto required : descriptor->requiredFeatures) {
-                switch (required) {
-                    case interop::GPUFeatureName::kDepthClamping:
-                        desc.requiredFeatures.emplace_back("depth_clamping");
-                        continue;
-                    case interop::GPUFeatureName::kPipelineStatisticsQuery:
-                        desc.requiredFeatures.emplace_back("pipeline_statistics_query");
-                        continue;
-                    case interop::GPUFeatureName::kTextureCompressionBc:
-                        desc.requiredFeatures.emplace_back("texture_compression_bc");
-                        continue;
-                    case interop::GPUFeatureName::kTimestampQuery:
-                        desc.requiredFeatures.emplace_back("timestamp_query");
-                        continue;
-                    case interop::GPUFeatureName::kDepth24UnormStencil8:
-                    case interop::GPUFeatureName::kDepth32FloatStencil8:
-                        continue;  // TODO(crbug.com/dawn/1130)
-                }
-                UNIMPLEMENTED("required: ", required);
+        // See src/dawn_native/Features.cpp for enum <-> string mappings.
+        for (auto required : descriptor.requiredFeatures) {
+            switch (required) {
+                case interop::GPUFeatureName::kDepthClamping:
+                    desc.requiredFeatures.emplace_back("depth_clamping");
+                    continue;
+                case interop::GPUFeatureName::kPipelineStatisticsQuery:
+                    desc.requiredFeatures.emplace_back("pipeline_statistics_query");
+                    continue;
+                case interop::GPUFeatureName::kTextureCompressionBc:
+                    desc.requiredFeatures.emplace_back("texture_compression_bc");
+                    continue;
+                case interop::GPUFeatureName::kTimestampQuery:
+                    desc.requiredFeatures.emplace_back("timestamp_query");
+                    continue;
+                case interop::GPUFeatureName::kDepth24UnormStencil8:
+                case interop::GPUFeatureName::kDepth32FloatStencil8:
+                    continue;  // TODO(crbug.com/dawn/1130)
             }
+            UNIMPLEMENTED("required: ", required);
         }
 
         auto wgpu_device = adapter_.CreateDevice(&desc);
diff --git a/src/dawn_node/binding/GPUAdapter.h b/src/dawn_node/binding/GPUAdapter.h
index 3140ff8..1b44f57 100644
--- a/src/dawn_node/binding/GPUAdapter.h
+++ b/src/dawn_node/binding/GPUAdapter.h
@@ -34,7 +34,7 @@
         bool getIsFallbackAdapter(Napi::Env) override;
         interop::Promise<interop::Interface<interop::GPUDevice>> requestDevice(
             Napi::Env env,
-            std::optional<interop::GPUDeviceDescriptor> descriptor) override;
+            interop::GPUDeviceDescriptor descriptor) override;
 
       private:
         dawn_native::Adapter adapter_;
diff --git a/src/dawn_node/binding/GPUBuffer.cpp b/src/dawn_node/binding/GPUBuffer.cpp
index 9921b72..ac5ae54 100644
--- a/src/dawn_node/binding/GPUBuffer.cpp
+++ b/src/dawn_node/binding/GPUBuffer.cpp
@@ -42,7 +42,7 @@
 
     interop::Promise<void> GPUBuffer::mapAsync(Napi::Env env,
                                                interop::GPUMapModeFlags mode,
-                                               std::optional<interop::GPUSize64> offset,
+                                               interop::GPUSize64 offset,
                                                std::optional<interop::GPUSize64> size) {
         wgpu::MapMode md{};
         Converter conv(env);
@@ -67,16 +67,14 @@
         auto ctx = new Context{env, interop::Promise<void>(env), async_, state_};
         auto promise = ctx->promise;
 
-        uint64_t o = offset.has_value() ? offset.value() : 0;
-        uint64_t s = size.has_value() ? size.value() : (desc_.size - o);
+        uint64_t s = size.has_value() ? size.value() : (desc_.size - offset);
 
         state_ = State::MappingPending;
 
         buffer_.MapAsync(
-            md, o, s,
+            md, offset, s,
             [](WGPUBufferMapAsyncStatus status, void* userdata) {
                 auto c = std::unique_ptr<Context>(static_cast<Context*>(userdata));
-
                 c->state = State::Unmapped;
                 switch (status) {
                     case WGPUBufferMapAsyncStatus_Force32:
@@ -107,18 +105,17 @@
     }
 
     interop::ArrayBuffer GPUBuffer::getMappedRange(Napi::Env env,
-                                                   std::optional<interop::GPUSize64> offset,
+                                                   interop::GPUSize64 offset,
                                                    std::optional<interop::GPUSize64> size) {
         if (state_ != State::Mapped && state_ != State::MappedAtCreation) {
             Errors::OperationError(env).ThrowAsJavaScriptException();
             return {};
         }
 
-        uint64_t o = offset.has_value() ? offset.value() : 0;
-        uint64_t s = size.has_value() ? size.value() : (desc_.size - o);
+        uint64_t s = size.has_value() ? size.value() : (desc_.size - offset);
 
-        uint64_t start = o;
-        uint64_t end = o + s;
+        uint64_t start = offset;
+        uint64_t end = offset + s;
         for (auto& mapping : mapped_) {
             if (mapping.Intersects(start, end)) {
                 Errors::OperationError(env).ThrowAsJavaScriptException();
@@ -127,8 +124,8 @@
         }
 
         auto* ptr = (desc_.usage & wgpu::BufferUsage::MapWrite)
-                        ? buffer_.GetMappedRange(o, s)
-                        : const_cast<void*>(buffer_.GetConstMappedRange(o, s));
+                        ? buffer_.GetMappedRange(offset, s)
+                        : const_cast<void*>(buffer_.GetConstMappedRange(offset, s));
         if (!ptr) {
             Errors::OperationError(env).ThrowAsJavaScriptException();
             return {};
diff --git a/src/dawn_node/binding/GPUBuffer.h b/src/dawn_node/binding/GPUBuffer.h
index 0c4d17c..c3d8b03 100644
--- a/src/dawn_node/binding/GPUBuffer.h
+++ b/src/dawn_node/binding/GPUBuffer.h
@@ -44,10 +44,10 @@
         // interop::GPUBuffer interface compliance
         interop::Promise<void> mapAsync(Napi::Env env,
                                         interop::GPUMapModeFlags mode,
-                                        std::optional<interop::GPUSize64> offset,
+                                        interop::GPUSize64 offset,
                                         std::optional<interop::GPUSize64> size) override;
         interop::ArrayBuffer getMappedRange(Napi::Env env,
-                                            std::optional<interop::GPUSize64> offset,
+                                            interop::GPUSize64 offset,
                                             std::optional<interop::GPUSize64> size) override;
         void unmap(Napi::Env) override;
         void destroy(Napi::Env) override;
diff --git a/src/dawn_node/binding/GPUCommandEncoder.cpp b/src/dawn_node/binding/GPUCommandEncoder.cpp
index 533ed21..cf3925c 100644
--- a/src/dawn_node/binding/GPUCommandEncoder.cpp
+++ b/src/dawn_node/binding/GPUCommandEncoder.cpp
@@ -50,7 +50,7 @@
 
     interop::Interface<interop::GPUComputePassEncoder> GPUCommandEncoder::beginComputePass(
         Napi::Env env,
-        std::optional<interop::GPUComputePassDescriptor> descriptor) {
+        interop::GPUComputePassDescriptor descriptor) {
         wgpu::ComputePassDescriptor desc{};
         return interop::GPUComputePassEncoder::Create<GPUComputePassEncoder>(
             env, enc_.BeginComputePass(&desc));
@@ -180,7 +180,7 @@
 
     interop::Interface<interop::GPUCommandBuffer> GPUCommandEncoder::finish(
         Napi::Env env,
-        std::optional<interop::GPUCommandBufferDescriptor> descriptor) {
+        interop::GPUCommandBufferDescriptor descriptor) {
         wgpu::CommandBufferDescriptor desc{};
         return interop::GPUCommandBuffer::Create<GPUCommandBuffer>(env, enc_.Finish(&desc));
     }
diff --git a/src/dawn_node/binding/GPUCommandEncoder.h b/src/dawn_node/binding/GPUCommandEncoder.h
index 081032a..f23e281 100644
--- a/src/dawn_node/binding/GPUCommandEncoder.h
+++ b/src/dawn_node/binding/GPUCommandEncoder.h
@@ -34,7 +34,7 @@
             interop::GPURenderPassDescriptor descriptor) override;
         interop::Interface<interop::GPUComputePassEncoder> beginComputePass(
             Napi::Env,
-            std::optional<interop::GPUComputePassDescriptor> descriptor) override;
+            interop::GPUComputePassDescriptor descriptor) override;
         void copyBufferToBuffer(Napi::Env,
                                 interop::Interface<interop::GPUBuffer> source,
                                 interop::GPUSize64 sourceOffset,
@@ -67,7 +67,7 @@
                              interop::GPUSize64 destinationOffset) override;
         interop::Interface<interop::GPUCommandBuffer> finish(
             Napi::Env env,
-            std::optional<interop::GPUCommandBufferDescriptor> descriptor) override;
+            interop::GPUCommandBufferDescriptor descriptor) override;
         std::optional<std::string> getLabel(Napi::Env) override;
         void setLabel(Napi::Env, std::optional<std::string> value) override;
 
diff --git a/src/dawn_node/binding/GPUComputePassEncoder.cpp b/src/dawn_node/binding/GPUComputePassEncoder.cpp
index 4cf3caf..6edc467 100644
--- a/src/dawn_node/binding/GPUComputePassEncoder.cpp
+++ b/src/dawn_node/binding/GPUComputePassEncoder.cpp
@@ -38,9 +38,9 @@
 
     void GPUComputePassEncoder::dispatch(Napi::Env,
                                          interop::GPUSize32 x,
-                                         std::optional<interop::GPUSize32> y,
-                                         std::optional<interop::GPUSize32> z) {
-        enc_.Dispatch(x, y.value_or(1), z.value_or(1));
+                                         interop::GPUSize32 y,
+                                         interop::GPUSize32 z) {
+        enc_.Dispatch(x, y, z);
     }
 
     void GPUComputePassEncoder::dispatchIndirect(
@@ -82,29 +82,17 @@
         Napi::Env env,
         interop::GPUIndex32 index,
         interop::Interface<interop::GPUBindGroup> bindGroup,
-        std::optional<std::vector<interop::GPUBufferDynamicOffset>> dynamicOffsets) {
+        std::vector<interop::GPUBufferDynamicOffset> dynamicOffsets) {
         Converter conv(env);
 
         wgpu::BindGroup bg{};
-        if (!conv(bg, bindGroup)) {
+        uint32_t* offsets = nullptr;
+        uint32_t num_offsets = 0;
+        if (!conv(bg, bindGroup) || !conv(offsets, num_offsets, dynamicOffsets)) {
             return;
         }
-        std::vector<uint32_t> offsets;
-        if (dynamicOffsets.has_value() && dynamicOffsets->size() > 0) {
-            offsets.resize(dynamicOffsets->size());
-            for (size_t i = 0; i < offsets.size(); i++) {
-                if (!conv(offsets[i], dynamicOffsets.value()[i])) {
-                    return;
-                }
-            }
-            uint32_t offsets_size;
-            if (!conv(offsets_size, offsets.size())) {
-                return;
-            }
-            enc_.SetBindGroup(index, bg, offsets_size, offsets.data());
-        } else {
-            enc_.SetBindGroup(index, bg);
-        }
+
+        enc_.SetBindGroup(index, bg, num_offsets, offsets);
     }
 
     void GPUComputePassEncoder::setBindGroup(Napi::Env env,
diff --git a/src/dawn_node/binding/GPUComputePassEncoder.h b/src/dawn_node/binding/GPUComputePassEncoder.h
index f387ca0..9c7064b 100644
--- a/src/dawn_node/binding/GPUComputePassEncoder.h
+++ b/src/dawn_node/binding/GPUComputePassEncoder.h
@@ -38,8 +38,8 @@
                          interop::Interface<interop::GPUComputePipeline> pipeline) override;
         void dispatch(Napi::Env,
                       interop::GPUSize32 x,
-                      std::optional<interop::GPUSize32> y,
-                      std::optional<interop::GPUSize32> z) override;
+                      interop::GPUSize32 y,
+                      interop::GPUSize32 z) override;
         void dispatchIndirect(Napi::Env,
                               interop::Interface<interop::GPUBuffer> indirectBuffer,
                               interop::GPUSize64 indirectOffset) override;
@@ -51,11 +51,10 @@
                             interop::Interface<interop::GPUQuerySet> querySet,
                             interop::GPUSize32 queryIndex) override;
         void endPass(Napi::Env) override;
-        void setBindGroup(
-            Napi::Env,
-            interop::GPUIndex32 index,
-            interop::Interface<interop::GPUBindGroup> bindGroup,
-            std::optional<std::vector<interop::GPUBufferDynamicOffset>> dynamicOffsets) override;
+        void setBindGroup(Napi::Env,
+                          interop::GPUIndex32 index,
+                          interop::Interface<interop::GPUBindGroup> bindGroup,
+                          std::vector<interop::GPUBufferDynamicOffset> dynamicOffsets) override;
         void setBindGroup(Napi::Env,
                           interop::GPUIndex32 index,
                           interop::Interface<interop::GPUBindGroup> bindGroup,
diff --git a/src/dawn_node/binding/GPUDevice.cpp b/src/dawn_node/binding/GPUDevice.cpp
index 21cd40d..73b5e18 100644
--- a/src/dawn_node/binding/GPUDevice.cpp
+++ b/src/dawn_node/binding/GPUDevice.cpp
@@ -172,28 +172,24 @@
 
     interop::Interface<interop::GPUSampler> GPUDevice::createSampler(
         Napi::Env env,
-        std::optional<interop::GPUSamplerDescriptor> descriptor) {
+        interop::GPUSamplerDescriptor descriptor) {
         Converter conv(env);
 
-        if (descriptor.has_value()) {
-            wgpu::SamplerDescriptor desc{};
-            if (!conv(desc.label, descriptor->label) ||                //
-                !conv(desc.addressModeU, descriptor->addressModeU) ||  //
-                !conv(desc.addressModeV, descriptor->addressModeV) ||  //
-                !conv(desc.addressModeW, descriptor->addressModeW) ||  //
-                !conv(desc.magFilter, descriptor->magFilter) ||        //
-                !conv(desc.minFilter, descriptor->minFilter) ||        //
-                !conv(desc.mipmapFilter, descriptor->mipmapFilter) ||  //
-                !conv(desc.lodMinClamp, descriptor->lodMinClamp) ||    //
-                !conv(desc.lodMaxClamp, descriptor->lodMaxClamp) ||    //
-                !conv(desc.compare, descriptor->compare) ||            //
-                !conv(desc.maxAnisotropy, descriptor->maxAnisotropy)) {
-                return {};
-            }
-            return interop::GPUSampler::Create<GPUSampler>(env, device_.CreateSampler(&desc));
+        wgpu::SamplerDescriptor desc{};
+        if (!conv(desc.label, descriptor.label) ||                //
+            !conv(desc.addressModeU, descriptor.addressModeU) ||  //
+            !conv(desc.addressModeV, descriptor.addressModeV) ||  //
+            !conv(desc.addressModeW, descriptor.addressModeW) ||  //
+            !conv(desc.magFilter, descriptor.magFilter) ||        //
+            !conv(desc.minFilter, descriptor.minFilter) ||        //
+            !conv(desc.mipmapFilter, descriptor.mipmapFilter) ||  //
+            !conv(desc.lodMinClamp, descriptor.lodMinClamp) ||    //
+            !conv(desc.lodMaxClamp, descriptor.lodMaxClamp) ||    //
+            !conv(desc.compare, descriptor.compare) ||            //
+            !conv(desc.maxAnisotropy, descriptor.maxAnisotropy)) {
+            return {};
         }
-
-        return interop::GPUSampler::Create<GPUSampler>(env, device_.CreateSampler());
+        return interop::GPUSampler::Create<GPUSampler>(env, device_.CreateSampler(&desc));
     }
 
     interop::Interface<interop::GPUExternalTexture> GPUDevice::importExternalTexture(
@@ -374,7 +370,7 @@
 
     interop::Interface<interop::GPUCommandEncoder> GPUDevice::createCommandEncoder(
         Napi::Env env,
-        std::optional<interop::GPUCommandEncoderDescriptor> descriptor) {
+        interop::GPUCommandEncoderDescriptor descriptor) {
         wgpu::CommandEncoderDescriptor desc{};
         return interop::GPUCommandEncoder::Create<GPUCommandEncoder>(
             env, device_.CreateCommandEncoder(&desc));
diff --git a/src/dawn_node/binding/GPUDevice.h b/src/dawn_node/binding/GPUDevice.h
index f04fba8..a3c5dce 100644
--- a/src/dawn_node/binding/GPUDevice.h
+++ b/src/dawn_node/binding/GPUDevice.h
@@ -40,7 +40,7 @@
             interop::GPUTextureDescriptor descriptor) override;
         interop::Interface<interop::GPUSampler> createSampler(
             Napi::Env,
-            std::optional<interop::GPUSamplerDescriptor> descriptor) override;
+            interop::GPUSamplerDescriptor descriptor) override;
         interop::Interface<interop::GPUExternalTexture> importExternalTexture(
             Napi::Env,
             interop::GPUExternalTextureDescriptor descriptor) override;
@@ -70,7 +70,7 @@
             interop::GPURenderPipelineDescriptor descriptor) override;
         interop::Interface<interop::GPUCommandEncoder> createCommandEncoder(
             Napi::Env env,
-            std::optional<interop::GPUCommandEncoderDescriptor> descriptor) override;
+            interop::GPUCommandEncoderDescriptor descriptor) override;
         interop::Interface<interop::GPURenderBundleEncoder> createRenderBundleEncoder(
             Napi::Env,
             interop::GPURenderBundleEncoderDescriptor descriptor) override;
diff --git a/src/dawn_node/binding/GPUQueue.cpp b/src/dawn_node/binding/GPUQueue.cpp
index 92ad948..c8e39fe 100644
--- a/src/dawn_node/binding/GPUQueue.cpp
+++ b/src/dawn_node/binding/GPUQueue.cpp
@@ -73,7 +73,7 @@
                                interop::Interface<interop::GPUBuffer> buffer,
                                interop::GPUSize64 bufferOffset,
                                interop::BufferSource data,
-                               std::optional<interop::GPUSize64> dataOffset,
+                               interop::GPUSize64 dataOffset,
                                std::optional<interop::GPUSize64> size) {
         wgpu::Buffer buf = *buffer.As<GPUBuffer>();
         Converter::BufferSource src{};
@@ -83,12 +83,10 @@
         }
 
         // TODO(crbug.com/dawn/1132): Bounds check
-        if (dataOffset.has_value()) {
-            if (src.data) {
-                src.data = reinterpret_cast<uint8_t*>(src.data) + dataOffset.value();
-            }
-            src.size -= dataOffset.value();
+        if (src.data) {
+            src.data = reinterpret_cast<uint8_t*>(src.data) + dataOffset;
         }
+        src.size -= dataOffset;
         if (size.has_value()) {
             src.size = size.value();
         }
diff --git a/src/dawn_node/binding/GPUQueue.h b/src/dawn_node/binding/GPUQueue.h
index 5375120..69952c6 100644
--- a/src/dawn_node/binding/GPUQueue.h
+++ b/src/dawn_node/binding/GPUQueue.h
@@ -37,7 +37,7 @@
                          interop::Interface<interop::GPUBuffer> buffer,
                          interop::GPUSize64 bufferOffset,
                          interop::BufferSource data,
-                         std::optional<interop::GPUSize64> dataOffset,
+                         interop::GPUSize64 dataOffset,
                          std::optional<interop::GPUSize64> size) override;
         void writeTexture(Napi::Env,
                           interop::GPUImageCopyTexture destination,
diff --git a/src/dawn_node/binding/GPURenderBundleEncoder.cpp b/src/dawn_node/binding/GPURenderBundleEncoder.cpp
index 796f84b..123741d 100644
--- a/src/dawn_node/binding/GPURenderBundleEncoder.cpp
+++ b/src/dawn_node/binding/GPURenderBundleEncoder.cpp
@@ -32,7 +32,7 @@
 
     interop::Interface<interop::GPURenderBundle> GPURenderBundleEncoder::finish(
         Napi::Env env,
-        std::optional<interop::GPURenderBundleDescriptor> descriptor) {
+        interop::GPURenderBundleDescriptor descriptor) {
         wgpu::RenderBundleDescriptor desc{};
 
         return interop::GPURenderBundle::Create<GPURenderBundle>(env, enc_.Finish(&desc));
@@ -42,21 +42,17 @@
         Napi::Env env,
         interop::GPUIndex32 index,
         interop::Interface<interop::GPUBindGroup> bindGroup,
-        std::optional<std::vector<interop::GPUBufferDynamicOffset>> dynamicOffsets) {
+        std::vector<interop::GPUBufferDynamicOffset> dynamicOffsets) {
         Converter conv(env);
 
         wgpu::BindGroup bg{};
-        if (!conv(bg, bindGroup)) {
+        uint32_t* offsets = nullptr;
+        uint32_t num_offsets = 0;
+        if (!conv(bg, bindGroup) || !conv(offsets, num_offsets, dynamicOffsets)) {
             return;
         }
-        uint32_t* offsets = nullptr;
-        uint32_t offset_count = 0;
-        if (dynamicOffsets.has_value() && dynamicOffsets->size() > 0) {
-            if (!conv(offsets, offset_count, dynamicOffsets.value())) {
-                return;
-            }
-        }
-        enc_.SetBindGroup(index, bg, offset_count, offsets);
+
+        enc_.SetBindGroup(index, bg, num_offsets, offsets);
     }
 
     void GPURenderBundleEncoder::setBindGroup(Napi::Env env,
@@ -104,14 +100,14 @@
     void GPURenderBundleEncoder::setIndexBuffer(Napi::Env env,
                                                 interop::Interface<interop::GPUBuffer> buffer,
                                                 interop::GPUIndexFormat indexFormat,
-                                                std::optional<interop::GPUSize64> offset,
+                                                interop::GPUSize64 offset,
                                                 std::optional<interop::GPUSize64> size) {
         Converter conv(env);
 
         wgpu::Buffer b{};
         wgpu::IndexFormat f{};
         uint64_t o = 0;
-        uint64_t s = 0;
+        uint64_t s = wgpu::kWholeSize;
         if (!conv(b, buffer) ||       //
             !conv(f, indexFormat) ||  //
             !conv(o, offset) ||       //
@@ -125,68 +121,33 @@
     void GPURenderBundleEncoder::setVertexBuffer(Napi::Env env,
                                                  interop::GPUIndex32 slot,
                                                  interop::Interface<interop::GPUBuffer> buffer,
-                                                 std::optional<interop::GPUSize64> offset,
+                                                 interop::GPUSize64 offset,
                                                  std::optional<interop::GPUSize64> size) {
         Converter conv(env);
 
-        uint32_t s = 0;
         wgpu::Buffer b{};
-        uint64_t o = 0;
-        uint64_t sz = 0;
-        if (!conv(s, slot) ||    //
-            !conv(b, buffer) ||  //
-            !conv(o, offset) ||  //
-            !conv(sz, size)) {
+        uint64_t s = wgpu::kWholeSize;
+        if (!conv(b, buffer) || !conv(s, size)) {
             return;
         }
-
-        enc_.SetVertexBuffer(s, b, o, sz);
+        enc_.SetVertexBuffer(slot, b, offset, s);
     }
 
     void GPURenderBundleEncoder::draw(Napi::Env env,
                                       interop::GPUSize32 vertexCount,
-                                      std::optional<interop::GPUSize32> instanceCount,
-                                      std::optional<interop::GPUSize32> firstVertex,
-                                      std::optional<interop::GPUSize32> firstInstance) {
-        Converter conv(env);
-
-        uint32_t vc = 0;
-        uint32_t ic = 1;
-        uint32_t fv = 0;
-        uint32_t fi = 0;
-        if (!conv(vc, vertexCount) ||    //
-            !conv(ic, instanceCount) ||  //
-            !conv(fv, firstVertex) ||    //
-            !conv(fi, firstInstance)) {
-            return;
-        }
-
-        enc_.Draw(vc, ic, fv, fi);
+                                      interop::GPUSize32 instanceCount,
+                                      interop::GPUSize32 firstVertex,
+                                      interop::GPUSize32 firstInstance) {
+        enc_.Draw(vertexCount, instanceCount, firstVertex, firstInstance);
     }
 
     void GPURenderBundleEncoder::drawIndexed(Napi::Env env,
                                              interop::GPUSize32 indexCount,
-                                             std::optional<interop::GPUSize32> instanceCount,
-                                             std::optional<interop::GPUSize32> firstIndex,
-                                             std::optional<interop::GPUSignedOffset32> baseVertex,
-                                             std::optional<interop::GPUSize32> firstInstance) {
-        Converter conv(env);
-
-        uint32_t idx_c = 0;
-        uint32_t ins_c = 1;
-        uint32_t f_idx = 0;
-        int32_t bv = 0;
-        uint32_t f_ins = 0;
-
-        if (!conv(idx_c, indexCount) ||     //
-            !conv(ins_c, instanceCount) ||  //
-            !conv(f_idx, firstIndex) ||     //
-            !conv(bv, baseVertex) ||        //
-            !conv(f_ins, firstInstance)) {
-            return;
-        }
-
-        enc_.DrawIndexed(idx_c, ins_c, f_idx, bv, f_ins);
+                                             interop::GPUSize32 instanceCount,
+                                             interop::GPUSize32 firstIndex,
+                                             interop::GPUSignedOffset32 baseVertex,
+                                             interop::GPUSize32 firstInstance) {
+        enc_.DrawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
     }
 
     void GPURenderBundleEncoder::drawIndirect(Napi::Env env,
diff --git a/src/dawn_node/binding/GPURenderBundleEncoder.h b/src/dawn_node/binding/GPURenderBundleEncoder.h
index e9ee6b2..3d11e33 100644
--- a/src/dawn_node/binding/GPURenderBundleEncoder.h
+++ b/src/dawn_node/binding/GPURenderBundleEncoder.h
@@ -31,12 +31,11 @@
         // interop::GPURenderBundleEncoder interface compliance
         interop::Interface<interop::GPURenderBundle> finish(
             Napi::Env,
-            std::optional<interop::GPURenderBundleDescriptor> descriptor) override;
-        void setBindGroup(
-            Napi::Env,
-            interop::GPUIndex32 index,
-            interop::Interface<interop::GPUBindGroup> bindGroup,
-            std::optional<std::vector<interop::GPUBufferDynamicOffset>> dynamicOffsets) override;
+            interop::GPURenderBundleDescriptor descriptor) override;
+        void setBindGroup(Napi::Env,
+                          interop::GPUIndex32 index,
+                          interop::Interface<interop::GPUBindGroup> bindGroup,
+                          std::vector<interop::GPUBufferDynamicOffset> dynamicOffsets) override;
         void setBindGroup(Napi::Env,
                           interop::GPUIndex32 index,
                           interop::Interface<interop::GPUBindGroup> bindGroup,
@@ -51,24 +50,24 @@
         void setIndexBuffer(Napi::Env,
                             interop::Interface<interop::GPUBuffer> buffer,
                             interop::GPUIndexFormat indexFormat,
-                            std::optional<interop::GPUSize64> offset,
+                            interop::GPUSize64 offset,
                             std::optional<interop::GPUSize64> size) override;
         void setVertexBuffer(Napi::Env,
                              interop::GPUIndex32 slot,
                              interop::Interface<interop::GPUBuffer> buffer,
-                             std::optional<interop::GPUSize64> offset,
+                             interop::GPUSize64 offset,
                              std::optional<interop::GPUSize64> size) override;
         void draw(Napi::Env,
                   interop::GPUSize32 vertexCount,
-                  std::optional<interop::GPUSize32> instanceCount,
-                  std::optional<interop::GPUSize32> firstVertex,
-                  std::optional<interop::GPUSize32> firstInstance) override;
+                  interop::GPUSize32 instanceCount,
+                  interop::GPUSize32 firstVertex,
+                  interop::GPUSize32 firstInstance) override;
         void drawIndexed(Napi::Env,
                          interop::GPUSize32 indexCount,
-                         std::optional<interop::GPUSize32> instanceCount,
-                         std::optional<interop::GPUSize32> firstIndex,
-                         std::optional<interop::GPUSignedOffset32> baseVertex,
-                         std::optional<interop::GPUSize32> firstInstance) override;
+                         interop::GPUSize32 instanceCount,
+                         interop::GPUSize32 firstIndex,
+                         interop::GPUSignedOffset32 baseVertex,
+                         interop::GPUSize32 firstInstance) override;
         void drawIndirect(Napi::Env,
                           interop::Interface<interop::GPUBuffer> indirectBuffer,
                           interop::GPUSize64 indirectOffset) override;
diff --git a/src/dawn_node/binding/GPURenderPassEncoder.cpp b/src/dawn_node/binding/GPURenderPassEncoder.cpp
index 4e504ae..5dce4f2 100644
--- a/src/dawn_node/binding/GPURenderPassEncoder.cpp
+++ b/src/dawn_node/binding/GPURenderPassEncoder.cpp
@@ -117,21 +117,17 @@
         Napi::Env env,
         interop::GPUIndex32 index,
         interop::Interface<interop::GPUBindGroup> bindGroup,
-        std::optional<std::vector<interop::GPUBufferDynamicOffset>> dynamicOffsets) {
+        std::vector<interop::GPUBufferDynamicOffset> dynamicOffsets) {
         Converter conv(env);
 
         wgpu::BindGroup bg{};
-        if (!conv(bg, bindGroup)) {
+        uint32_t* offsets = nullptr;
+        uint32_t num_offsets = 0;
+        if (!conv(bg, bindGroup) || !conv(offsets, num_offsets, dynamicOffsets)) {
             return;
         }
-        uint32_t* offsets = nullptr;
-        uint32_t offset_count = 0;
-        if (dynamicOffsets.has_value() && dynamicOffsets->size() > 0) {
-            if (!conv(offsets, offset_count, dynamicOffsets.value())) {
-                return;
-            }
-        }
-        enc_.SetBindGroup(index, bg, offset_count, offsets);
+
+        enc_.SetBindGroup(index, bg, num_offsets, offsets);
     }
 
     void GPURenderPassEncoder::setBindGroup(Napi::Env env,
@@ -177,85 +173,51 @@
     void GPURenderPassEncoder::setIndexBuffer(Napi::Env env,
                                               interop::Interface<interop::GPUBuffer> buffer,
                                               interop::GPUIndexFormat indexFormat,
-                                              std::optional<interop::GPUSize64> offset,
+                                              interop::GPUSize64 offset,
                                               std::optional<interop::GPUSize64> size) {
         Converter conv(env);
 
         wgpu::Buffer b{};
         wgpu::IndexFormat f;
-        uint64_t o = 0;
         uint64_t s = wgpu::kWholeSize;
         if (!conv(b, buffer) ||       //
             !conv(f, indexFormat) ||  //
-            !conv(o, offset) ||       //
             !conv(s, size)) {
             return;
         }
-        enc_.SetIndexBuffer(b, f, o, s);
+        enc_.SetIndexBuffer(b, f, offset, s);
     }
 
     void GPURenderPassEncoder::setVertexBuffer(Napi::Env env,
                                                interop::GPUIndex32 slot,
                                                interop::Interface<interop::GPUBuffer> buffer,
-                                               std::optional<interop::GPUSize64> offset,
+                                               interop::GPUSize64 offset,
                                                std::optional<interop::GPUSize64> size) {
         Converter conv(env);
 
         wgpu::Buffer b{};
-        uint64_t o = 0;
         uint64_t s = wgpu::kWholeSize;
-        if (!conv(b, buffer) ||  //
-            !conv(o, offset) ||  //
-            !conv(s, size)) {
+        if (!conv(b, buffer) || !conv(s, size)) {
             return;
         }
-        enc_.SetVertexBuffer(slot, b, o, s);
+        enc_.SetVertexBuffer(slot, b, offset, s);
     }
 
     void GPURenderPassEncoder::draw(Napi::Env env,
                                     interop::GPUSize32 vertexCount,
-                                    std::optional<interop::GPUSize32> instanceCount,
-                                    std::optional<interop::GPUSize32> firstVertex,
-                                    std::optional<interop::GPUSize32> firstInstance) {
-        Converter conv(env);
-
-        uint32_t vc = 0;
-        uint32_t ic = 1;
-        uint32_t fv = 0;
-        uint32_t fi = 0;
-        if (!conv(vc, vertexCount) ||    //
-            !conv(ic, instanceCount) ||  //
-            !conv(fv, firstVertex) ||    //
-            !conv(fi, firstInstance)) {
-            return;
-        }
-
-        enc_.Draw(vc, ic, fv, fi);
+                                    interop::GPUSize32 instanceCount,
+                                    interop::GPUSize32 firstVertex,
+                                    interop::GPUSize32 firstInstance) {
+        enc_.Draw(vertexCount, instanceCount, firstVertex, firstInstance);
     }
 
     void GPURenderPassEncoder::drawIndexed(Napi::Env env,
                                            interop::GPUSize32 indexCount,
-                                           std::optional<interop::GPUSize32> instanceCount,
-                                           std::optional<interop::GPUSize32> firstIndex,
-                                           std::optional<interop::GPUSignedOffset32> baseVertex,
-                                           std::optional<interop::GPUSize32> firstInstance) {
-        Converter conv(env);
-
-        uint32_t idx_c = 0;
-        uint32_t ins_c = 1;
-        uint32_t f_idx = 0;
-        int32_t bv = 0;
-        uint32_t f_ins = 0;
-
-        if (!conv(idx_c, indexCount) ||     //
-            !conv(ins_c, instanceCount) ||  //
-            !conv(f_idx, firstIndex) ||     //
-            !conv(bv, baseVertex) ||        //
-            !conv(f_ins, firstInstance)) {
-            return;
-        }
-
-        enc_.DrawIndexed(idx_c, ins_c, f_idx, bv, f_ins);
+                                           interop::GPUSize32 instanceCount,
+                                           interop::GPUSize32 firstIndex,
+                                           interop::GPUSignedOffset32 baseVertex,
+                                           interop::GPUSize32 firstInstance) {
+        enc_.DrawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
     }
 
     void GPURenderPassEncoder::drawIndirect(Napi::Env env,
diff --git a/src/dawn_node/binding/GPURenderPassEncoder.h b/src/dawn_node/binding/GPURenderPassEncoder.h
index adde062..866aaab 100644
--- a/src/dawn_node/binding/GPURenderPassEncoder.h
+++ b/src/dawn_node/binding/GPURenderPassEncoder.h
@@ -61,11 +61,10 @@
             Napi::Env,
             std::vector<interop::Interface<interop::GPURenderBundle>> bundles) override;
         void endPass(Napi::Env) override;
-        void setBindGroup(
-            Napi::Env,
-            interop::GPUIndex32 index,
-            interop::Interface<interop::GPUBindGroup> bindGroup,
-            std::optional<std::vector<interop::GPUBufferDynamicOffset>> dynamicOffsets) override;
+        void setBindGroup(Napi::Env,
+                          interop::GPUIndex32 index,
+                          interop::Interface<interop::GPUBindGroup> bindGroup,
+                          std::vector<interop::GPUBufferDynamicOffset> dynamicOffsets) override;
         void setBindGroup(Napi::Env,
                           interop::GPUIndex32 index,
                           interop::Interface<interop::GPUBindGroup> bindGroup,
@@ -80,24 +79,24 @@
         void setIndexBuffer(Napi::Env,
                             interop::Interface<interop::GPUBuffer> buffer,
                             interop::GPUIndexFormat indexFormat,
-                            std::optional<interop::GPUSize64> offset,
+                            interop::GPUSize64 offset,
                             std::optional<interop::GPUSize64> size) override;
         void setVertexBuffer(Napi::Env,
                              interop::GPUIndex32 slot,
                              interop::Interface<interop::GPUBuffer> buffer,
-                             std::optional<interop::GPUSize64> offset,
+                             interop::GPUSize64 offset,
                              std::optional<interop::GPUSize64> size) override;
         void draw(Napi::Env,
                   interop::GPUSize32 vertexCount,
-                  std::optional<interop::GPUSize32> instanceCount,
-                  std::optional<interop::GPUSize32> firstVertex,
-                  std::optional<interop::GPUSize32> firstInstance) override;
+                  interop::GPUSize32 instanceCount,
+                  interop::GPUSize32 firstVertex,
+                  interop::GPUSize32 firstInstance) override;
         void drawIndexed(Napi::Env,
                          interop::GPUSize32 indexCount,
-                         std::optional<interop::GPUSize32> instanceCount,
-                         std::optional<interop::GPUSize32> firstIndex,
-                         std::optional<interop::GPUSignedOffset32> baseVertex,
-                         std::optional<interop::GPUSize32> firstInstance) override;
+                         interop::GPUSize32 instanceCount,
+                         interop::GPUSize32 firstIndex,
+                         interop::GPUSignedOffset32 baseVertex,
+                         interop::GPUSize32 firstInstance) override;
         void drawIndirect(Napi::Env,
                           interop::Interface<interop::GPUBuffer> indirectBuffer,
                           interop::GPUSize64 indirectOffset) override;
diff --git a/src/dawn_node/binding/GPUTexture.cpp b/src/dawn_node/binding/GPUTexture.cpp
index 2ebb785..284cd8a 100644
--- a/src/dawn_node/binding/GPUTexture.cpp
+++ b/src/dawn_node/binding/GPUTexture.cpp
@@ -29,28 +29,24 @@
 
     interop::Interface<interop::GPUTextureView> GPUTexture::createView(
         Napi::Env env,
-        std::optional<interop::GPUTextureViewDescriptor> descriptor) {
+        interop::GPUTextureViewDescriptor descriptor) {
         if (!texture_) {
             Errors::OperationError(env).ThrowAsJavaScriptException();
             return {};
         }
 
-        if (descriptor.has_value()) {
-            wgpu::TextureViewDescriptor desc{};
-            Converter conv(env);
-            if (!conv(desc.baseMipLevel, descriptor->baseMipLevel) ||
-                !conv(desc.mipLevelCount, descriptor->mipLevelCount) ||
-                !conv(desc.baseArrayLayer, descriptor->baseArrayLayer) ||
-                !conv(desc.arrayLayerCount, descriptor->arrayLayerCount) ||
-                !conv(desc.format, descriptor->format) ||
-                !conv(desc.dimension, descriptor->dimension) ||
-                !conv(desc.aspect, descriptor->aspect)) {
-                return {};
-            }
-            return interop::GPUTextureView::Create<GPUTextureView>(env, texture_.CreateView(&desc));
+        wgpu::TextureViewDescriptor desc{};
+        Converter conv(env);
+        if (!conv(desc.baseMipLevel, descriptor.baseMipLevel) ||        //
+            !conv(desc.mipLevelCount, descriptor.mipLevelCount) ||      //
+            !conv(desc.baseArrayLayer, descriptor.baseArrayLayer) ||    //
+            !conv(desc.arrayLayerCount, descriptor.arrayLayerCount) ||  //
+            !conv(desc.format, descriptor.format) ||                    //
+            !conv(desc.dimension, descriptor.dimension) ||              //
+            !conv(desc.aspect, descriptor.aspect)) {
+            return {};
         }
-
-        return interop::GPUTextureView::Create<GPUTextureView>(env, texture_.CreateView());
+        return interop::GPUTextureView::Create<GPUTextureView>(env, texture_.CreateView(&desc));
     }
 
     void GPUTexture::destroy(Napi::Env) {
diff --git a/src/dawn_node/binding/GPUTexture.h b/src/dawn_node/binding/GPUTexture.h
index 0058d87..f5a2a47 100644
--- a/src/dawn_node/binding/GPUTexture.h
+++ b/src/dawn_node/binding/GPUTexture.h
@@ -35,7 +35,7 @@
         // interop::GPUTexture interface compliance
         interop::Interface<interop::GPUTextureView> createView(
             Napi::Env,
-            std::optional<interop::GPUTextureViewDescriptor> descriptor) override;
+            interop::GPUTextureViewDescriptor descriptor) override;
         void destroy(Napi::Env) override;
         std::optional<std::string> getLabel(Napi::Env) override;
         void setLabel(Napi::Env, std::optional<std::string> value) override;
diff --git a/src/dawn_node/interop/Core.h b/src/dawn_node/interop/Core.h
index 4460f9f..e05f0b1 100644
--- a/src/dawn_node/interop/Core.h
+++ b/src/dawn_node/interop/Core.h
@@ -550,16 +550,60 @@
             env, std::forward<T>(value));
     }
 
+    // DefaultedParameter can be used in the tuple parameter types passed to
+    // FromJS(const Napi::CallbackInfo& info, PARAM_TYPES& args), for parameters
+    // that have a default value. If the argument is omitted in the call, then
+    // DefaultedParameter::default_value will be assigned to
+    // DefaultedParameter::value.
+    template <typename T>
+    struct DefaultedParameter {
+        T value;          // The argument value assigned by FromJS()
+        T default_value;  // The default value if no argument supplied
+
+        // Implicit conversion operator. Returns value.
+        inline operator const T&() const {
+            return value;
+        }
+    };
+
+    // IsDefaultedParameter<T>::value is true iff T is of type DefaultedParameter.
+    template <typename T>
+    struct IsDefaultedParameter {
+        static constexpr bool value = false;
+    };
+    template <typename T>
+    struct IsDefaultedParameter<DefaultedParameter<T>> {
+        static constexpr bool value = true;
+    };
+
     // FromJS() is a helper function for bulk converting the arguments of 'info'.
     // PARAM_TYPES is a std::tuple<> describing the C++ function parameter types.
+    // Parameters may be of the templated DefaultedParameter type, in which case
+    // the parameter will default to the default-value if omitted.
     // Returns true on success, false on failure.
     template <typename PARAM_TYPES, int BASE_INDEX = 0>
     inline bool FromJS(const Napi::CallbackInfo& info, PARAM_TYPES& args) {
         if constexpr (BASE_INDEX < std::tuple_size_v<PARAM_TYPES>) {
             using T = std::tuple_element_t<BASE_INDEX, PARAM_TYPES>;
-            if (!FromJS<T>(info.Env(), info[BASE_INDEX], std::get<BASE_INDEX>(args))) {
-                return false;
+            auto& value = info[BASE_INDEX];
+            auto& out = std::get<BASE_INDEX>(args);
+            if constexpr (IsDefaultedParameter<T>::value) {
+                // Parameter has a default value.
+                // Check whether the argument was provided.
+                if (value.IsNull() || value.IsUndefined()) {
+                    // Use default value for this parameter
+                    out.value = out.default_value;
+                } else if (!FromJS(info.Env(), value, out.value)) {
+                    // Argument was provided, but failed to convert.
+                    return false;
+                }
+            } else {
+                // Parameter does not have a default value.
+                if (!FromJS(info.Env(), value, out)) {
+                    return false;
+                }
             }
+            // Convert the rest of the arguments
             return FromJS<PARAM_TYPES, BASE_INDEX + 1>(info, args);
         } else {
             return true;
diff --git a/src/dawn_node/interop/WebGPU.cpp.tmpl b/src/dawn_node/interop/WebGPU.cpp.tmpl
index 0c0dc3fd..9ec75c0 100644
--- a/src/dawn_node/interop/WebGPU.cpp.tmpl
+++ b/src/dawn_node/interop/WebGPU.cpp.tmpl
@@ -181,10 +181,18 @@
         std::tuple<
 {{-        range $i, $p := $o.Parameters}}
 {{-          if $i}}, {{end}}
-{{-          if $p.Optional}}std::optional<{{template "Type" $p.Type}}>
-{{-          else          }}{{template "Type" $p.Type}}
+{{-          if      $p.Init    }}DefaultedParameter<{{template "Type" $p.Type}}>
+{{-          else if $p.Optional}}std::optional<{{template "Type" $p.Type}}>
+{{-          else               }}{{template "Type" $p.Type}}
 {{-          end}}
 {{-        end}}> args;
+
+{{-        range $i, $p := $o.Parameters}}
+{{-          if $p.Init}}
+        std::get<{{$i}} /* {{$p.Name}} */>(args).default_value = {{Eval "Literal" "Value" $p.Init "Type" $p.Type}};
+{{-          end}}
+{{-        end}}
+
         if (FromJS(info, args)) {
           {{/* indent */}}INTEROP_LOG(
 {{-        range $i, $p := $o.Parameters}}
diff --git a/src/dawn_node/interop/WebGPU.h.tmpl b/src/dawn_node/interop/WebGPU.h.tmpl
index 883f33f..e23be0c 100644
--- a/src/dawn_node/interop/WebGPU.h.tmpl
+++ b/src/dawn_node/interop/WebGPU.h.tmpl
@@ -275,9 +275,8 @@
 --------------------------------------------------------------------------------
 */ -}}
 {{- define "Parameter" -}}
-{{-   if $.Optional -}}
-std::optional<{{template "Type" $.Type}}> {{$.Name}}
-{{-   else}}
-{{-     template "Type" $.Type}} {{$.Name}}
-{{-   end}}
+{{-   if      $.Init    }}{{template "Type" $.Type}} {{$.Name}}
+{{-   else if $.Optional}}std::optional<{{template "Type" $.Type}}> {{$.Name}}
+{{-   else              }}{{template "Type" $.Type}} {{$.Name}}
+{{-   end               }}
 {{- end}}