当后台缓冲区格式为 DXGI_FORMAT_B8G8R8A8_UNORM 时,为什么像素着色器 returns float4?
Why pixel shader returns float4 when the back buffer format is DXGI_FORMAT_B8G8R8A8_UNORM?
好吧,这已经困扰我一段时间了,在 MSDN 上找不到我需要的任何细节。
这更像是一个由 3 部分组成的问题,所以这里是:
1-) 创建交换链应用程序时指定后台缓冲区像素格式,最常见的是 B8G8R8A8 或 R8G8B8A8。这为每个颜色通道提供了 8 位,因此每个像素总共使用了 4 个字节....那么当 float4 实际上是 16 个字节时,为什么像素着色器必须 return 一种颜色作为 float4?
2-) 将纹理绑定到像素着色器时,我的纹理是 DXGI_FORMAT_B8G8R8A8_UNORM 格式,但为什么采样器需要每个像素一个 float4 才能工作?
3-) 我在这里遗漏了什么吗?我是想多了还是什么?
请提供链接以支持您的声明。最好来自 MSDN!!!!
GPU 设计用于对 32 位浮点数据执行计算,至少如果它们想要支持 D3D11。从 D3D10 开始,您还可以执行 32 位有符号和无符号整数运算。对于 HLSL 中小于 4 字节的类型没有要求或语言支持,因此没有 "byte/char" 或 "short" 用于 1 字节和 2 字节整数或较低精度的浮点数。
任何使用 "FLOAT"、"UNORM" 或 "SNORM" 后缀的 DXGI 格式都是非整数格式,而 "UINT" 和 "SINT" 是无符号和有符号整数。着色器对前三种类型执行的任何读取都将作为 32 位浮点提供给着色器,而不管原始格式是 8 位 UNORM/SNORM 还是 10/11/16/32 位浮点。顶点中的数据通常以低于全脂 32 位浮点数的精度存储以节省内存,但当它到达着色器时它已经被转换为 32 位浮点数。
在输出(到无人机或渲染目标)时,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 会 compress/truncate 根据需要将您的输出存储在您当前根据其类型绑定的资源中。为 GPU 支持的每种格式设置特殊的关键字和类型将是疯狂的。
2) "sampler" 没有 "need a float4 per pixel to work"。我认为你在混合你的术语。纹理是 Texture2D<float4>
的声明实际上只是说明该纹理有四个分量,并且格式不是整数格式。 "float" 并不一定意味着源数据是 32 位浮点数(或者实际上什至是浮点数),而只是数据具有小数部分(例如 0.54、1.32)。同样,将纹理声明为 Texture2D<uint4>
并不意味着源数据一定是 32 位无符号数据,更多的是它包含无符号整数数据的四个分量。但是,数据将返回给您并转换为 32 位浮点数或 32 位整数以供在着色器中使用。
3) 您忽略了 GPU 在读取时解压缩纹理/顶点数据并在写入时再次压缩的事实。用于 vertices/texture 数据的存储量仅与您创建资源的格式一样多,与着色器在 32 位浮点数/整数上运行这一事实无关。
好吧,这已经困扰我一段时间了,在 MSDN 上找不到我需要的任何细节。
这更像是一个由 3 部分组成的问题,所以这里是:
1-) 创建交换链应用程序时指定后台缓冲区像素格式,最常见的是 B8G8R8A8 或 R8G8B8A8。这为每个颜色通道提供了 8 位,因此每个像素总共使用了 4 个字节....那么当 float4 实际上是 16 个字节时,为什么像素着色器必须 return 一种颜色作为 float4?
2-) 将纹理绑定到像素着色器时,我的纹理是 DXGI_FORMAT_B8G8R8A8_UNORM 格式,但为什么采样器需要每个像素一个 float4 才能工作?
3-) 我在这里遗漏了什么吗?我是想多了还是什么?
请提供链接以支持您的声明。最好来自 MSDN!!!!
GPU 设计用于对 32 位浮点数据执行计算,至少如果它们想要支持 D3D11。从 D3D10 开始,您还可以执行 32 位有符号和无符号整数运算。对于 HLSL 中小于 4 字节的类型没有要求或语言支持,因此没有 "byte/char" 或 "short" 用于 1 字节和 2 字节整数或较低精度的浮点数。
任何使用 "FLOAT"、"UNORM" 或 "SNORM" 后缀的 DXGI 格式都是非整数格式,而 "UINT" 和 "SINT" 是无符号和有符号整数。着色器对前三种类型执行的任何读取都将作为 32 位浮点提供给着色器,而不管原始格式是 8 位 UNORM/SNORM 还是 10/11/16/32 位浮点。顶点中的数据通常以低于全脂 32 位浮点数的精度存储以节省内存,但当它到达着色器时它已经被转换为 32 位浮点数。
在输出(到无人机或渲染目标)时,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 会 compress/truncate 根据需要将您的输出存储在您当前根据其类型绑定的资源中。为 GPU 支持的每种格式设置特殊的关键字和类型将是疯狂的。
2) "sampler" 没有 "need a float4 per pixel to work"。我认为你在混合你的术语。纹理是 Texture2D<float4>
的声明实际上只是说明该纹理有四个分量,并且格式不是整数格式。 "float" 并不一定意味着源数据是 32 位浮点数(或者实际上什至是浮点数),而只是数据具有小数部分(例如 0.54、1.32)。同样,将纹理声明为 Texture2D<uint4>
并不意味着源数据一定是 32 位无符号数据,更多的是它包含无符号整数数据的四个分量。但是,数据将返回给您并转换为 32 位浮点数或 32 位整数以供在着色器中使用。
3) 您忽略了 GPU 在读取时解压缩纹理/顶点数据并在写入时再次压缩的事实。用于 vertices/texture 数据的存储量仅与您创建资源的格式一样多,与着色器在 32 位浮点数/整数上运行这一事实无关。