当前位置: 首页 > news >正文

MiniEngine学习笔记 : RootSignature

学习RootSignature类

  • 前言
  • 1.RootParameter
    • 1.1 源码展示
    • 1.2 源码分析
  • 2.RootSignature
    • 2.1 源码展示
    • 2.2 源码分析
  • 3.总结

前言

  • 书接上回DescriptorHeap,本篇文章分析RootSignature.h文件,包含RootParameter和RootSignature类。

1.RootParameter

1.1 源码展示

  • 类头文件如下:
#pragma once#include "pch.h"class DescriptorCache;class RootParameter
{friend class RootSignature;
public:RootParameter() {m_RootParam.ParameterType = (D3D12_ROOT_PARAMETER_TYPE)0xFFFFFFFF;}~RootParameter(){Clear();}void Clear(){if (m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)delete [] m_RootParam.DescriptorTable.pDescriptorRanges;m_RootParam.ParameterType = (D3D12_ROOT_PARAMETER_TYPE)0xFFFFFFFF;}void InitAsConstants( UINT Register, UINT NumDwords, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL, UINT Space = 0 ){m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;m_RootParam.ShaderVisibility = Visibility;m_RootParam.Constants.Num32BitValues = NumDwords;m_RootParam.Constants.ShaderRegister = Register;m_RootParam.Constants.RegisterSpace = Space;}void InitAsConstantBuffer( UINT Register, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL, UINT Space = 0 ){m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;m_RootParam.ShaderVisibility = Visibility;m_RootParam.Descriptor.ShaderRegister = Register;m_RootParam.Descriptor.RegisterSpace = Space;}void InitAsBufferSRV( UINT Register, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL, UINT Space = 0 ){m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;m_RootParam.ShaderVisibility = Visibility;m_RootParam.Descriptor.ShaderRegister = Register;m_RootParam.Descriptor.RegisterSpace = Space;}void InitAsBufferUAV( UINT Register, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL, UINT Space = 0 ){m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;m_RootParam.ShaderVisibility = Visibility;m_RootParam.Descriptor.ShaderRegister = Register;m_RootParam.Descriptor.RegisterSpace = Space;}void InitAsDescriptorRange( D3D12_DESCRIPTOR_RANGE_TYPE Type, UINT Register, UINT Count, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL, UINT Space = 0 ){InitAsDescriptorTable(1, Visibility);SetTableRange(0, Type, Register, Count, Space);}void InitAsDescriptorTable( UINT RangeCount, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL ){m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;m_RootParam.ShaderVisibility = Visibility;m_RootParam.DescriptorTable.NumDescriptorRanges = RangeCount;m_RootParam.DescriptorTable.pDescriptorRanges = new D3D12_DESCRIPTOR_RANGE[RangeCount];}void SetTableRange( UINT RangeIndex, D3D12_DESCRIPTOR_RANGE_TYPE Type, UINT Register, UINT Count, UINT Space = 0 ){D3D12_DESCRIPTOR_RANGE* range = const_cast<D3D12_DESCRIPTOR_RANGE*>(m_RootParam.DescriptorTable.pDescriptorRanges + RangeIndex);range->RangeType = Type;range->NumDescriptors = Count;range->BaseShaderRegister = Register;range->RegisterSpace = Space;range->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;}const D3D12_ROOT_PARAMETER& operator() ( void ) const { return m_RootParam; }protected:D3D12_ROOT_PARAMETER m_RootParam;
};

1.2 源码分析

类成员变量如下:

// 仅包含D3D12根签名对象,在其上封装一系列管理方法
D3D12_ROOT_PARAMETER m_RootParam;

类方法如下:

class RootParameter
{friend class RootSignature;
public:// 构造函数,初始化根参数类型为无效值RootParameter() {m_RootParam.ParameterType = (D3D12_ROOT_PARAMETER_TYPE)0xFFFFFFFF;}// 析构时Clear~RootParameter(){Clear();}// 清理根签名void Clear(){// 若是描述符表,则释放动态分配的描述符范围数组if (m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)delete [] m_RootParam.DescriptorTable.pDescriptorRanges;// 重置类型为无效值m_RootParam.ParameterType = (D3D12_ROOT_PARAMETER_TYPE)0xFFFFFFFF;}// 初始化根参数,为根常量void InitAsConstants( UINT Register, UINT NumDwords, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL, UINT Space = 0 ){// 类型为根常量m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;// 哪个着色器可见m_RootParam.ShaderVisibility = Visibility;// 可以包含多少个float变量m_RootParam.Constants.Num32BitValues = NumDwords;// 绑定到Shader哪个寄存器m_RootParam.Constants.ShaderRegister = Register;// 寄存器空间m_RootParam.Constants.RegisterSpace = Space;}// 初始化根参数,为一个常量缓冲区描述符void InitAsConstantBuffer( UINT Register, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL, UINT Space = 0 ){m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;m_RootParam.ShaderVisibility = Visibility;m_RootParam.Descriptor.ShaderRegister = Register;m_RootParam.Descriptor.RegisterSpace = Space;}// 初始化根参数,为一个着色器资源视图void InitAsBufferSRV( UINT Register, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL, UINT Space = 0 ){m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;m_RootParam.ShaderVisibility = Visibility;m_RootParam.Descriptor.ShaderRegister = Register;m_RootParam.Descriptor.RegisterSpace = Space;}// 初始化根参数,为一个无序访问视图void InitAsBufferUAV( UINT Register, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL, UINT Space = 0 ){m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;m_RootParam.ShaderVisibility = Visibility;m_RootParam.Descriptor.ShaderRegister = Register;m_RootParam.Descriptor.RegisterSpace = Space;}// 初始化根参数,为一个根描述符范围void InitAsDescriptorRange( D3D12_DESCRIPTOR_RANGE_TYPE Type, UINT Register, UINT Count, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL, UINT Space = 0 ){InitAsDescriptorTable(1, Visibility);SetTableRange(0, Type, Register, Count, Space);}// 初始为描述符表void InitAsDescriptorTable( UINT RangeCount, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL ){// 描述符表类型和着色器可见性m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;m_RootParam.ShaderVisibility = Visibility;// 描述符范围数量和内存分配m_RootParam.DescriptorTable.NumDescriptorRanges = RangeCount;m_RootParam.DescriptorTable.pDescriptorRanges = new D3D12_DESCRIPTOR_RANGE[RangeCount];}// 设置描述符范围void SetTableRange( UINT RangeIndex, D3D12_DESCRIPTOR_RANGE_TYPE Type, UINT Register, UINT Count, UINT Space = 0 ){// 获取描述符范围D3D12_DESCRIPTOR_RANGE* range = const_cast<D3D12_DESCRIPTOR_RANGE*>(m_RootParam.DescriptorTable.pDescriptorRanges + RangeIndex);// 设置描述符范围range->RangeType = Type;range->NumDescriptors = Count;range->BaseShaderRegister = Register;range->RegisterSpace = Space;// 一个描述符表只能绑定到一个描述符堆,D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND// 指定该描述符范围在描述符表中的起始位置相对于描述符表起始位置的偏移量。range->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;}// 在需要时返回D3D12_ROOT_PARAMETERconst D3D12_ROOT_PARAMETER& operator() ( void ) const { return m_RootParam; }protected:// 仅包含D3D12根签名对象,在其上封装一系列管理方法D3D12_ROOT_PARAMETER m_RootParam;
};

RootSignature封装了D3D12_ROOT_PARAMETER并提供了一系列操作函数。

2.RootSignature

2.1 源码展示

RootSignature头文件:

// Maximum 64 DWORDS divied up amongst all root parameters.
// Root constants = 1 DWORD * NumConstants
// Root descriptor (CBV, SRV, or UAV) = 2 DWORDs each
// Descriptor table pointer = 1 DWORD
// Static samplers = 0 DWORDS (compiled into shader)
class RootSignature
{friend class DynamicDescriptorHeap;public:RootSignature( UINT NumRootParams = 0, UINT NumStaticSamplers = 0 ) : m_Finalized(FALSE), m_NumParameters(NumRootParams){Reset(NumRootParams, NumStaticSamplers);}~RootSignature(){}static void DestroyAll(void);void Reset( UINT NumRootParams, UINT NumStaticSamplers = 0 ){if (NumRootParams > 0)m_ParamArray.reset(new RootParameter[NumRootParams]);elsem_ParamArray = nullptr;m_NumParameters = NumRootParams;if (NumStaticSamplers > 0)m_SamplerArray.reset(new D3D12_STATIC_SAMPLER_DESC[NumStaticSamplers]);elsem_SamplerArray = nullptr;m_NumSamplers = NumStaticSamplers;m_NumInitializedStaticSamplers = 0;}RootParameter& operator[] ( size_t EntryIndex ){ASSERT(EntryIndex < m_NumParameters);return m_ParamArray.get()[EntryIndex];}const RootParameter& operator[] ( size_t EntryIndex ) const{ASSERT(EntryIndex < m_NumParameters);return m_ParamArray.get()[EntryIndex];}void InitStaticSampler( UINT Register, const D3D12_SAMPLER_DESC& NonStaticSamplerDesc,D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL );void Finalize(const std::wstring& name, D3D12_ROOT_SIGNATURE_FLAGS Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE);ID3D12RootSignature* GetSignature() const { return m_Signature; }protected:BOOL m_Finalized;UINT m_NumParameters;UINT m_NumSamplers;UINT m_NumInitializedStaticSamplers;uint32_t m_DescriptorTableBitMap;		// One bit is set for root parameters that are non-sampler descriptor tablesuint32_t m_SamplerTableBitMap;			// One bit is set for root parameters that are sampler descriptor tablesuint32_t m_DescriptorTableSize[16];		// Non-sampler descriptor tables need to know their descriptor countstd::unique_ptr<RootParameter[]> m_ParamArray;std::unique_ptr<D3D12_STATIC_SAMPLER_DESC[]> m_SamplerArray;ID3D12RootSignature* m_Signature;
};

RootSignature源文件:

static std::map< size_t, ComPtr<ID3D12RootSignature> > s_RootSignatureHashMap;void RootSignature::DestroyAll(void)
{s_RootSignatureHashMap.clear();
}void RootSignature::InitStaticSampler(UINT Register,const D3D12_SAMPLER_DESC& NonStaticSamplerDesc,D3D12_SHADER_VISIBILITY Visibility )
{ASSERT(m_NumInitializedStaticSamplers < m_NumSamplers);D3D12_STATIC_SAMPLER_DESC& StaticSamplerDesc = m_SamplerArray[m_NumInitializedStaticSamplers++];StaticSamplerDesc.Filter = NonStaticSamplerDesc.Filter;StaticSamplerDesc.AddressU = NonStaticSamplerDesc.AddressU;StaticSamplerDesc.AddressV = NonStaticSamplerDesc.AddressV;StaticSamplerDesc.AddressW = NonStaticSamplerDesc.AddressW;StaticSamplerDesc.MipLODBias = NonStaticSamplerDesc.MipLODBias;StaticSamplerDesc.MaxAnisotropy = NonStaticSamplerDesc.MaxAnisotropy;StaticSamplerDesc.ComparisonFunc = NonStaticSamplerDesc.ComparisonFunc;StaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;StaticSamplerDesc.MinLOD = NonStaticSamplerDesc.MinLOD;StaticSamplerDesc.MaxLOD = NonStaticSamplerDesc.MaxLOD;StaticSamplerDesc.ShaderRegister = Register;StaticSamplerDesc.RegisterSpace = 0;StaticSamplerDesc.ShaderVisibility = Visibility;if (StaticSamplerDesc.AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER ||StaticSamplerDesc.AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER ||StaticSamplerDesc.AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER){WARN_ONCE_IF_NOT(// Transparent BlackNonStaticSamplerDesc.BorderColor[0] == 0.0f &&NonStaticSamplerDesc.BorderColor[1] == 0.0f &&NonStaticSamplerDesc.BorderColor[2] == 0.0f &&NonStaticSamplerDesc.BorderColor[3] == 0.0f ||// Opaque BlackNonStaticSamplerDesc.BorderColor[0] == 0.0f &&NonStaticSamplerDesc.BorderColor[1] == 0.0f &&NonStaticSamplerDesc.BorderColor[2] == 0.0f &&NonStaticSamplerDesc.BorderColor[3] == 1.0f ||// Opaque WhiteNonStaticSamplerDesc.BorderColor[0] == 1.0f &&NonStaticSamplerDesc.BorderColor[1] == 1.0f &&NonStaticSamplerDesc.BorderColor[2] == 1.0f &&NonStaticSamplerDesc.BorderColor[3] == 1.0f,"Sampler border color does not match static sampler limitations");if (NonStaticSamplerDesc.BorderColor[3] == 1.0f){if (NonStaticSamplerDesc.BorderColor[0] == 1.0f)StaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;elseStaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;}elseStaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;}
}void RootSignature::Finalize(const std::wstring& name, D3D12_ROOT_SIGNATURE_FLAGS Flags)
{if (m_Finalized)return;ASSERT(m_NumInitializedStaticSamplers == m_NumSamplers);D3D12_ROOT_SIGNATURE_DESC RootDesc;RootDesc.NumParameters = m_NumParameters;RootDesc.pParameters = (const D3D12_ROOT_PARAMETER*)m_ParamArray.get();RootDesc.NumStaticSamplers = m_NumSamplers;RootDesc.pStaticSamplers = (const D3D12_STATIC_SAMPLER_DESC*)m_SamplerArray.get();RootDesc.Flags = Flags;m_DescriptorTableBitMap = 0;m_SamplerTableBitMap = 0;size_t HashCode = Utility::HashState(&RootDesc.Flags);HashCode = Utility::HashState( RootDesc.pStaticSamplers, m_NumSamplers, HashCode );for (UINT Param = 0; Param < m_NumParameters; ++Param){const D3D12_ROOT_PARAMETER& RootParam = RootDesc.pParameters[Param];m_DescriptorTableSize[Param] = 0;if (RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE){ASSERT(RootParam.DescriptorTable.pDescriptorRanges != nullptr);HashCode = Utility::HashState( RootParam.DescriptorTable.pDescriptorRanges,RootParam.DescriptorTable.NumDescriptorRanges, HashCode );// We keep track of sampler descriptor tables separately from CBV_SRV_UAV descriptor tablesif (RootParam.DescriptorTable.pDescriptorRanges->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER)m_SamplerTableBitMap |= (1 << Param);elsem_DescriptorTableBitMap |= (1 << Param);for (UINT TableRange = 0; TableRange < RootParam.DescriptorTable.NumDescriptorRanges; ++TableRange)m_DescriptorTableSize[Param] += RootParam.DescriptorTable.pDescriptorRanges[TableRange].NumDescriptors;}elseHashCode = Utility::HashState( &RootParam, 1, HashCode );}ID3D12RootSignature** RSRef = nullptr;bool firstCompile = false;{static mutex s_HashMapMutex;lock_guard<mutex> CS(s_HashMapMutex);auto iter = s_RootSignatureHashMap.find(HashCode);// Reserve space so the next inquiry will find that someone got here first.if (iter == s_RootSignatureHashMap.end()){RSRef = s_RootSignatureHashMap[HashCode].GetAddressOf();firstCompile = true;}elseRSRef = iter->second.GetAddressOf();}if (firstCompile){ComPtr<ID3DBlob> pOutBlob, pErrorBlob;ASSERT_SUCCEEDED( D3D12SerializeRootSignature(&RootDesc, D3D_ROOT_SIGNATURE_VERSION_1,pOutBlob.GetAddressOf(), pErrorBlob.GetAddressOf()));ASSERT_SUCCEEDED( g_Device->CreateRootSignature(1, pOutBlob->GetBufferPointer(), pOutBlob->GetBufferSize(),MY_IID_PPV_ARGS(&m_Signature)) );m_Signature->SetName(name.c_str());s_RootSignatureHashMap[HashCode].Attach(m_Signature);ASSERT(*RSRef == m_Signature);}else{while (*RSRef == nullptr)this_thread::yield();m_Signature = *RSRef;}m_Finalized = TRUE;
}

2.2 源码分析

类成员变量如下:

// 此对象是否完成构建
BOOL m_Finalized;// 包含的根参数个数
UINT m_NumParameters;// 包含的采样数个数
UINT m_NumSamplers;// 已经初始化的采样器个数
UINT m_NumInitializedStaticSamplers;// 每个位表示对应索引的根参数 是否为非采样器描述符表
uint32_t m_DescriptorTableBitMap;		// 每个位表示对应索引的根参数 是否为采样器描述符表
uint32_t m_SamplerTableBitMap;		// 根签名最多包含16个根参数,此数组表示每个根参数包含的描述符数量
uint32_t m_DescriptorTableSize[16];		// 根参数数组
std::unique_ptr<RootParameter[]> m_ParamArray;// 采样器数组
std::unique_ptr<D3D12_STATIC_SAMPLER_DESC[]> m_SamplerArray;// D3D12根签名对象
ID3D12RootSignature* m_Signature;

类方法如下:

// 定义在.cpp里的全局静态根签名表,键为根签名的hash值
static std::map<size_t, ComPtr<ID3D12RootSignature>> s_RootSignatureHashMap;// 构造函数,初始化m_Finalized=false,m_NumParamete=NumRootParams
RootSignature::RootSignature(UINT NumRootParams = 0, UINT NumStaticSamplers = 0) : m_Finalized(FALSE), m_NumParameters(NumRootParams)
{// 调用ResetReset(NumRootParams, NumStaticSamplers);
}RootSignature::~RootSignature()
{
}// 重置根签名
void RootSignature::Reset(UINT NumRootParams, UINT NumStaticSamplers = 0)
{// 根据根参数数量,初始化m_ParamArrayif (NumRootParams > 0)m_ParamArray.reset(new RootParameter[NumRootParams]);elsem_ParamArray = nullptr;m_NumParameters = NumRootParams;// 根据静态采样器数量,初始化m_SamplerArrayif (NumStaticSamplers > 0)m_SamplerArray.reset(new D3D12_STATIC_SAMPLER_DESC[NumStaticSamplers]);elsem_SamplerArray = nullptr;// 记录采样器数量,重置已初始化采样器数为0m_NumSamplers = NumStaticSamplers;m_NumInitializedStaticSamplers = 0;
}// 获取根参数
RootParameter& RootSignature::operator[] (size_t EntryIndex)
{ASSERT(EntryIndex < m_NumParameters);return m_ParamArray.get()[EntryIndex];
}const RootParameter& RootSignature::operator[] (size_t EntryIndex) const
{ASSERT(EntryIndex < m_NumParameters);return m_ParamArray.get()[EntryIndex];
}// 获取D3D12根签名对象
ID3D12RootSignature* RootSignature::GetSignature() const { return m_Signature; }// 静态方法-销毁所有根签名
void RootSignature::DestroyAll(void)
{// 清空全局根签名表,COM指针保证调用ID3D12RootSignature的析构函数s_RootSignatureHashMap.clear();
}// 初始化一个静态采样器
void RootSignature::InitStaticSampler(UINT Register,const D3D12_SAMPLER_DESC& NonStaticSamplerDesc,D3D12_SHADER_VISIBILITY Visibility )
{// 检查没有超过预计采样器数ASSERT(m_NumInitializedStaticSamplers < m_NumSamplers);// 获取要修改的采样器D3D12_STATIC_SAMPLER_DESC& StaticSamplerDesc = m_SamplerArray[m_NumInitializedStaticSamplers++];// 赋值StaticSamplerDesc.Filter = NonStaticSamplerDesc.Filter;StaticSamplerDesc.AddressU = NonStaticSamplerDesc.AddressU;StaticSamplerDesc.AddressV = NonStaticSamplerDesc.AddressV;StaticSamplerDesc.AddressW = NonStaticSamplerDesc.AddressW;StaticSamplerDesc.MipLODBias = NonStaticSamplerDesc.MipLODBias;StaticSamplerDesc.MaxAnisotropy = NonStaticSamplerDesc.MaxAnisotropy;StaticSamplerDesc.ComparisonFunc = NonStaticSamplerDesc.ComparisonFunc;StaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;StaticSamplerDesc.MinLOD = NonStaticSamplerDesc.MinLOD;StaticSamplerDesc.MaxLOD = NonStaticSamplerDesc.MaxLOD;StaticSamplerDesc.ShaderRegister = Register;     // 使用Register覆盖StaticSamplerDesc.RegisterSpace = 0;             // 使用Space-0覆盖StaticSamplerDesc.ShaderVisibility = Visibility; // 使用Visibility覆盖// 如果寻址模式为D3D12_TEXTURE_ADDRESS_MODE_BORDERif (StaticSamplerDesc.AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER ||StaticSamplerDesc.AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER ||StaticSamplerDesc.AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER){// 检查采样器边框颜色必须静态采样器限制匹配 // 静态采样器在编译时确定,性能更好,但只能使用有限的预定义边框颜色WARN_ONCE_IF_NOT(// Transparent BlackNonStaticSamplerDesc.BorderColor[0] == 0.0f &&NonStaticSamplerDesc.BorderColor[1] == 0.0f &&NonStaticSamplerDesc.BorderColor[2] == 0.0f &&NonStaticSamplerDesc.BorderColor[3] == 0.0f ||// Opaque BlackNonStaticSamplerDesc.BorderColor[0] == 0.0f &&NonStaticSamplerDesc.BorderColor[1] == 0.0f &&NonStaticSamplerDesc.BorderColor[2] == 0.0f &&NonStaticSamplerDesc.BorderColor[3] == 1.0f ||// Opaque WhiteNonStaticSamplerDesc.BorderColor[0] == 1.0f &&NonStaticSamplerDesc.BorderColor[1] == 1.0f &&NonStaticSamplerDesc.BorderColor[2] == 1.0f &&NonStaticSamplerDesc.BorderColor[3] == 1.0f,"Sampler border color does not match static sampler limitations");/*根据输入的边框颜色值,转换为对应的DX12静态边框颜色枚举值: 如果Alpha=1且RGB全为1 → 不透明白如果Alpha=1但RGB不全为1 → 不透明黑如果Alpha≠1 → 透明黑*/if (NonStaticSamplerDesc.BorderColor[3] == 1.0f){if (NonStaticSamplerDesc.BorderColor[0] == 1.0f)StaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;elseStaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;}elseStaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;}
}// 完成根签名创建
void RootSignature::Finalize(const std::wstring& name, D3D12_ROOT_SIGNATURE_FLAGS Flags)
{// 若已经创建则退出if (m_Finalized)return;// 检测已初始化静态采样器数目等于设置的采样器数ASSERT(m_NumInitializedStaticSamplers == m_NumSamplers);// 根签名描述D3D12_ROOT_SIGNATURE_DESC RootDesc;// 设置根参数RootDesc.NumParameters = m_NumParameters;RootDesc.pParameters = (const D3D12_ROOT_PARAMETER*)m_ParamArray.get();// 设置静态采样器RootDesc.NumStaticSamplers = m_NumSamplers;RootDesc.pStaticSamplers = (const D3D12_STATIC_SAMPLER_DESC*)m_SamplerArray.get();// 设置根签名标志RootDesc.Flags = Flags;// 重置位掩码都为0m_DescriptorTableBitMap = 0;m_SamplerTableBitMap = 0;// 对根签名标志计算Hashsize_t HashCode = Utility::HashState(&RootDesc.Flags);// 在HashCode基础上,再对静态采样器指向的数据计算新的HashHashCode = Utility::HashState( RootDesc.pStaticSamplers, m_NumSamplers, HashCode );// 遍历每个根参数for (UINT Param = 0; Param < m_NumParameters; ++Param){// 获取根参数const D3D12_ROOT_PARAMETER& RootParam = RootDesc.pParameters[Param];// 重置根参数包含的描述符数目为0m_DescriptorTableSize[Param] = 0;// 如果根参数是描述符表if (RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE){// 描述符范围必须有数据ASSERT(RootParam.DescriptorTable.pDescriptorRanges != nullptr);// 对描述符表中的所有描述符范围数据计算HashHashCode = Utility::HashState( RootParam.DescriptorTable.pDescriptorRanges,RootParam.DescriptorTable.NumDescriptorRanges, HashCode );// 我们将采样器描述符表与 CBV_SRV_UAV 描述符表分开跟踪。// 如果此描述符表是D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,则将m_SamplerTableBitMap对应位置为1if (RootParam.DescriptorTable.pDescriptorRanges->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER)m_SamplerTableBitMap |= (1 << Param);elsem_DescriptorTableBitMap |= (1 << Param);// 遍历描述符中每个描述符范围,累计该描述符表包含的描述符总数for (UINT TableRange = 0; TableRange < RootParam.DescriptorTable.NumDescriptorRanges; ++TableRange)m_DescriptorTableSize[Param] += RootParam.DescriptorTable.pDescriptorRanges[TableRange].NumDescriptors;}// 如果不是描述符表,则直接计算根参数的HashelseHashCode = Utility::HashState( &RootParam, 1, HashCode );}ID3D12RootSignature** RSRef = nullptr;bool firstCompile = false;{// 加锁,保护全局根签名表s_RootSignatureHashMapstatic mutex s_HashMapMutex;lock_guard<mutex> CS(s_HashMapMutex);// 根据根参数和静态采样器配置信息,得到最终的HashCode// 使用最终HashCode查询全局根签名表auto iter = s_RootSignatureHashMap.find(HashCode);// 如果此中根签名没有登记在表里if (iter == s_RootSignatureHashMap.end()){// 则在表里创建此Hash(先占位键,值还未初始化)RSRef = s_RootSignatureHashMap[HashCode].GetAddressOf();// 标记需要创建firstCompile = true;}else// 如果表内存在,则直接使用表中RootSignatureRSRef = iter->second.GetAddressOf();}// 构建if (firstCompile){ComPtr<ID3DBlob> pOutBlob, pErrorBlob;ASSERT_SUCCEEDED( D3D12SerializeRootSignature(&RootDesc, D3D_ROOT_SIGNATURE_VERSION_1,pOutBlob.GetAddressOf(), pErrorBlob.GetAddressOf()));ASSERT_SUCCEEDED( g_Device->CreateRootSignature(1, pOutBlob->GetBufferPointer(), pOutBlob->GetBufferSize(),MY_IID_PPV_ARGS(&m_Signature)) );m_Signature->SetName(name.c_str());// 最终构建完毕再替换到表中s_RootSignatureHashMap[HashCode].Attach(m_Signature);ASSERT(*RSRef == m_Signature);}else{// 如果在表中找到,可能另一个线程还在创建// 检查表内对应值,若为空则循环等待while (*RSRef == nullptr)// 让出CPU,减少资源消耗this_thread::yield();// 获取对应值m_Signature = *RSRef;}// 标记已经初始化m_Finalized = TRUE;
}

3.总结

  • RootParameter封装了D3D12_ROOT_PARAMETER,提供了一系列辅助方法。
  • RootSignature封装了ID3D12RootSignature,并使用全局根签名表,以复用同样的根签名。
  • 要将二者作为独立组件,只需为RootSignature::Finalize添加ID3D12Device参数,替代实现中的g_Device。
  • 额外需要添加Common.h和Hash.h,支持Hash计算功能。还在pch.h最后添加了如下代码,链接d3d12库,避免链接错误。
#pragma comment(lib, "d3d12.lib")
#pragma comment(lib, "d3dcompiler.lib")
  • 最终独立组件代码位于:RootSignature。
http://www.dtcms.com/a/574112.html

相关文章:

  • 企业建设门户网站成本如何外贸网店建站模板
  • 吴川手机网站建设公司招代理最好的推广方式
  • mid360实现路径规划
  • 下载了网站建设asp网站建设框架注意事项
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段-二阶段(14):文法和单词-第三课
  • soho 网站建设网站上搜索的动图怎么做壁纸
  • 评测:10 款安卓备份软件和应用(最新资讯)
  • Responses API——OpenAI 下一代智能体与多模态 API 完整开发者指南
  • 自然语言处理实战——基于IMDB影评的情感分析
  • 邹平网站建设微网站建设比较全面的是
  • Linux系统入门:进程控制
  • wordpress 微信绑定域名咸宁网站seo排名
  • STM32——定时器
  • 贵港购物网站开发设计医院网站建设ppt
  • OmniFocus:专为 macOS 与 iOS 打造的专业级任务管理利器
  • 深入理解 C++ STL 中的 map 与 set:从原理到实战
  • 怎么通过做网站挣钱活动公司
  • [特殊字符] MySQL 报错 Invalid default value?罪魁祸首是 NO_ZERO_DATE 和 NO_ZERO_IN_DATE
  • 公司网站制作需要什么步骤邢台网站建设服务周到
  • 自学网络安全学习的误区和陷阱
  • 电商网站怎么做搜索建各公司网站要多少钱
  • BendSQL v0.30.3 Web UI 功能介绍
  • DeepSeek-OCR和Glyph用视觉压缩思路对比
  • 做动漫网站要多少钱tp框架网站开发参考文献
  • 会做网站的公司个人做门户网站需要注册
  • 【数据结构】常见的排序算法 -- 插入排序
  • 电源模块的冲击电流是什么,会对电源模块造成哪些影响?
  • 【机器学习14】深度学习推荐系统、降维技术PCA
  • 烟台网站建设薇企汇互联见效付款静态网站制作流程
  • 2.1 ShaderLab - 渲染状态