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 "
|
||||
"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
|
||||
|
|
|
@ -73,6 +73,7 @@ enum class Toggle {
|
|||
MetalRenderR8RG8UnormSmallMipToTempTexture,
|
||||
EnableBlobCache,
|
||||
D3D12ForceInitializeCopyableDepthStencilTextureOnCreation,
|
||||
D3D12DontSetClearValueOnDepthTextureCreation,
|
||||
|
||||
EnumCount,
|
||||
InvalidEnum = EnumCount,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<ResourceHeapAllocation> 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;
|
||||
}
|
||||
|
|
|
@ -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<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
|
||||
|
|
Loading…
Reference in New Issue