diff --git a/rendering_api/vulkan/src/buffers/vulkan_buffer.c b/rendering_api/vulkan/src/buffers/vulkan_buffer.c index 0cfbbad..a9e0fac 100644 --- a/rendering_api/vulkan/src/buffers/vulkan_buffer.c +++ b/rendering_api/vulkan/src/buffers/vulkan_buffer.c @@ -13,12 +13,12 @@ case GN_VERTEX_BUFFER: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; gnReturnCode VkCreateBuffer( VkBuffer* buffer, VkDeviceMemory* memory, gnBufferInfo info, VkDevice device, VkPhysicalDevice physcialDevice, - VkMemoryPropertyFlags flags + VkMemoryPropertyFlags flags, VkBufferUsageFlags usage ) { VkBufferCreateInfo bufferInfo = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .size = info.size, - .usage = vkGryphnBufferType(info.type), + .usage = usage, .sharingMode = VK_SHARING_MODE_EXCLUSIVE }; @@ -52,30 +52,77 @@ gnReturnCode VkCreateBuffer( return GN_SUCCESS; } +void VkCopyBuffer(VkBuffer source, VkBuffer destination, size_t size, VkCommandPool pool, VkDevice device, VkQueue queue) { + VkCommandBufferAllocateInfo allocInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandPool = pool, + .commandBufferCount = 1 + }; + + VkCommandBuffer commandBuffer; + vkAllocateCommandBuffers(device, &allocInfo, &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 = { + .size = size + }; + vkCmdCopyBuffer(commandBuffer, source, destination, 1, ©Region); + vkEndCommandBuffer(commandBuffer); + + VkSubmitInfo submitInfo = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &commandBuffer + }; + + vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); + vkQueueWaitIdle(queue); +} + gnReturnCode gnCreateBufferFn(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info) { buffer->buffer = malloc(sizeof(struct gnPlatformBuffer_t)); - gnReturnCode createdBuffer = VkCreateBuffer( - &buffer->buffer->buffer, &buffer->buffer->bufferMemory, - info, device->outputDevice->device, device->physicalDevice.physicalDevice->device, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT - ); - + VkBufferUsageFlags usage = vkGryphnBufferType(info.type); if (info.usage == GN_STATIC_DRAW) { gnReturnCode createdBuffer = VkCreateBuffer( &buffer->buffer->stagingBuffer, &buffer->buffer->stagingBufferMemory, info, device->outputDevice->device, device->physicalDevice.physicalDevice->device, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT ); + usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; buffer->buffer->useStagingBuffer = gnTrue; } + gnReturnCode createdBuffer = VkCreateBuffer( + &buffer->buffer->buffer, &buffer->buffer->bufferMemory, + info, device->outputDevice->device, device->physicalDevice.physicalDevice->device, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, usage + ); + + return GN_SUCCESS; } void gnBufferDataFn(gnBufferHandle buffer, size_t dataSize, void* data) { void* bufferData; - vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->bufferMemory, 0, dataSize, 0, &bufferData); - memcpy(bufferData, data, dataSize); - vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->bufferMemory); + if (buffer->buffer->useStagingBuffer) { + vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBufferMemory, 0, dataSize, 0, &bufferData); + memcpy(bufferData, data, dataSize); + vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBufferMemory); + VkCopyBuffer( + buffer->buffer->stagingBuffer, buffer->buffer->buffer, dataSize, + buffer->device->outputDevice->transferCommandPool, buffer->device->outputDevice->device, + buffer->device->outputDevice->transferQueue); + } else { + vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->bufferMemory, 0, dataSize, 0, &bufferData); + memcpy(bufferData, data, dataSize); + vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->bufferMemory); + } } void gnDestroyBufferFn(gnBufferHandle buffer) { if (buffer->buffer->useStagingBuffer == gnTrue) {