D3D12: Don't set D3D12_CLEAR_VALUE on depth textures on Gen12 GPUs
This patch adds a workaround for Intel Gen12 GPUs that we don't set D3D12_CLEAR_VALUE when creating a texture with any DXGI depth formats (DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_D32_FLOAT_S8X24_UINT) because on these GPUs the texture data may be corrupted after several call of ClearDepthStencilView() if D3D12_CLEAR_VALUE is set in the call of CreatePlacedResource() or CreateCommittedResource(). Bug: dawn:1487 Test: dawn_end2end_tests Change-Id: Id44af0f6fe31773820f5e20d05edd275dd921e53 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/96482 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
parent
aea3154e46
commit
44b0a5e9a3
|
@ -274,6 +274,11 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{
|
||||||
"the initialization when the entire subresource is the copy destination as a workaround on "
|
"the initialization when the entire subresource is the copy destination as a workaround on "
|
||||||
"Intel D3D12 drivers.",
|
"Intel D3D12 drivers.",
|
||||||
"https://crbug.com/dawn/1487"}},
|
"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.
|
// Comment to separate the }} so it is clearer what to copy-paste to add a toggle.
|
||||||
}};
|
}};
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
|
@ -73,6 +73,7 @@ enum class Toggle {
|
||||||
MetalRenderR8RG8UnormSmallMipToTempTexture,
|
MetalRenderR8RG8UnormSmallMipToTempTexture,
|
||||||
EnableBlobCache,
|
EnableBlobCache,
|
||||||
D3D12ForceInitializeCopyableDepthStencilTextureOnCreation,
|
D3D12ForceInitializeCopyableDepthStencilTextureOnCreation,
|
||||||
|
D3D12DontSetClearValueOnDepthTextureCreation,
|
||||||
|
|
||||||
EnumCount,
|
EnumCount,
|
||||||
InvalidEnum = EnumCount,
|
InvalidEnum = EnumCount,
|
||||||
|
|
|
@ -661,6 +661,12 @@ void Device::InitTogglesFromDriver() {
|
||||||
SetToggle(Toggle::D3D12ForceInitializeCopyableDepthStencilTextureOnCreation, true);
|
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.
|
// 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
|
// 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.
|
// https://crbug.com/dawn/1289 for more information.
|
||||||
|
|
|
@ -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
|
// Optimized clear color cannot be set on buffers, non-render-target/depth-stencil
|
||||||
// textures, or typeless resources
|
// textures, or typeless resources
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createcommittedresource
|
// https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createcommittedresource
|
||||||
|
@ -192,7 +204,7 @@ ResultOrError<ResourceHeapAllocation> ResourceAllocatorManager::AllocateMemory(
|
||||||
// some architectures.
|
// some architectures.
|
||||||
D3D12_CLEAR_VALUE zero{};
|
D3D12_CLEAR_VALUE zero{};
|
||||||
D3D12_CLEAR_VALUE* optimizedClearValue = nullptr;
|
D3D12_CLEAR_VALUE* optimizedClearValue = nullptr;
|
||||||
if (IsClearValueOptimizable(resourceDescriptor)) {
|
if (IsClearValueOptimizable(mDevice, resourceDescriptor)) {
|
||||||
zero.Format = resourceDescriptor.Format;
|
zero.Format = resourceDescriptor.Format;
|
||||||
optimizedClearValue = &zero;
|
optimizedClearValue = &zero;
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,4 +303,124 @@ DAWN_INSTANTIATE_TEST_P(StencilClearValueOverflowTest,
|
||||||
wgpu::TextureFormat::Depth32FloatStencil8, wgpu::TextureFormat::Stencil8},
|
wgpu::TextureFormat::Depth32FloatStencil8, wgpu::TextureFormat::Stencil8},
|
||||||
{Check::CopyStencil, Check::StencilTest});
|
{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<DepthTextureClearTwiceTestParams> {
|
||||||
|
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<wgpu::FeatureName> 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<uint32_t, 2> 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<uint32_t, 3> kLevelsToTest = {0, 1u, 3u};
|
||||||
|
for (uint32_t level : kLevelsToTest) {
|
||||||
|
uint32_t sizeAtLevel = kSize >> level;
|
||||||
|
std::vector<float> 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
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue