Vulkan의 버퍼는 그래픽 카드에서 읽을 수 있는 임의의 데이터를 저장하는데 사용되는 메모리 영역입니다. 이것들은 우리가 이 챕터에서 할 정점 데이터를 저장하는데 사용할 수 있지만, 향후 챕터에서 탐색할 다른 많은 목적들에도 사용할 수 있습니다. 지금까지 다루었던 Vulkan 객체와 다르게, 버퍼는 자동으로 메모리를 할당하지 않습니다. 이전 챕터의 작업은 Vulkan API가 프로그래머로 하여금 거의 모든 것을 제어할 수 있도록 하며, 메모리 관리가 그 중 하나라는 것을 보여주었습니다.
createVertexBuffer 함수를 만들고 initVulkan에서 createCommandBuffers 전에 호출하도록 합니다.
void initVulkan() {
createInstance();
setupDebugMessenger();
createSurface();
pickPhysicalDevice();
createLogicalDevice();
createSwapChain();
createImageViews();
createRenderPass();
createGraphicsPipeline();
createFramebuffers();
createCommandPool();
createVertexBuffer();
createCommandBuffers();
createSyncObjects();
}
...
void createVertexBuffer() {
}
버퍼를 생성하려면 VkBufferCreateInfo 구조체를 채워야 합니다.
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = sizeof(vertices[0]) * vertices.size();
첫번째 필드는 구조체의 size입니다. 바이트 단위로 버퍼의 크기를 지정합니다. 정점 데이터의 바이트 크기를 계산하는 것은 sizeof로 간단히 할 수 있습니다.
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
두번째 필드는 usage입니다. 버퍼의 데이터가 사용되는 목적을 나타냅니다. 비트 or연산으로 다양한 목적을 지정할 수 있습니다. 우리의 경우 정점 버퍼가 될 것이며, 향후 챕터에서 다른 유형을 살펴보겠습니다.
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
스왑체인의 이미지와 마찬가지로, 버퍼는 특정 큐 패밀리가 소유하거나 여러 큐에서 동시에 소유할 수 있습니다. 버퍼는 그래픽 큐에서만 사용될 것이므로 독점 엑세스를 유지할 수 있습니다.
flags 매개변수는 지금은 관련이 없는 희소 버퍼 메모리를 구성하는데 사용됩니다. 기본값 0으로 두겠습니다.
이제 vkCreateBuffer로 버퍼르 생성할 수 있습니다. 버퍼 핸들을 보유하고 호출할 클래스 멤버 vertexBuffer를 정의하세요.
VkBuffer vertexBuffer;
...
void createVertexBuffer() {
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = sizeof(vertices[0]) * vertices.size();
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(device, &bufferInfo, nullptr, &vertexBuffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create vertex buffer!");
}
}
버퍼는 프로그램이 끝날 때까지 명령을 렌더링하는데 사용할 수 있어야 하며 스왑체인에 의존하지 않으므로, cleanup 함수에서 정리합니다.
void cleanup() {
cleanupSwapChain();
vkDestroyBuffer(device, vertexBuffer, nullptr);
...
}
버퍼가 생성되었지만, 아직 실제로 할당된 메모리가 없습니다. 버퍼에 메모리를 할당하는 첫번째 단계는 vkGetBufferMemoryRequirements라는 함수를 사용하여 메모리 요구사항을 쿼리하는 것입니다.
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device, vertexBuffer, &memRequirements);