Add staging buffer
This commit is contained in:
1 parent
f4a6260a5e
commit
f8b32717f3
2 files changed
+150
-41
No files matched your search
@@ -33,7 +33,7 @@ enum Errors
|
|||||||
VULKAN_FAILED_TO_CREATE_DEVICE,
|
VULKAN_FAILED_TO_CREATE_DEVICE,
|
||||||
VULKAN_ALLOCATOR_CREATION_FAILED,
|
VULKAN_ALLOCATOR_CREATION_FAILED,
|
||||||
VULKAN_COMMAND_POOL_CREATION_FAILED,
|
VULKAN_COMMAND_POOL_CREATION_FAILED,
|
||||||
VULKAN_VERTEX_BUFFER_CREATION_FAILED,
|
VULKAN_BUFFER_CREATION_FAILED,
|
||||||
VULKAN_VERTEX_BUFFER_MAPPING_FAILED,
|
VULKAN_VERTEX_BUFFER_MAPPING_FAILED,
|
||||||
VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED,
|
VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED,
|
||||||
VULKAN_SURFACE_CREATION_FAILED,
|
VULKAN_SURFACE_CREATION_FAILED,
|
||||||
@@ -70,7 +70,7 @@ std::array<std::array<const char*, LAST_MESSAGE>, LAST_LANGUAGE> vulkanErrorMess
|
|||||||
"Failed to create Vulkan Memory Allocator",
|
"Failed to create Vulkan Memory Allocator",
|
||||||
/* VULKAN_COMMAND_POOL_CREATION_FAILED */
|
/* VULKAN_COMMAND_POOL_CREATION_FAILED */
|
||||||
"Failed to create command pool",
|
"Failed to create command pool",
|
||||||
/* VULKAN_VERTEX_BUFFER_CREATION_FAILED */
|
/* VULKAN_BUFFER_CREATION_FAILED */
|
||||||
"Failed to create a vertex buffer",
|
"Failed to create a vertex buffer",
|
||||||
/* VULKAN_VERTEX_BUFFER_MAPPING_FAILED */
|
/* VULKAN_VERTEX_BUFFER_MAPPING_FAILED */
|
||||||
"Failed to map vulkan memory buffer",
|
"Failed to map vulkan memory buffer",
|
||||||
|
|||||||
+148
-39
@@ -72,7 +72,7 @@ enum VULKAN_ERROR
|
|||||||
VULKAN_ERROR_DEVICE_CREATION_FAILED,
|
VULKAN_ERROR_DEVICE_CREATION_FAILED,
|
||||||
VULKAN_ERROR_ALLOCATOR_CREATION_FAILED,
|
VULKAN_ERROR_ALLOCATOR_CREATION_FAILED,
|
||||||
VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED,
|
VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED,
|
||||||
VULKAN_ERROR_VERTEX_BUFFER_CREATION_FAILED,
|
VULKAN_ERROR_BUFFER_CREATION_FAILED,
|
||||||
VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED,
|
VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED,
|
||||||
VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED,
|
VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED,
|
||||||
VULKAN_ERROR_SURFACE_CREATION_FAILED,
|
VULKAN_ERROR_SURFACE_CREATION_FAILED,
|
||||||
@@ -202,17 +202,43 @@ std::vector<VkShaderModule> gShaderModules;
|
|||||||
VkRenderPass gRenderPass = VK_NULL_HANDLE;
|
VkRenderPass gRenderPass = VK_NULL_HANDLE;
|
||||||
VkPipelineLayout gPipelineLayout = VK_NULL_HANDLE;
|
VkPipelineLayout gPipelineLayout = VK_NULL_HANDLE;
|
||||||
VkPipeline gGraphicsPipeline = VK_NULL_HANDLE;
|
VkPipeline gGraphicsPipeline = VK_NULL_HANDLE;
|
||||||
std::vector<VkFramebuffer> gSwapchainFramebuffers;
|
std::vector<VkFramebuffer> gSwapchainFramebuffers = {};
|
||||||
std::vector<VkSemaphore> gImageAvailableSemaphores;
|
std::vector<VkSemaphore> gImageAvailableSemaphores = {};
|
||||||
std::vector<VkSemaphore> gRenderFinishedSemaphores;
|
std::vector<VkSemaphore> gRenderFinishedSemaphores = {};
|
||||||
std::vector<VkFence> gInFlightFences;
|
std::vector<VkFence> gInFlightFences = {};
|
||||||
Buffer gVertexBuffer;
|
/* GPU visible buffer */
|
||||||
|
Buffer gVertexBuffer = {};
|
||||||
|
/* CPU visible buffer. TODO: Do we need this global? */
|
||||||
|
Buffer gVertexStagingBuffer = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper function. Creates a buffer object
|
||||||
|
*
|
||||||
|
* @param size Size of the target buffer
|
||||||
|
* @param bufferUsage Buffer usage flags
|
||||||
|
* @param memoryUsage memory usage flags (mostly VMA_MEMORY_USAGE_AUTO)
|
||||||
|
* @param allocationFlags VMA allocation flags
|
||||||
|
* @param buffer Buffer, that will be allocated
|
||||||
|
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
||||||
|
* VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED
|
||||||
|
*/
|
||||||
|
static uint8_t createBuffer(const VkDeviceSize size, VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage,
|
||||||
|
const VmaAllocationCreateFlags allocationFlags, Buffer& buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy one buffer's data to another
|
||||||
|
*
|
||||||
|
* @param src Source buffer
|
||||||
|
* @param dst Destination buffer
|
||||||
|
* @param size Size of buffer to copy
|
||||||
|
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
||||||
|
*/
|
||||||
|
static uint8_t copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create the Vulkan Instance object
|
* @brief Create the Vulkan Instance object
|
||||||
*
|
*
|
||||||
* @return int VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
||||||
* VULKAN_ERROR_INSTANCE_INIT_FAILED
|
* VULKAN_ERROR_INSTANCE_INIT_FAILED
|
||||||
*/
|
*/
|
||||||
static uint8_t createInstance();
|
static uint8_t createInstance();
|
||||||
@@ -269,7 +295,7 @@ static uint8_t createCommandPools();
|
|||||||
* @brief Create a buffer holding all vertex data
|
* @brief Create a buffer holding all vertex data
|
||||||
*
|
*
|
||||||
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
|
||||||
* VULKAN_ERROR_VERTEX_BUFFER_CREATION_FAILED
|
* VULKAN_ERROR_BUFFER_CREATION_FAILED
|
||||||
* VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED
|
* VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED
|
||||||
*/
|
*/
|
||||||
static uint8_t createVertexBuffer();
|
static uint8_t createVertexBuffer();
|
||||||
@@ -406,6 +432,92 @@ static uint8_t createFrambuffers();
|
|||||||
static void recreateSwapchain();
|
static void recreateSwapchain();
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t createBuffer(const VkDeviceSize size, VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage,
|
||||||
|
const VmaAllocationCreateFlags allocationFlags, Buffer& buffer)
|
||||||
|
{
|
||||||
|
VkBufferCreateInfo vertexBufferInfo;
|
||||||
|
VmaAllocationCreateInfo allocInfo;
|
||||||
|
|
||||||
|
vertexBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
vertexBufferInfo.pNext = nullptr;
|
||||||
|
vertexBufferInfo.flags = 0U;
|
||||||
|
vertexBufferInfo.size = size;
|
||||||
|
vertexBufferInfo.usage = bufferUsage;
|
||||||
|
vertexBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
vertexBufferInfo.queueFamilyIndexCount = 0U;
|
||||||
|
vertexBufferInfo.pQueueFamilyIndices = nullptr;
|
||||||
|
|
||||||
|
/* Disalows random access to memory. TODO: Consider changing to VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT? */
|
||||||
|
allocInfo.flags = allocationFlags;
|
||||||
|
allocInfo.usage = memoryUsage;
|
||||||
|
allocInfo.memoryTypeBits = 0U;
|
||||||
|
allocInfo.requiredFlags = 0U;
|
||||||
|
allocInfo.preferredFlags = 0U;
|
||||||
|
allocInfo.pool = VK_NULL_HANDLE;
|
||||||
|
allocInfo.pUserData = VK_NULL_HANDLE;
|
||||||
|
allocInfo.priority = 0.0f;
|
||||||
|
|
||||||
|
if (VK_SUCCESS != vmaCreateBuffer(gAllocator,
|
||||||
|
&vertexBufferInfo,
|
||||||
|
&allocInfo,
|
||||||
|
&buffer.buffer,
|
||||||
|
&buffer.allocation,
|
||||||
|
nullptr)) {
|
||||||
|
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||||
|
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VULKAN_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size)
|
||||||
|
{
|
||||||
|
/* Vulkan buffers can only be copied using command buffers */
|
||||||
|
VkBufferCopy copyRegion;
|
||||||
|
VkSubmitInfo submitInfo;
|
||||||
|
VkCommandBuffer copyCommandBuffer;
|
||||||
|
VkCommandBufferBeginInfo beginInfo;
|
||||||
|
VkCommandBufferAllocateInfo allocInfo;
|
||||||
|
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
|
allocInfo.pNext = nullptr;
|
||||||
|
allocInfo.commandPool = gCommandPool;
|
||||||
|
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
|
allocInfo.commandBufferCount = 1;
|
||||||
|
|
||||||
|
|
||||||
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
beginInfo.pNext = nullptr;
|
||||||
|
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
|
beginInfo.pInheritanceInfo = nullptr;
|
||||||
|
|
||||||
|
copyRegion.srcOffset = 0;
|
||||||
|
copyRegion.dstOffset = 0;
|
||||||
|
copyRegion.size = size;
|
||||||
|
|
||||||
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
submitInfo.pNext = nullptr;
|
||||||
|
submitInfo.waitSemaphoreCount = 0;
|
||||||
|
submitInfo.pWaitSemaphores = nullptr;
|
||||||
|
submitInfo.pWaitDstStageMask = nullptr;
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = ©CommandBuffer;
|
||||||
|
submitInfo.signalSemaphoreCount = 0;
|
||||||
|
submitInfo.pSignalSemaphores = nullptr;
|
||||||
|
|
||||||
|
// FIXME: At result checks
|
||||||
|
vkAllocateCommandBuffers(gDevice, &allocInfo, ©CommandBuffer);
|
||||||
|
vkBeginCommandBuffer(copyCommandBuffer, &beginInfo);
|
||||||
|
vkCmdCopyBuffer(copyCommandBuffer, src, dst, 1, ©Region);
|
||||||
|
vkEndCommandBuffer(copyCommandBuffer);
|
||||||
|
vkQueueSubmit(gGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||||
|
/* TODO: Use fences to wait instead of idle */
|
||||||
|
vkQueueWaitIdle(gGraphicsQueue);
|
||||||
|
vkFreeCommandBuffers(gDevice, gCommandPool, 1, ©CommandBuffer);
|
||||||
|
|
||||||
|
return VULKAN_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||||
@@ -738,47 +850,43 @@ static uint8_t createCommandPools()
|
|||||||
|
|
||||||
static uint8_t createVertexBuffer()
|
static uint8_t createVertexBuffer()
|
||||||
{
|
{
|
||||||
VkBufferCreateInfo vertexBufferInfo;
|
|
||||||
VmaAllocationCreateInfo allocInfo;
|
|
||||||
void* mappedData;
|
void* mappedData;
|
||||||
|
VkDeviceSize bufferSize;
|
||||||
|
|
||||||
vertexBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
bufferSize = sizeof(vertices[0]) * vertices.size();
|
||||||
vertexBufferInfo.pNext = nullptr;
|
|
||||||
vertexBufferInfo.flags = 0U;
|
|
||||||
vertexBufferInfo.size = sizeof(vertices[0]) * vertices.size();
|
|
||||||
vertexBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
|
||||||
vertexBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
vertexBufferInfo.queueFamilyIndexCount = 0U;
|
|
||||||
vertexBufferInfo.pQueueFamilyIndices = nullptr;
|
|
||||||
|
|
||||||
/* Disalows random access to memory. TODO: Consider changing to VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT? */
|
/* Creating staging buffer*/
|
||||||
allocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
if (VK_SUCCESS != createBuffer(bufferSize,
|
||||||
allocInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
allocInfo.memoryTypeBits = 0U;
|
VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||||
allocInfo.requiredFlags = 0U;
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||||
allocInfo.preferredFlags = 0U;
|
gVertexStagingBuffer)) {
|
||||||
allocInfo.pool = VK_NULL_HANDLE;
|
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||||
allocInfo.pUserData = VK_NULL_HANDLE;
|
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||||
allocInfo.priority = 0.0f;
|
|
||||||
|
|
||||||
if (VK_SUCCESS != vmaCreateBuffer(gAllocator,
|
|
||||||
&vertexBufferInfo,
|
|
||||||
&allocInfo,
|
|
||||||
&gVertexBuffer.buffer,
|
|
||||||
&gVertexBuffer.allocation,
|
|
||||||
nullptr)) {
|
|
||||||
LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_CREATION_FAILED];
|
|
||||||
return VULKAN_ERROR_VERTEX_BUFFER_CREATION_FAILED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill vertex buffer */
|
/* Create Vertex Buffer*/
|
||||||
if (VK_SUCCESS != vmaMapMemory(gAllocator, gVertexBuffer.allocation, &mappedData))
|
if (VK_SUCCESS != createBuffer(bufferSize,
|
||||||
|
VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||||
|
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||||
|
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
||||||
|
0, /* Will not be mapped with vmaMapMemory */
|
||||||
|
gVertexBuffer)) {
|
||||||
|
LOGF << vulkanErrorMesssages[VULKAN_BUFFER_CREATION_FAILED];
|
||||||
|
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Fill staging buffer */
|
||||||
|
if (VK_SUCCESS != vmaMapMemory(gAllocator, gVertexStagingBuffer.allocation, &mappedData))
|
||||||
{
|
{
|
||||||
LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_MAPPING_FAILED];
|
LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_MAPPING_FAILED];
|
||||||
return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED;
|
return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED;
|
||||||
}
|
}
|
||||||
memcpy(mappedData, vertices.data(), sizeof(Vertex) * vertices.size());
|
memcpy(mappedData, vertices.data(), sizeof(Vertex) * vertices.size());
|
||||||
vmaUnmapMemory(gAllocator, gVertexBuffer.allocation);
|
vmaUnmapMemory(gAllocator, gVertexStagingBuffer.allocation);
|
||||||
|
|
||||||
|
copyBuffer(gVertexStagingBuffer.buffer, gVertexBuffer.buffer, bufferSize);
|
||||||
|
|
||||||
return VULKAN_ERROR_NO_ERROR;
|
return VULKAN_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
@@ -1460,6 +1568,7 @@ void deinitVulkan()
|
|||||||
cleanupSwapchain();
|
cleanupSwapchain();
|
||||||
|
|
||||||
vmaDestroyBuffer(gAllocator, gVertexBuffer.buffer, gVertexBuffer.allocation);
|
vmaDestroyBuffer(gAllocator, gVertexBuffer.buffer, gVertexBuffer.allocation);
|
||||||
|
vmaDestroyBuffer(gAllocator, gVertexStagingBuffer.buffer, gVertexStagingBuffer.allocation);
|
||||||
for (size_t i = 0; i < SWAP_BUFFER_COUNT; ++i) {
|
for (size_t i = 0; i < SWAP_BUFFER_COUNT; ++i) {
|
||||||
vkDestroySemaphore(gDevice, gImageAvailableSemaphores[i], nullptr);
|
vkDestroySemaphore(gDevice, gImageAvailableSemaphores[i], nullptr);
|
||||||
vkDestroySemaphore(gDevice, gRenderFinishedSemaphores[i], nullptr);
|
vkDestroySemaphore(gDevice, gRenderFinishedSemaphores[i], nullptr);
|
||||||
|
|||||||
Reference in new issue
Block a user