DirectX11 HLSL打包(packing)格式和“pad”变量的必要性
来源:互联网 发布:抢魅族手机用什么软件 编辑:程序博客网 时间:2024/05/17 04:18
HLSL打包(packing)格式和“pad”变量的必要性
1. C++复制缓存
定义了HLSL结构体后,我们就可以像以下代码一样初始化常量缓冲:
cbuffer cbPerFrame{ DirectionalLight gDirLight; PointLight gPointLight; SpotLight gSpotLight; float3 gEyePosW;};
在应用程序中初始化对应的灯光结构体,我们想在一次调用中将灯光实例设置到effect变量中,而不是单独地设置每个成员变量。可以用以下函数将一个结构实例设置到一个effect变量实例上:
ID3DX11EffectVariable::SetRawValue(void *pData, UINT Offset,UINT Count);// 调用示例:DirectionalLight mDirLight;mfxDirLight->SetRawValue(&mDirLight, 0, sizeof(mDirLight));
但是,由于这个函数只是简单地复制原始字节,因此如果你不仔细的话会导致很难找到错误,这里所说的要仔细对待的东西是指C++的打包(packing)规则与HLSL不同。
2. HLSL打包
HLSL打包规则一:禁止拆分
在HLSL中,当元素打包到要给4D矢量中时会发生结构填充(padding),根据HLSL的规则,一个元素无法拆分到两个4D矢量中。考虑下面的例子:
//HLSLstruct S{ float3 Pos; float3 Dir;};
如果将这个数据打包在4D矢量中,你可能以为会是这样:
vector1:(Pos.x,Pos.y,Pos.z,Dir.x)vector2:(Dir.y,Dir.z,empty,empty)
但是,将元素dir打包在两个不同的4D矢量中违反了HLSL的规则,是不被允许的——一个元素不可以跨过一个4D矢量的范围,它只能这样被打包:
vector 1: (Pos.x, Pos.y, Pos.z,empty) vector 2: (Dir.x, Dir.y, Dir.z,empty)
现在假设我们对应的C++结构如下所示:
// C++struct S{ XMFLOAT3 Pos; XMFLOAT3 Dir;};
如果我们不注意打包规则,只是盲目地调用并复制数据,我们就会得到错误的结果,这是不被HLSL允许的:
vector1:(Pos.x,Pos.y,Pos.z,Dir.x)vector2:(Dir.y,Dir.z,empty,empty)
3. 使用“pad”变量解决打包问题
HLSL打包规则二:允许不拆分插空
所以我们必须基于HLSL打包规则定义C++结构,才能让元素正确地复制到HLSL结构中。我们要使用一个“pad”变量解决上述问题。让我们看几个HLSL打包的例子。
第一个例子。有下列一个结构:
// HLSLstruct S{ float3 v; float s; float2 p; float3 q;} ;
这个结构会有空隙,数据会被打包到3个4D矢量中:
vector1:(v.x,v.y,v.z,s)vector2:(p.x,p.y,empty,empty)vector3:(q.x,q.y,q.z,empty)
我们可以将标量放在第1个矢量的第4个分量中。但是,我们无法在第2个矢量中匹配q的全部分量,所以需要为它分配单独的矢量。(这时候就需要定义pack变量补上空位)
最后一个例子,结构:
struct S{ float2 u; float2 v; float a0; float a1; float a2;} ;
会这样被打包:
vector1:(u.x,u.y,v.x,v.y)vector2:(a0,a1,a2,empty)
HLSL打包规则三:数组的处理方法例外,有所不同。SDK文档中这样说明:“数组中的每个元素都存储在一个4个分量的矢量中。”
所以,若你有一个float2的数组:
float2 TexOffsets[8];
你可能会认为如上面的例子所说,两个float2会包装在一个float4中。但是,数组是例外,上面的代码等同于:
float4 TexOffsets[8];
所以,你需要在C++中定义一个8个XMFLOAT4的数组,而不是8个XMFLOAT2的数组,这样才能正常运行。我们实际上只需要一个float2数组,所以每个元素浪费了两个float的空间。SDK文档指出你可以使用转换和额外的地址计算指令提高内存的使用效率:
float4 array[4];static float2 aggressivePackArray[8] = (float2[8])array;
4. 打包格式规则总结
- 禁止拆分
- 允许不拆分插空
- 数组的处理方法例外,有所不同。SDK文档中这样说明:“数组中的每个元素都存储在一个4个分量的矢量中。”
- DirectX11 HLSL打包(packing)格式和“pad”变量的必要性
- 记录下Directx11中几个易错点_C++和HLSL的变量绑定
- 记录下Directx11中几个易错点_C++和HLSL的变量绑定
- Directx11中获取HLSL中变量一些问题
- DirectX11 HLSL常量缓存
- DirectX11教程4-缓冲区、着色器和HLSL
- Directx11 HelloWorld之HLSL的Effect框架的使用
- Directx11 HelloWorld之HLSL的Effect框架的使用
- Directx11 HelloWorld之HLSL的Effect框架的使用
- Directx11 HelloWorld之HLSL的Effect框架的使用
- 提问的必要性和不必要性
- (网页界面设计的特性和必要性)
- regular pad(正规焊盘),thermal pad(热风焊盘) 和anti pad(隔离盘)的区别使用
- regular pad(正规焊盘),thermal pad(热风焊盘) 和anti pad(隔离盘)的区别使用
- 变量~HLSL
- 关于变量定义时初始化的必要性
- via和pad的区别
- git和maven的必要性
- tomcat出现的PermGen Space问题
- Storm数据流模型的分析及讨论
- 学习ThinkPHP3.2.2:video8,在模板中用随机数函数输出1-5的随机数
- CF 580D Kefa and Dishes(简单状压dp)
- cleaning_shifts
- DirectX11 HLSL打包(packing)格式和“pad”变量的必要性
- Set Matrix Zeroes
- 学习ThinkPHP3.2.2:video8,高难度创新——让许愿墙更漂亮一些
- Swift学习笔记8——枚举类(Enumerations)
- 安卓控件使用系列23:HorizontalScrollView 水平滚动控件的使用方法
- [摘要]Effective Objective-C 2.0(四)
- 学习ThinkPHP3.2.2:video8完成后的完整代码
- UIPickerView组件的使用之随机点菜系统(一)——利用AutoResizing进行屏幕适配,拖线进行实现
- 关于[UIColor clearColor] 与控件的属性:alpha