当后台缓冲区格式为DXGI_FORMAT_B8G8R8A8_UNORM时,为什么像素着色器返回float4?

4

好的,这个问题困扰我有一段时间了,但是在MSDN上没有找到我需要的详细信息。

这是一个由三部分组成的问题:

1-) 在创建交换链应用程序时,会指定后备缓冲区像素格式,通常是B8G8R8A8或R8G8B8A8。这给出每个颜色通道8位,因此每个像素使用4个字节....那么为什么像素着色器必须返回一个float4颜色,而float4实际上是16个字节?

2-) 当将纹理绑定到像素着色器时,我的纹理是DXGI_FORMAT_B8G8R8A8_UNORM格式,但为什么采样器需要每个像素一个float4才能工作?

3-) 我是否遗漏了什么?我是否想得太多了?

请提供支持您论点的链接。最好是来自MSDN!!!


像素着色器返回单精度浮点数,这样它就可以输出到任何格式的后台缓冲区。 - Chuck Walbourn
很高兴在这里见到你,Chuck,我是DxTex和DxTK的忠实粉丝...回到我的问题上...单精度浮点数仍然是4个字节,所以我不明白为什么当渲染目标需要时,SV_TARGET不能只使用一个单精度浮点数而非4个浮点数。我可以理解这样做更容易进行数据操作,但这会使内存使用量增加四倍。我唯一的解释是认为OM阶段将每个浮点数截断为8位,但是文档中哪里有说明呢? - Miguel
截断并不是正确的词。在着色器中,只有三种类型真正重要,即有符号整数、无符号整数和单精度浮点数。双精度浮点数也存在,但我从未见过它在科学模拟之外使用。 在从像素着色器导出时,GPU会将32位浮点数转换(而不是截断)为渲染目标创建的任何格式。这可以是每个通道8位、10位、11位、16位或32位,具体取决于格式。存储中没有内存增加,着色器只是以更高的精度运行计算。 - Adam Miles
1个回答

7
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位浮点/整数无关。

好的,亚当,尽管你在使用“截断”一词时自相矛盾,但我愿意给你答案。然而,在文档(MSDN)中我可以在哪里找到这个呢?你说的确有道理,但我想在文档中再读一些相关内容。 - Miguel
1
我承认在某些情况下可能会发生截断,但通常情况下,您不会尝试将超出范围的值写入目标,因为您知道它无法存储您要求存储的值。压缩或量化通常是正确操作时会看到的情况。如果您想尝试在8位类型中存储100万,则不要指望它能执行奇迹。就我所说的内容而言,很难找到有用的文档。自着色器首次存在以来,它一直是这样。 - Adam Miles
值得注意的是,尽管32位浮点数是默认值,但驱动程序编译器在某些情况下可以降低精度,如果它确定不必要。例如,直通和简单算术着色器可能在幕后运行16或10位算术单元。您可以通过使用HLSL中的min-precision types来帮助促进这些优化。 - MooseBoys
1
我有和Miguel一样的问题,Miguel的回答对我来说很有意义,所以谢谢。而且我和Miguel有类似的愿望:有人能提供关于这个的官方文档链接吗?我花了很多时间但没有找到足够的信息。如果没有文档,你是如何解决这个问题的? - Jiao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接