很久没有做图形系统的东西了,之前因为家中出了些事情,把精力主要放到了一些杂务和俗务上。最近回过头来看看,离京前的日记里,清楚地标明着,DX11 Shader Reflect的问题还没有解决。
DX9时代带过来的习惯,因为DX9时代的Shader编撰是离不开D3DX库的,因此,感觉上总是习惯把Shader Reflect和ID3DXEffect9理解为同一个层次的东西,而且当时学习DX的时候,也是Effect的文档要远多于Shader Reflect的文档。
因此带来的一个毛病就是,写Shader系统时一直是比较依赖Effect的,组织结构上基于Effect来组织,即便是迁移OpenGL的时候,也会考虑直接使用CG里跟Effect相近的一系列概念。Effect好用、简单、粗暴、有效,围绕其进行组织也没有什么大错,只不过,它确实还不够“本质”,准备写篇“本质论”什么的,如果拿这个堂而皇之地写进去,估计要笑掉围观者的大牙。
因此,当DX11一下子将Effect“扫进垃圾堆”的时候,我多少有些措手不及。编译一个Samples里带的CEffect,总感觉不如自己全新去写一个或者研究一下,到底是怎么个情况,既然您带了CEffect的代码,读读总是无害的。
1.Basic & Misc
1? Shader Parameter以Constant Buffer来组织,不放到某个具体CB的,默认会认为是放到了全局的一个CB中。
2 一次更新一个CBuffer [?],这样比起之前DX9时一刷整个Shader所有的参数要好。如果不用CB,就是DX9那个样子。
3 CB最好按频率来进行组织:PerView、PerDrawCall、PerObject……
4 想到既然CB和Texture一个地位,也就是说Texture和Sampler虽然放到了Global下,但仍然也只是一刷只一个,不会一刷刷一堆的哈,与此同理,UAV哪些东西也是一样的咯?
2.关于Parameter
2.1.基础概念Basic
D3DReflect一个Shader后,交还给用户的是一个ID3D11ShaderReflection接口。这个接口有几个应用是对Parameter分析有关系的:
GetConstantBufferByIndex / GetConstantBufferByName
GetResourceBindingDesc / GetResourceBindingDescByName
Constant Buffer的总数量和Resource Binding的总数量在ID3D11ShaderReflection->GetDesc里面。
那么,这两者什么关系呢?
粗略来说,Resource Binding里包括很多,CBuffer、TBuffer、Texture、Sampler、UAVResource,都在里面,这里面的CBuffer一般就是我们所说的参数部分,这些东西统称为Resource Binding,也就是Resource Binding不仅仅包括CBuffer。
但是Resource Binding Description只有这些资源的一些基本信息:
Name:Resource名称,对于CBuffer来说就是你写的那个"cbuffer xxxx { ...... } "里的那个xxxx,CBuffer的本名。
Type:此Resource是个啥玩意儿?对应D3D_SHADER_INPUT_TYPE。0(D3D_SIT_CBUFFER)就是CBuffer。
BindPoint / BindCount:绑定到了哪个索引上,总共绑了多少个。对于CBuffer而言,就是XSSetConstantBuffer()里那些个index该怎么填,查这里就对了。
uFlags:Resource Binding的这个uFlags对应D3D_SHADER_INPUT_FLAGS。
其它几个都跟纹理有关,跟CBuffer半毛钱关系没有,暂时无视之。
呃,好了,问题来了:这里面一个参数的信息都没有呀?!
没错,因为这里才是对Shader而言真正有用的东西:Shader绑定的资源。
参数是你程序员看了方便的东西,跟Shader本身就半毛钱关系没有,我这绑定资源的接口,凭啥要给你参数信息呢?
不过参数确实是太有用了,没了参数,那不抓瞎了,啥都跟DX文档上那样写,一个cbuffer什么样,我就C++写一个struct也什么样,然后提交CBuffer,我累不累……
所以人微软还是很厚道滴给了另一组信息,就是GetConstantBufferByIndex / GetConstantBufferByName这一组接口。
这组接口里信息就多了,直接一下子返回了一个新的接口:ID3D11ShaderReflectionConstantBuffer,这里面就有一大堆参数信息了,Description里的