Add more supported swapchain texture usages.
Adds the CopySrc and CopyDst usages to swapchain textures when
available in backends so that the wgpu::Texture returned from
GetCurrentTexture can be used in copies.
Also adds a swapchain tests to check that these usages indeed
work.
Bug: dawn:1551
Change-Id: I8495075b0bfb5b8dd953a7811a9d75a76096b143
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/133464
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/native/d3d/DeviceD3D.cpp b/src/dawn/native/d3d/DeviceD3D.cpp
index b92f169..6e9b45d 100644
--- a/src/dawn/native/d3d/DeviceD3D.cpp
+++ b/src/dawn/native/d3d/DeviceD3D.cpp
@@ -48,8 +48,9 @@
ResultOrError<wgpu::TextureUsage> Device::GetSupportedSurfaceUsageImpl(
const Surface* surface) const {
- wgpu::TextureUsage usages =
- wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
+ wgpu::TextureUsage usages = wgpu::TextureUsage::RenderAttachment |
+ wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc |
+ wgpu::TextureUsage::CopyDst;
return usages;
}
diff --git a/src/dawn/native/metal/DeviceMTL.mm b/src/dawn/native/metal/DeviceMTL.mm
index 9409cb9..116837b 100644
--- a/src/dawn/native/metal/DeviceMTL.mm
+++ b/src/dawn/native/metal/DeviceMTL.mm
@@ -243,8 +243,9 @@
ResultOrError<wgpu::TextureUsage> Device::GetSupportedSurfaceUsageImpl(
const Surface* surface) const {
- wgpu::TextureUsage usages =
- wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
+ wgpu::TextureUsage usages = wgpu::TextureUsage::RenderAttachment |
+ wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc |
+ wgpu::TextureUsage::CopyDst;
return usages;
}
diff --git a/src/dawn/native/opengl/DeviceGL.cpp b/src/dawn/native/opengl/DeviceGL.cpp
index 356d9c2..4b0cf82 100644
--- a/src/dawn/native/opengl/DeviceGL.cpp
+++ b/src/dawn/native/opengl/DeviceGL.cpp
@@ -255,8 +255,9 @@
ResultOrError<wgpu::TextureUsage> Device::GetSupportedSurfaceUsageImpl(
const Surface* surface) const {
- wgpu::TextureUsage usages =
- wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
+ wgpu::TextureUsage usages = wgpu::TextureUsage::RenderAttachment |
+ wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc |
+ wgpu::TextureUsage::CopyDst;
return usages;
}
diff --git a/src/dawn/native/vulkan/SwapChainVk.cpp b/src/dawn/native/vulkan/SwapChainVk.cpp
index 72b89db..7794804 100644
--- a/src/dawn/native/vulkan/SwapChainVk.cpp
+++ b/src/dawn/native/vulkan/SwapChainVk.cpp
@@ -223,8 +223,16 @@
fn.GetPhysicalDeviceSurfaceCapabilitiesKHR(vkPhysicalDevice, surfaceVk, &surfaceCapsVk),
"GetPhysicalDeviceSurfaceCapabilitiesKHR"));
- wgpu::TextureUsage supportedUsages = wgpu::TextureUsage::RenderAttachment;
-
+ wgpu::TextureUsage supportedUsages = wgpu::TextureUsage::None;
+ if (surfaceCapsVk.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
+ supportedUsages |= wgpu::TextureUsage::CopySrc;
+ }
+ if (surfaceCapsVk.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
+ supportedUsages |= wgpu::TextureUsage::CopyDst;
+ }
+ if (surfaceCapsVk.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
+ supportedUsages |= wgpu::TextureUsage::RenderAttachment;
+ }
if (surfaceCapsVk.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) {
supportedUsages |= wgpu::TextureUsage::TextureBinding;
}
diff --git a/src/dawn/tests/end2end/SwapChainTests.cpp b/src/dawn/tests/end2end/SwapChainTests.cpp
index 8c10fb4..a626d9f 100644
--- a/src/dawn/tests/end2end/SwapChainTests.cpp
+++ b/src/dawn/tests/end2end/SwapChainTests.cpp
@@ -69,8 +69,8 @@
DawnTest::TearDown();
}
- void ClearTexture(wgpu::TextureView view, wgpu::Color color) {
- utils::ComboRenderPassDescriptor desc({view});
+ void ClearTexture(wgpu::Texture texture, wgpu::Color color) {
+ utils::ComboRenderPassDescriptor desc({texture.CreateView()});
desc.cColorAttachments[0].loadOp = wgpu::LoadOp::Clear;
desc.cColorAttachments[0].clearValue = color;
@@ -92,35 +92,35 @@
// Basic test for creating a swapchain and presenting one frame.
TEST_P(SwapChainTests, Basic) {
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
- ClearTexture(swapchain.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
+ ClearTexture(swapchain.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
swapchain.Present();
}
// Test replacing the swapchain
TEST_P(SwapChainTests, ReplaceBasic) {
wgpu::SwapChain swapchain1 = device.CreateSwapChain(surface, &baseDescriptor);
- ClearTexture(swapchain1.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
+ ClearTexture(swapchain1.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
swapchain1.Present();
wgpu::SwapChain swapchain2 = device.CreateSwapChain(surface, &baseDescriptor);
- ClearTexture(swapchain2.GetCurrentTextureView(), {0.0, 1.0, 0.0, 1.0});
+ ClearTexture(swapchain2.GetCurrentTexture(), {0.0, 1.0, 0.0, 1.0});
swapchain2.Present();
}
-// Test replacing the swapchain after GetCurrentTextureView
+// Test replacing the swapchain after GetCurrentTexture
TEST_P(SwapChainTests, ReplaceAfterGet) {
wgpu::SwapChain swapchain1 = device.CreateSwapChain(surface, &baseDescriptor);
- ClearTexture(swapchain1.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
+ ClearTexture(swapchain1.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
wgpu::SwapChain swapchain2 = device.CreateSwapChain(surface, &baseDescriptor);
- ClearTexture(swapchain2.GetCurrentTextureView(), {0.0, 1.0, 0.0, 1.0});
+ ClearTexture(swapchain2.GetCurrentTexture(), {0.0, 1.0, 0.0, 1.0});
swapchain2.Present();
}
-// Test destroying the swapchain after GetCurrentTextureView
+// Test destroying the swapchain after GetCurrentTexture
TEST_P(SwapChainTests, DestroyAfterGet) {
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
- ClearTexture(swapchain.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
+ ClearTexture(swapchain.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
}
// Test destroying the surface before the swapchain
@@ -129,10 +129,10 @@
surface = nullptr;
}
-// Test destroying the surface before the swapchain but after GetCurrentTextureView
+// Test destroying the surface before the swapchain but after GetCurrentTexture
TEST_P(SwapChainTests, DestroySurfaceAfterGet) {
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
- ClearTexture(swapchain.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
+ ClearTexture(swapchain.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
surface = nullptr;
}
@@ -158,12 +158,12 @@
desc.presentMode = mode1;
wgpu::SwapChain swapchain1 = device.CreateSwapChain(surface, &desc);
- ClearTexture(swapchain1.GetCurrentTextureView(), {0.0, 0.0, 0.0, 1.0});
+ ClearTexture(swapchain1.GetCurrentTexture(), {0.0, 0.0, 0.0, 1.0});
swapchain1.Present();
desc.presentMode = mode2;
wgpu::SwapChain swapchain2 = device.CreateSwapChain(surface, &desc);
- ClearTexture(swapchain2.GetCurrentTextureView(), {0.0, 0.0, 0.0, 1.0});
+ ClearTexture(swapchain2.GetCurrentTexture(), {0.0, 0.0, 0.0, 1.0});
swapchain2.Present();
}
}
@@ -177,7 +177,7 @@
desc.height -= i * 10;
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
- ClearTexture(swapchain.GetCurrentTextureView(), {0.05f * i, 0.0f, 0.0f, 1.0f});
+ ClearTexture(swapchain.GetCurrentTexture(), {0.05f * i, 0.0f, 0.0f, 1.0f});
swapchain.Present();
}
}
@@ -190,7 +190,7 @@
glfwSetWindowSize(window, 400 - 10 * i, 400 + 10 * i);
glfwPollEvents();
- ClearTexture(swapchain.GetCurrentTextureView(), {0.05f * i, 0.0f, 0.0f, 1.0f});
+ ClearTexture(swapchain.GetCurrentTexture(), {0.05f * i, 0.0f, 0.0f, 1.0f});
swapchain.Present();
}
}
@@ -212,7 +212,7 @@
desc.height = height;
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
- ClearTexture(swapchain.GetCurrentTextureView(), {0.05f * i, 0.0f, 0.0f, 1.0f});
+ ClearTexture(swapchain.GetCurrentTexture(), {0.05f * i, 0.0f, 0.0f, 1.0f});
swapchain.Present();
}
}
@@ -230,7 +230,7 @@
}
wgpu::SwapChain swapchain = deviceToUse.CreateSwapChain(surface, &baseDescriptor);
- swapchain.GetCurrentTextureView();
+ swapchain.GetCurrentTexture();
swapchain.Present();
}
}
@@ -281,15 +281,16 @@
GTEST_SKIP();
}
+ // TODO(dawn:1551): Reenable on D3D11 after suppressing the D3D11 debug layer warning for
+ // setting the same private data multiple times.
+ DAWN_SUPPRESS_TEST_IF(IsD3D11());
+
DAWN_TEST_UNSUPPORTED_IF(!SupportsFeatures({wgpu::FeatureName::SurfaceCapabilities}));
}
- void SampleTexture(wgpu::TextureView view,
- uint32_t width,
- uint32_t height,
- utils::RGBA8 expectedColor) {
+ void SampleTexture(wgpu::Texture texture, utils::RGBA8 expectedColor) {
wgpu::TextureDescriptor texDescriptor;
- texDescriptor.size = {width, height, 1};
+ texDescriptor.size = {texture.GetWidth(), texture.GetHeight(), 1};
texDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
texDescriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc |
wgpu::TextureUsage::CopyDst;
@@ -329,8 +330,8 @@
{
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDesc);
- wgpu::BindGroup bindGroup =
- utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, view}});
+ wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
+ {{0, texture.CreateView()}});
utils::ComboRenderPassDescriptor renderPassInfo({dstView});
@@ -345,7 +346,16 @@
queue.Submit(1, &commands);
EXPECT_TEXTURE_EQ(expectedColor, dstTexture, {0, 0});
- EXPECT_TEXTURE_EQ(expectedColor, dstTexture, {width - 1, height - 1});
+ EXPECT_TEXTURE_EQ(expectedColor, dstTexture,
+ {texture.GetWidth() - 1, texture.GetHeight() - 1});
+ }
+
+ void WriteTexture(wgpu::Texture texture, const utils::RGBA8& data) {
+ wgpu::Extent3D writeSize = {1, 1, 1};
+ wgpu::ImageCopyTexture dest = {};
+ dest.texture = texture;
+ wgpu::TextureDataLayout dataLayout = {};
+ queue.WriteTexture(&dest, &data, sizeof(utils::RGBA8), &dataLayout, &writeSize);
}
};
@@ -356,22 +366,17 @@
// Test that sampling from swapchain is supported.
TEST_P(SwapChainWithAdditionalUsageTests, SamplingFromSwapChain) {
- // TODO(dawn:1551): Reenable on D3D11 after suppressing the D3D11 debug layer warning for
- // setting the same private data multiple times.
- DAWN_SUPPRESS_TEST_IF(IsD3D11());
-
// Skip all tests if readable surface doesn't support texture binding
DAWN_TEST_UNSUPPORTED_IF(
- (device.GetSupportedSurfaceUsage(surface) & wgpu::TextureUsage::TextureBinding) == 0);
+ !(device.GetSupportedSurfaceUsage(surface) & wgpu::TextureUsage::TextureBinding));
auto desc = baseDescriptor;
desc.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
- ClearTexture(swapchain.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
+ ClearTexture(swapchain.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
- SampleTexture(swapchain.GetCurrentTextureView(), baseDescriptor.width, baseDescriptor.height,
- utils::RGBA8::kRed);
+ SampleTexture(swapchain.GetCurrentTexture(), utils::RGBA8::kRed);
swapchain.Present();
}
@@ -383,7 +388,7 @@
auto supportedUsage = device.GetSupportedSurfaceUsage(surface);
// Assuming StorageBinding is not supported.
- DAWN_TEST_UNSUPPORTED_IF((supportedUsage & wgpu::TextureUsage::StorageBinding) != 0);
+ DAWN_TEST_UNSUPPORTED_IF(supportedUsage & wgpu::TextureUsage::StorageBinding);
auto desc = baseDescriptor;
desc.usage = supportedUsage | wgpu::TextureUsage::StorageBinding;
@@ -392,6 +397,48 @@
testing::HasSubstr("is not supported"));
}
+// Test copying to a swapchain texture when it is supported.
+TEST_P(SwapChainWithAdditionalUsageTests, CopyingToSwapChain) {
+ wgpu::TextureUsage supportedUsages = device.GetSupportedSurfaceUsage(surface);
+ // We need the swapchain to support copying to the texture and at least one readback method.
+ DAWN_TEST_UNSUPPORTED_IF(!(supportedUsages & wgpu::TextureUsage::CopyDst));
+ DAWN_TEST_UNSUPPORTED_IF(
+ !(supportedUsages & (wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding)));
+
+ wgpu::SwapChainDescriptor desc = baseDescriptor;
+ desc.usage |= supportedUsages;
+ desc.width = 1;
+ desc.height = 1;
+
+ wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
+ wgpu::Texture texture = swapchain.GetCurrentTexture();
+ WriteTexture(texture, utils::RGBA8::kRed);
+
+ if (supportedUsages & wgpu::TextureUsage::CopySrc) {
+ EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kRed, swapchain.GetCurrentTexture(), 0, 0);
+ } else {
+ // kBlue because the texture is actually BGRA
+ SampleTexture(texture, utils::RGBA8::kBlue);
+ }
+}
+
+// Test copying from a swapchain texture when it is supported.
+TEST_P(SwapChainWithAdditionalUsageTests, CopyingFromSwapChain) {
+ // We need the swapchain to support copying from the texture
+ DAWN_TEST_UNSUPPORTED_IF(
+ !(device.GetSupportedSurfaceUsage(surface) & wgpu::TextureUsage::CopySrc));
+
+ wgpu::SwapChainDescriptor desc = baseDescriptor;
+ desc.usage |= wgpu::TextureUsage::CopySrc;
+
+ wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
+ wgpu::Texture texture = swapchain.GetCurrentTexture();
+
+ ClearTexture(swapchain.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
+ // kBlue because the texture is actually BGRA8
+ EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kBlue, swapchain.GetCurrentTexture(), 0, 0);
+}
+
DAWN_INSTANTIATE_TEST(SwapChainTests, MetalBackend(), VulkanBackend());
DAWN_INSTANTIATE_TEST(SwapChainWithAdditionalUsageTests,
D3D11Backend(),