Add multiplanar usages to SharedTextureMemory if supported by Device
Adjusts SharedTextureMemory to preserve CopyDst and/or RenderAttachment usages for multiplanar textures if the relevant Features are enabled.
Change-Id: Iffaee8bca3724c6558e2169efa39e8c840a2f749
Bug: chromium:1493854
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/162311
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Colin Blundell <blundell@chromium.org>
diff --git a/src/dawn/native/SharedTextureMemory.cpp b/src/dawn/native/SharedTextureMemory.cpp
index bd3be8a..c45fb13 100644
--- a/src/dawn/native/SharedTextureMemory.cpp
+++ b/src/dawn/native/SharedTextureMemory.cpp
@@ -88,10 +88,12 @@
if (!internalFormat.supportsStorageUsage || internalFormat.IsMultiPlanar()) {
mProperties.usage = mProperties.usage & ~wgpu::TextureUsage::StorageBinding;
}
- if (!internalFormat.isRenderable || internalFormat.IsMultiPlanar()) {
+ if (!internalFormat.isRenderable || (internalFormat.IsMultiPlanar() &&
+ !device->HasFeature(Feature::MultiPlanarRenderTargets))) {
mProperties.usage = mProperties.usage & ~wgpu::TextureUsage::RenderAttachment;
}
- if (internalFormat.IsMultiPlanar()) {
+ if (internalFormat.IsMultiPlanar() &&
+ !device->HasFeature(Feature::MultiPlanarFormatExtendedUsages)) {
mProperties.usage = mProperties.usage & ~wgpu::TextureUsage::CopyDst;
}
diff --git a/src/dawn/tests/end2end/SharedTextureMemoryTests.cpp b/src/dawn/tests/end2end/SharedTextureMemoryTests.cpp
index 521a36e..5d6dd99 100644
--- a/src/dawn/tests/end2end/SharedTextureMemoryTests.cpp
+++ b/src/dawn/tests/end2end/SharedTextureMemoryTests.cpp
@@ -44,9 +44,18 @@
if (!SupportsFeatures(features)) {
return {};
}
- if (SupportsFeatures({wgpu::FeatureName::TransientAttachments})) {
- features.push_back(wgpu::FeatureName::TransientAttachments);
+
+ const wgpu::FeatureName kOptionalFeatures[] = {
+ wgpu::FeatureName::MultiPlanarFormatExtendedUsages,
+ wgpu::FeatureName::MultiPlanarRenderTargets,
+ wgpu::FeatureName::TransientAttachments,
+ };
+ for (auto feature : kOptionalFeatures) {
+ if (SupportsFeatures({feature})) {
+ features.push_back(feature);
+ }
}
+
return features;
}
@@ -66,6 +75,22 @@
return memories;
}
+std::vector<wgpu::SharedTextureMemory>
+SharedTextureMemoryTestBackend::CreateSinglePlanarSharedTextureMemories(wgpu::Device& device) {
+ std::vector<wgpu::SharedTextureMemory> out;
+ for (auto& memory : CreateSharedTextureMemories(device)) {
+ wgpu::SharedTextureMemoryProperties properties;
+ memory.GetProperties(&properties);
+
+ if (utils::IsMultiPlanarFormat(properties.format)) {
+ continue;
+ }
+
+ out.push_back(std::move(memory));
+ }
+ return out;
+}
+
std::vector<std::vector<wgpu::SharedTextureMemory>>
SharedTextureMemoryTestBackend::CreatePerDeviceSharedTextureMemoriesFilterByUsage(
const std::vector<wgpu::Device>& devices,
@@ -76,7 +101,17 @@
memories[0].GetProperties(&properties);
if ((properties.usage & requiredUsage) == requiredUsage) {
- out.push_back(std::move(memories));
+ // Tests using RenderAttachment will get a TextureView from the
+ // texture. This currently doesn't work with multiplanar textures. The
+ // superficial problem is that the plane would need to be passed for
+ // multiplanar formats, and the deep problem is that the tests fail to
+ // create valid backing textures for some multiplanar formats (e.g.,
+ // on Apple), which results in a crash when accessing plane 0.
+ // TODO(crbug.com/dawn/2263): Fix this and remove this short-circuit.
+ if (!utils::IsMultiPlanarFormat(properties.format) &&
+ (requiredUsage & wgpu::TextureUsage::RenderAttachment)) {
+ out.push_back(std::move(memories));
+ }
}
}
return out;
@@ -405,29 +440,31 @@
wgpu::TextureUsage expectedUsage =
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding;
- // Additional usages are potentially supported for single-planar
- // formats.
- if (!utils::IsMultiPlanarFormat(properties.format)) {
+ bool isSinglePlanar = !utils::IsMultiPlanarFormat(properties.format);
+
+ if (isSinglePlanar ||
+ device.HasFeature(wgpu::FeatureName::MultiPlanarFormatExtendedUsages)) {
expectedUsage |= wgpu::TextureUsage::CopyDst;
+ }
- // TODO(crbug.com/dawn/2262): RenderAttachment support on D3D11/D3D12 is
- // additionally dependent on the flags passed to the underlying
- // texture (the relevant flag is currently always passed in the test
- // context). Add tests where the D3D texture is not created with the
- // relevant flag.
- if (utils::IsRenderableFormat(device, properties.format)) {
- expectedUsage |= wgpu::TextureUsage::RenderAttachment;
- }
+ // TODO(crbug.com/dawn/2262): RenderAttachment support on D3D11/D3D12 is
+ // additionally dependent on the flags passed to the underlying
+ // texture (the relevant flag is currently always passed in the test
+ // context). Add tests where the D3D texture is not created with the
+ // relevant flag.
+ if ((isSinglePlanar || device.HasFeature(wgpu::FeatureName::MultiPlanarRenderTargets)) &&
+ utils::IsRenderableFormat(device, properties.format)) {
+ expectedUsage |= wgpu::TextureUsage::RenderAttachment;
+ }
- // TODO(crbug.com/dawn/2262): StorageBinding support on D3D11/D3D12 is
- // additionally dependent on the flags passed to the underlying
- // texture (the relevant flag is currently always passed in the test
- // context). Add tests where the D3D texture is not created with the
- // relevant flag.
- if (utils::TextureFormatSupportsStorageTexture(properties.format,
- IsCompatibilityMode())) {
- expectedUsage |= wgpu::TextureUsage::StorageBinding;
- }
+ // TODO(crbug.com/dawn/2262): StorageBinding support on D3D11/D3D12 is
+ // additionally dependent on the flags passed to the underlying
+ // texture (the relevant flag is currently always passed in the test
+ // context). Add tests where the D3D texture is not created with the
+ // relevant flag.
+ if (isSinglePlanar &&
+ utils::TextureFormatSupportsStorageTexture(properties.format, IsCompatibilityMode())) {
+ expectedUsage |= wgpu::TextureUsage::StorageBinding;
}
EXPECT_EQ(properties.usage, expectedUsage) << properties.format;
@@ -706,8 +743,10 @@
// Test that it is valid (does not crash) if the memory is dropped while a texture access has begun.
TEST_P(SharedTextureMemoryTests, TextureAccessOutlivesMemory) {
+ // NOTE: UseInRenderPass()/UseInCopy() do not currently support multiplanar
+ // formats.
for (wgpu::SharedTextureMemory memory :
- GetParam().mBackend->CreateSharedTextureMemories(device)) {
+ GetParam().mBackend->CreateSinglePlanarSharedTextureMemories(device)) {
wgpu::SharedTextureMemoryProperties properties;
memory.GetProperties(&properties);
@@ -722,9 +761,7 @@
// Use the texture on the GPU; it should not crash.
if (properties.usage & wgpu::TextureUsage::RenderAttachment) {
UseInRenderPass(device, texture);
- } else if (properties.format != wgpu::TextureFormat::R8BG8Biplanar420Unorm &&
- properties.format != wgpu::TextureFormat::R10X6BG10X6Biplanar420Unorm &&
- properties.format != wgpu::TextureFormat::R8BG8A8Triplanar420Unorm) {
+ } else {
DAWN_ASSERT(properties.usage & wgpu::TextureUsage::CopySrc);
UseInCopy(device, texture);
}
@@ -819,15 +856,24 @@
// Test that if the texture is uninitialized, EndAccess writes the state out as uninitialized.
TEST_P(SharedTextureMemoryTests, UninitializedOnEndAccess) {
+ // It is not possible to run these tests for multiplanar formats for
+ // multiple reasons:
+ // * Test basic begin+end access exports the state as uninitialized
+ // if it starts as uninitialized. Multiplanar formats must be initialized on import.
+ // * RenderAttachment gets a TextureView from the texture. This has a
+ // superficial problem and a deep problem: The superficial problem is that
+ // the plane would need to be passed for multiplanar formats, and the deep
+ // problem is that the tests fail to create valid backing textures for some multiplanar
+ // formats (e.g., on Apple), which results in a crash when accessing plane
+ // 0.
+ // TODO(crbug.com/dawn/2263): Fix this and change the below to
+ // CreateSharedTextureMemories().
for (wgpu::SharedTextureMemory memory :
- GetParam().mBackend->CreateSharedTextureMemories(device)) {
+ GetParam().mBackend->CreateSinglePlanarSharedTextureMemories(device)) {
wgpu::SharedTextureMemoryProperties properties;
memory.GetProperties(&properties);
- // Test basic begin+end access exports the state as uninitialized
- // if it starts as uninitialized. Skipped for multiplanar formats
- // because those must be initialized on import.
- if (!utils::IsMultiPlanarFormat(properties.format)) {
+ {
wgpu::Texture texture = memory.CreateTexture();
wgpu::SharedTextureMemoryBeginAccessDescriptor beginDesc = {};
diff --git a/src/dawn/tests/end2end/SharedTextureMemoryTests.h b/src/dawn/tests/end2end/SharedTextureMemoryTests.h
index f6523cc..340e75e 100644
--- a/src/dawn/tests/end2end/SharedTextureMemoryTests.h
+++ b/src/dawn/tests/end2end/SharedTextureMemoryTests.h
@@ -63,6 +63,11 @@
// device.
std::vector<wgpu::SharedTextureMemory> CreateSharedTextureMemories(wgpu::Device& device);
+ // Wrapper around CreateSharedTextureMemories() that restricts the returned
+ // vector to only the single-planar instances.
+ std::vector<wgpu::SharedTextureMemory> CreateSinglePlanarSharedTextureMemories(
+ wgpu::Device& device);
+
// Wrapper around CreatePerDeviceSharedTextureMemories that filters the memories by
// usage to ensure they have `requiredUsage`.
std::vector<std::vector<wgpu::SharedTextureMemory>>