diff --git a/projects/apis/vulkan/CMakeLists.txt b/projects/apis/vulkan/CMakeLists.txt index ff898fa..f61e53d 100644 --- a/projects/apis/vulkan/CMakeLists.txt +++ b/projects/apis/vulkan/CMakeLists.txt @@ -14,6 +14,8 @@ find_package(Vulkan REQUIRED) add_library(GryphnVulkanImpl STATIC ${SOURCE_FILES} ${METAL_FILES} ${LOADER_FILES} depends/memory_allocator/vk_mem_alloc.cpp) target_link_libraries(GryphnVulkanImpl ${Vulkan_LIBRARY}) +target_compile_options(GryphnVulkanImpl PRIVATE -Wno-nullability-completeness) + target_include_directories(GryphnVulkanImpl PUBLIC ${Vulkan_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/src/ diff --git a/projects/apis/vulkan/loader/vulkan_device_loader.c b/projects/apis/vulkan/loader/vulkan_device_loader.c index bbbae5a..9b993aa 100644 --- a/projects/apis/vulkan/loader/vulkan_device_loader.c +++ b/projects/apis/vulkan/loader/vulkan_device_loader.c @@ -37,7 +37,7 @@ gnDeviceFunctions loadVulkanDeviceFunctions(void) { ._gnCreateBuffer = createBuffer, ._gnBufferData = vulkanBufferData, ._gnBufferSubData = vulkanBufferSubData, - ._gnMapBuffer = mapBuffer, + ._gnMapBuffer = vulkanMapBuffer, ._gnDestroyBuffer = destroyBuffer, ._gnCreateUniformPool = createUniformPool, diff --git a/projects/apis/vulkan/src/buffers/vulkan_buffer.c b/projects/apis/vulkan/src/buffers/vulkan_buffer.c index 7e7e116..15ba043 100644 --- a/projects/apis/vulkan/src/buffers/vulkan_buffer.c +++ b/projects/apis/vulkan/src/buffers/vulkan_buffer.c @@ -7,57 +7,13 @@ 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; - case GN_STORAGE_BUFFER: usageFlags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; break; - } + if ((type & GN_VERTEX_BUFFER) == GN_VERTEX_BUFFER) usageFlags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + if ((type & GN_INDEX_BUFFER) == GN_INDEX_BUFFER) usageFlags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + if ((type & GN_UNIFORM_BUFFER) == GN_UNIFORM_BUFFER) usageFlags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + if ((type & GN_STORAGE_BUFFER) == GN_STORAGE_BUFFER) usageFlags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; return usageFlags; } -uint32_t VkMemoryIndex(VkPhysicalDevice device, uint32_t memoryType, VkMemoryPropertyFlags flags, gnBool* foundMemory) { - VkPhysicalDeviceMemoryProperties memoryProperties; - vkGetPhysicalDeviceMemoryProperties(device, &memoryProperties); - for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) { - if ((memoryType & (1 << i)) && (memoryProperties.memoryTypes[i].propertyFlags & flags) == flags) { - *foundMemory = GN_TRUE; - return i; - } - } // this whole thing was adapted from vulkan-tutorial.com - return 0; -} -gnReturnCode VkCreateBuffer( - VkGryphnBuffer* buffer, size_t size, gnDevice device, - VkMemoryPropertyFlags flags, VkBufferUsageFlags usage -) { - VkBufferCreateInfo bufferInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = size, - .usage = usage, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE - }; - - VkResult created_buffer = vkCreateBuffer(device->outputDevice->device, &bufferInfo, NULL, &buffer->buffer); - if (created_buffer != VK_SUCCESS) - return VkResultToGnReturnCode(created_buffer); - - VkMemoryRequirements bufferRequirements; - vkGetBufferMemoryRequirements(device->outputDevice->device, buffer->buffer, &bufferRequirements); - - gnBool foundMemory = GN_FALSE; - VkMemoryAllocateInfo memoryAllocateInfo = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = bufferRequirements.size, - .memoryTypeIndex = VkMemoryIndex(device->outputDevice->physicalDevice, bufferRequirements.memoryTypeBits, flags, &foundMemory) - }; - if (!foundMemory) return GN_FAILED_TO_ALLOCATE_MEMORY; - - VkResult memoryFound = vkAllocateMemory(device->outputDevice->device, &memoryAllocateInfo, NULL, &buffer->memory); - if (memoryFound == VK_SUCCESS) vkBindBufferMemory(device->outputDevice->device, buffer->buffer, buffer->memory, 0); - return VkResultToGnReturnCode(memoryFound); -} - void VkCopyBuffer(gnDevice device, VkBuffer source, VkBuffer destination, VkBufferCopy copy) { VkCommandBuffer transferBuffer = gnBeginVulkanTransferOperation(device); vkCmdCopyBuffer(transferBuffer, source, destination, 1, ©); @@ -68,19 +24,41 @@ gnReturnCode createBuffer(gnBufferHandle buffer, gnOutputDeviceHandle device, gn buffer->buffer = malloc(sizeof(struct gnPlatformBuffer_t)); buffer->buffer->useStagingBuffer = (info.usage == GN_STATIC_DRAW); if (info.usage == GN_STATIC_DRAW) { - return VkCreateBuffer( - &buffer->buffer->buffer, - info.size, device, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - vkGryphnBufferType(info.type) | VK_BUFFER_USAGE_TRANSFER_DST_BIT - ); + VkBufferCreateInfo bufferCreateInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = NULL, + .flags = 0, + .queueFamilyIndexCount = 0, + .size = info.size, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .usage = vkGryphnBufferType(info.type) | VK_BUFFER_USAGE_TRANSFER_DST_BIT + }; + + VmaAllocationCreateInfo bufferAllocationInfo = { + .usage = VMA_MEMORY_USAGE_AUTO, + .flags = 0, + .requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + }; + + return VkResultToGnReturnCode(vmaCreateBuffer(device->outputDevice->allocator, &bufferCreateInfo, &bufferAllocationInfo, &buffer->buffer->buffer.buffer, &buffer->buffer->buffer.allocation, NULL)); } else { - return VkCreateBuffer( - &buffer->buffer->buffer, - info.size, device, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - vkGryphnBufferType(info.type) - ); + VkBufferCreateInfo bufferCreateInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = NULL, + .flags = 0, + .queueFamilyIndexCount = 0, + .size = info.size, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .usage = vkGryphnBufferType(info.type) + }; + + VmaAllocationCreateInfo bufferAllocationInfo = { + .usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, + .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + .requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + }; + + return VkResultToGnReturnCode(vmaCreateBuffer(device->outputDevice->allocator, &bufferCreateInfo, &bufferAllocationInfo, &buffer->buffer->buffer.buffer, &buffer->buffer->buffer.allocation, NULL)); } return GN_SUCCESS; @@ -95,9 +73,9 @@ void vulkanBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, VkDeviceSize sizeLeft = dataSize; while (sizeLeft > 0) { VkDeviceSize chunkSize = (buffer->device->outputDevice->stagingBufferSize < sizeLeft) ? buffer->device->outputDevice->stagingBufferSize : sizeLeft; - vkMapMemory(buffer->device->outputDevice->device, stagingBuffer->memory, 0, chunkSize, 0, &bufferData); + vulkanMapBufferInternal(buffer->device, *stagingBuffer, &bufferData); memcpy(bufferData, (char*)data + (dataSize - sizeLeft), chunkSize); - vkUnmapMemory(buffer->device->outputDevice->device, stagingBuffer->memory); + vulkanUnmapBufferInternal(buffer->device, *stagingBuffer); VkBufferCopy copyRegion = { .srcOffset = 0, @@ -108,24 +86,35 @@ void vulkanBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, sizeLeft -= chunkSize; } } else { - vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, dataSize, 0, &bufferData); + bufferData = vulkanMapBuffer(buffer); memcpy((char*)bufferData + offset, data, dataSize); - vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory); + vulkanUnmapBuffer(buffer); } } -void* mapBuffer(gnBufferHandle buffer) { + + +void vulkanMapBufferInternal(gnDevice device, VkGryphnBuffer buffer, void* data) { + vmaMapMemory(device->outputDevice->allocator, buffer.allocation, data); +} +void vulkanUnmapBufferInternal(gnDevice device, VkGryphnBuffer buffer) { + vmaUnmapMemory(device->outputDevice->allocator, buffer.allocation); +} + +void* vulkanMapBuffer(gnBufferHandle buffer) { void* data; - vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, buffer->info.size, 0, &data); + vulkanMapBufferInternal(buffer->device, buffer->buffer->buffer, &data); return data; } -void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device) { - vkDestroyBuffer(device, buffer->buffer, NULL); - vkFreeMemory(device, buffer->memory, NULL); +void vulkanUnmapBuffer(gnBufferHandle buffer) { + vulkanUnmapBufferInternal(buffer->device, buffer->buffer->buffer); +} + +void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, gnDevice device) { + vmaDestroyBuffer(device->outputDevice->allocator, buffer->buffer, buffer->allocation); } void destroyBuffer(gnBufferHandle buffer) { - // if (buffer->buffer->useStagingBuffer == gnTrue) gnDestroyVulkanBuffer(&buffer->buffer->stagingBuffer, buffer->device->outputDevice->device); - gnDestroyVulkanBuffer(&buffer->buffer->buffer, buffer->device->outputDevice->device); + gnDestroyVulkanBuffer(&buffer->buffer->buffer, buffer->device); free(buffer->buffer); } diff --git a/projects/apis/vulkan/src/buffers/vulkan_buffer.h b/projects/apis/vulkan/src/buffers/vulkan_buffer.h index 48847f5..75f22c9 100644 --- a/projects/apis/vulkan/src/buffers/vulkan_buffer.h +++ b/projects/apis/vulkan/src/buffers/vulkan_buffer.h @@ -2,27 +2,32 @@ #include #include "utils/gryphn_bool.h" #include +#include typedef struct VkGryphnBuffer { VkBuffer buffer; - VkDeviceMemory memory; + VmaAllocation allocation; } VkGryphnBuffer; -void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device); struct gnPlatformBuffer_t { VkGryphnBuffer buffer; gnBool useStagingBuffer; }; -gnReturnCode VkCreateBuffer( - VkGryphnBuffer* buffer, size_t size, gnDevice device, - VkMemoryPropertyFlags flags, VkBufferUsageFlags usage -); -void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device); -uint32_t VkMemoryIndex(VkPhysicalDevice device, uint32_t memoryType, VkMemoryPropertyFlags flags, gnBool* foundMemory); +// gnReturnCode VkCreateBuffer( +// VkGryphnBuffer* buffer, size_t size, gnDevice device, +// VkMemoryPropertyFlags flags, VkBufferUsageFlags usage +// ); +// void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, gnDevice device); +// uint32_t VkMemoryIndex(VkPhysicalDevice device, uint32_t memoryType, VkMemoryPropertyFlags flags, gnBool* foundMemory); gnReturnCode createBuffer(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info); void vulkanBufferData(gnBufferHandle buffer, size_t dataSize, void* data); void vulkanBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, void* data); -void* mapBuffer(gnBufferHandle buffer); + +void vulkanMapBufferInternal(gnDevice device, VkGryphnBuffer buffer, void* data); +void vulkanUnmapBufferInternal(gnDevice device, VkGryphnBuffer buffer); +void* vulkanMapBuffer(gnBufferHandle buffer); +void vulkanUnmapBuffer(gnBufferHandle buffer); + void destroyBuffer(gnBufferHandle buffer); diff --git a/projects/apis/vulkan/src/output_device/vulkan_output_device.c b/projects/apis/vulkan/src/output_device/vulkan_output_device.c index 9991973..2a8be6d 100644 --- a/projects/apis/vulkan/src/output_device/vulkan_output_device.c +++ b/projects/apis/vulkan/src/output_device/vulkan_output_device.c @@ -4,6 +4,7 @@ #include "vulkan_device_extensions.h" #include "instance/gryphn_instance.h" #include "commands/command_buffer/vulkan_command_buffer.h" +#include "instance/vulkan_instance.h" #include "vulkan_result_converter.h" #include "string.h" @@ -95,15 +96,34 @@ gnReturnCode createVulkanOutputDevice(gnInstanceHandle instance, gnOutputDeviceH VkResult fence_result = vkCreateFence(device->outputDevice->device, &fenceInfo, NULL, &device->outputDevice->barrierFence); if (fence_result != VK_SUCCESS) VkResultToGnReturnCode(fence_result); + VmaAllocatorCreateInfo allocatorCreateInfo = { + .device = device->outputDevice->device, + .physicalDevice = device->outputDevice->physicalDevice, + .instance = instance->instance->vk_instance, + }; + if (vmaCreateAllocator(&allocatorCreateInfo, &device->outputDevice->allocator) != VK_SUCCESS) + return GN_FAILED_CREATE_ALLOCATOR; + // create the massive staging buffer device->outputDevice->stagingBufferSize = 128 * 1024 * 1024; - gnReturnCode code = VkCreateBuffer( - &device->outputDevice->stagingBuffer, - device->outputDevice->stagingBufferSize, device, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT - ); - return code; // lowkey is a hack + + VkBufferCreateInfo bufferCreateInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = NULL, + .flags = 0, + .queueFamilyIndexCount = 0, + .size = device->outputDevice->stagingBufferSize, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT + }; + + VmaAllocationCreateInfo bufferAllocationInfo = { + .usage = VMA_MEMORY_USAGE_CPU_ONLY, + .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + .requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + }; + + return VkResultToGnReturnCode(vmaCreateBuffer(device->outputDevice->allocator, &bufferCreateInfo, &bufferAllocationInfo, &device->outputDevice->stagingBuffer.buffer, &device->outputDevice->stagingBuffer.allocation, NULL)); // lowkey is a hack } void waitForDevice(const gnOutputDeviceHandle device) { @@ -112,9 +132,10 @@ void waitForDevice(const gnOutputDeviceHandle device) { void destroyVulkanOutputDevice(gnOutputDeviceHandle device) { vkDestroyFence(device->outputDevice->device, device->outputDevice->barrierFence, NULL); - gnDestroyVulkanBuffer(&device->outputDevice->stagingBuffer, device->outputDevice->device); + vmaDestroyBuffer(device->outputDevice->allocator, device->outputDevice->stagingBuffer.buffer, device->outputDevice->stagingBuffer.allocation); vkDestroyCommandPool(device->outputDevice->device, device->outputDevice->transferCommandPool, NULL); vkDestroyDevice(device->outputDevice->device, NULL); + vmaDestroyAllocator(device->outputDevice->allocator); free(device->outputDevice); } diff --git a/projects/apis/vulkan/src/output_device/vulkan_output_devices.h b/projects/apis/vulkan/src/output_device/vulkan_output_devices.h index 6300f66..3719f01 100644 --- a/projects/apis/vulkan/src/output_device/vulkan_output_devices.h +++ b/projects/apis/vulkan/src/output_device/vulkan_output_devices.h @@ -3,6 +3,7 @@ #include #include "buffers/vulkan_buffer.h" #include "vulkan_physical_device.h" +#include typedef struct vulkanQueue { VkQueue queue; @@ -24,6 +25,8 @@ typedef struct gnPlatformOutputDevice_t { VkFence barrierFence; gnBool enabledOversizedDescriptorPools; + + VmaAllocator allocator; } gnPlatformOutputDevice; VkCommandBuffer gnBeginVulkanTransferOperation(gnDevice device); diff --git a/projects/core/gryphn_return_code.h b/projects/core/gryphn_return_code.h index 561e606..ee4405a 100644 --- a/projects/core/gryphn_return_code.h +++ b/projects/core/gryphn_return_code.h @@ -12,7 +12,7 @@ typedef enum gnReturnCode { GN_FAILED_TO_FIND_ENTRY_POINT, GN_FAILED_TO_LOAD_FUNCTION, GN_INCOMPLETE, GN_NOT_READY, GN_TIMEOUT, GN_DEVICE_LOST, GN_FAILED_MEMORY_MAP, GN_UNSUPPORTED_FEATURE, GN_OVERALLOCATION, GN_FRAGMENTATION, GN_INVALID_HANDLE, GN_SURFACE_LOST, GN_WINDOW_IN_USE, - GN_INCOMPATIBLE_DISPLAY, GN_UNSUPPORTED_IMAGE_USE, + GN_INCOMPATIBLE_DISPLAY, GN_UNSUPPORTED_IMAGE_USE, GN_FAILED_CREATE_ALLOCATOR, GN_UNLOADED_EXTENSION = -1, GN_UNLOADED_LAYER = -2, diff --git a/projects/core/src/buffers/gryphn_buffer.h b/projects/core/src/buffers/gryphn_buffer.h index fa93a15..6494144 100644 --- a/projects/core/src/buffers/gryphn_buffer.h +++ b/projects/core/src/buffers/gryphn_buffer.h @@ -9,10 +9,10 @@ typedef enum gnIndexType { } gnIndexType; typedef enum gnBufferType { - GN_VERTEX_BUFFER = 0x00000001, - GN_INDEX_BUFFER = 0x00000002, - GN_UNIFORM_BUFFER = 0x00000004, - GN_STORAGE_BUFFER = 0x00000008 + GN_VERTEX_BUFFER = 1 << 0, + GN_INDEX_BUFFER = 1 << 2, + GN_UNIFORM_BUFFER = 1 << 3, + GN_STORAGE_BUFFER = 1 << 4 } gnBufferType; // I need to support more buffer types // i love that OpenGL does this so im stealing it