这里写目录标题
heap
runtime struct
typedef enum D3D12_HEAP_TYPE
{
D3D12_HEAP_TYPE_DEFAULT = 1,
D3D12_HEAP_TYPE_UPLOAD = 2,
D3D12_HEAP_TYPE_READBACK = 3,
D3D12_HEAP_TYPE_CUSTOM = 4,
D3D12_HEAP_TYPE_GPU_UPLOAD = 5,
} D3D12_HEAP_TYPE;
//如果创建 Heap 时使用了1,2,3,5类型,则 CPUPageProperty 和 MemoryPoolPreference 需要设置为 UNKNOWN,这样驱动会根据当前的架构自动选择合适的 CPUPageProperty 和 MemoryPoolPreference 属性
// 自定义的 Custom Heap 类型可以通过修改 CPUPageProperty 和 MemoryPoolPreference 来设置 Heap 的属性
typedef enum D3D12_CPU_PAGE_PROPERTY
{
D3D12_CPU_PAGE_PROPERTY_UNKNOWN = 0,
D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE = 1,
D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE = 2,
D3D12_CPU_PAGE_PROPERTY_WRITE_BACK = 3,
} D3D12_CPU_PAGE_PROPERTY;
typedef enum D3D12_MEMORY_POOL
{
D3D12_MEMORY_POOL_UNKNOWN = 0,
D3D12_MEMORY_POOL_L0 = 1,
D3D12_MEMORY_POOL_L1 = 2,
} D3D12_MEMORY_POOL;
typedef struct D3D12_HEAP_PROPERTIES
{
D3D12_HEAP_TYPE Type;
D3D12_CPU_PAGE_PROPERTY CPUPageProperty;
D3D12_MEMORY_POOL MemoryPoolPreference;
UINT CreationNodeMask;
UINT VisibleNodeMask;
} D3D12_HEAP_PROPERTIES;
typedef enum D3D12_HEAP_FLAGS
{
D3D12_HEAP_FLAG_NONE = 0x00,
D3D12_HEAP_FLAG_SHARED = 0x01,
D3D12_HEAP_FLAG_DENY_BUFFERS = 0x04,
D3D12_HEAP_FLAG_ALLOW_DISPLAY = 0x08,
D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER = 0x20,
D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES = 0x40,
D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES = 0x80,
D3D12_HEAP_FLAG_HARDWARE_PROTECTED = 0x100,
D3D12_HEAP_FLAG_ALLOW_WRITE_WATCH = 0x200,
D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS = 0x400,
D3D12_HEAP_FLAG_CREATE_NOT_RESIDENT = 0x800,
D3D12_HEAP_FLAG_CREATE_NOT_ZEROED = 0x1000,
D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES = 0x00,
D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS = 0xc0,
D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES = 0x44,
D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES = 0x84,
} D3D12_HEAP_FLAGS;
typedef struct D3D12_HEAP_DESC
{
UINT64 SizeInBytes;
D3D12_HEAP_PROPERTIES Properties;
UINT64 Alignment;
D3D12_HEAP_FLAGS Flags;
} D3D12_HEAP_DESC;
ddi struct
typedef enum D3D12DDI_CPU_PAGE_PROPERTY
{
D3D12DDI_CPU_PAGE_PROPERTY_NOT_AVAILABLE = 0,
D3D12DDI_CPU_PAGE_PROPERTY_WRITE_COMBINE = 1,
D3D12DDI_CPU_PAGE_PROPERTY_WRITE_BACK = 2,
} D3D12DDI_CPU_PAGE_PROPERTY;
typedef enum D3D12DDI_MEMORY_POOL
{
D3D12DDI_MEMORY_POOL_L0 = 0, // Always system memory
D3D12DDI_MEMORY_POOL_L1 = 1, // Typically local video memory
} D3D12DDI_MEMORY_POOL;
typedef enum D3D12DDI_HEAP_FLAGS
{
D3D12DDI_HEAP_FLAG_NONE = 0x0, // Constant for no flags
D3D12DDI_HEAP_FLAG_NON_RT_DS_TEXTURES = 0x2,
D3D12DDI_HEAP_FLAG_BUFFERS = 0x4,
D3D12DDI_HEAP_FLAG_COHERENT_SYSTEMWIDE = 0x8,
D3D12DDI_HEAP_FLAG_PRIMARY = 0x10,
D3D12DDI_HEAP_FLAG_RT_DS_TEXTURES = 0x20,
D3D12DDI_HEAP_FLAG_0041_DENY_L0_DEMOTION = 0x40,
} D3D12DDI_HEAP_FLAGS;
DEFINE_ENUM_FLAG_OPERATORS( D3D12DDI_HEAP_FLAGS );
typedef struct D3D12DDIARG_CREATEHEAP_0001
{
UINT64 ByteSize;
UINT64 Alignment;
D3D12DDI_MEMORY_POOL MemoryPool;
D3D12DDI_CPU_PAGE_PROPERTY CPUPageProperty;
D3D12DDI_HEAP_FLAGS Flags;
UINT CreationNodeMask;
UINT VisibleNodeMask;
} D3D12DDIARG_CREATEHEAP_0001;
Discrete graphics card .VS. Integrated graphics
根据 D3D12 API,主要有两种类型的平台:NUMA (Non-Unifed Memory Architecture,非统一内存架构)和 UMA(Unified Memory Architecture,统一内存架构),可以通过caps查询D3D12_FEATURE_DATA_ARCHITECTURE::UMA。
在NUMA 架构下:
D3D12_MEMORY_POOL_L0 是 system memory
D3D12_MEMORY_POOL_L1 是 video memory
以下heap 类型,存在如下映射关系,可以通过ID3D12Device::GetCustomHeapProperties查询
D3D12_HEAP_TYPE_DEFAULT 等同于: CPUPageProperty = NOT_AVAILABLE, MemoryPoolPreference = L1
D3D12_HEAP_TYPE_UPLOAD 等同于: CPUPageProperty = WRITE_COMBINE, MemoryPoolPreference = L0
D3D12_HEAP_TYPE_READBACK 等同于: CPUPageProperty = WRITE_BACK, MemoryPoolPreference = L0
D3D12_HEAP_TYPE_GPU_UPLOAD等同于CPUPageProperty = WRITE_COMBINE,MemoryPoolPreference = L1
在UMA架构下:
UMA 架构还根据 GPU 和 CPU 是否共享 LLC (Last Level Cache)分为两类,一种是共享 LLC 的 CacheCoherentUMA,另外一类是只共享 SysRAM 的 NonCacheCoherentUMA。CacheCoherentUMA 架构下 CPU 和 GPU 传输数据不需要通过 SysRAM,只需要通过 LLC 速度会更快;
UMA 架构下只有 D3D12_MEMORY_POOL_L0
以下heap 类型,存在如下映射关系,可以通过ID3D12Device::GetCustomHeapProperties查询
D3D12_HEAP_TYPE_DEFAULT 等同于: CPUPageProperty = NOT_AVAILABLE, MemoryPoolPreference = L0
D3D12_HEAP_TYPE_UPLOAD 等同于: CPUPageProperty = CacheCoherentUMA ? WRITE_BACK :WRITE_COMBINE , MemoryPoolPreference = L0
D3D12_HEAP_TYPE_READBACK 等同于: CPUPageProperty = WRITE_BACK, MemoryPoolPreference = L0
D3D12_HEAP_TYPE_GPU_UPLOAD等同于CPUPageProperty = CacheCoherentUMA ? WRITE_BACK :WRITE_COMBINE,MemoryPoolPreference = L0
D3D12_HEAP_TYPE Type .VS . VkMemoryPropertyFlagBits
type | D3D12 | vulkan |
---|---|---|
– | D3D12_HEAP_TYPE_DEFAULT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
– | D3D12_HEAP_TYPE_UPLOAD | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 、VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
– | D3D12_HEAP_TYPE_GPU_UPLOAD | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT、VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 、VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
– | D3D12_HEAP_TYPE_READBACK | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 、VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
– | D3D12_HEAP_TYPE_CUSTOM |
case D3D12_HEAP_TYPE_CUSTOM:
switch (heap_properties->CPUPageProperty)
{
case D3D12_CPU_PAGE_PROPERTY_WRITE_BACK:
*type_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
break;
case D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE:
*type_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
if (heap_properties->MemoryPoolPreference == D3D12_MEMORY_POOL_L1)
*type_flags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
break;
case D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE:
*type_flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
break;
default:
return E_INVALIDARG;
}
break;
validate heap properties
- Textures cannot be created on upload/readback heaps
- Render target and unordered access buffers cannot be created on upload/readback heaps
- For D3D12_HEAP_TYPE_UPLOAD the state must be part of the D3D12_RESOURCE_STATE_GENERIC_READ bitmask (or COMMON)
- ALLOW_CROSS_ADAPTER flag must be set to use ROW_MAJOR layout on textures.
- For ROW_MAJOR textures, MipLevels and DepthOrArraySize must be 1.
ROW_MAJOR textures cannot be CPU visible with CUSTOM heaps.
1D and 3D textures cannot be ROW_MAJOR layout.
if (heap_properties->Type == D3D12_HEAP_TYPE_UPLOAD
|| heap_properties->Type == D3D12_HEAP_TYPE_READBACK)
{
if (desc->Dimension != D3D12_RESOURCE_DIMENSION_BUFFER)
{
WARN("Textures cannot be created on upload/readback heaps.\n");
return E_INVALIDARG;
}
if (desc->Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS))
{
WARN("Render target and unordered access buffers cannot be created on upload/readback heaps.\n");
return E_INVALIDARG;
}
}
if (heap_properties->Type == D3D12_HEAP_TYPE_UPLOAD &&
(initial_state & ~D3D12_RESOURCE_STATE_GENERIC_READ))
{
/* AgilitySDK 606 suddenly started allowing COMMON state in UPLOAD heaps.
* This is not publicly documented, but it's not a big problem to allow it either.
* It also allows any state which is read-only. */
WARN("For D3D12_HEAP_TYPE_UPLOAD the state must be part of the D3D12_RESOURCE_STATE_GENERIC_READ bitmask (or COMMON).\n");
return E_INVALIDARG;
}
if (heap_properties->Type == D3D12_HEAP_TYPE_READBACK &&
initial_state != D3D12_RESOURCE_STATE_COPY_DEST &&
initial_state != D3D12_RESOURCE_STATE_COMMON)
{
/* AgilitySDK 606 suddenly started allowing COMMON state in READBACK heaps.
* This is not publicly documented, but it's not a big problem to allow it either.
* F1 22 hits this case. */
WARN("For D3D12_HEAP_TYPE_READBACK the state must be D3D12_RESOURCE_STATE_COPY_DEST (or COMMON).\n");
return E_INVALIDARG;
}
if (desc->Layout == D3D12_TEXTURE_LAYOUT_ROW_MAJOR)
{
/* ROW_MAJOR textures are severely restricted in D3D12.
* See test_map_texture_validation() for details. */
if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D)
{
if (!(desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER))
{
WARN("ALLOW_CROSS_ADAPTER flag must be set to use ROW_MAJOR layout on textures.\n");
return E_INVALIDARG;
}
if (desc->MipLevels > 1 || desc->DepthOrArraySize > 1)
{
WARN("For ROW_MAJOR textures, MipLevels and DepthOrArraySize must be 1.\n");
return E_INVALIDARG;
}
if (heap_properties->Type == D3D12_HEAP_TYPE_CUSTOM &&
heap_properties->CPUPageProperty != D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE)
{
WARN("ROW_MAJOR textures cannot be CPU visible with CUSTOM heaps.\n");
return E_INVALIDARG;
}
}
else if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D ||
desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
{
WARN("1D and 3D textures cannot be ROW_MAJOR layout.\n");
return E_INVALIDARG;
}
}
return S_OK;
DX12 中的资源创建
Committed Resource
通过 ID3D12Device::CreateCommittedResource 方法创建资源
根据 HeapProperties 创建一个隐式的 Heap,然后在 Heap 上再创建满足 ResourceDesc 类型的资源,一个 Heap 上只存放一个资源
Placed resource
首先通过 ID3D12Device::CreateHeap 创建一个较大的 Heap,然后再通过 ID3D12Device::CreatePlacedResource 在这个 Heap 的区域内进行多次 Sub-Allocate
Reserved resource
首先通过 ID3D12Device::CreateReservedResource 创建一个比较大的资源(虚拟内存,甚至可以超过显存大小),然后创建一个或多个比较小的 Heap(物理内存),在运行时如果 ReservedResource 的某一部分需要被访问到,则通过 ID3D12CommandQueue::UpdateTileMappings 将需要被访问的部分映射到 Heap 物理内存上(一个 Reserved Resource 的不同区域可以被映射到不同的 Heap 上)
Driver
//TODO