use device local buffer instead of host's

This commit is contained in:
IlyaShurupov 2024-11-18 13:51:46 +03:00
parent 115e92ec23
commit eb269cc88e

134
main.cpp
View file

@ -107,8 +107,6 @@ private:
createSynchronizationObjects();
createVertexBuffer();
allocateVertexBufferMemory();
sendVertexBufferData();
}
void mainLoop() {
@ -787,57 +785,104 @@ private:
return {};
}
void allocateVertexBufferMemory() {
VkMemoryRequirements memoryRequirements;
vkGetBufferMemoryRequirements(mDevice, mVertexBuffer, &memoryRequirements);
void createVertexBuffer() {
size_t size = vertices.size() * sizeof(vertices[0]);
// FIXME : use explicit memory flushing instead of coherent_bit
auto memoryFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
createBuffer(&stagingBuffer, &stagingBufferMemory,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
{
void* memory;
vkMapMemory(mDevice, stagingBufferMemory, 0, size, 0, &memory);
memcpy(memory, vertices.data(), size);
vkUnmapMemory(mDevice, stagingBufferMemory);
}
createBuffer(&mVertexBuffer, &mVertexBufferMemory,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
copyBuffer(stagingBuffer, mVertexBuffer, size);
destroyBuffer(stagingBuffer, stagingBufferMemory);
}
void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size) {
VkCommandBufferAllocateInfo allocateInfo {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = mCommandPool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1
};
VkCommandBuffer commandBuffer;
vkAllocateCommandBuffers(mDevice, &allocateInfo, &commandBuffer);
VkCommandBufferBeginInfo beginInfo {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
};
vkBeginCommandBuffer(commandBuffer, &beginInfo);
VkBufferCopy copyRegion {
.srcOffset = 0,
.dstOffset = 0,
.size = size,
};
vkCmdCopyBuffer(commandBuffer, src, dst, 1, &copyRegion);
vkEndCommandBuffer(commandBuffer);
VkSubmitInfo submitInfo {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1,
.pCommandBuffers = &commandBuffer,
};
vkQueueSubmit(mGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
vkQueueWaitIdle(mGraphicsQueue);
vkFreeCommandBuffers(mDevice, mCommandPool, 1, &commandBuffer);
}
void createBuffer(VkBuffer *buffer, VkDeviceMemory *memory, VkMemoryPropertyFlags properties, VkDeviceSize size,
VkBufferUsageFlags usage) {
VkBufferCreateInfo createInfo {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = size,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
if (vkCreateBuffer(mDevice, &createInfo, nullptr, buffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create vertex buffer");
}
VkMemoryRequirements memoryRequirements;
vkGetBufferMemoryRequirements(mDevice, *buffer, &memoryRequirements);
VkMemoryAllocateInfo allocateInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = memoryRequirements.size,
.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, memoryFlags),
.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, properties),
};
if (vkAllocateMemory(mDevice, &allocateInfo, nullptr, &mVertexBufferMemory) != VK_SUCCESS) {
if (vkAllocateMemory(mDevice, &allocateInfo, nullptr, memory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate vertex buffer memory");
}
vkBindBufferMemory(mDevice, mVertexBuffer, mVertexBufferMemory, 0);
vkBindBufferMemory(mDevice, *buffer, *memory, 0);
}
void sendVertexBufferData() {
size_t memoryLength = vertices.size() * sizeof(vertices[0]);
void* memory;
if (vkMapMemory(mDevice, mVertexBufferMemory, 0, memoryLength, 0, &memory) != VK_SUCCESS) {
throw std::runtime_error("failed to map memory");
}
memcpy(memory, vertices.data(), memoryLength);
vkUnmapMemory(mDevice, mVertexBufferMemory);
}
void freeVertexBufferMemory() {
vkFreeMemory(mDevice, mVertexBufferMemory, nullptr);
}
void createVertexBuffer() {
VkBufferCreateInfo createInfo {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = vertices.size() * sizeof(vertices[0]),
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
if (vkCreateBuffer(mDevice, &createInfo, nullptr, &mVertexBuffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create vertex buffer");
}
}
void destroyVertexBuffer() {
vkDestroyBuffer(mDevice, mVertexBuffer, nullptr);
void destroyBuffer(VkBuffer buffer, VkDeviceMemory memory) {
vkDestroyBuffer(mDevice, buffer, nullptr);
vkFreeMemory(mDevice, memory, nullptr);
}
void populateGraphicsCommandBuffer(VkCommandBuffer commandBuffer, uint32_t swapChainImageIndex) {
@ -969,6 +1014,10 @@ private:
*/
}
void createBuffer() {
}
static VkVertexInputBindingDescription getShaderVertexInputDescription() {
return {
.binding = 0,
@ -1004,8 +1053,7 @@ private:
}
void cleanup() {
freeVertexBufferMemory();
destroyVertexBuffer();
destroyBuffer(mVertexBuffer, mVertexBufferMemory);
destroySynchronizationObjects();