刚开始我想通过常量缓存上传几个数据到着色器使用,却出现了数据错误,结果调试发现是ByteWidth 的问题。
我的刚开始的常量缓存结构体为:
struct SceneConstantBuffer { XMFLOAT4X4 mvp; // Model-view-projection (MVP) matrix. XMFLOAT3 lightPos; XMFLOAT3 viewPos; XMFLOAT3 color; };
着色器代码对应为:
cbuffer SceneConstantBuffer : register(b0) { float4x4 g_mWorldViewProj; float3 lightPos; float3 viewPos; float3 color; };
因为常量缓存需要256字节对齐,所以通过如下代码进行对齐:
const UINT constantBufferSize = (sizeof(SceneConstantBuffer) + 255) & ~255;
本以为数据可以正常传过去,可惜却并不是。通过RenderDoc调试发现,上传的数据不正确。
通过数据可以看出来,问题出现在哪。viewPos以前的数据都是正常的,而我的viewPos的第一个数据不见了,第二个数据填充到了第一个数据,第三个数据填充到了第二个数据,color的第一个数据填充了我viewPos的第三个数据,而color的第三个数据填充到了第一个数据,后面两个都被0填充了。通过数据的分析可以看出来是ByteWidth的问题,通过官方文档的解释好像是数据都必须是16的整数倍数,言外之意就是数据是通过16的整数倍进行填充的。然后我就把常量缓存结构体改为:
struct SceneConstantBuffer { XMFLOAT4X4 mvp; // Model-view-projection (MVP) matrix. XMFLOAT4 lightPos; XMFLOAT4 viewPos; XMFLOAT4 color; };
着色器对应代码:
cbuffer SceneConstantBuffer : register(b0) { float4x4 g_mWorldViewProj; float4 lightPos; float4 viewPos; float4 color; };
也就是我把数据从float3变为float4,也就是从12字节变为16字节。
最后通过RenderDoc调试查看数据为:
也就是正常把数据上传过去啦。
结论:HLSL将数据打包为4字节对齐,此外,它不允许数据跨16字节(即4个float的vector)的访问。
DirectX12里面常量缓存数据传输出错
原创
©著作权归作者所有:来自51CTO博客作者嘿克不黑的原创作品,请联系作者获取转载授权,否则将追究法律责任
上一篇:现代图形API的比较
下一篇:在DirectX 12中绘制文字
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
还在为慢速数据传输苦恼?Linux 零拷贝技术来帮你!
还在为慢速数据传输苦恼?Linux 零拷贝技术来帮你!
Linux 编程 Linux 零拷贝