【问题标题】:Compiling GLSL written for OpenGL ES versions to Vulkan将针对 OpenGL ES 版本编写的 GLSL 编译为 Vulkan
【发布时间】:2016-06-17 15:21:59
【问题描述】:

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

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

尝试在 GLSL ES 310 代码中执行此操作会导致错误“'offset on block member': not supported with this profile: 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 中是否有任何选项可以实现相同的目标?

【问题讨论】:

  • "将我所有的 310 ES 着色器代码转换为 430 可以解决我的问题,但这并不理想。" 您的着色器被编写为供 使用Vulkan,而不是 OpenGL ES。那么为什么必须对它们进行更改才能使其正常工作不是“理想的”呢?为什么要使用 ES 版本 3.10 附加到着色器?
  • 随着这个问题不断获得偶尔的观点和支持,我想我会跟进。我的目标是移动设备,包括 OpenGLES2 和 Metal 设备,并希望使用 SPIR-V cross 将单个着色器集交叉编译到我的所有目标平台。我坚持使用 310 ES+GL_KHR_vulkan_glsl,并破解了 glslang 和 SPIRV-Cross 以允许布局偏移(对于 Vulkan)和 lowp(对于 GLES2)。 Glslang 和 SPIRV-Cross 都是开源的,并且相对容易修改以满足我的需求 - YMMV。

标签: vulkan


【解决方案1】:

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

正在发生的事情是这样的。为 Vulkan 编译 GLSL 的一些内容添加到语言中,如 defined by KHR_vulkan_glsl。例如,push_constant 布局显式添加到 GLSL 语法中。

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

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

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

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

【讨论】:

  • 我可能会误解您的答案,但您似乎是说参考编译器完全允许 ​​GLSL-ES 310 只是一个错误。但是,GL_KHR_vulkan_glsl 确实指定它可以应用于 GLSL-ES 310(在依赖项部分)。虽然没有任何实现布局偏移的方法,但 GLSL-ES 310 似乎确实是二等公民,所以我可能会听从您的建议并切换到桌面版本。
  • @Columbo:我认为这是“规范”中的一个错误。 VKSL 应该是一种语言,某种伪扩展,可能支持也可能不支持其所有功能。
  • 是的,对于 GL_KHR_vulkan_glsl 来说,尝试支持太宽泛的 GLSL 版本可能是一个错误步骤。当然,对我来说,如果 GL_KHR_vulkan_glsl 从未支持 GLSL-ES 会更好。然后,在发现我支持错误的马之前,我不会花时间让很多着色器在一种方言中工作。不过,可能不会花费太多精力来重做它们。对于任何试图决定以哪种语言为基础的 vulkan 着色器代码的人,我建议选择桌面 GLSL。
【解决方案2】:

如果您为 Vulkan 编译 SPIR-V,您的着色器中有一个“VULKAN”定义集(请参阅 GL_KHR_VULKAN_glsl),因此您可以执行以下操作:

#ifdef VULKAN
    layout(push_constant) uniform pushConstants {
        vec4 (offset = 12) pos;
    } pushConstBlock;
#else
    // GLES stuff
#endif

【讨论】:

  • 感谢您的回答。我不是在尝试为 GLES 编译着色器,而是在尝试使用 310 ES+GL_KHR_vulkan_glsl 方言为 vulkan 编译着色器。我在我的问题中添加了几个示例,希望可以使问题更清楚。我正在尝试做的工作适用于 430+GL_KHR_vulkan_glsl,但不适用于 310 ES+GL_KHR_vulkan_glsl。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-15
  • 1970-01-01
相关资源
最近更新 更多