【问题标题】:Vulkan Memory Alignment for Uniform Buffers统一缓冲区的 Vulkan 内存对齐
【发布时间】:2020-09-08 01:37:58
【问题描述】:

我正在关注在线教程:vulkan-tutorial,作者正在其中添加描述符池和描述符集的功能。

我正在使用 Vulkan v1.2.135.0,我的着色器设置为 #version 450

我几乎完成了教程的这一部分,我能够渲染一个旋转的正方形,当我在调试模式下编译和运行时,我没有从 Vulkan 层中得​​到任何错误。

我在上面链接提供的页面底部附近,他在UniformBufferOjbect 结构中引入了glm::vec2,在shader.vert 中的同一相应结构中引入了vec2

他改变了这些:

// Defined in C++ file
struct UniformBufferObject {
    glm::mat4 model;
    glm::mat4 view;
    glm::mat4 proj;
};

// Defined in shader.vert
layout(binding = 0) uniform UniformBufferObject {
    mat4 model;
    mat4 view;
    mat4 proj;
} ubo;

致以下:

// Defined in C++ file
struct UniformBufferObject {
    glm::vec2 foo;
    glm::mat4 model;
    glm::mat4 view;
    glm::mat4 proj;
};

// Defined in shader.vert
layout(binding = 0) uniform UniformBufferObject {
    vec2 foo;
    mat4 model;
    mat4 view;
    mat4 proj;
} ubo;

我按照示例并使用提供的工具重新编译了着色器,将其转换为SPV 二进制文件。正如他所暗示的那样,屏幕上没有渲染任何内容,因为这与 Vulkan 所需的 memory-alignment 有关...

他通过说明如何解决此问题简要解释了内存对齐问题。他建议做两件事……第一件事是使用 C++11 或更高版本的 alignas(16) 修饰符。

然后他说如果我们要将UniformBufferObject 更改为以下内容:

// Defined in C++ file
struct UniformBufferObject {
    glm::vec2 foo;
    alignas(16) glm::mat4 model;
    glm::mat4 view;
    glm::mat4 proj;
};

然后再次编译并运行程序,它应该可以正确呈现,但是,我仍然得到一个黑屏。

他还建议在包含我所做的头文件之前使用glm#define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES 指令。它仍然没有在屏幕上渲染任何东西......

我什至将UniformBufferObject 修改为:

// Defined in C++ file
struct UniformBufferObject {
    glm::vec2 foo;
    alignas(16) glm::mat4 model;
    alignas(16) glm::mat4 view;
    alignas(16) glm::mat4 proj;
};

仍然没有渲染。我不知道为什么这不能按照教程的建议工作。

【问题讨论】:

    标签: c++ c++17 shader vulkan memory-alignment


    【解决方案1】:

    vec2 的对齐必须为 8

    • 浮点数为 4 的对齐方式
    • vec2 对齐 8
    • 一个 vec3, vec4, mat4 一个 16 的对齐方式

    你必须这样改正:

    struct UniformBufferObject {
        alignas(8) glm::vec2 foo;
        alignas(16) glm::mat4 model;
        alignas(16) glm::mat4 view;
        alignas(16) glm::mat4 proj;
    };
    

    UBO 使用规则 std140,您可以查看此规则以了解如何处理它:)

    【讨论】:

      【解决方案2】:

      根据个人经验,UBO 结构应该与 vec4 对齐。结构的第一个字段打破了这种对齐方式。

      快速(est)修复可以是

      struct UniformBufferObject {
          glm::vec4 foo;
          glm::mat4 model;
          glm::mat4 view;
          glm::mat4 proj;
      };
      

      在着色器中,只需使用ubo.foo.xy swizzle 即可获得 vec2。

      当然,shader代码也要修改为

      layout(binding = 0) uniform UniformBufferObject {
          vec4 foo;
          mat4 model;
          mat4 view;
          mat4 proj;
      } ubo;
      

      【讨论】:

      • 我明白...只是我正在遵循教程并且正如作者建议的那样使用alignas(16) 并且它应该可以工作,但它没有...这就是惊人的我很好奇……不知道是不是因为API版本、卡的驱动版本、C++编译器版本等的变化……
      • 可能是因为驱动中的对齐。我猜你正在使用 AMD 的 Radeon。
      • 不完全是,我使用的是 EVGA 的 NVidia Geforce GTX 750 TI。
      猜你喜欢
      • 1970-01-01
      • 2018-03-23
      • 1970-01-01
      • 2021-05-03
      • 1970-01-01
      • 2018-11-07
      • 1970-01-01
      • 1970-01-01
      • 2017-12-09
      相关资源
      最近更新 更多