D3D12: Fix resource placement alignment for textures
This patch fixes resource placement aligment for textures by always
trying to use small placement alignment first so that we can have a
chance to allocate less memory for small-sized textures. When
GetResourceAllocationInfo() shows we cannot use small placement
alignment we can call GetResourceAllocationInfo() again with 0 as
alignment to get the correct system alignment.
Previously we always directly use 0 as alignment for resource heap
tier 2, so we won't be able to use small placement alignment because
according to D3D12 SPEC, if Alignment is set to 0, the runtime will
always use 4MB for MSAA textures and 64KB for everything else.
Bug: dawn:282
Test: dawn_end2end_tests
Change-Id: I425e7454e481d24317eb8a2e760e234c698e575f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/142220
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp
index 9ea85a8..1c66c0b 100644
--- a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp
+++ b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp
@@ -132,24 +132,30 @@
}
}
-uint64_t GetResourcePlacementAlignment(ResourceHeapKind resourceHeapKind,
- uint32_t sampleCount,
- uint64_t requestedAlignment) {
- switch (resourceHeapKind) {
- // Small resources can take advantage of smaller alignments. For example,
- // if the most detailed mip can fit under 64KB, 4KB alignments can be used.
- // Must be non-depth or without render-target to use small resource alignment.
- // This also applies to MSAA textures (4MB => 64KB).
- //
- // Note: Only known to be used for small textures; however, MSDN suggests
- // it could be extended for more cases. If so, this could default to always
- // attempt small resource placement.
- // https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_resource_desc
- case Default_OnlyNonRenderableOrDepthTextures:
- return (sampleCount > 1) ? D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT
- : D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT;
+uint64_t GetInitialResourcePlacementAlignment(
+ const D3D12_RESOURCE_DESC& requestedResourceDescriptor) {
+ switch (requestedResourceDescriptor.Dimension) {
+ case D3D12_RESOURCE_DIMENSION_BUFFER:
+ return requestedResourceDescriptor.Alignment;
+
+ // Always try using small resource placement aligment first when Alignment == 0 because if
+ // Alignment is set to 0, the runtime will use 4MB for MSAA textures and 64KB for everything
+ // else.
+ // https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_resource_desc
+ case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
+ case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
+ case D3D12_RESOURCE_DIMENSION_TEXTURE3D: {
+ if (requestedResourceDescriptor.Alignment > 0) {
+ return requestedResourceDescriptor.Alignment;
+ } else {
+ return requestedResourceDescriptor.SampleDesc.Count > 1
+ ? D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT
+ : D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT;
+ }
+ }
+ case D3D12_RESOURCE_DIMENSION_UNKNOWN:
default:
- return requestedAlignment;
+ UNREACHABLE();
}
}
@@ -455,19 +461,20 @@
requestedResourceDescriptor.Flags, mResourceHeapTier);
D3D12_RESOURCE_DESC resourceDescriptor = requestedResourceDescriptor;
- resourceDescriptor.Alignment = GetResourcePlacementAlignment(
- resourceHeapKind, requestedResourceDescriptor.SampleDesc.Count,
- requestedResourceDescriptor.Alignment);
+ resourceDescriptor.Alignment =
+ GetInitialResourcePlacementAlignment(requestedResourceDescriptor);
- // TODO(bryan.bernhart): Figure out how to compute the alignment without calling this
- // twice.
+ // When you're using CreatePlacedResource, your application must use GetResourceAllocationInfo
+ // in order to understand the size and alignment characteristics of texture resources.
D3D12_RESOURCE_ALLOCATION_INFO resourceInfo =
mDevice->GetD3D12Device()->GetResourceAllocationInfo(0, 1, &resourceDescriptor);
- // If the requested resource alignment was rejected, let D3D tell us what the
- // required alignment is for this resource.
- if (resourceDescriptor.Alignment != 0 &&
- resourceDescriptor.Alignment != resourceInfo.Alignment) {
+ // If the requested resource alignment was rejected, set alignment to 0 to do allocation with
+ // default alignment in D3D12 (4MB for MSAA textures and 64KB for everything else).
+ // If an error occurs, then D3D12_RESOURCE_ALLOCATION_INFO::SizeInBytes equals UINT64_MAX.
+ if (resourceInfo.SizeInBytes == std::numeric_limits<uint64_t>::max() ||
+ (resourceDescriptor.Alignment != 0 &&
+ resourceDescriptor.Alignment != resourceInfo.Alignment)) {
resourceDescriptor.Alignment = 0;
resourceInfo =
mDevice->GetD3D12Device()->GetResourceAllocationInfo(0, 1, &resourceDescriptor);
diff --git a/src/dawn/tests/white_box/D3D12ResourceHeapTests.cpp b/src/dawn/tests/white_box/D3D12ResourceHeapTests.cpp
index d90eb1d..3788850 100644
--- a/src/dawn/tests/white_box/D3D12ResourceHeapTests.cpp
+++ b/src/dawn/tests/white_box/D3D12ResourceHeapTests.cpp
@@ -47,9 +47,6 @@
TEST_P(D3D12ResourceHeapTests, AlignSmallCompressedTexture) {
DAWN_TEST_UNSUPPORTED_IF(!IsBCFormatSupported());
- // TODO(http://crbug.com/dawn/282): Investigate GPU/driver rejections of small alignment.
- DAWN_SUPPRESS_TEST_IF(IsIntel() || IsNvidia() || IsWARP());
-
wgpu::TextureDescriptor descriptor;
descriptor.dimension = wgpu::TextureDimension::e2D;
descriptor.size.width = 8;