6

我的问题与这个问题类似,但部分(有用的)给出的答案与基于 OpenGL ES ESSL 3.10 为 vulkan 编译 GLSL 不兼容。

为了在顶点着色器和片段着色器中使用单独的推送常量内存部分,建议的解决方案是在推送常量结构的第一个成员之前使用 layout(offset = #)。

尝试在 GLSL ES 310 代码中执行此操作会导致错误“'块成员偏移':此配置文件不支持:es”。

是否有支持的方式来声明与 es 兼容的这种偏移量?

我发现的唯一解决方法是在片段着色器中声明一堆虚拟变量。当我这样做时,如果我没有在 VkPipelineLayoutCreateInfo 中声明片段着色器的推送常量缓冲区的全部范围,我会收到验证层错误。修复该问题后,我收到有关“vkCreatePipelineLayout() 调用具有具有重叠范围的推送常量”的验证层警告。

显然我可以忽略警告,但如果有一个更整洁的解决方案,那会更可取。

简单示例,使用 VulkanSDK\1.0.13.0\Bin\glslangValidator.exe 编译成功:

#version 430
#extension GL_ARB_enhanced_layouts: enable

layout(std140, push_constant) uniform PushConstants
{
        layout(offset=64) mat4 matWorldViewProj;
} ubuf;

layout(location = 0) in vec4 i_Position;

void main() {
    gl_Position = ubuf.matWorldViewProj * i_Position;
}

而这不是:

#version 310 es
#extension GL_ARB_enhanced_layouts: enable

layout(std140, push_constant) uniform PushConstants
{
        layout(offset=64) mat4 matWorldViewProj;
} ubuf;

layout(location = 0) in vec4 i_Position;

void main() {
    gl_Position = ubuf.matWorldViewProj * i_Position;
}

将我所有的 310 ES 着色器代码转换为 430 可以解决我的问题,但这并不理想。GL_ARB_enhanced_layouts 不适用于 310 ES 代码,所以我的问题不是为什么它不起作用,而是我在 ES 中是否有任何选项可以实现相同的目标?

4

2 回答 2

3

我认为这是 GLSL 编译器中的错误。

正在发生的事情是这样的。根据 KHR_vulkan_glsl 的定义,为 Vulkan 编译 GLSL会增加一些语言。例如,布局被显式添加到 GLSL 语法中。push_constant

但是,有些东西并没有添加到语言中。对您的用例来说重要的是能够将偏移量应用于统一块的成员。哦,是的,KHR_vulkan_glsl在构建着色器的块布局时使用该信息。但是允许你说的语法layout(offset=#)是由 GLSL 定义的,而不是由 KHR_vulkan_glsl 定义的。

并且该语法不是任何版本的 GLSL-ES 的一部分。我知道的任何 ES 扩展也没有提供它。所以你不能使用它。

我想说的是,在为 Vulkan 编译着色器时,参考编译器应该无法编译任何基于 GLSL-ES 的版本,或者默默地忽略任何版本和扩展声明,并假设桌面 GLSL 4.50。

至于你能做些什么……没什么。除非您自己将该解决方案破解到编译器中,否则您的主要解决方案是针对桌面 OpenGL 版本编写代码。像4.50。

于 2016-06-17T17:35:21.550 回答
1

如果你为 Vulkan 编译 SPIR-V,你的着色器中有一个“VULKAN”定义集(参见GL_KHR_VULKAN_glsl),所以你可以这样做:

#ifdef VULKAN
    layout(push_constant) uniform pushConstants {
        vec4 (offset = 12) pos;
    } pushConstBlock;
#else
    // GLES stuff
#endif
于 2016-06-17T15:36:40.740 回答