From 016c9e0bbfc7226ecd82fd0c861551c2aebc180a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Thu, 26 May 2022 17:36:35 +0200 Subject: [PATCH] set vma optional, wip --- CMakeLists.txt | 15 ++++----- include/vkh.h | 84 ++++++++++++++++++++++++++++++++++++++++++--- src/vkh_app.c | 2 +- src/vkh_buffer.c | 88 ++++++++++++++++++++++++++++++++++++++++++------ src/vkh_buffer.h | 12 ++++++- src/vkh_device.h | 7 +++- src/vkh_image.c | 31 +++++++++++++---- src/vkh_image.h | 4 +++ 8 files changed, 210 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b8a7fc0..8cc5fab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.16) OPTION (VKH_BUILD_SHARED_LIB "Build using shared libraries" OFF) -OPTION(VKH_ENABLE_VMA "enable Vulkan Memory Allocator" ON) +OPTION(VKH_USE_VMA "enable Vulkan Memory Allocator" ON) SET(LANG "C") SET(CMAKE_${LANG}_STANDARD 11) @@ -25,14 +25,15 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug") ADD_DEFINITIONS (-DDEBUG) OPTION(ENABLE_VALIDATION "enable vulkan validation layer" ON) IF (UNIX) - SET(CMAKE_${LANG}_FLAGS "-Wall -Wno-extra -Wno-unknown-pragmas") + SET(CMAKE_${LANG}_FLAGS "-Wall -Wno-extra -Wno-unknown-pragmas") ELSEIF (MSVC) SET(CMAKE_${LANG}_FLAGS "/W4 /wd4204 /wd4221 /wd4100") ENDIF() ELSE() UNSET(ENABLE_VALIDATION CACHE) IF (UNIX) - SET(CMAKE_${LANG}_FLAGS "-w") + SET(CMAKE_${LANG}_FLAGS "-w -flto -fvisibility=hidden") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -flto -fvisibility=hidden") ELSEIF(MSVC) SET(CMAKE_${LANG}_FLAGS "/W0") ENDIF() @@ -42,10 +43,6 @@ if (${LANG} EQUAL "C" AND MSVC) SET(CMAKE_C_FLAGS "/TC ${CMAKE_C_FLAGS}") endif () -IF (VKH_ENABLE_VMA) - ADD_DEFINITIONS (-DUSE_VMA) -ENDIF () - IF (ENABLE_VALIDATION) ADD_DEFINITIONS (-DVKH_USE_VALIDATION) ENDIF () @@ -90,7 +87,9 @@ ENDFUNCTION(setup_lib) GET_DIRECTORY_PROPERTY (vkh_has_root_project PARENT_DIRECTORY) -if (VKH_ENABLE_VMA) +if (VKH_USE_VMA) + ADD_DEFINITIONS (-DVKH_USE_VMA) + SET(VKH_USE_VMA ON PARENT_SCOPE) ADD_LIBRARY(libVMA OBJECT src/VmaUsage.cpp) SET_TARGET_PROPERTIES( libVMA PROPERTIES diff --git a/include/vkh.h b/include/vkh.h index 7e1d8e9..9c693ac 100644 --- a/include/vkh.h +++ b/include/vkh.h @@ -32,7 +32,72 @@ extern "C" { #include "deps/tinycthread.h" -typedef enum VmaMemoryUsage VmaMemoryUsage; +typedef enum VkhMemoryUsage +{ + /** No intended memory usage specified. + Use other members of VmaAllocationCreateInfo to specify your requirements. + */ + VKH_MEMORY_USAGE_UNKNOWN = 0, + /** Memory will be used on device only, so fast access from the device is preferred. + It usually means device-local GPU (video) memory. + No need to be mappable on host. + It is roughly equivalent of `D3D12_HEAP_TYPE_DEFAULT`. + + Usage: + + - Resources written and read by device, e.g. images used as attachments. + - Resources transferred from host once (immutable) or infrequently and read by + device multiple times, e.g. textures to be sampled, vertex buffers, uniform + (constant) buffers, and majority of other types of resources used on GPU. + + Allocation may still end up in `HOST_VISIBLE` memory on some implementations. + In such case, you are free to map it. + You can use #VMA_ALLOCATION_CREATE_MAPPED_BIT with this usage type. + */ + VKH_MEMORY_USAGE_GPU_ONLY = 1, + /** Memory will be mappable on host. + It usually means CPU (system) memory. + Guarantees to be `HOST_VISIBLE` and `HOST_COHERENT`. + CPU access is typically uncached. Writes may be write-combined. + Resources created in this pool may still be accessible to the device, but access to them can be slow. + It is roughly equivalent of `D3D12_HEAP_TYPE_UPLOAD`. + + Usage: Staging copy of resources used as transfer source. + */ + VKH_MEMORY_USAGE_CPU_ONLY = 2, + /** + Memory that is both mappable on host (guarantees to be `HOST_VISIBLE`) and preferably fast to access by GPU. + CPU access is typically uncached. Writes may be write-combined. + + Usage: Resources written frequently by host (dynamic), read by device. E.g. textures, vertex buffers, uniform buffers updated every frame or every draw call. + */ + VKH_MEMORY_USAGE_CPU_TO_GPU = 3, + /** Memory mappable on host (guarantees to be `HOST_VISIBLE`) and cached. + It is roughly equivalent of `D3D12_HEAP_TYPE_READBACK`. + + Usage: + + - Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping. + - Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection. + */ + VKH_MEMORY_USAGE_GPU_TO_CPU = 4, + /** CPU memory - memory that is preferably not `DEVICE_LOCAL`, but also not guaranteed to be `HOST_VISIBLE`. + + Usage: Staging copy of resources moved from GPU memory to CPU memory as part + of custom paging/residency mechanism, to be moved back to GPU memory when needed. + */ + VKH_MEMORY_USAGE_CPU_COPY = 5, + /** Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`. + Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation. + + Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`. + + Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + */ + VKH_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6, + + VKH_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF +} VkhMemoryUsage; #include #include @@ -189,13 +254,13 @@ vkh_public VkhImage vkh_image_import (VkhDevice pDev, VkImage vkImg, VkFormat format, uint32_t width, uint32_t height); vkh_public VkhImage vkh_image_create (VkhDevice pDev, VkFormat format, uint32_t width, uint32_t height, VkImageTiling tiling, - VmaMemoryUsage memprops, VkImageUsageFlags usage); + VkhMemoryUsage memprops, VkImageUsageFlags usage); vkh_public VkhImage vkh_image_ms_create (VkhDevice pDev, VkFormat format, VkSampleCountFlagBits num_samples, uint32_t width, uint32_t height, - VmaMemoryUsage memprops, VkImageUsageFlags usage); + VkhMemoryUsage memprops, VkImageUsageFlags usage); vkh_public VkhImage vkh_tex2d_array_create (VkhDevice pDev, VkFormat format, uint32_t width, uint32_t height, uint32_t layers, - VmaMemoryUsage memprops, VkImageUsageFlags usage); + VkhMemoryUsage memprops, VkImageUsageFlags usage); vkh_public void vkh_image_set_sampler (VkhImage img, VkSampler sampler); vkh_public @@ -242,14 +307,23 @@ VkDescriptorImageInfo vkh_image_get_descriptor(VkhImage img, VkImageLayout ima * VkhBuffer * *************/ vkh_public +void vkh_buffer_init (VkhDevice pDev, VkBufferUsageFlags usage, + VkhMemoryUsage memprops, VkDeviceSize size, VkhBuffer buff, bool mapped); +vkh_public VkhBuffer vkh_buffer_create (VkhDevice pDev, VkBufferUsageFlags usage, - VmaMemoryUsage memprops, VkDeviceSize size); + VkhMemoryUsage memprops, VkDeviceSize size); vkh_public void vkh_buffer_destroy (VkhBuffer buff); vkh_public +void vkh_buffer_resize (VkhBuffer buff, VkDeviceSize newSize); +vkh_public +void vkh_buffer_reset (VkhBuffer buff); +vkh_public VkResult vkh_buffer_map (VkhBuffer buff); vkh_public void vkh_buffer_unmap (VkhBuffer buff); +vkh_public +void vkh_buffer_flush (VkhBuffer buff); vkh_public VkBuffer vkh_buffer_get_vkbuffer (VkhBuffer buff); diff --git a/src/vkh_app.c b/src/vkh_app.c index 8a7bbf4..7dff5ed 100644 --- a/src/vkh_app.c +++ b/src/vkh_app.c @@ -20,7 +20,7 @@ * THE SOFTWARE. */ #include "vkh_app.h" -#include "vk_mem_alloc.h" +//#include "vk_mem_alloc.h" #define ENGINE_NAME "vkhelpers" #define ENGINE_VERSION 1 diff --git a/src/vkh_buffer.c b/src/vkh_buffer.c index c5a7c64..69e3fbc 100644 --- a/src/vkh_buffer.c +++ b/src/vkh_buffer.c @@ -22,28 +22,77 @@ #include "vkh_buffer.h" #include "vkh_device.h" -VkhBuffer vkh_buffer_create(VkhDevice pDev, VkBufferUsageFlags usage, VmaMemoryUsage memprops, VkDeviceSize size){ - VkhBuffer buff = (VkhBuffer)malloc(sizeof(vkh_buffer_t)); - buff->pDev = pDev; - VkBufferCreateInfo* pInfo = &buff->infos; - pInfo->sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - pInfo->usage = usage; - pInfo->size = size; - pInfo->sharingMode = VK_SHARING_MODE_EXCLUSIVE; +#ifndef VKH_USE_VMA +void _set_size_and_map(VkhDevice pDev, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size, VkhBuffer buff){ + VkMemoryRequirements memReq; + vkGetBufferMemoryRequirements(pDev->dev, buff->buffer, &memReq); + VkMemoryAllocateInfo memAllocInfo = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = memReq.size }; + assert(vkh_memory_type_from_properties(&pDev->phyMemProps, memReq.memoryTypeBits,memoryPropertyFlags, &memAllocInfo.memoryTypeIndex)); + VK_CHECK_RESULT(vkAllocateMemory(pDev->dev, &memAllocInfo, NULL, &buff->memory)); + + buff->alignment = memReq.alignment; + buff->size = memAllocInfo.allocationSize; + buff->usageFlags = usage; + buff->memprops = memoryPropertyFlags; + VK_CHECK_RESULT(vkBindBufferMemory(buff->pDev->dev, buff->buffer, buff->memory, 0)); + VK_CHECK_RESULT(vkMapMemory(buff->pDev->dev, buff->memory, 0, VK_WHOLE_SIZE, 0, &buff->mapped)); +} +#endif + +void vkh_buffer_init(VkhDevice pDev, VkBufferUsageFlags usage, VkhMemoryUsage memprops, VkDeviceSize size, VkhBuffer buff, bool mapped){ + buff->pDev = pDev; + VkBufferCreateInfo* pInfo = &buff->infos; + pInfo->sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + pInfo->usage = usage; + pInfo->size = size; + pInfo->sharingMode = VK_SHARING_MODE_EXCLUSIVE; +#ifdef VKH_USE_VMA + buff->allocCreateInfo.usage = (VmaMemoryUsage)memprops; + if (mapped) + buff->allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + VK_CHECK_RESULT(vmaCreateBuffer(pDev->allocator, pInfo, &buff->allocCreateInfo, &buff->buffer, &buff->alloc, &buff->allocInfo)); +#else buff->memprops = memprops; +#endif +} - VmaAllocationCreateInfo allocInfo = { .usage = memprops }; - VK_CHECK_RESULT(vmaCreateBuffer(pDev->allocator, pInfo, &allocInfo, &buff->buffer, &buff->alloc, &buff->allocInfo)); +VkhBuffer vkh_buffer_create(VkhDevice pDev, VkBufferUsageFlags usage, VkhMemoryUsage memprops, VkDeviceSize size){ + VkhBuffer buff = (VkhBuffer)calloc(1, sizeof(vkh_buffer_t)); + vkh_buffer_init(pDev, usage, memprops, size, buff, false); return buff; } +void vkh_buffer_reset(VkhBuffer buff){ + if (buff->buffer) +#ifdef VKH_USE_VMA + vmaDestroyBuffer(buff->pDev->allocator, buff->buffer, buff->alloc); +#else +#endif +} void vkh_buffer_destroy(VkhBuffer buff){ if (buff->buffer) +#ifdef VKH_USE_VMA vmaDestroyBuffer(buff->pDev->allocator, buff->buffer, buff->alloc); +#else +#endif free(buff); buff = NULL; } +void vkh_buffer_resize(VkhBuffer buff, VkDeviceSize newSize){ + if (buff->buffer) +#ifdef VKH_USE_VMA + vmaDestroyBuffer(buff->pDev->allocator, buff->buffer, buff->alloc); + VK_CHECK_RESULT(vmaCreateBuffer(buff->pDev->allocator, &buff->infos, &buff->allocCreateInfo, &buff->buffer, &buff->alloc, &buff->allocInfo)); +#else +#endif +#ifdef VKH_USE_VMA +#else + buff->memprops = memprops; +#endif + +} VkDescriptorBufferInfo vkh_buffer_get_descriptor (VkhBuffer buff){ VkDescriptorBufferInfo desc = { @@ -55,17 +104,34 @@ VkDescriptorBufferInfo vkh_buffer_get_descriptor (VkhBuffer buff){ VkResult vkh_buffer_map(VkhBuffer buff){ +#ifdef VKH_USE_VMA return vmaMapMemory(buff->pDev->allocator, buff->alloc, &buff->mapped); +#else +#endif } void vkh_buffer_unmap(VkhBuffer buff){ +#ifdef VKH_USE_VMA + vmaUnmapMemory(buff->pDev->allocator, buff->alloc); +#else if (!buff->mapped) return; - vmaUnmapMemory(buff->pDev->allocator, buff->alloc); buff->mapped = NULL; +#endif } VkBuffer vkh_buffer_get_vkbuffer (VkhBuffer buff){ return buff->buffer; } void* vkh_buffer_get_mapped_pointer (VkhBuffer buff){ +#ifdef VKH_USE_VMA + //vmaFlushAllocation (buff->pDev->allocator, buff->alloc, buff->allocInfo.offset, buff->allocInfo.size); + return buff->allocInfo.pMappedData; +#else return buff->mapped; +#endif +} +void vkh_buffer_flush (VkhBuffer buff){ +#ifdef VKH_USE_VMA + vmaFlushAllocation (buff->pDev->allocator, buff->alloc, buff->allocInfo.offset, buff->allocInfo.size); +#else +#endif } diff --git a/src/vkh_buffer.h b/src/vkh_buffer.h index 2db2efb..9b5c0ff 100644 --- a/src/vkh_buffer.h +++ b/src/vkh_buffer.h @@ -27,15 +27,25 @@ extern "C" { #endif #include "vkh.h" + +#ifdef VKH_USE_VMA #include "vk_mem_alloc.h" +#endif typedef struct _vkh_buffer_t { VkhDevice pDev; VkBufferCreateInfo infos; - VmaMemoryUsage memprops; VkBuffer buffer; +#ifdef VKH_USE_VMA VmaAllocation alloc; VmaAllocationInfo allocInfo; + VmaAllocationCreateInfo allocCreateInfo; +#else + VkDeviceMemory memory; + VkDeviceSize size; + VkBufferUsageFlags usageFlags; + VkMemoryPropertyFlags memprops; +#endif VkDescriptorBufferInfo descriptor; VkDeviceSize alignment; void* mapped; diff --git a/src/vkh_device.h b/src/vkh_device.h index 491816d..365f362 100644 --- a/src/vkh_device.h +++ b/src/vkh_device.h @@ -27,14 +27,19 @@ extern "C" { #endif #include "vkh.h" + +#ifdef VKH_USE_VMA #include "vk_mem_alloc.h" +#endif typedef struct _vkh_device_t{ VkDevice dev; VkPhysicalDeviceMemoryProperties phyMemProps; VkPhysicalDevice phy; - VmaAllocator allocator; VkInstance instance; +#ifdef VKH_USE_VMA + VmaAllocator allocator; +#endif VkhApp vkhApplication; }vkh_device_t; diff --git a/src/vkh_image.c b/src/vkh_image.c index d6a82df..c2ff84c 100644 --- a/src/vkh_image.c +++ b/src/vkh_image.c @@ -24,7 +24,7 @@ VkhImage _vkh_image_create (VkhDevice pDev, VkImageType imageType, VkFormat format, uint32_t width, uint32_t height, - VmaMemoryUsage memprops, VkImageUsageFlags usage, + VkhMemoryUsage memprops, VkImageUsageFlags usage, VkSampleCountFlagBits samples, VkImageTiling tiling, uint32_t mipLevels, uint32_t arrayLayers){ @@ -53,9 +53,18 @@ VkhImage _vkh_image_create (VkhDevice pDev, VkImageType imageType, img->image = VK_NULL_HANDLE; img->sampler= VK_NULL_HANDLE; img->view = VK_NULL_HANDLE;*/ - - VmaAllocationCreateInfo allocInfo = { .usage = memprops }; +#ifdef VKH_USE_VMA + VmaAllocationCreateInfo allocInfo = { .usage = (VmaMemoryUsage)memprops }; VK_CHECK_RESULT(vmaCreateImage (pDev->allocator, pInfo, &allocInfo, &img->image, &img->alloc, &img->allocInfo)); +#else + VkMemoryRequirements memReq; + vkGetImageMemoryRequirements(pDev->dev, img->image, &memReq); + VkMemoryAllocateInfo memAllocInfo = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = memReq.size }; + assert(vkh_memory_type_from_properties(&pDev->phyMemProps, memReq.memoryTypeBits, memprops,&memAllocInfo.memoryTypeIndex)); + VK_CHECK_RESULT(vkAllocateMemory(pDev->dev, &memAllocInfo, NULL, &img->memory)); + VK_CHECK_RESULT(vkBindImageMemory(pDev->dev, img->image, img->memory, 0)); +#endif mtx_init(&img->mutex, mtx_plain); img->references = 1; @@ -83,7 +92,11 @@ void vkh_image_destroy(VkhImage img) vkDestroySampler (img->pDev->dev,img->sampler, NULL); if (!img->imported) +#ifdef VKH_USE_VMA vmaDestroyImage (img->pDev->allocator, img->image, img->alloc); +#else +#endif + free(img); img = NULL; @@ -95,13 +108,13 @@ void vkh_image_reference (VkhImage img) { } VkhImage vkh_tex2d_array_create (VkhDevice pDev, VkFormat format, uint32_t width, uint32_t height, uint32_t layers, - VmaMemoryUsage memprops, VkImageUsageFlags usage){ + VkhMemoryUsage memprops, VkImageUsageFlags usage){ return _vkh_image_create (pDev, VK_IMAGE_TYPE_2D, format, width, height, memprops,usage, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, 1, layers); } VkhImage vkh_image_create (VkhDevice pDev, VkFormat format, uint32_t width, uint32_t height, VkImageTiling tiling, - VmaMemoryUsage memprops, + VkhMemoryUsage memprops, VkImageUsageFlags usage) { return _vkh_image_create (pDev, VK_IMAGE_TYPE_2D, format, width, height, memprops,usage, @@ -131,7 +144,7 @@ VkhImage vkh_image_import (VkhDevice pDev, VkImage vkImg, VkFormat format, uint3 } VkhImage vkh_image_ms_create(VkhDevice pDev, VkFormat format, VkSampleCountFlagBits num_samples, uint32_t width, uint32_t height, - VmaMemoryUsage memprops, + VkhMemoryUsage memprops, VkImageUsageFlags usage){ return _vkh_image_create (pDev, VK_IMAGE_TYPE_2D, format, width, height, memprops,usage, num_samples, VK_IMAGE_TILING_OPTIMAL, 1, 1); @@ -261,11 +274,17 @@ void vkh_image_destroy_sampler (VkhImage img) { void* vkh_image_map (VkhImage img) { void* data; +#ifdef VKH_USE_VMA vmaMapMemory(img->pDev->allocator, img->alloc, &data); +#else +#endif return data; } void vkh_image_unmap (VkhImage img) { +#ifdef VKH_USE_VMA vmaUnmapMemory(img->pDev->allocator, img->alloc); +#else +#endif } void vkh_image_set_name (VkhImage img, const char* name){ if (img==NULL) diff --git a/src/vkh_image.h b/src/vkh_image.h index cde04dc..c74a6b2 100644 --- a/src/vkh_image.h +++ b/src/vkh_image.h @@ -33,8 +33,12 @@ typedef struct _vkh_image_t { VkhDevice pDev; VkImageCreateInfo infos; VkImage image; +#ifdef VKH_USE_VMA VmaAllocation alloc; VmaAllocationInfo allocInfo; +#else + VkDeviceMemory memory; +#endif VkSampler sampler; VkImageView view; VkImageLayout layout; //current layout -- 2.47.3