创建缓冲区
译者注:示例代码点击此处
缓冲区是最简单的资源,因为他们代表的数据只能线形布局在内存中,就像典型的C/C++数组一样:
缓冲区可用于各种目的。它们可以通过描述符集在管线中用于统一缓冲区,记录缓冲区或纹理缓冲区等数据储存。它们可以是顶点索引或属性的数据源,也可以用作分段资源-用于从CPU到GPU的数据传输的中间资源。出于所有这些目的,我们只需要创建一个缓冲区并制定其用法。
怎么做...
1.获取已创建的设备逻辑句柄,将其存储在名为logical_device的VkDevice类型变量中。
2.创建一个名为size的VkDeviceSize类型的变量,该变量表示缓冲区能够存储的数据大小。
3.考虑将使用的缓冲区的所需方案。创建名为usage的VkBufferUsageFlags位域类型变量。
4.创建名为buffer_create_info的VkBufferCreateInfo类型的变量。将以下值分配给其成员:
·sType为VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
·pNext为nullptr value
·flags为0
·usage为usage
·sharingMode为VK_SHARING_MODE_EXCLUSIVE
·queueFamilyIndexCount为0
·pQueueFamilyIndices为nullptr
5.创建一个名为buffer的VkBuffer类型的变量,其中将存储创建的缓冲区的句柄。
6.调用vkCreateBuffer( logical_device, &buffer_create_info, nullptr, &buffer ),并在第一个参数中提供逻辑设备句柄,在第二个参数中提供指向buffer_create_info变量的指针,第三个参数为nullptr,以及最后一个参数指向缓冲区变量。
7.通过检查返回的值是否等于VK_SUCCESS,确保函数调用成功。
这个怎么运作...
在我们创建缓冲区之前,需要知道缓冲区应该有多大以及想要如何使用缓冲区。缓冲区大小由我们希望储存在其中的数据决定。缓冲区在应用程序中使用的方式由缓冲区的用法指定。我们不能以缓冲区创建期间未定义的方式使用缓冲区。
提示:缓冲区只能在创建期间指定用途(用法)。
以下是可以使用缓冲区的受支持方式列表:
·VK_BUFFER_USAGE_TRANSFER_SRC_BIT表示缓冲区可以是复制操作的数据源
·VK_BUFFER_USAGE_TRANSFER_DST_BIT表示可以将数据赋值到缓冲区
·VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT表示缓冲区可以在着色器中用作统一纹理缓冲区
·VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT表示缓冲区可以在着色器中用作储存纹理缓冲区
·VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT表示缓冲区可以在着色器中用作统一变量的值来源
·VK_BUFFER_USAGE_STORAGE_BUFFER_BIT表示可以在着色器中将数储存在缓冲区中
·VK_BUFFER_USAGE_INDEX_BUFFER_BIT表示缓冲区可以在绘制期间用作顶点索引数据源
·VK_BUFFER_USAGE_VERTEX_BUFFER_BIT表示缓冲区可以是绘图期间指定的顶点属性的数据源
·VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT表示缓冲区可以包含间接绘制期间将使用的数据
要创建缓冲区,我们需要准备一个VkBufferCreateInfo类型的变量,在其中提供以下数据:
VkBufferCreateInfo buffer_create_info = {
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, nullptr,
0,
size,
usage,
VK_SHARING_MODE_EXCLUSIVE,
0,
nullptr
};
size和usage变量分别定义了缓冲区可以容纳的数据量以及我们在应用程序中使用缓冲区的方式。
为sharingMode成员提供前面的VK_SHARING_MODE_EXCLUSIVE值是另一个非常重要的参数。通过它我们指定来自多个族的队列是否可以同时访问缓冲区。独占共享模式(Exclusive sharing mode)告诉驱动程序缓冲区只能由一个族中的队列引用一次,我们必须明确告诉驱动程序何时所有权发生了变换(当我们将所有权从一个族转移到另一个族时)。这个选项给了我们更好的性能,但需付出了更多的工作。
我们还可以指定共享模式(VK_SHARING_MODE_CONCURRENT)有了它来自多个族的多个队列可以同时访问缓冲区,我们不需要执行所有权转移。但是需要权衡的是,并发访问可能具有较低的性能。
在我们准备好创建数据之后,可以创建一个这样的缓冲区:
VkResult result = vkCreateBuffer( logical_device, &buffer_create_info, nullptr, &buffer );
if( VK_SUCCESS != result ) {
std::cout << "Could not create a buffer." << std::endl;
return false;
}
return true;