Vulkan Cookbook 第五章 7 创建统一(uniform)缓冲区

创建统一缓冲区

译者注:示例代码点击此处

在Vulkan中着色器中使用的统一(uniform)变量不能放在全局命名空间中。它们只能在统一缓冲区中定义。我们还需要使用VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT创建缓冲区。

怎么做...

  1. 获取已创建的逻辑设备句柄并用其初始化名为logical_device的VkDevice变量。
  2. 创建一个名为uniform_buffer的VkBuffer类型变量。它将存储要创建的缓冲区。
  3. 使用logical_device变量创建缓冲区并指定所选的大小和用法。必须至少包含一个VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT标志。将缓冲区的句柄存储在uniform_buffer变量中(请参阅第4章,资源和内存中的创建缓冲区内容)。
  4. 使用VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT属性分配内存对象(或使用现有内存对象的部分范围)并将其绑定到缓冲区(请参阅第4章,资源和内存中的为缓冲区分配和绑定内存对象内容)。

这个怎么运作...

统一缓冲区用于为着色器内的只读uniform变量提供值。

提示:统一缓冲区使用VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER或VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC描述符类型。

通常,统一缓冲区包含不经常更改的参数数据即矩阵(对于少量数据,推荐使用压入式常量(push constants)因为更新它们通常要快得多,通过压入式常量向着着色器提供数据,有关压入式常量的信息可以在第9章命令中的命令记录与绘图)。

创建一个缓冲区,其中将存储uniform变量的数据,这要求我们在缓冲区创建期间指定VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT标志。创建缓冲区时,我们需要准备一个内存对象并将其绑定到创建的缓冲区。(也可是使用现有的内存对象并将其一部分绑定到缓冲区):

if( !CreateBuffer( logical_device, size, usage | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, uniform_buffer ) ) {
  return false;
}

if( !AllocateAndBindMemoryObjectToBuffer( physical_device, logical_device, uniform_buffer, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, memory_object ) ) {
  return false;
}
return true;

在缓冲区及其内存对象准备就绪后,我们可以像使用任何其他类型的缓冲区一样将数据上传到它们,只需记住uniform变量必须放在适当的偏移处。这些偏移量与GLSL语言中的std140布局相同,定义如下:

  • 大小为N的标量变量必须放在N的倍数的偏移处
  • 具有两个分量的向量,其中每个分量的大小为N,必须放在2N的倍数偏移处
  • 具有三个或四个分量的矢量,其中每个分量的大小为N,必须放置在4N的偏移处
  • 具有大小为N个元素的数组放在N的倍数的偏移处,该偏移量必须被舍入到16的倍数。
  • 结构体必须被放置在与其成员的最大偏移量相同的偏移量处,该偏移量必须被舍入到16的倍数(具有最大偏移量要求的成员偏移量,舍入到16的倍数)
  • 行主序矩阵必须放置在等于矢量偏移的偏移处,其中分量数等于矩阵中的列数。
  • 列主序矩阵必须放置在与其列相同的偏移处

动态统一(Dynamic uniform)缓冲区与普通缓冲区的不同之处在于它们指定地址的方式。在描述符集更新期间,我们指定应该用于统一缓冲区的内存大小以及从缓冲区内存开始的偏移量。对于普通的统一缓冲区这些参数保持不变。而对于统一动态缓冲区,指定的偏移量变为从基偏移量(base offset),稍后可以通过在描述符集绑定到命令缓冲区时添加的动态偏移量来修改基偏移。

提示:在GLSL着色器中,统一缓冲区和动态统一缓冲区都使用uniform限定符和块语法定义。

GLSL着色器中的统一缓冲区定义的示例如下:

layout (set=m, binding=n) uniform <variable name> 
{
  vec4 <member 1 name>; 
  mat4 <member 2 name>; 
  // ...
};

猜你喜欢

转载自blog.csdn.net/qq_19473837/article/details/85245068
今日推荐