diff --git a/src/dawn/node/binding/Converter.cpp b/src/dawn/node/binding/Converter.cpp index b42a8eaa5e..b4614bbd3c 100644 --- a/src/dawn/node/binding/Converter.cpp +++ b/src/dawn/node/binding/Converter.cpp @@ -14,6 +14,8 @@ #include "src/dawn/node/binding/Converter.h" +#include + #include "src/dawn/node/binding/GPUBuffer.h" #include "src/dawn/node/binding/GPUPipelineLayout.h" #include "src/dawn/node/binding/GPUQuerySet.h" @@ -31,6 +33,13 @@ Converter::~Converter() { } } +bool Converter::HasFeature(wgpu::FeatureName feature) { + // Not all uses of the converter will have a device (for example for adapter-related + // conversions). + assert(device.Get() != nullptr); + return device.HasFeature(feature); +} + bool Converter::Convert(wgpu::Extent3D& out, const interop::GPUExtent3D& in) { out = {}; if (auto* dict = std::get_if(&in)) { @@ -172,6 +181,7 @@ bool Converter::Convert(wgpu::TextureDataLayout& out, const interop::GPUImageDat bool Converter::Convert(wgpu::TextureFormat& out, const interop::GPUTextureFormat& in) { out = wgpu::TextureFormat::Undefined; + wgpu::FeatureName requiredFeature = wgpu::FeatureName::Undefined; switch (in) { case interop::GPUTextureFormat::kR8Unorm: out = wgpu::TextureFormat::R8Unorm; @@ -296,168 +306,234 @@ bool Converter::Convert(wgpu::TextureFormat& out, const interop::GPUTextureForma case interop::GPUTextureFormat::kDepth32Float: out = wgpu::TextureFormat::Depth32Float; return true; + case interop::GPUTextureFormat::kDepth32FloatStencil8: out = wgpu::TextureFormat::Depth32FloatStencil8; - return true; + requiredFeature = wgpu::FeatureName::Depth32FloatStencil8; + break; case interop::GPUTextureFormat::kBc1RgbaUnorm: out = wgpu::TextureFormat::BC1RGBAUnorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc1RgbaUnormSrgb: out = wgpu::TextureFormat::BC1RGBAUnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc2RgbaUnorm: out = wgpu::TextureFormat::BC2RGBAUnorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc2RgbaUnormSrgb: out = wgpu::TextureFormat::BC2RGBAUnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc3RgbaUnorm: out = wgpu::TextureFormat::BC3RGBAUnorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc3RgbaUnormSrgb: out = wgpu::TextureFormat::BC3RGBAUnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc4RUnorm: out = wgpu::TextureFormat::BC4RUnorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc4RSnorm: out = wgpu::TextureFormat::BC4RSnorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc5RgUnorm: out = wgpu::TextureFormat::BC5RGUnorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc5RgSnorm: out = wgpu::TextureFormat::BC5RGSnorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc6HRgbUfloat: out = wgpu::TextureFormat::BC6HRGBUfloat; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc6HRgbFloat: out = wgpu::TextureFormat::BC6HRGBFloat; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc7RgbaUnorm: out = wgpu::TextureFormat::BC7RGBAUnorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kBc7RgbaUnormSrgb: out = wgpu::TextureFormat::BC7RGBAUnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionBC; + break; case interop::GPUTextureFormat::kEtc2Rgb8Unorm: out = wgpu::TextureFormat::ETC2RGB8Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionETC2; + break; case interop::GPUTextureFormat::kEtc2Rgb8UnormSrgb: out = wgpu::TextureFormat::ETC2RGB8UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionETC2; + break; case interop::GPUTextureFormat::kEtc2Rgb8A1Unorm: out = wgpu::TextureFormat::ETC2RGB8A1Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionETC2; + break; case interop::GPUTextureFormat::kEtc2Rgb8A1UnormSrgb: out = wgpu::TextureFormat::ETC2RGB8A1UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionETC2; + break; case interop::GPUTextureFormat::kEtc2Rgba8Unorm: out = wgpu::TextureFormat::ETC2RGBA8Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionETC2; + break; case interop::GPUTextureFormat::kEtc2Rgba8UnormSrgb: out = wgpu::TextureFormat::ETC2RGBA8UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionETC2; + break; case interop::GPUTextureFormat::kEacR11Unorm: out = wgpu::TextureFormat::EACR11Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionETC2; + break; case interop::GPUTextureFormat::kEacR11Snorm: out = wgpu::TextureFormat::EACR11Snorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionETC2; + break; case interop::GPUTextureFormat::kEacRg11Unorm: out = wgpu::TextureFormat::EACRG11Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionETC2; + break; case interop::GPUTextureFormat::kEacRg11Snorm: out = wgpu::TextureFormat::EACRG11Snorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionETC2; + break; case interop::GPUTextureFormat::kAstc4X4Unorm: out = wgpu::TextureFormat::ASTC4x4Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc4X4UnormSrgb: out = wgpu::TextureFormat::ASTC4x4UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc5X4Unorm: out = wgpu::TextureFormat::ASTC5x4Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc5X4UnormSrgb: out = wgpu::TextureFormat::ASTC5x4UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc5X5Unorm: out = wgpu::TextureFormat::ASTC5x5Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc5X5UnormSrgb: out = wgpu::TextureFormat::ASTC5x5UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc6X5Unorm: out = wgpu::TextureFormat::ASTC6x5Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc6X5UnormSrgb: out = wgpu::TextureFormat::ASTC6x5UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc6X6Unorm: out = wgpu::TextureFormat::ASTC6x6Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc6X6UnormSrgb: out = wgpu::TextureFormat::ASTC6x6UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc8X5Unorm: out = wgpu::TextureFormat::ASTC8x5Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc8X5UnormSrgb: out = wgpu::TextureFormat::ASTC8x5UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc8X6Unorm: out = wgpu::TextureFormat::ASTC8x6Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc8X6UnormSrgb: out = wgpu::TextureFormat::ASTC8x6UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc8X8Unorm: out = wgpu::TextureFormat::ASTC8x8Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc8X8UnormSrgb: out = wgpu::TextureFormat::ASTC8x8UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc10X5Unorm: out = wgpu::TextureFormat::ASTC10x5Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc10X5UnormSrgb: out = wgpu::TextureFormat::ASTC10x5UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc10X6Unorm: out = wgpu::TextureFormat::ASTC10x6Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc10X6UnormSrgb: out = wgpu::TextureFormat::ASTC10x6UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc10X8Unorm: out = wgpu::TextureFormat::ASTC10x8Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc10X8UnormSrgb: out = wgpu::TextureFormat::ASTC10x8UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc10X10Unorm: out = wgpu::TextureFormat::ASTC10x10Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc10X10UnormSrgb: out = wgpu::TextureFormat::ASTC10x10UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc12X10Unorm: out = wgpu::TextureFormat::ASTC12x10Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc12X10UnormSrgb: out = wgpu::TextureFormat::ASTC12x10UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc12X12Unorm: out = wgpu::TextureFormat::ASTC12x12Unorm; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; case interop::GPUTextureFormat::kAstc12X12UnormSrgb: out = wgpu::TextureFormat::ASTC12x12UnormSrgb; - return true; + requiredFeature = wgpu::FeatureName::TextureCompressionASTC; + break; + + default: + Napi::Error::New(env, "invalid value for GPUTextureFormat") + .ThrowAsJavaScriptException(); + return false; } - Napi::Error::New(env, "invalid value for GPUTextureFormat").ThrowAsJavaScriptException(); - return false; + + assert(requiredFeature != wgpu::FeatureName::Undefined); + if (!HasFeature(requiredFeature)) { + Napi::TypeError::New(env, "invalid value for GPUTextureFormat") + .ThrowAsJavaScriptException(); + return false; + } + + return true; } bool Converter::Convert(interop::GPUTextureFormat& out, wgpu::TextureFormat in) { diff --git a/src/dawn/node/binding/Converter.h b/src/dawn/node/binding/Converter.h index 452cc2e070..564b8a608a 100644 --- a/src/dawn/node/binding/Converter.h +++ b/src/dawn/node/binding/Converter.h @@ -69,6 +69,8 @@ using ImplOf = typename ImplOfTraits::type; class Converter { public: explicit Converter(Napi::Env e) : env(e) {} + Converter(Napi::Env e, wgpu::Device extensionDevice) + : env(e), device(std::move(extensionDevice)) {} ~Converter(); // Conversion function. Converts the interop type IN to the Dawn type OUT. @@ -408,6 +410,9 @@ class Converter { } Napi::Env env; + wgpu::Device device = nullptr; + + bool HasFeature(wgpu::FeatureName feature); // Allocate() allocates and constructs an array of 'n' elements, and returns a pointer to // the first element. The array is freed when the Converter is destructed. diff --git a/src/dawn/node/binding/GPUCommandEncoder.cpp b/src/dawn/node/binding/GPUCommandEncoder.cpp index e5ffa14a00..8e38168a29 100644 --- a/src/dawn/node/binding/GPUCommandEncoder.cpp +++ b/src/dawn/node/binding/GPUCommandEncoder.cpp @@ -31,12 +31,13 @@ namespace wgpu::binding { //////////////////////////////////////////////////////////////////////////////// // wgpu::bindings::GPUCommandEncoder //////////////////////////////////////////////////////////////////////////////// -GPUCommandEncoder::GPUCommandEncoder(wgpu::CommandEncoder enc) : enc_(std::move(enc)) {} +GPUCommandEncoder::GPUCommandEncoder(wgpu::Device device, wgpu::CommandEncoder enc) + : device_(std::move(device)), enc_(std::move(enc)) {} interop::Interface GPUCommandEncoder::beginRenderPass( Napi::Env env, interop::GPURenderPassDescriptor descriptor) { - Converter conv(env); + Converter conv(env, device_); wgpu::RenderPassDescriptor desc{}; wgpu::RenderPassDescriptorMaxDrawCount maxDrawCountDesc{}; diff --git a/src/dawn/node/binding/GPUCommandEncoder.h b/src/dawn/node/binding/GPUCommandEncoder.h index a3878c62bc..3573274e3c 100644 --- a/src/dawn/node/binding/GPUCommandEncoder.h +++ b/src/dawn/node/binding/GPUCommandEncoder.h @@ -28,7 +28,7 @@ namespace wgpu::binding { // wgpu::CommandEncoder. class GPUCommandEncoder final : public interop::GPUCommandEncoder { public: - explicit GPUCommandEncoder(wgpu::CommandEncoder enc); + GPUCommandEncoder(wgpu::Device device, wgpu::CommandEncoder enc); // interop::GPUCommandEncoder interface compliance interop::Interface beginRenderPass( @@ -78,6 +78,7 @@ class GPUCommandEncoder final : public interop::GPUCommandEncoder { void setLabel(Napi::Env, std::string value) override; private: + wgpu::Device device_; wgpu::CommandEncoder enc_; }; diff --git a/src/dawn/node/binding/GPUDevice.cpp b/src/dawn/node/binding/GPUDevice.cpp index 4b512c8edc..b540d501a5 100644 --- a/src/dawn/node/binding/GPUDevice.cpp +++ b/src/dawn/node/binding/GPUDevice.cpp @@ -225,7 +225,7 @@ interop::Interface GPUDevice::createBuffer( interop::Interface GPUDevice::createTexture( Napi::Env env, interop::GPUTextureDescriptor descriptor) { - Converter conv(env); + Converter conv(env, device_); wgpu::TextureDescriptor desc{}; if (!conv(desc.label, descriptor.label) || !conv(desc.usage, descriptor.usage) || // @@ -237,7 +237,7 @@ interop::Interface GPUDevice::createTexture( !conv(desc.viewFormats, desc.viewFormatCount, descriptor.viewFormats)) { return {}; } - return interop::GPUTexture::Create(env, device_.CreateTexture(&desc)); + return interop::GPUTexture::Create(env, device_, device_.CreateTexture(&desc)); } interop::Interface GPUDevice::createSampler( @@ -271,7 +271,7 @@ interop::Interface GPUDevice::importExternalTexture interop::Interface GPUDevice::createBindGroupLayout( Napi::Env env, interop::GPUBindGroupLayoutDescriptor descriptor) { - Converter conv(env); + Converter conv(env, device_); wgpu::BindGroupLayoutDescriptor desc{}; if (!conv(desc.label, descriptor.label) || @@ -345,7 +345,7 @@ interop::Interface GPUDevice::createComputePipeline interop::Interface GPUDevice::createRenderPipeline( Napi::Env env, interop::GPURenderPipelineDescriptor descriptor) { - Converter conv(env); + Converter conv(env, device_); wgpu::RenderPipelineDescriptor desc{}; if (!conv(desc, descriptor)) { @@ -404,7 +404,7 @@ GPUDevice::createRenderPipelineAsync(Napi::Env env, interop::GPURenderPipelineDescriptor descriptor) { using Promise = interop::Promise>; - Converter conv(env); + Converter conv(env, device_); wgpu::RenderPipelineDescriptor desc{}; if (!conv(desc, descriptor)) { @@ -447,13 +447,13 @@ interop::Interface GPUDevice::createCommandEncoder( interop::GPUCommandEncoderDescriptor descriptor) { wgpu::CommandEncoderDescriptor desc{}; return interop::GPUCommandEncoder::Create( - env, device_.CreateCommandEncoder(&desc)); + env, device_, device_.CreateCommandEncoder(&desc)); } interop::Interface GPUDevice::createRenderBundleEncoder( Napi::Env env, interop::GPURenderBundleEncoderDescriptor descriptor) { - Converter conv(env); + Converter conv(env, device_); wgpu::RenderBundleEncoderDescriptor desc{}; if (!conv(desc.label, descriptor.label) || diff --git a/src/dawn/node/binding/GPUTexture.cpp b/src/dawn/node/binding/GPUTexture.cpp index 24c682d87d..7702c81326 100644 --- a/src/dawn/node/binding/GPUTexture.cpp +++ b/src/dawn/node/binding/GPUTexture.cpp @@ -26,7 +26,8 @@ namespace wgpu::binding { //////////////////////////////////////////////////////////////////////////////// // wgpu::bindings::GPUTexture //////////////////////////////////////////////////////////////////////////////// -GPUTexture::GPUTexture(wgpu::Texture texture) : texture_(std::move(texture)) {} +GPUTexture::GPUTexture(wgpu::Device device, wgpu::Texture texture) + : device_(std::move(device)), texture_(std::move(texture)) {} interop::Interface GPUTexture::createView( Napi::Env env, @@ -37,7 +38,7 @@ interop::Interface GPUTexture::createView( } wgpu::TextureViewDescriptor desc{}; - Converter conv(env); + Converter conv(env, device_); if (!conv(desc.baseMipLevel, descriptor.baseMipLevel) || // !conv(desc.mipLevelCount, descriptor.mipLevelCount) || // !conv(desc.baseArrayLayer, descriptor.baseArrayLayer) || // diff --git a/src/dawn/node/binding/GPUTexture.h b/src/dawn/node/binding/GPUTexture.h index e108d78184..d3b20756d6 100644 --- a/src/dawn/node/binding/GPUTexture.h +++ b/src/dawn/node/binding/GPUTexture.h @@ -27,7 +27,7 @@ namespace wgpu::binding { // GPUTexture is an implementation of interop::GPUTexture that wraps a wgpu::Texture. class GPUTexture final : public interop::GPUTexture { public: - explicit GPUTexture(wgpu::Texture texture); + explicit GPUTexture(wgpu::Device device, wgpu::Texture texture); // Implicit cast operator to Dawn GPU object inline operator const wgpu::Texture&() const { return texture_; } @@ -49,6 +49,7 @@ class GPUTexture final : public interop::GPUTexture { void setLabel(Napi::Env, std::string value) override; private: + wgpu::Device device_; wgpu::Texture texture_; };