d3d12 Heap and resource

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

typeD3D12vulkan
D3D12_HEAP_TYPE_DEFAULTVK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
D3D12_HEAP_TYPE_UPLOADVK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 、VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
D3D12_HEAP_TYPE_GPU_UPLOADVK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT、VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 、VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
D3D12_HEAP_TYPE_READBACKVK_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

  1. Textures cannot be created on upload/readback heaps
  2. Render target and unordered access buffers cannot be created on upload/readback heaps
  3. For D3D12_HEAP_TYPE_UPLOAD the state must be part of the D3D12_RESOURCE_STATE_GENERIC_READ bitmask (or COMMON)
  4. ALLOW_CROSS_ADAPTER flag must be set to use ROW_MAJOR layout on textures.
  5. 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值