Direct3D 11/HLSL Texture3D<float3> 假错误?

Direct3D 11/HLSL Texture3D<float3> False Error?

我收到此错误:

D3D11 ERROR: ID3D11DeviceContext::Dispatch: The Shader Resource View in slot 0 of the Compute Shader unit is using the Format (R32G32B32_FLOAT). This format does not support 'Sample', 'SampleLevel', 'SampleBias' or 'SampleGrad', at least one of which may being used on the Resource by the shader. This mismatch is invalid if the shader actually uses the view (e.g. it is not skipped due to shader code branching). [ EXECUTION ERROR #371: DEVICE_DRAW_RESOURCE_FORMAT_SAMPLE_UNSUPPORTED]

这是我的工作代码:

Texture3D< float4 > g_VectorField;
float3 ... = g_VectorField.SampleLevel( ... ).rgb;

这是导致错误的我的代码:

Texture3D< float3 > g_VectorField;
float3 ... = g_VectorField.SampleLevel( ... );

当我没有捕捉到 Direct3D 错误(禁用 D3D11_CREATE_DEVICE_DEBUG)时,我的应用程序工作正常。据我所知,SampleLevel 的行为并非未定义。它在 中的表现与第一个片段完全相同 ,但它给了我这个错误。 This format does not support 'SampleLevel'我的屁股。

看来这个错误可以忽略,不会导致未定义的行为,那为什么会报错呢?

"undefined behaviour" 给您预期的结果是完全有效的。问题是,它也完全可以让图形驱动程序崩溃或重新安装操作系统,可以这么说。 "warning"来自DirectX,但实际操作是由显卡完成的。因此,您正在执行对 DirectX 11 无效的操作,但特定的 GPU 可能会支持它。其他人不必。未来的卡片也不必。它可能会做一些非常愚蠢的事情来允许您使用采样或将资源转换为 float4。

以C++为例,函数参数的求值顺序未定义。这意味着虽然它可能正在做你期望它在你的编译器和你的计算机上做的事情,但它在不同的地方可能会有所不同(例如,不同的优化可能),或者在不同的编译器/计算机上。代码不再可移植或可靠。

至于为什么这个特定的操作是未定义的,很难说。不同的纹理格式以非常不同的方式表现 - 一些重新校准伽玛,一些预乘阿尔法......很可能没有人期望你的特定类型被广泛使用,所以它不值得在规范中增加额外的分支。可能是他们没有将其包含在规范中,因为没有足够的 GPU 支持它。它真的会给你带来可衡量的性能优势吗?例如,如果支持是通过转换纹理来完成的,float3 变体实际上可能会更慢。

当然,在一般的计算中,存储数据时通常首选2的幂,因为它们可以使一些操作变得容易得多。 GPU 很可能仍然依赖于老式的位黑客来处理一些操作——12​​8 很好,96 ……不是那么多。也许他们仍然将数据存储在 128 位寄存器中,所以使用 96 没有意义。也许,也许,也许一路走来 :D

编辑:我在 DirectX 文档中找到了相关内容:

A resource declared with the DXGI_FORMAT_R32G32B32 family of formats cannot be used simultaneously for vertex and texture data. That is, you may not create a buffer resource with the DXGI_FORMAT_R32G32B32 family of formats that uses any of the following bind flags: D3D10_BIND_VERTEX_BUFFER, D3D10_BIND_INDEX_BUFFER, D3D10_BIND_CONSTANT_BUFFER, or D3D10_BIND_STREAM_OUTPUT

因此,对于实际纹理使用 R32G32B32 似乎没问题,但对于 vertex/index/constant 缓冲区则不行。