Vulkan大闷锅之Vertex Buffer

Modern OpenGL中,我们至少需要配置VBOVAO,不过Vulkan只需创建好Vertex Buffer,类似VAO的信息将属于后续Pipeline的一部分。

我们已经创建很多Buffer了,这里也类似:

VkBufferCreateInfo vb_info = {};
vb_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
vb_info.pNext = nullptr;
vb_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
//vertex data defined elsewhere
vb_info.size = sizeof(g_vb_solid_face_colors_Data);
vb_info.queueFamilyIndexCount = 0;
vb_info.pQueueFamilyIndices = nullptr;
vb_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
vb_info.flags = 0;
struct
{
  VkBuffer buf;
  VkDeviceMemory mem;
  VkDescriptorBufferInfo buffer_info;
} vertex_buffer;
res = vkCreateBuffer(device, &vb_info, nullptr, &vertex_buffer.buf);
assert(res == VK_SUCCESS);

mem_reqs = {};
vkGetBufferMemoryRequirements(device, vertex_buffer.buf, &mem_reqs);

VkMemoryAllocateInfo vb_alloc = {};
vb_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
vb_alloc.pNext = nullptr;
vb_alloc.memoryTypeIndex = 0;
vb_alloc.allocationSize = mem_reqs.size;

下面这段代码之前已经重复了2次,所以在这里封装了:

auto memory_type_from_properties = [&](uint32_t typeBits, 
        VkFlags requirements_mask, uint32_t * typeIndex)
{
  for (uint32_t i = 0; i < memory_properties.memoryTypeCount; i++)
  {
    if ((typeBits & 1) == 1)
    {
      if ((memory_properties.memoryTypes[i].propertyFlags & 
               requirements_mask) == requirements_mask)
      {
        *typeIndex = i;
        return true;
      }
    }
    typeBits >>= 1;
  }
  return false;
};

pass = memory_type_from_properties(mem_reqs.memoryTypeBits,
                                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 
                                    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
                                    &alloc_info.memoryTypeIndex);
assert(pass && "No mappable, coherent memory");

和之前Uniform Buffer创建过程非常相似:

res = vkAllocateMemory(device, &vb_alloc, NULL, &vertex_buffer.mem);
assert(res == VK_SUCCESS);
uint8_t *pVBData;
res = vkMapMemory(device, vertex_buffer.mem, 0, mem_reqs.size, 0, (void **)&pVBData);
assert(res == VK_SUCCESS);

memcpy(pVBData, g_vb_solid_face_colors_Data, sizeof(g_vb_solid_face_colors_Data));

vkUnmapMemory(device, vertex_buffer.mem);

res = vkBindBufferMemory(device, vertex_buffer.buf, vertex_buffer.mem, 0);
assert(res == VK_SUCCESS);

顶点数据可以储存在别处,下面是个简单的例子:
[showhide more_text=”show more” less_text=”show less”]

struct Vertex {
    float posX, posY, posZ, posW;  // Position data
    float r, g, b, a;              // Color
};
#define XYZ1(_x_, _y_, _z_) (_x_), (_y_), (_z_), 1.f
static const Vertex g_vb_solid_face_colors_Data[] = {
    // red face
    {XYZ1(-1, -1, 1), XYZ1(1.f, 0.f, 0.f)},
    {XYZ1(-1, 1, 1), XYZ1(1.f, 0.f, 0.f)},
    {XYZ1(1, -1, 1), XYZ1(1.f, 0.f, 0.f)},
    {XYZ1(1, -1, 1), XYZ1(1.f, 0.f, 0.f)},
    {XYZ1(-1, 1, 1), XYZ1(1.f, 0.f, 0.f)},
    {XYZ1(1, 1, 1), XYZ1(1.f, 0.f, 0.f)},
    // green face
    {XYZ1(-1, -1, -1), XYZ1(0.f, 1.f, 0.f)},
    {XYZ1(1, -1, -1), XYZ1(0.f, 1.f, 0.f)},
    {XYZ1(-1, 1, -1), XYZ1(0.f, 1.f, 0.f)},
    {XYZ1(-1, 1, -1), XYZ1(0.f, 1.f, 0.f)},
    {XYZ1(1, -1, -1), XYZ1(0.f, 1.f, 0.f)},
    {XYZ1(1, 1, -1), XYZ1(0.f, 1.f, 0.f)},
    // blue face
    {XYZ1(-1, 1, 1), XYZ1(0.f, 0.f, 1.f)},
    {XYZ1(-1, -1, 1), XYZ1(0.f, 0.f, 1.f)},
    {XYZ1(-1, 1, -1), XYZ1(0.f, 0.f, 1.f)},
    {XYZ1(-1, 1, -1), XYZ1(0.f, 0.f, 1.f)},
    {XYZ1(-1, -1, 1), XYZ1(0.f, 0.f, 1.f)},
    {XYZ1(-1, -1, -1), XYZ1(0.f, 0.f, 1.f)},
    // yellow face
    {XYZ1(1, 1, 1), XYZ1(1.f, 1.f, 0.f)},
    {XYZ1(1, 1, -1), XYZ1(1.f, 1.f, 0.f)},
    {XYZ1(1, -1, 1), XYZ1(1.f, 1.f, 0.f)},
    {XYZ1(1, -1, 1), XYZ1(1.f, 1.f, 0.f)},
    {XYZ1(1, 1, -1), XYZ1(1.f, 1.f, 0.f)},
    {XYZ1(1, -1, -1), XYZ1(1.f, 1.f, 0.f)},
    // magenta face
    {XYZ1(1, 1, 1), XYZ1(1.f, 0.f, 1.f)},
    {XYZ1(-1, 1, 1), XYZ1(1.f, 0.f, 1.f)},
    {XYZ1(1, 1, -1), XYZ1(1.f, 0.f, 1.f)},
    {XYZ1(1, 1, -1), XYZ1(1.f, 0.f, 1.f)},
    {XYZ1(-1, 1, 1), XYZ1(1.f, 0.f, 1.f)},
    {XYZ1(-1, 1, -1), XYZ1(1.f, 0.f, 1.f)},
    // cyan face
    {XYZ1(1, -1, 1), XYZ1(0.f, 1.f, 1.f)},
    {XYZ1(1, -1, -1), XYZ1(0.f, 1.f, 1.f)},
    {XYZ1(-1, -1, 1), XYZ1(0.f, 1.f, 1.f)},
    {XYZ1(-1, -1, 1), XYZ1(0.f, 1.f, 1.f)},
    {XYZ1(1, -1, -1), XYZ1(0.f, 1.f, 1.f)},
    {XYZ1(-1, -1, -1), XYZ1(0.f, 1.f, 1.f)},
};

[/showhide]
我们可以提前在这里定义好(类似的)VAO数据:

VkVertexInputBindingDescription vi_binding;
vi_binding.binding = 0;
vi_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
vi_binding.stride = sizeof(g_vb_solid_face_colors_Data[0]);
VkVertexInputAttributeDescription vi_attribs[2];
vi_attribs[0].binding = 0;
vi_attribs[0].location = 0;
vi_attribs[0].format = VK_FORMAT_R32G32B32A32_SFLOAT;
vi_attribs[0].offset = 0;
vi_attribs[1].binding = 0;
vi_attribs[1].location = 1;
vi_attribs[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;
vi_attribs[1].offset = 16;

下一章将演示创建Pipeline的过程。敬请关注后续博文。

Leave a Reply

Your email address will not be published. Required fields are marked *