先借由龙书中的描述引入Descriptors的作用。
在渲染处理过程中,GPU可能会对资源进行读和写。在发出绘制命令之前,我们需要将与本次绘制调用相关的资源绑定到渲染流水线上。部分资源可能在每次绘制调用时都会有所变化,所以我们也就需要每次按需更新绑定。但是,GPU资源并非直接与渲染流水线相绑定,而是要通过一种名为描述符的对象来使用。
可以看出描述符是用于资源绑定的,微软在D3D12中为资源绑定添加了新的概念,包括descriptors, descriptor tables, descriptor heaps,和 root signatures,接下来我们依次介绍。(因为这些概念会相互关联,所以建议至少阅读两次来关联上下文理解)
Descriptors
定义:资源描述符,是一块用来描述在GPU中的各种渲染资源的数据。从本质上来讲,descriptors实际上即为一个中间层,它描述了资源的地址和类型信息。
descriptors共有以下几种类型:(注意在d3d12中,descriptors与view同义)
描述符的大小是和gpu硬件关联的,可以通过接口GetDescriptorHandleIncrementSize获取。
描述符的创建通过驱动层API完成,对于不同的描述符有不同的API,但基本都是用一个对应的结构体来描述descriptors所包含的信息(如下图)
,以下以SRV为例,SRV对应的结构体是D3D12_SHADER_RESOURCE_VIEW_DESC,
typedef struct D3D12_SHADER_RESOURCE_VIEW_DESC
{
DXGI_FORMAT Format;
D3D12_SRV_DIMENSION ViewDimension;
UINT Shader4ComponentMapping;
union
{
D3D12_BUFFER_SRV Buffer;
D3D12_TEX1D_SRV Texture1D;
D3D12_TEX1D_ARRAY_SRV Texture1DArray;
D3D12_TEX2D_SRV Texture2D;
D3D12_TEX2D_ARRAY_SRV Texture2DArray;
D3D12_TEX2DMS_SRV Texture2DMS;
D3D12_TEX2DMS_ARRAY_SRV Texture2DMSArray;
D3D12_TEX3D_SRV Texture3D;
D3D12_TEXCUBE_SRV TextureCube;
D3D12_TEXCUBE_ARRAY_SRV TextureCubeArray;
} ;
} D3D12_SHADER_RESOURCE_VIEW_DESC;
Format表示贴图资源的数据格式。
typedef enum DXGI_FORMAT {
DXGI_FORMAT_UNKNOWN = 0,
DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
DXGI_FORMAT_R32G32B32A32_UINT = 3,
DXGI_FORMAT_R32G32B32A32_SINT = 4,
DXGI_FORMAT_R32G32B32_TYPELESS = 5,
DXGI_FORMAT_R32G32B32_FLOAT = 6,
DXGI_FORMAT_R32G32B32_UINT = 7,
DXGI_FORMAT_R32G32B32_SINT = 8,
···
} ;
ViewDimension表示资源的尺寸,比如1D贴图,2D贴图,立方体贴图等。
typedef enum D3D12_SRV_DIMENSION {
D3D12_SRV_DIMENSION_UNKNOWN = 0,
D3D12_SRV_DIMENSION_BUFFER = 1,
D3D12_SRV_DIMENSION_TEXTURE1D = 2,
D3D12_SRV_DIMENSION_TEXTURE1DARRAY = 3,
D3D12_SRV_DIMENSION_TEXTURE2D = 4,
D3D12_SRV_DIMENSION_TEXTURE2DARRAY = 5,
D3D12_SRV_DIMENSION_TEXTURE2DMS = 6,
D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY = 7,
D3D12_SRV_DIMENSION_TEXTURE3D = 8,
D3D12_SRV_DIMENSION_TEXTURECUBE = 9,
D3D12_SRV_DIMENSION_TEXTURECUBEARRAY = 10,
D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE = 11
} ;
Shader4ComponentMapping表示对采样贴图时返回的数据进行排序,正常情况使用D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING即可。
结构体内包含的Union表示这个资源只能选择其中一个元素使用,如果要生成2D贴图资源就选择D3D12_TEX2D_SRV Texture2D。
typedef struct D3D12_TEX2D_SRV {
UINT MostDetailedMip; //确定细节程度最高的mipmap索引,范围[0,Mipmap - 1]
UINT MipLevels; //mimap数量
UINT PlaneSlice; //平面索引
FLOAT ResourceMinLODClamp; //可以获取的最小的mipmap等级,0表示所有等级都可以获取
} D3D12_TEX2D_SRV;
最后是完整的创建:
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_C