node: Throw a TypeError for unsupported GPUTextureFormats
The WebGPU spec requires this so that an extension not being enabled or
not implemented by the browser both behave the same.
Bug: None
Change-Id: Iba449c1f67d266aa53b924501577d646cd944f55
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112421
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/node/binding/Converter.cpp b/src/dawn/node/binding/Converter.cpp
index b42a8ea..b4614bb 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 <cassert>
+
#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 @@
}
}
+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<interop::GPUExtent3DDict>(&in)) {
@@ -172,6 +181,7 @@
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 @@
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 452cc2e..564b8a6 100644
--- a/src/dawn/node/binding/Converter.h
+++ b/src/dawn/node/binding/Converter.h
@@ -69,6 +69,8 @@
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 @@
}
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 e5ffa14..8e38168 100644
--- a/src/dawn/node/binding/GPUCommandEncoder.cpp
+++ b/src/dawn/node/binding/GPUCommandEncoder.cpp
@@ -31,12 +31,13 @@
////////////////////////////////////////////////////////////////////////////////
// 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<interop::GPURenderPassEncoder> 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 a3878c6..3573274 100644
--- a/src/dawn/node/binding/GPUCommandEncoder.h
+++ b/src/dawn/node/binding/GPUCommandEncoder.h
@@ -28,7 +28,7 @@
// 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<interop::GPURenderPassEncoder> beginRenderPass(
@@ -78,6 +78,7 @@
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 4b512c8..b540d50 100644
--- a/src/dawn/node/binding/GPUDevice.cpp
+++ b/src/dawn/node/binding/GPUDevice.cpp
@@ -225,7 +225,7 @@
interop::Interface<interop::GPUTexture> 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 @@
!conv(desc.viewFormats, desc.viewFormatCount, descriptor.viewFormats)) {
return {};
}
- return interop::GPUTexture::Create<GPUTexture>(env, device_.CreateTexture(&desc));
+ return interop::GPUTexture::Create<GPUTexture>(env, device_, device_.CreateTexture(&desc));
}
interop::Interface<interop::GPUSampler> GPUDevice::createSampler(
@@ -271,7 +271,7 @@
interop::Interface<interop::GPUBindGroupLayout> 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<interop::GPURenderPipeline> 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 @@
interop::GPURenderPipelineDescriptor descriptor) {
using Promise = interop::Promise<interop::Interface<interop::GPURenderPipeline>>;
- Converter conv(env);
+ Converter conv(env, device_);
wgpu::RenderPipelineDescriptor desc{};
if (!conv(desc, descriptor)) {
@@ -447,13 +447,13 @@
interop::GPUCommandEncoderDescriptor descriptor) {
wgpu::CommandEncoderDescriptor desc{};
return interop::GPUCommandEncoder::Create<GPUCommandEncoder>(
- env, device_.CreateCommandEncoder(&desc));
+ env, device_, device_.CreateCommandEncoder(&desc));
}
interop::Interface<interop::GPURenderBundleEncoder> 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 24c682d..7702c81 100644
--- a/src/dawn/node/binding/GPUTexture.cpp
+++ b/src/dawn/node/binding/GPUTexture.cpp
@@ -26,7 +26,8 @@
////////////////////////////////////////////////////////////////////////////////
// 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<interop::GPUTextureView> GPUTexture::createView(
Napi::Env env,
@@ -37,7 +38,7 @@
}
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 e108d78..d3b2075 100644
--- a/src/dawn/node/binding/GPUTexture.h
+++ b/src/dawn/node/binding/GPUTexture.h
@@ -27,7 +27,7 @@
// 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 @@
void setLabel(Napi::Env, std::string value) override;
private:
+ wgpu::Device device_;
wgpu::Texture texture_;
};