fix(🐛): Route surfaces configured with viewFormats through the blit path The Vulkan swapchain creates its images without VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT and wraps them in a texture descriptor that omits the configuration's viewFormats, so the first GetCurrentTexture() fails the viewFormats consistency DAWN_CHECK and aborts. Any non-empty viewFormats now sets needsBlit, like an unsupported extent or usage: the user-facing texture becomes the intermediate blit texture, a regular texture created from the full descriptor, which supports reinterpretation. Metal already builds the swapchain texture from the full descriptor and is unaffected. Adds a SurfaceTests end2end case; the file previously only exercised viewFormatCount = 0, which is why this went unnoticed. Change-Id: If09df3749bb4de9c9ed011bf924141ea1fbfe15b Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/325476 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Brandon Jones <bajones@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/vulkan/SwapChainVk.cpp b/src/dawn/native/vulkan/SwapChainVk.cpp index 7090b4a..90d3b00 100644 --- a/src/dawn/native/vulkan/SwapChainVk.cpp +++ b/src/dawn/native/vulkan/SwapChainVk.cpp
@@ -271,7 +271,10 @@ VkImageUsageFlags targetUsages = VulkanImageUsage(GetDevice(), GetUsage(), GetDevice()->GetValidInternalFormat(GetFormat())); VkImageUsageFlags supportedUsages = surfaceInfo.capabilities.supportedUsageFlags; - if (!IsSubset(targetUsages, supportedUsages)) { + // The swapchain images are also unable to satisfy viewFormats: they are created without + // VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, so they cannot be reinterpreted. The blit texture is a + // regular texture and can. + if (!IsSubset(targetUsages, supportedUsages) || !GetViewFormats().empty()) { config.needsBlit = true; } else { config.usage = targetUsages;
diff --git a/src/dawn/tests/end2end/SurfaceTests.cpp b/src/dawn/tests/end2end/SurfaceTests.cpp index 44a7d09..24d9710 100644 --- a/src/dawn/tests/end2end/SurfaceTests.cpp +++ b/src/dawn/tests/end2end/SurfaceTests.cpp
@@ -859,6 +859,39 @@ ASSERT_EQ(wgpu::Status::Success, surface.Present()); } +// Test acquiring a texture from a surface configured with viewFormats. +TEST_P(SurfaceTests, ConfigureWithViewFormats) { + // Reinterpreting the surface format as its srgb counterpart isn't allowed in compatibility + // mode: viewFormats must match the format there. + DAWN_TEST_UNSUPPORTED_IF(IsCompatibilityMode()); + + wgpu::Surface surface = CreateTestSurface(); + wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface); + + // Reinterpretation between a format and its srgb counterpart is always + // allowed; pick the counterpart of whatever the surface prefers. + wgpu::TextureFormat viewFormat; + switch (config.format) { + case wgpu::TextureFormat::BGRA8Unorm: + viewFormat = wgpu::TextureFormat::BGRA8UnormSrgb; + break; + case wgpu::TextureFormat::RGBA8Unorm: + viewFormat = wgpu::TextureFormat::RGBA8UnormSrgb; + break; + default: + // Add a case above if a platform starts preferring another format. + DAWN_UNREACHABLE(); + } + config.viewFormatCount = 1; + config.viewFormats = &viewFormat; + surface.Configure(&config); + + wgpu::SurfaceTexture surfaceTexture; + surface.GetCurrentTexture(&surfaceTexture); + ClearTexture(surfaceTexture.texture, {1.0, 0.0, 0.0, 1.0}); + surface.Present(); +} + // TODO(crbug.com/465183957): Implement swap chain for WebGPUBackend. DAWN_INSTANTIATE_TEST(SurfaceTests, D3D11Backend(),