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)
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()
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 ()
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
#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 <stdlib.h>
#include <stdio.h>
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
* 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);
* THE SOFTWARE.
*/
#include "vkh_app.h"
-#include "vk_mem_alloc.h"
+//#include "vk_mem_alloc.h"
#define ENGINE_NAME "vkhelpers"
#define ENGINE_VERSION 1
#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 = {
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
}
#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;
#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;
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){
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;
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;
}
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,
}
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);
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)
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