From 1b48cc0d6fa8e58eeb3ff6923210494124944135 Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Fri, 26 May 2023 15:48:12 +0000 Subject: [PATCH] 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 Commit-Queue: Corentin Wallez Kokoro: Kokoro --- src/dawn/native/d3d/DeviceD3D.cpp | 5 +- src/dawn/native/metal/DeviceMTL.mm | 5 +- src/dawn/native/opengl/DeviceGL.cpp | 5 +- src/dawn/native/vulkan/SwapChainVk.cpp | 12 ++- src/dawn/tests/end2end/SwapChainTests.cpp | 117 +++++++++++++++------- 5 files changed, 101 insertions(+), 43 deletions(-) diff --git a/src/dawn/native/d3d/DeviceD3D.cpp b/src/dawn/native/d3d/DeviceD3D.cpp index b92f169000..6e9b45d886 100644 --- a/src/dawn/native/d3d/DeviceD3D.cpp +++ b/src/dawn/native/d3d/DeviceD3D.cpp @@ -48,8 +48,9 @@ void Device::DestroyImpl() { ResultOrError 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 9409cb934f..116837b726 100644 --- a/src/dawn/native/metal/DeviceMTL.mm +++ b/src/dawn/native/metal/DeviceMTL.mm @@ -243,8 +243,9 @@ void Device::InitializeRenderPipelineAsyncImpl(Ref renderPip ResultOrError 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 356d9c2f17..4b0cf825c8 100644 --- a/src/dawn/native/opengl/DeviceGL.cpp +++ b/src/dawn/native/opengl/DeviceGL.cpp @@ -255,8 +255,9 @@ ResultOrError> Device::CreateTextureViewImpl( ResultOrError 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 72b89db89c..7794804f56 100644 --- a/src/dawn/native/vulkan/SwapChainVk.cpp +++ b/src/dawn/native/vulkan/SwapChainVk.cpp @@ -223,8 +223,16 @@ ResultOrError SwapChain::GetSupportedSurfaceUsage(const Devi 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 8c10fb412c..a626d9f712 100644 --- a/src/dawn/tests/end2end/SwapChainTests.cpp +++ b/src/dawn/tests/end2end/SwapChainTests.cpp @@ -69,8 +69,8 @@ class SwapChainTests : public DawnTest { 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 @@ class SwapChainTests : public DawnTest { // 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 @@ TEST_P(SwapChainTests, DestroySurface) { 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 @@ TEST_P(SwapChainTests, SwitchPresentMode) { 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 @@ TEST_P(SwapChainTests, ResizingSwapChainOnly) { 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 @@ TEST_P(SwapChainTests, ResizingWindowOnly) { 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 @@ TEST_P(SwapChainTests, ResizingWindowAndSwapChain) { 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 @@ TEST_P(SwapChainTests, SwitchingDevice) { } wgpu::SwapChain swapchain = deviceToUse.CreateSwapChain(surface, &baseDescriptor); - swapchain.GetCurrentTextureView(); + swapchain.GetCurrentTexture(); swapchain.Present(); } } @@ -281,15 +281,16 @@ class SwapChainWithAdditionalUsageTests : public SwapChainTests { 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 @@ class SwapChainWithAdditionalUsageTests : public SwapChainTests { { 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 @@ class SwapChainWithAdditionalUsageTests : public SwapChainTests { 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_P(SwapChainWithAdditionalUsageTests, GetSurfaceSupportedUsage) { // 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 @@ TEST_P(SwapChainWithAdditionalUsageTests, ErrorIncludeUnsupportedUsage) { 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 @@ TEST_P(SwapChainWithAdditionalUsageTests, ErrorIncludeUnsupportedUsage) { 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(),