157 lines
6.3 KiB
C
157 lines
6.3 KiB
C
#include "vulkan_buffer.h"
|
|
#include "core/buffers/gryphn_buffer.h"
|
|
#include "core/output_device/gryphn_output_device.h"
|
|
#include "output_device/vulkan_output_devices.h"
|
|
#include "output_device/vulkan_physical_device.h"
|
|
|
|
VkBufferUsageFlags vkGryphnBufferType(gnBufferType type) {
|
|
VkBufferUsageFlags usageFlags = 0;
|
|
switch (type) {
|
|
case GN_VERTEX_BUFFER: usageFlags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; break;
|
|
case GN_INDEX_BUFFER: usageFlags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; break;
|
|
case GN_UNIFORM_BUFFER: usageFlags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; break;
|
|
}
|
|
return usageFlags;
|
|
}
|
|
|
|
gnReturnCode VkCreateBuffer(
|
|
VkBuffer* buffer, VkDeviceMemory* memory, gnBufferInfo info,
|
|
VkDevice device, VkPhysicalDevice physcialDevice,
|
|
VkMemoryPropertyFlags flags, VkBufferUsageFlags usage
|
|
) {
|
|
VkBufferCreateInfo bufferInfo = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
.size = info.size,
|
|
.usage = usage,
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
|
};
|
|
|
|
if (vkCreateBuffer(device, &bufferInfo, NULL, buffer) != VK_SUCCESS)
|
|
return GN_FAILED_TO_CREATE_BUFFER;
|
|
|
|
VkMemoryRequirements bufferRequirements;
|
|
vkGetBufferMemoryRequirements(device, *buffer, &bufferRequirements);
|
|
|
|
VkMemoryAllocateInfo memoryAllocateInfo = {
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
.allocationSize = bufferRequirements.size,
|
|
};
|
|
|
|
VkPhysicalDeviceMemoryProperties memoryProperties;
|
|
vkGetPhysicalDeviceMemoryProperties(physcialDevice, &memoryProperties);
|
|
|
|
gnBool foundMemory = gnFalse;
|
|
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
|
|
if ((bufferRequirements.memoryTypeBits & (1 << i)) && (memoryProperties.memoryTypes[i].propertyFlags & flags) == flags) {
|
|
memoryAllocateInfo.memoryTypeIndex = i;
|
|
foundMemory = gnTrue;
|
|
}
|
|
} // this whole thing was adapted from vulkan-tutorial.com
|
|
if (!foundMemory) return GN_FAILED_TO_ALLOCATE_MEMORY;
|
|
|
|
if (vkAllocateMemory(device, &memoryAllocateInfo, NULL, memory) != VK_SUCCESS) {
|
|
return GN_FAILED_TO_ALLOCATE_MEMORY;
|
|
}
|
|
vkBindBufferMemory(device, *buffer, *memory, 0);
|
|
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);
|
|
vkFreeCommandBuffers(device, pool, 1, &commandBuffer);
|
|
}
|
|
|
|
gnReturnCode gnCreateBufferFn(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info) {
|
|
buffer->buffer = malloc(sizeof(struct gnPlatformBuffer_t));
|
|
VkBufferUsageFlags usage = vkGryphnBufferType(info.type);
|
|
buffer->buffer->useStagingBuffer = gnFalse;
|
|
if (info.usage == GN_STATIC_DRAW) {
|
|
buffer->buffer->useStagingBuffer = gnTrue;
|
|
VkCreateBuffer(
|
|
&buffer->buffer->stagingBuffer, &buffer->buffer->stagingBufferMemory,
|
|
info, device->outputDevice->device, device->physicalDevice.physicalDevice->device,
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
|
);
|
|
|
|
return VkCreateBuffer(
|
|
&buffer->buffer->buffer, &buffer->buffer->bufferMemory,
|
|
info, device->outputDevice->device, device->physicalDevice.physicalDevice->device,
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
vkGryphnBufferType(info.type) | VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
|
);
|
|
} else {
|
|
return VkCreateBuffer(
|
|
&buffer->buffer->buffer, &buffer->buffer->bufferMemory,
|
|
info, device->outputDevice->device, device->physicalDevice.physicalDevice->device,
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
|
vkGryphnBufferType(info.type)
|
|
);
|
|
}
|
|
|
|
|
|
|
|
return GN_SUCCESS;
|
|
}
|
|
void gnBufferDataFn(gnBufferHandle buffer, size_t dataSize, void* data) {
|
|
void* bufferData;
|
|
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* gnMapBufferFn(gnBufferHandle buffer) {
|
|
void* data;
|
|
vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->bufferMemory, 0, buffer->info.size, 0, &data);
|
|
return data;
|
|
}
|
|
void gnDestroyBufferFn(gnBufferHandle buffer) {
|
|
if (buffer->buffer->useStagingBuffer == gnTrue) {
|
|
vkDestroyBuffer(buffer->device->outputDevice->device, buffer->buffer->stagingBuffer, NULL);
|
|
vkFreeMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBufferMemory, NULL);
|
|
}
|
|
|
|
vkDestroyBuffer(buffer->device->outputDevice->device, buffer->buffer->buffer, NULL);
|
|
vkFreeMemory(buffer->device->outputDevice->device, buffer->buffer->bufferMemory, NULL);
|
|
free(buffer->buffer);
|
|
}
|