周笔记(552) - DX11 - 学习dx sample browser 的 tutorial 和 sample……

    xiaoxiao2021-03-26  20

    git地址:https://github.com/YgritteSnow/Testdemo_dx11/ 【- 夭寿了w(゚Д゚)w又开新坑

    向shader的constant buffer传入数据

    关于 constant buffer

    在shader中定义一个cbuffer作为外部传入数据方便起见,可以在cpp中定义相同结构的struct,方便设置对应数据最终要使用VSSetConstantBuffers/PSSetConstantBuffers来设置

    传入步骤

    方法一:使用动态资源(map/unmap来锁定后修改)

    创建 ID3D11Buffer* ,作为动态资源来进行修改 CreateBuffer是,注意这是一个动态资源,cpu为只写, bind flag 为 D3D11_BIND_CONSTANT_BUFFER在需要改变时,使用 context->Map 来从GPU获取该数据的使用权(D3D11_MAPPED_SUBRESOURCE),注意使用D3D11_MAP_WRITE_DISCARD对该数据赋值,亦即改变此buffer使用 context->Unmap交还给GPU

    方法二:UpdateSubResource

    CPU将资源从内存拷贝到一个不能映射的内存中。(The CPU copies data from memory to a subresource created in non-mappable memory.)对于shader的constant buffer,应当把pDstBox变量设置为NULL。注意这个函数只能修改constant buffer的全部而不是一部分。(For a shader-constant buffer; set pDstBox to NULL. It is not possible to use this method to partially update a shader-constant buffer.)其速度会因为GPU和CPU对目标资源的竞争而降低,例如先在draw后接着UpdateSubResource时,如果Update时Draw正在进行,那么就会造成竞争。(The performance of UpdateSubresource depends on whether or not there is contention for the destination resource.) (同1)也用VSSetConstantBuffers/PSSetConstantBuffers来设置

    Dynamic shader linkage

    在制作shader时经常遇到,同一段shader代码,在很多shader中都会用到。 如何避免这种情况?

    方案1. Uber Shader

    在Shade Model 5以前大多用这种方法通常Uber Shader指的是一个包含很多分支的巨大的Shader,通过下面两种方式来获得不同的特性 在编译期使用不同的#define在运行时使用不同的分支缺点是分支多会难以管理(引用自网络) Frequently when people refer to an ubershader they’re referring to one large shader that’s compiled many times with different #defines for different features.a complex shader with lots of runtime branches, or a complex shader-source-file that uses compile-time branching to generate many permutations / similar programs.The problem with ubershaders is that you can easily get a massive number of compilation permutations, which is hard to manage.

    方案2. 运行时链接

    非效果框架版

    关键类:ID3D11ClassLinkage作用: 收集和储存shader中的所有可链接的对象(interface之派生类)最多可以保存64K的对象(A class linkage object can hold up to 64K gotten instances. A gotten instance is a handle that references a variable name in any shader that is created with that linkage object. When you create a shader with a class linkage object, the runtime gathers these instances and stores them in the class linkage object.)步骤: 在CreateXXXShader时获取 ClassLinkage使用ClassLinkage获取所需的抽象类的接口(abstract class interface)(GetClassInstance函数获取ID3D11ClassInstance*)创建抽象类接口的数组 dynamicLinkArray,根据需要,用之前获取的抽象类接口填充次数组在SetXXXShader时传入 dynamicLinkArray

    效果框架版

    关键词类:没有,一切都在effect上进行步骤: 使用effect->GetVariableByName->AsClassInstance来获取所有子类(ID3DX11EffectClassInstanceVariable)使用effect->GetVariableByName->AsInterface来获取需要被链接的类(ID3DX11EffectInterfaceVariable)将子类设置给需要被链接的类(interface->SetClassInstance(classInstance)所以果然还是效果框架比较简洁~

    对比

    作用非效果框架版效果框架版Shader相关资源ID3D11ClassLinkageID3DX11EffectShader中的子类型变量ID3D11ClassInstanceID3DX11EffectClassInstanceVariable获取shader中的子类型变量linkage->GetClassInstanceeffect->GetVariableByName->AsClassInstanceshader中的普通变量ID3D11BufferID3DX11EffectVectorVariable获取shader中的普通变量Map(index,…) //获得第index个cbuffereffectClassInstance->GetMemberByName->AsXXX //AsVector等设置shader中的普通变量SetConstantBufferseffectVectorVariable->SetXXX //SetFloatVector等需要连接的类类型ID3D11ClassInstanceID3DX11EffectInterfaceVariable获取shader中需要链接的类的信息pReflector->GetVariableByName->GetInterfaceSlot //获得该列表的数据的偏移effect->GetVariableByName->AsInterface //直接获得该类运行时改变的内容利用偏移值及获取的子类型填充上述列表effectInterfaceVariable->SetClassInstance //修改上述获得的类提交GPUPSSetShader/VSSetShader无特殊步骤

    不论如何,从编译期到运行期,是很炫酷的样子…… - 过程的话就是可以在运行期告诉shader,我之前在你这里定义的爸爸,你要把他当成某某某大哥来看待…… - 然后灵活性呢……就好像去理发时,Uber Shader只允许你在开始剪头发的时候选一个剪刀,但是dynamic linkage 允许你在剪到一半的时候也能换,所以…… - 啊……讲道理这点灵活性真的需要么…… - 恩……我觉得我应该做一个……小球碰撞的游戏!然后在游戏中不停的变换Shader!哇!可以完美利用这个特性嗷~~ - ┗|`O′|┛ 嗷~~决定了!这个git里的demo就做这个东东!

    方案3. 运行时生成shader貌似也算是一种方法……

    或者机器生成之类的类似UE啊Unity啊的shader编辑器,其实我最关心的貌似只是怎么避免手动写辣些重复的代码呐……

    杂项小记

    HLSL中,SV_POSITION表示在clip空间下的位置坐标传入constant buffer时注意:对于matrix,因为在C++和HLSL中矩阵的存储方式不同,所以传入matrix时需要先进行转置注意back buffer是通过swapChain->GetBuffer获取的……不然好像没有能填充description的bind flag用……
    转载请注明原文地址: https://ju.6miu.com/read-660638.html

    最新回复(0)