• 在DirectX12中使用Dynamic Indexing


    dynamic indexing是shader model 5.1才支持的功能,目的是在CPU层减少有关material const buffer和texture descriptor的切换,提高绘制效率。要使用dynamic indexing,首先要对shader代码进行调整:

    struct MaterialData
    {
    	float4   diffuseAlbedo;
    	float3   fresnelR0;
    	float    shininess;
    	uint     diffuseMapIndex;
    	uint     matPad0;
    	uint     matPad1;
    	uint     matPad2;
    };
    
    Texture2D gDiffuseMap[4] : register(t0);
    StructuredBuffer<MaterialData> gMaterialData : register(t0, space1);
    
    cbuffer cbPerObject : register(b0)
    {
    	float4x4 gWorld;
    	float4x4 gInvWorld;
    	float4x4 gWorldViewProj; 
    	uint gMaterialIndex;
    	uint gObjPad0;
    	uint gObjPad1;
    	uint gObjPad2;
    };
    

    这里我们直接使用了Texture2D的数组,意味着我们把用到的texture组合在了一起,可以通过MaterialData中的diffuseMapIndex动态索引。类似地,gMaterialData是一个StructuredBuffer,相当于我们把用到的material const buffer组合在一起,通过object const buffer中的gMaterialIndex动态索引。有了这两个index,我们就不必在绘制每个物体是去设置它的texture和material,只需要调整object const buffer的index即可。

    另外,注意到shader的gDiffuseMap和gMaterialData都使用的register t0,但位于不同的space,因此我们需要调整一下根签名的创建:

    	CD3DX12_DESCRIPTOR_RANGE cbvSrvTable[4];
    	cbvSrvTable[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0);
    	cbvSrvTable[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 1);
    	cbvSrvTable[2].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 2);
    	cbvSrvTable[3].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
    
    	CD3DX12_ROOT_PARAMETER rootParams[4];
    	rootParams[0].InitAsDescriptorTable(1, &cbvSrvTable[0]);
    	rootParams[1].InitAsDescriptorTable(1, &cbvSrvTable[1]);
    	// rootParams[2].InitAsDescriptorTable(1, &cbvSrvTable[2]);
    	rootParams[2].InitAsShaderResourceView(0, 1);
    	rootParams[3].InitAsDescriptorTable(1, &cbvSrvTable[3]);
    

    然后,就是将原先绘制每个物体的过程中切换的代码提前到绘制之前:

    	mCommandList->SetGraphicsRootShaderResourceView(2, res.mMaterialConstBuffer->GetGPUVirtualAddress());
    
    	CD3DX12_GPU_DESCRIPTOR_HANDLE cpuSrvHandle = CD3DX12_GPU_DESCRIPTOR_HANDLE(
    		mCbvSrvHeap->GetGPUDescriptorHandleForHeapStart());
    	cpuSrvHandle.Offset(srvHeapIndex, mCbvSrvHeapIncSize);
    	mCommandList->SetGraphicsRootDescriptorTable(3, cpuSrvHandle);
    

    最后,别忘记在拷贝material buffer和object buffer时对相应的index赋值:

    objConstants.MaterialIndex = object->mMaterial->mID;
    matConstants.diffuseMapIndex = object->mTexture->mID;
    

    如果你觉得我的文章有帮助,欢迎关注我的微信公众号(大龄社畜的游戏开发之路-

  • 相关阅读:
    部署K2 Blackpearl流程时出错(与基础事务管理器的通信失败或Communication with the underlying transaction manager has failed.)
    用SQL命令将查询结果集导出为文本文件
    SQL函数计算两个日期间的工作日天数
    CommonJS模块加载方法
    async 属性
    如何用VS.NET2005调式.asp和.aspx混合的web系统
    对web.config文件的节点进行加解密
    [转]看似简单的问题 静态方法和实例化方法的区别
    单引号(')和双引号(")
    从一个时间段中查找出星期为“Sunday”的日期
  • 原文地址:https://www.cnblogs.com/back-to-the-past/p/15341117.html
Copyright © 2020-2023  润新知