Support for resource heap tier 2.

Enables mixing of texture and buffers in the same heap.
This allows better heap re-use and reduces internal fragmentation.
A toggle has been added and enabled by default.

BUG=dawn:27

Change-Id: I466dc96240fe1e8de6e3dc56ed5547d7b61ee045
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/12821
Commit-Queue: Bryan Bernhart <bryan.bernhart@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Bryan Bernhart 2019-11-01 18:19:01 +00:00 committed by Commit Bot service account
parent 314fd3513d
commit 6df81ebf1d
10 changed files with 80 additions and 12 deletions

View File

@ -70,7 +70,12 @@ namespace dawn_native {
"workaround is enabled by default on all Vulkan drivers to solve an issue in the " "workaround is enabled by default on all Vulkan drivers to solve an issue in the "
"Vulkan SPEC about the texture-to-texture copies with compressed formats. See #1005 " "Vulkan SPEC about the texture-to-texture copies with compressed formats. See #1005 "
"(https://github.com/KhronosGroup/Vulkan-Docs/issues/1005) for more details.", "(https://github.com/KhronosGroup/Vulkan-Docs/issues/1005) for more details.",
"https://bugs.chromium.org/p/dawn/issues/detail?id=42"}}}}; "https://bugs.chromium.org/p/dawn/issues/detail?id=42"}},
{Toggle::UseD3D12ResourceHeapTier2,
{"use_d3d12_resource_heap_tier2",
"Enable support for resource heap tier 2. Resource heap tier 2 allows mixing of "
"texture and buffers in the same heap. This allows better heap re-use and reduces "
"fragmentation."}}}};
} // anonymous namespace } // anonymous namespace

View File

@ -30,6 +30,7 @@ namespace dawn_native {
LazyClearResourceOnFirstUse, LazyClearResourceOnFirstUse,
TurnOffVsync, TurnOffVsync,
UseTemporaryBufferInCompressedTextureToTextureCopy, UseTemporaryBufferInCompressedTextureToTextureCopy,
UseD3D12ResourceHeapTier2,
EnumCount, EnumCount,
InvalidEnum = EnumCount, InvalidEnum = EnumCount,

View File

@ -16,7 +16,7 @@
#include "dawn_native/d3d12/AdapterD3D12.h" #include "dawn_native/d3d12/AdapterD3D12.h"
#include "dawn_native/d3d12/BackendD3D12.h" #include "dawn_native/d3d12/BackendD3D12.h"
#include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/PlatformFunctions.h" #include "dawn_native/d3d12/PlatformFunctions.h"
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
@ -31,12 +31,18 @@ namespace dawn_native { namespace d3d12 {
// for backwards compat. // for backwards compat.
// https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_feature // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_feature
D3D12_FEATURE_DATA_ARCHITECTURE arch = {}; D3D12_FEATURE_DATA_ARCHITECTURE arch = {};
if (FAILED(adapter.GetDevice()->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &arch, DAWN_TRY(CheckHRESULT(adapter.GetDevice()->CheckFeatureSupport(
sizeof(arch)))) { D3D12_FEATURE_ARCHITECTURE, &arch, sizeof(arch)),
return DAWN_DEVICE_LOST_ERROR("CheckFeatureSupport failed"); "ID3D12Device::CheckFeatureSupport"));
}
info.isUMA = arch.UMA; info.isUMA = arch.UMA;
D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
DAWN_TRY(CheckHRESULT(adapter.GetDevice()->CheckFeatureSupport(
D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)),
"ID3D12Device::CheckFeatureSupport"));
info.resourceHeapTier = options.ResourceHeapTier;
} }
return info; return info;

View File

@ -24,6 +24,7 @@ namespace dawn_native { namespace d3d12 {
struct D3D12DeviceInfo { struct D3D12DeviceInfo {
bool isUMA; bool isUMA;
uint32_t resourceHeapTier;
}; };
ResultOrError<D3D12DeviceInfo> GatherDeviceInfo(const Adapter& adapter); ResultOrError<D3D12DeviceInfo> GatherDeviceInfo(const Adapter& adapter);

View File

@ -42,6 +42,7 @@ namespace dawn_native { namespace d3d12 {
Device::Device(Adapter* adapter, const DeviceDescriptor* descriptor) Device::Device(Adapter* adapter, const DeviceDescriptor* descriptor)
: DeviceBase(adapter, descriptor) { : DeviceBase(adapter, descriptor) {
InitTogglesFromDriver();
if (descriptor != nullptr) { if (descriptor != nullptr) {
ApplyToggleOverrides(descriptor); ApplyToggleOverrides(descriptor);
} }
@ -406,4 +407,13 @@ namespace dawn_native { namespace d3d12 {
mD3d11On12DeviceContext->Flush(); mD3d11On12DeviceContext->Flush();
} }
const D3D12DeviceInfo& Device::GetDeviceInfo() const {
return ToBackend(GetAdapter())->GetDeviceInfo();
}
void Device::InitTogglesFromDriver() {
const bool useResourceHeapTier2 = (GetDeviceInfo().resourceHeapTier >= 2);
SetToggle(Toggle::UseD3D12ResourceHeapTier2, useResourceHeapTier2);
}
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -20,6 +20,7 @@
#include "common/SerialQueue.h" #include "common/SerialQueue.h"
#include "dawn_native/Device.h" #include "dawn_native/Device.h"
#include "dawn_native/d3d12/CommandRecordingContext.h" #include "dawn_native/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/D3D12Info.h"
#include "dawn_native/d3d12/Forward.h" #include "dawn_native/d3d12/Forward.h"
#include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h" #include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h"
@ -71,6 +72,8 @@ namespace dawn_native { namespace d3d12 {
ResultOrError<CommandRecordingContext*> GetPendingCommandContext(); ResultOrError<CommandRecordingContext*> GetPendingCommandContext();
Serial GetPendingCommandSerial() const override; Serial GetPendingCommandSerial() const override;
const D3D12DeviceInfo& GetDeviceInfo() const;
MaybeError NextSerial(); MaybeError NextSerial();
MaybeError WaitForSerial(Serial serial); MaybeError WaitForSerial(Serial serial);
@ -99,6 +102,8 @@ namespace dawn_native { namespace d3d12 {
ID3D12Resource* d3d12Resource); ID3D12Resource* d3d12Resource);
void ReleaseKeyedMutexForTexture(ComPtr<IDXGIKeyedMutex> dxgiKeyedMutex); void ReleaseKeyedMutexForTexture(ComPtr<IDXGIKeyedMutex> dxgiKeyedMutex);
void InitTogglesFromDriver();
private: private:
ResultOrError<BindGroupBase*> CreateBindGroupImpl( ResultOrError<BindGroupBase*> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) override; const BindGroupDescriptor* descriptor) override;

View File

@ -24,12 +24,15 @@ namespace dawn_native { namespace d3d12 {
D3D12_HEAP_TYPE GetD3D12HeapType(ResourceHeapKind resourceHeapKind) { D3D12_HEAP_TYPE GetD3D12HeapType(ResourceHeapKind resourceHeapKind) {
switch (resourceHeapKind) { switch (resourceHeapKind) {
case Readback_OnlyBuffers: case Readback_OnlyBuffers:
case Readback_AllBuffersAndTextures:
return D3D12_HEAP_TYPE_READBACK; return D3D12_HEAP_TYPE_READBACK;
case Default_AllBuffersAndTextures:
case Default_OnlyBuffers: case Default_OnlyBuffers:
case Default_OnlyNonRenderableOrDepthTextures: case Default_OnlyNonRenderableOrDepthTextures:
case Default_OnlyRenderableOrDepthTextures: case Default_OnlyRenderableOrDepthTextures:
return D3D12_HEAP_TYPE_DEFAULT; return D3D12_HEAP_TYPE_DEFAULT;
case Upload_OnlyBuffers: case Upload_OnlyBuffers:
case Upload_AllBuffersAndTextures:
return D3D12_HEAP_TYPE_UPLOAD; return D3D12_HEAP_TYPE_UPLOAD;
default: default:
UNREACHABLE(); UNREACHABLE();
@ -38,6 +41,10 @@ namespace dawn_native { namespace d3d12 {
D3D12_HEAP_FLAGS GetD3D12HeapFlags(ResourceHeapKind resourceHeapKind) { D3D12_HEAP_FLAGS GetD3D12HeapFlags(ResourceHeapKind resourceHeapKind) {
switch (resourceHeapKind) { switch (resourceHeapKind) {
case Default_AllBuffersAndTextures:
case Readback_AllBuffersAndTextures:
case Upload_AllBuffersAndTextures:
return D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES;
case Default_OnlyBuffers: case Default_OnlyBuffers:
case Readback_OnlyBuffers: case Readback_OnlyBuffers:
case Upload_OnlyBuffers: case Upload_OnlyBuffers:
@ -53,7 +60,21 @@ namespace dawn_native { namespace d3d12 {
ResourceHeapKind GetResourceHeapKind(D3D12_RESOURCE_DIMENSION dimension, ResourceHeapKind GetResourceHeapKind(D3D12_RESOURCE_DIMENSION dimension,
D3D12_HEAP_TYPE heapType, D3D12_HEAP_TYPE heapType,
D3D12_RESOURCE_FLAGS flags) { D3D12_RESOURCE_FLAGS flags,
uint32_t resourceHeapTier) {
if (resourceHeapTier >= 2) {
switch (heapType) {
case D3D12_HEAP_TYPE_UPLOAD:
return Upload_AllBuffersAndTextures;
case D3D12_HEAP_TYPE_DEFAULT:
return Default_AllBuffersAndTextures;
case D3D12_HEAP_TYPE_READBACK:
return Readback_AllBuffersAndTextures;
default:
UNREACHABLE();
}
}
switch (dimension) { switch (dimension) {
case D3D12_RESOURCE_DIMENSION_BUFFER: { case D3D12_RESOURCE_DIMENSION_BUFFER: {
switch (heapType) { switch (heapType) {
@ -90,6 +111,10 @@ namespace dawn_native { namespace d3d12 {
} // namespace } // namespace
ResourceAllocatorManager::ResourceAllocatorManager(Device* device) : mDevice(device) { ResourceAllocatorManager::ResourceAllocatorManager(Device* device) : mDevice(device) {
mResourceHeapTier = (mDevice->IsToggleEnabled(Toggle::UseD3D12ResourceHeapTier2))
? mDevice->GetDeviceInfo().resourceHeapTier
: 1;
for (uint32_t i = 0; i < ResourceHeapKind::EnumCount; i++) { for (uint32_t i = 0; i < ResourceHeapKind::EnumCount; i++) {
const ResourceHeapKind resourceHeapKind = static_cast<ResourceHeapKind>(i); const ResourceHeapKind resourceHeapKind = static_cast<ResourceHeapKind>(i);
mHeapAllocators[i] = std::make_unique<HeapAllocator>( mHeapAllocators[i] = std::make_unique<HeapAllocator>(
@ -153,8 +178,9 @@ namespace dawn_native { namespace d3d12 {
const D3D12_RESOURCE_DESC resourceDescriptor = allocation.GetD3D12Resource()->GetDesc(); const D3D12_RESOURCE_DESC resourceDescriptor = allocation.GetD3D12Resource()->GetDesc();
const size_t resourceHeapKindIndex = GetResourceHeapKind( const size_t resourceHeapKindIndex =
resourceDescriptor.Dimension, heapProp.Type, resourceDescriptor.Flags); GetResourceHeapKind(resourceDescriptor.Dimension, heapProp.Type,
resourceDescriptor.Flags, mResourceHeapTier);
mSubAllocatedResourceAllocators[resourceHeapKindIndex]->Deallocate(allocation); mSubAllocatedResourceAllocators[resourceHeapKindIndex]->Deallocate(allocation);
} }
@ -163,8 +189,8 @@ namespace dawn_native { namespace d3d12 {
D3D12_HEAP_TYPE heapType, D3D12_HEAP_TYPE heapType,
const D3D12_RESOURCE_DESC& resourceDescriptor, const D3D12_RESOURCE_DESC& resourceDescriptor,
D3D12_RESOURCE_STATES initialUsage) { D3D12_RESOURCE_STATES initialUsage) {
const size_t resourceHeapKindIndex = const size_t resourceHeapKindIndex = GetResourceHeapKind(
GetResourceHeapKind(resourceDescriptor.Dimension, heapType, resourceDescriptor.Flags); resourceDescriptor.Dimension, heapType, resourceDescriptor.Flags, mResourceHeapTier);
BuddyMemoryAllocator* allocator = BuddyMemoryAllocator* allocator =
mSubAllocatedResourceAllocators[resourceHeapKindIndex].get(); mSubAllocatedResourceAllocators[resourceHeapKindIndex].get();

View File

@ -26,10 +26,21 @@ namespace dawn_native { namespace d3d12 {
class Device; class Device;
// Heap types + flags combinations are named after the D3D constants. // Resource heap types + flags combinations are named after the D3D constants.
// https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_heap_flags // https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_heap_flags
// https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_heap_type // https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_heap_type
enum ResourceHeapKind { enum ResourceHeapKind {
// Resource heap tier 2
// Allows resource heaps to contain all buffer and textures types.
// This enables better heap re-use by avoiding the need for separate heaps and
// also reduces fragmentation.
Readback_AllBuffersAndTextures,
Upload_AllBuffersAndTextures,
Default_AllBuffersAndTextures,
// Resource heap tier 1
// Resource heaps only support types from a single resource category.
Readback_OnlyBuffers, Readback_OnlyBuffers,
Upload_OnlyBuffers, Upload_OnlyBuffers,
Default_OnlyBuffers, Default_OnlyBuffers,
@ -70,6 +81,7 @@ namespace dawn_native { namespace d3d12 {
D3D12_RESOURCE_STATES initialUsage); D3D12_RESOURCE_STATES initialUsage);
Device* mDevice; Device* mDevice;
uint32_t mResourceHeapTier;
static constexpr uint64_t kMaxHeapSize = 32ll * 1024ll * 1024ll * 1024ll; // 32GB static constexpr uint64_t kMaxHeapSize = 32ll * 1024ll * 1024ll * 1024ll; // 32GB
static constexpr uint64_t kMinHeapSize = 4ll * 1024ll * 1024ll; // 4MB static constexpr uint64_t kMinHeapSize = 4ll * 1024ll * 1024ll; // 4MB

View File

@ -648,6 +648,7 @@ TEST_P(CreateBufferMappedTests, LargeBufferFails) {
DAWN_INSTANTIATE_TEST(CreateBufferMappedTests, DAWN_INSTANTIATE_TEST(CreateBufferMappedTests,
D3D12Backend, D3D12Backend,
ForceWorkarounds(D3D12Backend, {}, {"use_d3d12_resource_heap_tier2"}),
MetalBackend, MetalBackend,
OpenGLBackend, OpenGLBackend,
VulkanBackend); VulkanBackend);

View File

@ -505,6 +505,7 @@ TEST_P(MultisampledRenderingTest, ResolveInto2DArrayTexture) {
DAWN_INSTANTIATE_TEST(MultisampledRenderingTest, DAWN_INSTANTIATE_TEST(MultisampledRenderingTest,
D3D12Backend, D3D12Backend,
ForceWorkarounds(D3D12Backend, {}, {"use_d3d12_resource_heap_tier2"}),
MetalBackend, MetalBackend,
OpenGLBackend, OpenGLBackend,
VulkanBackend, VulkanBackend,