diff --git a/src/dawn/native/Toggles.cpp b/src/dawn/native/Toggles.cpp index 533ebec6d2..5f03891372 100644 --- a/src/dawn/native/Toggles.cpp +++ b/src/dawn/native/Toggles.cpp @@ -274,6 +274,11 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{ "the initialization when the entire subresource is the copy destination as a workaround on " "Intel D3D12 drivers.", "https://crbug.com/dawn/1487"}}, + {Toggle::D3D12DontSetClearValueOnDepthTextureCreation, + {"d3d12_dont_set_clear_value_on_depth_texture_creation", + "Don't set D3D12_CLEAR_VALUE when creating depth textures with CreatePlacedResource() or " + "CreateCommittedResource() as a workaround on Intel Gen12 D3D12 drivers.", + "https://crbug.com/dawn/1487"}}, // Comment to separate the }} so it is clearer what to copy-paste to add a toggle. }}; } // anonymous namespace diff --git a/src/dawn/native/Toggles.h b/src/dawn/native/Toggles.h index 3f9a16e6a9..d6c3664052 100644 --- a/src/dawn/native/Toggles.h +++ b/src/dawn/native/Toggles.h @@ -73,6 +73,7 @@ enum class Toggle { MetalRenderR8RG8UnormSmallMipToTempTexture, EnableBlobCache, D3D12ForceInitializeCopyableDepthStencilTextureOnCreation, + D3D12DontSetClearValueOnDepthTextureCreation, EnumCount, InvalidEnum = EnumCount, diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp index 2aafa57aea..7b67035a56 100644 --- a/src/dawn/native/d3d12/DeviceD3D12.cpp +++ b/src/dawn/native/d3d12/DeviceD3D12.cpp @@ -661,6 +661,12 @@ void Device::InitTogglesFromDriver() { SetToggle(Toggle::D3D12ForceInitializeCopyableDepthStencilTextureOnCreation, true); } + // Currently this workaround is only needed on Intel Gen12 GPUs. + // See http://crbug.com/dawn/1487 for more information. + if (gpu_info::IsIntelXe(vendorId, deviceId)) { + SetToggle(Toggle::D3D12DontSetClearValueOnDepthTextureCreation, true); + } + // Currently this workaround is needed on any D3D12 backend for some particular situations. // But we may need to limit it if D3D12 runtime fixes the bug on its new release. See // https://crbug.com/dawn/1289 for more information. diff --git a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp index dbcea824cd..454b924df0 100644 --- a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp +++ b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp @@ -152,7 +152,19 @@ uint64_t GetResourcePlacementAlignment(ResourceHeapKind resourceHeapKind, } } -bool IsClearValueOptimizable(const D3D12_RESOURCE_DESC& resourceDescriptor) { +bool IsClearValueOptimizable(DeviceBase* device, const D3D12_RESOURCE_DESC& resourceDescriptor) { + if (device->IsToggleEnabled(Toggle::D3D12DontSetClearValueOnDepthTextureCreation)) { + switch (resourceDescriptor.Format) { + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + return false; + default: + break; + } + } + // Optimized clear color cannot be set on buffers, non-render-target/depth-stencil // textures, or typeless resources // https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createcommittedresource @@ -192,7 +204,7 @@ ResultOrError ResourceAllocatorManager::AllocateMemory( // some architectures. D3D12_CLEAR_VALUE zero{}; D3D12_CLEAR_VALUE* optimizedClearValue = nullptr; - if (IsClearValueOptimizable(resourceDescriptor)) { + if (IsClearValueOptimizable(mDevice, resourceDescriptor)) { zero.Format = resourceDescriptor.Format; optimizedClearValue = &zero; } diff --git a/src/dawn/tests/end2end/DepthStencilLoadOpTests.cpp b/src/dawn/tests/end2end/DepthStencilLoadOpTests.cpp index d0de8f2738..5e1a33445b 100644 --- a/src/dawn/tests/end2end/DepthStencilLoadOpTests.cpp +++ b/src/dawn/tests/end2end/DepthStencilLoadOpTests.cpp @@ -303,4 +303,124 @@ DAWN_INSTANTIATE_TEST_P(StencilClearValueOverflowTest, wgpu::TextureFormat::Depth32FloatStencil8, wgpu::TextureFormat::Stencil8}, {Check::CopyStencil, Check::StencilTest}); +// Regression tests to reproduce a flaky failure when running whole WebGPU CTS on Intel Gen12 GPUs. +// See crbug.com/dawn/1487 for more details. +using SupportsTextureBinding = bool; +DAWN_TEST_PARAM_STRUCT(DepthTextureClearTwiceTestParams, Format, SupportsTextureBinding); + +class DepthTextureClearTwiceTest : public DawnTestWithParams { + public: + void RecordClearDepthAspectAtLevel(wgpu::CommandEncoder encoder, + wgpu::Texture depthTexture, + uint32_t level, + float clearValue) { + wgpu::TextureViewDescriptor viewDescriptor = {}; + viewDescriptor.baseArrayLayer = 0; + viewDescriptor.arrayLayerCount = 1; + viewDescriptor.baseMipLevel = level; + viewDescriptor.mipLevelCount = 1; + wgpu::TextureView view = depthTexture.CreateView(&viewDescriptor); + + wgpu::RenderPassDescriptor renderPassDescriptor = {}; + renderPassDescriptor.colorAttachmentCount = 0; + + wgpu::RenderPassDepthStencilAttachment depthStencilAttachment = {}; + depthStencilAttachment.view = view; + depthStencilAttachment.depthClearValue = clearValue; + depthStencilAttachment.depthLoadOp = wgpu::LoadOp::Clear; + depthStencilAttachment.depthStoreOp = wgpu::StoreOp::Store; + + if (!utils::IsDepthOnlyFormat(GetParam().mFormat)) { + depthStencilAttachment.stencilLoadOp = wgpu::LoadOp::Load; + depthStencilAttachment.stencilStoreOp = wgpu::StoreOp::Store; + } + + renderPassDescriptor.depthStencilAttachment = &depthStencilAttachment; + wgpu::RenderPassEncoder renderPass = encoder.BeginRenderPass(&renderPassDescriptor); + renderPass.End(); + } + + protected: + std::vector GetRequiredFeatures() override { + switch (GetParam().mFormat) { + case wgpu::TextureFormat::Depth32FloatStencil8: + if (SupportsFeatures({wgpu::FeatureName::Depth32FloatStencil8})) { + mIsFormatSupported = true; + return {wgpu::FeatureName::Depth32FloatStencil8}; + } + return {}; + default: + mIsFormatSupported = true; + return {}; + } + } + + bool mIsFormatSupported = false; +}; + +TEST_P(DepthTextureClearTwiceTest, ClearDepthAspectTwice) { + DAWN_SUPPRESS_TEST_IF(!mIsFormatSupported); + + constexpr uint32_t kSize = 64; + constexpr uint32_t kLevelCount = 5; + + wgpu::TextureFormat depthFormat = GetParam().mFormat; + + wgpu::TextureDescriptor descriptor; + descriptor.size = {kSize, kSize}; + descriptor.format = depthFormat; + descriptor.mipLevelCount = kLevelCount; + + // The toggle "d3d12_force_initialize_copyable_depth_stencil_texture_on_creation" is not related + // to this test as we don't specify wgpu::TextureUsage::CopyDst in the test. + descriptor.usage = wgpu::TextureUsage::RenderAttachment; + if (GetParam().mSupportsTextureBinding) { + descriptor.usage |= wgpu::TextureUsage::TextureBinding; + } + wgpu::Texture depthTexture = device.CreateTexture(&descriptor); + + // First, clear all the subresources to 0. + { + constexpr float kClearValue = 0.f; + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + for (uint32_t level = 0; level < kLevelCount; ++level) { + RecordClearDepthAspectAtLevel(encoder, depthTexture, level, kClearValue); + } + wgpu::CommandBuffer commandBuffer = encoder.Finish(); + queue.Submit(1, &commandBuffer); + } + + // Then, clear several mipmap levels to 0.8. + { + constexpr float kClearValue = 0.8f; + constexpr std::array kLevelsToSet = {2u, 4u}; + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + for (uint32_t level : kLevelsToSet) { + RecordClearDepthAspectAtLevel(encoder, depthTexture, level, kClearValue); + } + wgpu::CommandBuffer commandBuffer = encoder.Finish(); + queue.Submit(1, &commandBuffer); + } + + // Check if the data in remaining mipmap levels is still 0. + { + constexpr std::array kLevelsToTest = {0, 1u, 3u}; + for (uint32_t level : kLevelsToTest) { + uint32_t sizeAtLevel = kSize >> level; + std::vector expectedValue(sizeAtLevel * sizeAtLevel, 0.f); + ExpectAttachmentDepthTestData(depthTexture, GetParam().mFormat, sizeAtLevel, + sizeAtLevel, 0, level, expectedValue); + } + } +} + +DAWN_INSTANTIATE_TEST_P(DepthTextureClearTwiceTest, + {D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(), + VulkanBackend()}, + {wgpu::TextureFormat::Depth16Unorm, wgpu::TextureFormat::Depth24Plus, + wgpu::TextureFormat::Depth32Float, + wgpu::TextureFormat::Depth32FloatStencil8, + wgpu::TextureFormat::Depth24PlusStencil8}, + {true, false}); + } // namespace