GPUs旨在对32位浮点数据进行计算,至少如果它们想要支持D3D11的话。从D3D10开始,您还可以执行32位有符号和无符号整数运算。在HLSL中,没有小于4个字节的类型的要求或语言支持,因此没有用于1和2字节整数或低精度浮点的“byte / char”或“short”。
使用“FLOAT”,“UNORM”或“SNORM”后缀的任何DXGI格式都是非整数格式,而“UINT”和“SINT”是无符号和有符号整数。着色器对前三种类型执行的任何读取将作为32位浮点提供给着色器,无论原始格式是8位UNORM / SNORM还是10/11/16/32位浮点。顶点中的数据通常以比完整的32位浮点更低的精度存储以节省内存,但是当它到达着色器时,它已经被转换为32位浮点。
在输出(到UAV或Render Targets)时,GPU会将“float”或“uint”数据压缩到创建目标的任何格式中。如果您尝试将
float4(4.4,5.5,6.6,10.1)
输出到8位归一化的目标,则它将简单地被截断为(1.0,1.0,1.0,1.0),每像素仅使用4字节。
因此,回答您的问题:
1)因为着色器仅对32位类型进行操作,但GPU将根据其类型将您的输出压缩/截断为存储在当前绑定的资源中。为每种GPU支持的格式都有特殊的关键字和类型是疯狂的。
2)“采样器”不需要“每个像素一个float4才能工作”。我认为您混淆了术语。声明纹理为
Texture2D<float4>
实际上只是说明此纹理具有四个组件,并且格式不是整数格式。“float”不一定意味着源数据是32位浮点(或实际上甚至是浮点数),而只是该数据具有分数部分(例如0.54、1.32)。同样,将纹理声明为
Texture2D<uint4>
并不意味着源数据必然是32位无符号的,而更多地是表示它包含四个无符号整数数据组件。但是,数据将被返回并转换为32位浮点或32位整数以在着色器内使用。
3)您忽略了GPU在读取时解压缩纹理/顶点数据并在写入时再次压缩它的事实。用于顶点/纹理数据的存储使用量仅与您创建资源的格式一样多,与着色器操作32位浮点/整数无关。