Relax ExternalTexture format validation
This allows planes to be any 1/2 component filterable formats. This
also addes some test cases for Norm16 external textures.
Bug: chromium:1471362
Change-Id: I261b0867c84b0ef4ccee2284c471a55d7b62ea09
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/147861
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Jie A Chen <jie.a.chen@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Peng Huang <penghuang@chromium.org>
diff --git a/src/dawn/native/ExternalTexture.cpp b/src/dawn/native/ExternalTexture.cpp
index 8b082fc..c20ea90 100644
--- a/src/dawn/native/ExternalTexture.cpp
+++ b/src/dawn/native/ExternalTexture.cpp
@@ -55,8 +55,6 @@
DAWN_TRY(device->ValidateObject(descriptor->plane0));
- wgpu::TextureFormat plane0Format = descriptor->plane0->GetFormat().format;
-
DAWN_INVALID_IF(!descriptor->gamutConversionMatrix,
"The gamut conversion matrix must be non-null.");
@@ -66,37 +64,39 @@
DAWN_INVALID_IF(!descriptor->dstTransferFunctionParameters,
"The destination transfer function parameters must be non-null.");
+ DAWN_TRY(ValidateExternalTexturePlane(descriptor->plane0));
+
+ auto CheckPlaneFormat = [](const DeviceBase* device, const Format& format,
+ uint32_t requiredComponentCount) -> MaybeError {
+ DAWN_INVALID_IF(format.aspects != Aspect::Color, "The format (%s) is not a color format.",
+ format.format);
+ DAWN_INVALID_IF(!IsSubset(SampleTypeBit::Float,
+ format.GetAspectInfo(Aspect::Color).supportedSampleTypes),
+ "The format (%s) is not filterable float.", format.format);
+ DAWN_INVALID_IF(format.componentCount != requiredComponentCount,
+ "The format (%s) component count (%u) is not %u.", format.format,
+ requiredComponentCount, format.componentCount);
+ return {};
+ };
+
if (descriptor->plane1) {
DAWN_INVALID_IF(
!descriptor->yuvToRgbConversionMatrix,
"When more than one plane is set, the YUV-to-RGB conversion matrix must be non-null.");
DAWN_TRY(device->ValidateObject(descriptor->plane1));
- wgpu::TextureFormat plane1Format = descriptor->plane1->GetFormat().format;
+ DAWN_TRY(ValidateExternalTexturePlane(descriptor->plane1));
- DAWN_INVALID_IF(plane0Format != wgpu::TextureFormat::R8Unorm,
- "The bi-planar external texture plane (%s) format (%s) is not %s.",
- descriptor->plane0, plane0Format, wgpu::TextureFormat::R8Unorm);
- DAWN_INVALID_IF(plane1Format != wgpu::TextureFormat::RG8Unorm,
- "The bi-planar external texture plane (%s) format (%s) is not %s.",
- descriptor->plane1, plane1Format, wgpu::TextureFormat::RG8Unorm);
-
- DAWN_TRY(ValidateExternalTexturePlane(descriptor->plane0));
+ // Y + UV case.
+ DAWN_TRY_CONTEXT(CheckPlaneFormat(device, descriptor->plane0->GetFormat(), 1),
+ "validating the format of plane 0 (%s)", descriptor->plane0);
+ DAWN_TRY_CONTEXT(CheckPlaneFormat(device, descriptor->plane1->GetFormat(), 2),
+ "validating the format of plane 1 (%s)", descriptor->plane1);
DAWN_TRY(ValidateExternalTexturePlane(descriptor->plane1));
} else {
- switch (plane0Format) {
- case wgpu::TextureFormat::RGBA8Unorm:
- case wgpu::TextureFormat::BGRA8Unorm:
- case wgpu::TextureFormat::RGBA16Float:
- DAWN_TRY(ValidateExternalTexturePlane(descriptor->plane0));
- break;
- default:
- return DAWN_VALIDATION_ERROR(
- "The external texture plane (%s) format (%s) is not a supported format "
- "(%s, %s, %s).",
- descriptor->plane0, plane0Format, wgpu::TextureFormat::RGBA8Unorm,
- wgpu::TextureFormat::BGRA8Unorm, wgpu::TextureFormat::RGBA16Float);
- }
+ // RGBA case.
+ DAWN_TRY_CONTEXT(CheckPlaneFormat(device, descriptor->plane0->GetFormat(), 4),
+ "validating the format of plane 0 (%s)", descriptor->plane0);
}
DAWN_INVALID_IF(descriptor->visibleSize.width == 0 || descriptor->visibleSize.height == 0,
diff --git a/src/dawn/tests/end2end/ExternalTextureTests.cpp b/src/dawn/tests/end2end/ExternalTextureTests.cpp
index 46690c9..06cb928 100644
--- a/src/dawn/tests/end2end/ExternalTextureTests.cpp
+++ b/src/dawn/tests/end2end/ExternalTextureTests.cpp
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <vector>
+
#include "dawn/tests/DawnTest.h"
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
#include "dawn/utils/WGPUHelpers.h"
@@ -98,6 +100,17 @@
}
}
+ std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
+ std::vector<wgpu::FeatureName> requiredFeatures = {};
+ if (SupportsFeatures({wgpu::FeatureName::Norm16TextureFormats})) {
+ mIsNorm16TextureFormatsSupported = true;
+ requiredFeatures.push_back(wgpu::FeatureName::Norm16TextureFormats);
+ }
+ return requiredFeatures;
+ }
+
+ bool IsNorm16TextureFormatsSupported() { return mIsNorm16TextureFormatsSupported; }
+
static constexpr uint32_t kWidth = 4;
static constexpr uint32_t kHeight = 4;
static constexpr wgpu::TextureFormat kFormat = wgpu::TextureFormat::RGBA8Unorm;
@@ -107,6 +120,8 @@
wgpu::ShaderModule vsModule;
wgpu::ShaderModule fsSampleExternalTextureModule;
+
+ bool mIsNorm16TextureFormatsSupported = false;
};
TEST_P(ExternalTextureTests, CreateExternalTextureSuccess) {
@@ -291,6 +306,103 @@
}
}
+TEST_P(ExternalTextureTests, SampleMultiplanarExternalTextureNorm16) {
+ DAWN_TEST_UNSUPPORTED_IF(!IsNorm16TextureFormatsSupported());
+
+ // TODO(crbug.com/tint/1774): Tint has an issue compiling shaders that use external textures on
+ // OpenGL/OpenGLES.
+ DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
+
+ wgpu::Texture sampledTexturePlane0 =
+ Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::R16Unorm,
+ wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
+ wgpu::Texture sampledTexturePlane1 =
+ Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::RG16Unorm,
+ wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
+
+ wgpu::Texture renderTexture =
+ Create2DTexture(device, kWidth, kHeight, kFormat,
+ wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);
+
+ // Create a texture view for the external texture
+ wgpu::TextureView externalViewPlane0 = sampledTexturePlane0.CreateView();
+ wgpu::TextureView externalViewPlane1 = sampledTexturePlane1.CreateView();
+
+ struct ConversionExpectation {
+ double y;
+ double u;
+ double v;
+ utils::RGBA8 rgba;
+ };
+
+ // Conversion expectations for BT.709 YUV source and sRGB destination.
+ std::array<ConversionExpectation, 7> expectations = {
+ {{0.0, .5, .5, utils::RGBA8::kBlack},
+ {0.2126, 0.4172, 1.0, utils::RGBA8::kRed},
+ {0.7152, 0.1402, 0.0175, utils::RGBA8::kGreen},
+ {0.0722, 1.0, 0.4937, utils::RGBA8::kBlue},
+ {0.6382, 0.3232, 0.6644, {246, 169, 90, 255}},
+ {0.5423, 0.5323, 0.4222, {120, 162, 169, 255}},
+ {0.2345, 0.4383, 0.6342, {125, 53, 32, 255}}}};
+
+ for (const ConversionExpectation& expectation : expectations) {
+ // Initialize the texture planes with YUV data
+ {
+ utils::ComboRenderPassDescriptor renderPass({externalViewPlane0, externalViewPlane1},
+ nullptr);
+ renderPass.cColorAttachments[0].clearValue = {expectation.y, 0.0f, 0.0f, 0.0f};
+ renderPass.cColorAttachments[1].clearValue = {expectation.u, expectation.v, 0.0f, 0.0f};
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+ wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
+ pass.End();
+
+ wgpu::CommandBuffer commands = encoder.Finish();
+ queue.Submit(1, &commands);
+ }
+
+ // Pipeline Creation
+ utils::ComboRenderPipelineDescriptor descriptor;
+ descriptor.vertex.module = vsModule;
+ descriptor.cFragment.module = fsSampleExternalTextureModule;
+ descriptor.cTargets[0].format = kFormat;
+ wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
+
+ // Create an ExternalTextureDescriptor from the texture views
+ wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
+ externalDesc.plane0 = externalViewPlane0;
+ externalDesc.plane1 = externalViewPlane1;
+ externalDesc.visibleOrigin = {0, 0};
+ externalDesc.visibleSize = {kWidth, kHeight};
+
+ // Import the external texture
+ wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
+
+ // Create a sampler and bind group
+ wgpu::Sampler sampler = device.CreateSampler();
+
+ wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
+ {{0, sampler}, {1, externalTexture}});
+
+ // Run the shader, which should sample from the external texture and draw a triangle into
+ // the upper left corner of the render texture.
+ wgpu::TextureView renderView = renderTexture.CreateView();
+ utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+ wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
+ {
+ pass.SetPipeline(pipeline);
+ pass.SetBindGroup(0, bindGroup);
+ pass.Draw(3);
+ pass.End();
+ }
+
+ wgpu::CommandBuffer commands = encoder.Finish();
+ queue.Submit(1, &commands);
+
+ EXPECT_PIXEL_RGBA8_EQ(expectation.rgba, renderTexture, 0, 0);
+ }
+}
+
// Test draws a green square in the upper left quadrant, a black square in the upper right, a red
// square in the lower left and a blue square in the lower right. The image is then sampled as an
// external texture and rotated 0, 90, 180, and 270 degrees with and without the y-axis flipped.
diff --git a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
index cdc5680..a786922 100644
--- a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
@@ -407,15 +407,15 @@
// Setting the external texture to an error external texture is an error.
{
- wgpu::Texture errorTexture = CreateTexture(wgpu::TextureUsage::TextureBinding,
- wgpu::TextureFormat::RGBA8UnormSrgb, 1);
- wgpu::ExternalTextureDescriptor errorExternalDesciptor =
+ wgpu::Texture errorTexture =
+ CreateTexture(wgpu::TextureUsage::TextureBinding, wgpu::TextureFormat::R8Unorm, 1);
+ wgpu::ExternalTextureDescriptor errorExternalDescriptor =
CreateDefaultExternalTextureDescriptor();
- errorExternalDesciptor.plane0 = errorTexture.CreateView();
+ errorExternalDescriptor.plane0 = errorTexture.CreateView();
wgpu::ExternalTexture errorExternalTexture;
ASSERT_DEVICE_ERROR(errorExternalTexture =
- device.CreateExternalTexture(&errorExternalDesciptor));
+ device.CreateExternalTexture(&errorExternalDescriptor));
wgpu::ExternalTextureBindingEntry errorExternalBindingEntry;
errorExternalBindingEntry.externalTexture = errorExternalTexture;
diff --git a/src/dawn/tests/unittests/validation/ExternalTextureTests.cpp b/src/dawn/tests/unittests/validation/ExternalTextureTests.cpp
index a6dc44d..9e8d02d 100644
--- a/src/dawn/tests/unittests/validation/ExternalTextureTests.cpp
+++ b/src/dawn/tests/unittests/validation/ExternalTextureTests.cpp
@@ -175,15 +175,32 @@
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
}
- // Creating an external texture with an unsupported format should fail.
+ // Creating an external texture with a non 4-component format should fail.
{
- wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
- textureDescriptor.format = wgpu::TextureFormat::R8Uint;
- wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
+ for (const auto& format : {wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm}) {
+ wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
+ textureDescriptor.format = format;
+ wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
- wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
- externalDesc.plane0 = internalTexture.CreateView();
- ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
+ wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
+ externalDesc.plane0 = internalTexture.CreateView();
+ ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
+ }
+ }
+
+ // Creating an external texture with a non float-filterable format should fail.
+ {
+ for (const auto& format : {wgpu::TextureFormat::RGBA8Uint, wgpu::TextureFormat::RGBA8Sint,
+ wgpu::TextureFormat::RGBA32Uint, wgpu::TextureFormat::RGBA32Sint,
+ wgpu::TextureFormat::RGBA32Float}) {
+ wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
+ textureDescriptor.format = format;
+ wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
+
+ wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
+ externalDesc.plane0 = internalTexture.CreateView();
+ ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
+ }
}
// Creating an external texture with an multisampled texture should fail.
@@ -298,38 +315,125 @@
device.CreateExternalTexture(&externalDesc);
}
- // Creating a multiplanar external texture with an unsupported format for plane0 should
- // result in an error.
+ // Creating a multiplanar external texture with an 1-component float-filterable format for
+ // plane0 should succeed.
{
- wgpu::TextureDescriptor plane0TextureDescriptor =
- CreateTextureDescriptor(kDefaultTextureFormat);
- wgpu::TextureDescriptor plane1TextureDescriptor =
- CreateTextureDescriptor(kBiplanarPlane1Format);
- wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
- wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
+ for (const auto& format : {wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::R16Float}) {
+ wgpu::TextureDescriptor plane0TextureDescriptor = CreateTextureDescriptor(format);
+ wgpu::TextureDescriptor plane1TextureDescriptor =
+ CreateTextureDescriptor(wgpu::TextureFormat::RG8Unorm);
+ wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
+ wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
- wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
- externalDesc.plane0 = texture0.CreateView();
- externalDesc.plane1 = texture1.CreateView();
+ wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
+ externalDesc.plane0 = texture0.CreateView();
+ externalDesc.plane1 = texture1.CreateView();
- ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
+ device.CreateExternalTexture(&externalDesc);
+ }
}
- // Creating a multiplanar external texture with an unsupported format for plane1 should
- // result in an error.
+ // Creating a multiplanar external texture with a 2-component float-filterable format for
+ // plane1 should succeed.
{
- wgpu::TextureDescriptor plane0TextureDescriptor =
- CreateTextureDescriptor(kBiplanarPlane0Format);
- wgpu::TextureDescriptor plane1TextureDescriptor =
- CreateTextureDescriptor(kDefaultTextureFormat);
- wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
- wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
+ for (const auto& format : {wgpu::TextureFormat::RG8Unorm, wgpu::TextureFormat::RG16Float}) {
+ wgpu::TextureDescriptor plane0TextureDescriptor =
+ CreateTextureDescriptor(wgpu::TextureFormat::R8Unorm);
+ wgpu::TextureDescriptor plane1TextureDescriptor = CreateTextureDescriptor(format);
+ wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
+ wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
- wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
- externalDesc.plane0 = texture0.CreateView();
- externalDesc.plane1 = texture1.CreateView();
+ wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
+ externalDesc.plane0 = texture0.CreateView();
+ externalDesc.plane1 = texture1.CreateView();
- ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
+ device.CreateExternalTexture(&externalDesc);
+ }
+ }
+
+ // Creating a multiplanar external texture with an 1-component non float-filterable format for
+ // plane0 should fail.
+ {
+ for (const auto& format : {wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::R8Sint,
+ wgpu::TextureFormat::R16Uint, wgpu::TextureFormat::R16Sint,
+ wgpu::TextureFormat::R32Uint, wgpu::TextureFormat::R32Sint,
+ wgpu::TextureFormat::R32Float}) {
+ wgpu::TextureDescriptor plane0TextureDescriptor = CreateTextureDescriptor(format);
+ wgpu::TextureDescriptor plane1TextureDescriptor =
+ CreateTextureDescriptor(wgpu::TextureFormat::RG8Unorm);
+ wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
+ wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
+
+ wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
+ externalDesc.plane0 = texture0.CreateView();
+ externalDesc.plane1 = texture1.CreateView();
+
+ ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
+ }
+ }
+
+ // Creating a multiplanar external texture with a 2-component non float-filterable format for
+ // plane1 should fail.
+ {
+ for (const auto& format : {wgpu::TextureFormat::RG8Uint, wgpu::TextureFormat::RG8Sint,
+ wgpu::TextureFormat::RG16Uint, wgpu::TextureFormat::RG16Sint,
+ wgpu::TextureFormat::RG32Uint, wgpu::TextureFormat::RG32Sint,
+ wgpu::TextureFormat::RG32Float}) {
+ wgpu::TextureDescriptor plane0TextureDescriptor =
+ CreateTextureDescriptor(wgpu::TextureFormat::R8Unorm);
+ wgpu::TextureDescriptor plane1TextureDescriptor = CreateTextureDescriptor(format);
+ wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
+ wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
+
+ wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
+ externalDesc.plane0 = texture0.CreateView();
+ externalDesc.plane1 = texture1.CreateView();
+
+ ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
+ }
+ }
+
+ // Creating a multiplanar external texture with a non 1-component format for
+ // plane0 should fail.
+ {
+ for (const auto& format :
+ {wgpu::TextureFormat::RG8Unorm, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureFormat::RG8Uint, wgpu::TextureFormat::RGBA8Uint,
+ wgpu::TextureFormat::RG8Sint, wgpu::TextureFormat::RGBA8Sint,
+ wgpu::TextureFormat::RG32Float, wgpu::TextureFormat::RGBA32Float}) {
+ wgpu::TextureDescriptor plane0TextureDescriptor = CreateTextureDescriptor(format);
+ wgpu::TextureDescriptor plane1TextureDescriptor =
+ CreateTextureDescriptor(wgpu::TextureFormat::RG8Unorm);
+ wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
+ wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
+
+ wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
+ externalDesc.plane0 = texture0.CreateView();
+ externalDesc.plane1 = texture1.CreateView();
+
+ ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
+ }
+ }
+
+ // Creating a multiplanar external texture with a non 2-component format for
+ // plane1 should fail.
+ {
+ for (const auto& format :
+ {wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::RGBA8Uint,
+ wgpu::TextureFormat::R32Float, wgpu::TextureFormat::RGBA32Float}) {
+ wgpu::TextureDescriptor plane0TextureDescriptor =
+ CreateTextureDescriptor(wgpu::TextureFormat::R8Unorm);
+ wgpu::TextureDescriptor plane1TextureDescriptor = CreateTextureDescriptor(format);
+ wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
+ wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
+
+ wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
+ externalDesc.plane0 = texture0.CreateView();
+ externalDesc.plane1 = texture1.CreateView();
+
+ ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
+ }
}
}
@@ -643,5 +747,43 @@
}
}
+class ExternalTextureNorm16Test : public ExternalTextureTest {
+ protected:
+ void SetUp() override { ExternalTextureTest::SetUp(); }
+
+ WGPUDevice CreateTestDevice(native::Adapter dawnAdapter,
+ wgpu::DeviceDescriptor descriptor) override {
+ wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::Norm16TextureFormats};
+ descriptor.requiredFeatures = requiredFeatures;
+ descriptor.requiredFeatureCount = 1;
+ return dawnAdapter.CreateDevice(&descriptor);
+ }
+
+ static constexpr wgpu::TextureFormat kBiplanarPlane0FormatNorm16 =
+ wgpu::TextureFormat::R16Unorm;
+ static constexpr wgpu::TextureFormat kBiplanarPlane1FormatNorm16 =
+ wgpu::TextureFormat::RG16Unorm;
+};
+
+// Test that norm16 external texture creation works as expected in multiplane scenarios.
+TEST_F(ExternalTextureNorm16Test, CreateMultiplanarExternalTextureValidation) {
+ // Creating an external texture from two 2D, single-subresource textures with a biplanar
+ // format should succeed.
+ {
+ wgpu::TextureDescriptor plane0TextureDescriptor =
+ CreateTextureDescriptor(kBiplanarPlane0FormatNorm16);
+ wgpu::TextureDescriptor plane1TextureDescriptor =
+ CreateTextureDescriptor(kBiplanarPlane1FormatNorm16);
+ wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
+ wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
+
+ wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
+ externalDesc.plane0 = texture0.CreateView();
+ externalDesc.plane1 = texture1.CreateView();
+
+ device.CreateExternalTexture(&externalDesc);
+ }
+}
+
} // anonymous namespace
} // namespace dawn