Modify External Texture Interface For BiPlanar Formats

Changes dawn.json entry for ExternalTexture to take a secondary plane
and adds wgpu::PredefinedColorSpace. Includes validation tests.

Bug: dawn:1082
Change-Id: I76475e4a1bce6f25c728ac0251ff582ef6369cd1
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/76282
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Brandon1 Jones <brandon1.jones@intel.com>
This commit is contained in:
Brandon Jones 2022-01-25 18:09:00 +00:00 committed by Dawn LUCI CQ
parent 0999cb0371
commit 37b3df4337
7 changed files with 148 additions and 64 deletions

View File

@ -1314,7 +1314,8 @@
"members": [
{"name": "label", "type": "char", "annotation": "const*", "length": "strlen", "optional": true},
{"name": "plane 0", "type": "texture view"},
{"name": "format", "type": "texture format"}
{"name": "plane 1", "type": "texture view", "optional": true},
{"name": "color space", "type": "predefined color space", "default": "srgb"}
]
},
"feature name": {
@ -1507,6 +1508,13 @@
{"value": 2, "name": "high performance"}
]
},
"predefined color space": {
"category": "enum",
"values": [
{"value": 0, "name": "undefined"},
{"value": 1, "name": "srgb"}
]
},
"present mode": {
"category": "enum",
"emscripten_no_enum_table": true,

View File

@ -52,18 +52,41 @@ namespace dawn::native {
wgpu::TextureFormat plane0Format = descriptor->plane0->GetFormat().format;
switch (plane0Format) {
case wgpu::TextureFormat::RGBA8Unorm:
case wgpu::TextureFormat::BGRA8Unorm:
case wgpu::TextureFormat::RGBA16Float:
DAWN_TRY(ValidateExternalTexturePlane(descriptor->plane0));
break;
default:
return DAWN_FORMAT_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);
if (descriptor->plane1) {
DAWN_INVALID_IF(
device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs),
"Bi-planar external textures are disabled until the implementation is completed.");
DAWN_INVALID_IF(descriptor->colorSpace != wgpu::PredefinedColorSpace::Srgb,
"The specified color space (%s) is not %s.", descriptor->colorSpace,
wgpu::PredefinedColorSpace::Srgb);
DAWN_TRY(device->ValidateObject(descriptor->plane1));
wgpu::TextureFormat plane1Format = descriptor->plane1->GetFormat().format;
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));
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_FORMAT_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);
}
}
return {};
@ -75,13 +98,13 @@ namespace dawn::native {
const ExternalTextureDescriptor* descriptor) {
Ref<ExternalTextureBase> externalTexture =
AcquireRef(new ExternalTextureBase(device, descriptor));
DAWN_TRY(externalTexture->Initialize(device, descriptor));
return std::move(externalTexture);
}
ExternalTextureBase::ExternalTextureBase(DeviceBase* device,
const ExternalTextureDescriptor* descriptor)
: ApiObjectBase(device, descriptor->label), mState(ExternalTextureState::Alive) {
textureViews[0] = descriptor->plane0;
TrackInDevice();
}
@ -94,9 +117,18 @@ namespace dawn::native {
: ApiObjectBase(device, tag) {
}
MaybeError ExternalTextureBase::Initialize(DeviceBase* device,
const ExternalTextureDescriptor* descriptor) {
// Store any passed in TextureViews associated with individual planes.
mTextureViews[0] = descriptor->plane0;
mTextureViews[1] = descriptor->plane1;
return {};
}
const std::array<Ref<TextureViewBase>, kMaxPlanesPerFormat>&
ExternalTextureBase::GetTextureViews() const {
return textureViews;
return mTextureViews;
}
MaybeError ExternalTextureBase::ValidateCanUseInSubmitNow() const {

View File

@ -24,7 +24,6 @@
namespace dawn::native {
struct ExternalTextureDescriptor;
class TextureViewBase;
MaybeError ValidateExternalTextureDescriptor(const DeviceBase* device,
@ -39,7 +38,7 @@ namespace dawn::native {
const std::array<Ref<TextureViewBase>, kMaxPlanesPerFormat>& GetTextureViews() const;
MaybeError ValidateCanUseInSubmitNow() const;
MaybeError Initialize(DeviceBase* device, const ExternalTextureDescriptor* descriptor);
static ExternalTextureBase* MakeError(DeviceBase* device);
ObjectType GetType() const override;
@ -55,7 +54,7 @@ namespace dawn::native {
enum class ExternalTextureState { Alive, Destroyed };
ExternalTextureBase(DeviceBase* device, const ExternalTextureDescriptor* descriptor);
ExternalTextureBase(DeviceBase* device, ObjectBase::ErrorTag tag);
std::array<Ref<TextureViewBase>, kMaxPlanesPerFormat> textureViews;
std::array<Ref<TextureViewBase>, kMaxPlanesPerFormat> mTextureViews;
ExternalTextureState mState;
};
} // namespace dawn::native

View File

@ -53,7 +53,6 @@ TEST_P(ExternalTextureTests, CreateExternalTextureSuccess) {
// Create an ExternalTextureDescriptor from the texture view
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.plane0 = view;
externalDesc.format = kFormat;
// Import the external texture
wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
@ -106,7 +105,6 @@ TEST_P(ExternalTextureTests, SampleExternalTexture) {
// Create an ExternalTextureDescriptor from the texture view
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.plane0 = externalView;
externalDesc.format = kFormat;
// Import the external texture
wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

View File

@ -58,7 +58,6 @@ class BindGroupValidationTest : public ValidationTest {
mSampledTextureView = mSampledTexture.CreateView();
wgpu::ExternalTextureDescriptor externalTextureDesc;
externalTextureDesc.format = kDefaultTextureFormat;
externalTextureDesc.plane0 = mSampledTextureView;
mExternalTexture = device.CreateExternalTexture(&externalTextureDesc);
mExternalTextureBindingEntry.externalTexture = mExternalTexture;
@ -311,7 +310,6 @@ TEST_F(BindGroupValidationTest, ExternalTextureBindingType) {
CreateTexture(wgpu::TextureUsage::TextureBinding, kDefaultTextureFormat, 1);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.plane0 = texture.CreateView();
externalDesc.format = kDefaultTextureFormat;
wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
// Create a bind group layout for a single external texture

View File

@ -20,7 +20,8 @@
namespace {
class ExternalTextureTest : public ValidationTest {
public:
wgpu::TextureDescriptor CreateDefaultTextureDescriptor() {
wgpu::TextureDescriptor CreateTextureDescriptor(
wgpu::TextureFormat format = kDefaultTextureFormat) {
wgpu::TextureDescriptor descriptor;
descriptor.size.width = kWidth;
descriptor.size.height = kHeight;
@ -28,9 +29,8 @@ namespace {
descriptor.mipLevelCount = kDefaultMipLevels;
descriptor.sampleCount = kDefaultSampleCount;
descriptor.dimension = wgpu::TextureDimension::e2D;
descriptor.format = kDefaultTextureFormat;
descriptor.usage =
wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
descriptor.format = format;
descriptor.usage = kDefaultUsage;
return descriptor;
}
@ -46,9 +46,13 @@ namespace {
static constexpr uint32_t kDefaultDepth = 1;
static constexpr uint32_t kDefaultMipLevels = 1;
static constexpr uint32_t kDefaultSampleCount = 1;
static constexpr wgpu::TextureUsage kDefaultUsage =
wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
static constexpr wgpu::TextureFormat kDefaultTextureFormat =
wgpu::TextureFormat::RGBA8Unorm;
static constexpr wgpu::TextureFormat kBiplanarPlane0Format = wgpu::TextureFormat::R8Unorm;
static constexpr wgpu::TextureFormat kBiplanarPlane1Format = wgpu::TextureFormat::RG8Unorm;
wgpu::Queue queue;
};
@ -56,47 +60,32 @@ namespace {
TEST_F(ExternalTextureTest, CreateExternalTextureValidation) {
// Creating an external texture from a 2D, single-subresource texture should succeed.
{
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.format = kDefaultTextureFormat;
externalDesc.plane0 = texture.CreateView();
device.CreateExternalTexture(&externalDesc);
}
// Creating an external texture with a mismatched texture view format should fail.
{
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
textureDescriptor.format = wgpu::TextureFormat::RGBA8Uint;
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.format = kDefaultTextureFormat;
externalDesc.plane0 = texture.CreateView();
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
}
// Creating an external texture from a non-2D texture should fail.
{
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
textureDescriptor.dimension = wgpu::TextureDimension::e3D;
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.format = kDefaultTextureFormat;
externalDesc.plane0 = internalTexture.CreateView();
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
}
// Creating an external texture from a texture with mip count > 1 should fail.
{
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
textureDescriptor.mipLevelCount = 2;
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.format = kDefaultTextureFormat;
externalDesc.plane0 = internalTexture.CreateView();
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
}
@ -104,43 +93,40 @@ namespace {
// Creating an external texture from a texture without TextureUsage::TextureBinding should
// fail.
{
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
textureDescriptor.mipLevelCount = 2;
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.format = kDefaultTextureFormat;
externalDesc.plane0 = internalTexture.CreateView();
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
}
// Creating an external texture with an unsupported format should fail.
{
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
textureDescriptor.format = wgpu::TextureFormat::R8Uint;
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.plane0 = internalTexture.CreateView();
externalDesc.format = textureDescriptor.format;
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
}
// Creating an external texture with an multisampled texture should fail.
{
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
textureDescriptor.sampleCount = 4;
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.format = kDefaultTextureFormat;
externalDesc.plane0 = internalTexture.CreateView();
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
}
// Creating an external texture with an error texture view should fail.
{
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
wgpu::TextureViewDescriptor errorViewDescriptor;
@ -152,9 +138,77 @@ namespace {
internalTexture.CreateView(&errorViewDescriptor));
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.format = kDefaultTextureFormat;
externalDesc.plane0 = errorTextureView;
externalDesc.format = kDefaultTextureFormat;
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
}
}
// Test that external texture creation works as expected in multiplane scenarios.
TEST_F(ExternalTextureTest, CreateMultiplanarExternalTextureValidation) {
// Creating an external texture from two 2D, single-subresource textures with a biplanar
// format should succeed.
{
wgpu::TextureDescriptor plane0TextureDescriptor =
CreateTextureDescriptor(kBiplanarPlane0Format);
wgpu::TextureDescriptor plane1TextureDescriptor =
CreateTextureDescriptor(kBiplanarPlane1Format);
wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.plane0 = texture0.CreateView();
externalDesc.plane1 = texture1.CreateView();
device.CreateExternalTexture(&externalDesc);
}
// Creating a multiplanar external texture with an unsupported format for plane0 should
// result in an error.
{
wgpu::TextureDescriptor plane0TextureDescriptor =
CreateTextureDescriptor(kDefaultTextureFormat);
wgpu::TextureDescriptor plane1TextureDescriptor =
CreateTextureDescriptor(kBiplanarPlane1Format);
wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.plane0 = texture0.CreateView();
externalDesc.plane1 = texture1.CreateView();
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
}
// Creating a multiplanar external texture with an unsupported format for plane1 should
// result in an error.
{
wgpu::TextureDescriptor plane0TextureDescriptor =
CreateTextureDescriptor(kBiplanarPlane0Format);
wgpu::TextureDescriptor plane1TextureDescriptor =
CreateTextureDescriptor(kDefaultTextureFormat);
wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.plane0 = texture0.CreateView();
externalDesc.plane1 = texture1.CreateView();
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
}
// Creating a multiplanar external texture with a non-sRGB color space should fail.
{
wgpu::TextureDescriptor plane0TextureDescriptor =
CreateTextureDescriptor(kBiplanarPlane0Format);
wgpu::TextureDescriptor plane1TextureDescriptor =
CreateTextureDescriptor(kBiplanarPlane1Format);
wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.plane0 = texture0.CreateView();
externalDesc.plane1 = texture1.CreateView();
externalDesc.colorSpace = wgpu::PredefinedColorSpace::Undefined;
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
}
}
@ -162,11 +216,10 @@ namespace {
// Test that submitting a render pass that contains a destroyed external texture results in
// an error.
TEST_F(ExternalTextureTest, SubmitDestroyedExternalTextureInRenderPass) {
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.format = kDefaultTextureFormat;
externalDesc.plane0 = texture.CreateView();
wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
@ -176,7 +229,7 @@ namespace {
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
// Create another texture to use as a color attachment.
wgpu::TextureDescriptor renderTextureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor renderTextureDescriptor = CreateTextureDescriptor();
wgpu::Texture renderTexture = device.CreateTexture(&renderTextureDescriptor);
wgpu::TextureView renderView = renderTexture.CreateView();
@ -214,11 +267,10 @@ namespace {
// Test that submitting a render pass that contains a destroyed external texture plane
// results in an error.
TEST_F(ExternalTextureTest, SubmitDestroyedExternalTexturePlaneInRenderPass) {
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.format = kDefaultTextureFormat;
externalDesc.plane0 = texture.CreateView();
wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
@ -228,7 +280,7 @@ namespace {
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
// Create another texture to use as a color attachment.
wgpu::TextureDescriptor renderTextureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor renderTextureDescriptor = CreateTextureDescriptor();
wgpu::Texture renderTexture = device.CreateTexture(&renderTextureDescriptor);
wgpu::TextureView renderView = renderTexture.CreateView();
@ -266,11 +318,10 @@ namespace {
// Test that submitting a compute pass that contains a destroyed external texture results in
// an error.
TEST_F(ExternalTextureTest, SubmitDestroyedExternalTextureInComputePass) {
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.format = kDefaultTextureFormat;
externalDesc.plane0 = texture.CreateView();
wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
@ -313,11 +364,10 @@ namespace {
// Test that submitting a compute pass that contains a destroyed external texture plane
// results in an error.
TEST_F(ExternalTextureTest, SubmitDestroyedExternalTexturePlaneInComputePass) {
wgpu::TextureDescriptor textureDescriptor = CreateDefaultTextureDescriptor();
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor externalDesc;
externalDesc.format = kDefaultTextureFormat;
externalDesc.plane0 = texture.CreateView();
wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

View File

@ -228,7 +228,6 @@ TEST_F(LabelTest, ExternalTexture) {
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
wgpu::ExternalTextureDescriptor descriptor;
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
descriptor.plane0 = texture.CreateView();
// The label should be empty if one was not set.