由 SPIR-V 的 SPIRV-cross 生成的 GLSL 是不是违反了 std140 规则?

Posted

技术标签:

【中文标题】由 SPIR-V 的 SPIRV-cross 生成的 GLSL 是不是违反了 std140 规则?【英文标题】:GLSL produced by SPIRV-cross from SPIR-V breaks std140 rules?由 SPIR-V 的 SPIRV-cross 生成的 GLSL 是否违反了 std140 规则? 【发布时间】:2021-12-15 09:34:15 【问题描述】:

我已将我的 sn-p HLSL 代码放在这里:https://shader-playground.timjones.io/d9011ef7826a68ed93394792c2edb732

我使用 DXC 将 HLSL 编译为 SPIR-V,然后使用 SPIRV-Cross 获取 GLSL 代码。 GLSL 常量缓冲区用 std140 标记,它包含 vec3 和 float。 据我所知,这是行不通的。这里不应该使用 GL_EXT_scalar_block_layout 吗?常量块应该用标量而不是 std140 标记。我在这里遗漏了一些明显的东西吗?谢谢。

【问题讨论】:

【参考方案1】:

对于任意输入缓冲区,没有与 DX 常量缓冲区布局完全等效的通用 OpenGL 内存布局。

DX 常量缓冲区将添加停止跨越 16 字节边界的单个变量所需的填充,但变量本身仅 4 字节对齐。

GL std140 统一缓冲区将始终在 16 字节边界上对齐 vec3。这在 DX 中没有等价物。

GL std430 统一缓冲区(如果通过 GL_EXT_scalar_block_layout 支持)将始终在 16 字节边界上对齐 vec3。这在 DX 中没有等价物。

GL scalar 统一缓冲区(如果通过 GL_EXT_scalar_block_layout 支持)只会填充到组件元素大小,而不关心 16 字节边界。这在 DX 中没有等价物。

如果您开始使用结构和数组类型,事情会变得更加有趣......

TLDR,如果您想要在 DX 和 GL/GLES 和 Vulkan 之间可移植的固定二进制内存布局,您需要为常量缓冲区设计可移植内存布局。你不能乱扔任意布局并期望它能够工作。

【讨论】:

"GL std140 统一缓冲区在存储方面总是将 vec3 填充到 vec4。" 这不是它的工作原理。它们与 vec4 对齐,但实际上并不占用 16 个字节。所以 vec3 后跟 float 只会占用 16 个字节。 @NicolBolas 谢谢。所以,我认为这里有一些不精确的信息:oreilly.com/library/view/opengl-programming-guide/9780132748445/… 他们在那里声明 vec3 的对齐方式和大小都是 4N。在你所说的之后,我相信在我的情况下,HLSL 和 GLSL 版本都会从缓冲区中读取正确的数据。 再一次,不是一般的。 float1, float3 在 HLSL 中是 16 个字节,在 GLSL 中是 32 个字节 @solidpixel 是的,不是一般的,我理解:D。我询问了这个特殊情况,因为我不明白为什么 SPIRV-cross 生产它生产的 GLSL。我缺少的一件事是 O'Reilly 不准确地描述了 std140。顺便说一句,float, float3 SPIRV-cross 输出:“SPIRV-Cross 抛出异常:缓冲区块不能表示为 std430、std140、标量中的任何一个,即使具有增强的布局。您可以尝试展平此块以支持更灵活布局。”太棒了。

以上是关于由 SPIR-V 的 SPIRV-cross 生成的 GLSL 是不是违反了 std140 规则?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 Vulkan SPIR-V 中使用 OpenCL C mad 函数?

从 SPIR-V 到 ISPC:将 GPU 计算转化为 CPU 计算

如何使用 OpenGL ARB_gl_spirv 扩展?

ⓅChapter 1-Introduction

Vulkan Tutorial 11 Shader modules

解决方案中项目的生成顺序由项目依赖项决定