Changed "CONFIGURATION SECTION" to contain #ifndef so you can define these macros before including this header, not necessarily change them in the file. (Cherry pick from v1)

This commit is contained in:
Adam Sawicki 2017-07-04 15:52:30 +02:00
parent b0425876ec
commit 2a22d61297

View File

@ -122,15 +122,11 @@ When you want to create a buffer or image:
\section configuration Configuration \section configuration Configuration
Set VMA_STATS_STRING_ENABLED macro in vk_mem_alloc.h to 0 or 1 to disable/enable Please check "CONFIGURATION SECTION" in the code to find macros that you can define
compilation of code for dumping internal allocator state to string in JSON before each #include of this file or change directly in this file to provide
format. your own implementation of basic facilities like assert, min and max functions,
mutex etc. C++ STL is used by default, but changing these allows you to get rid
Please check "CONFIGURATION SECTION" below to find macros and other definitions of any STL usage if you want, as many game developers tend to do.
that you can change to connect the library to your own implementation of basic
facilities like assert, min and max functions, mutex etc. C++ STL is used by
default, but changing these allows you to get rid of any STL usage if you want,
as many game developers tend to do.
\section custom_memory_allocator Custom memory allocator \section custom_memory_allocator Custom memory allocator
@ -685,10 +681,12 @@ void vmaDestroyImage(
/******************************************************************************* /*******************************************************************************
CONFIGURATION SECTION CONFIGURATION SECTION
Change these definitions depending on your environment. Define some of these macros before each #include of this header or change them
here if you need other then default behavior depending on your environment.
*/ */
#define VMA_USE_STL_CONTAINERS 0 // Define this macro to 1 to make the library use STL containers instead of its own implementation.
//#define VMA_USE_STL_CONTAINERS 1
/* Set this macro to 1 to make the library including and using STL containers: /* Set this macro to 1 to make the library including and using STL containers:
std::pair, std::vector, std::list, std::unordered_map. std::pair, std::vector, std::list, std::unordered_map.
@ -697,21 +695,21 @@ Set it to 0 or undefined to make the library using its own implementation of
the containers. the containers.
*/ */
#if VMA_USE_STL_CONTAINERS #if VMA_USE_STL_CONTAINERS
#define VMA_USE_STL_VECTOR 1 #define VMA_USE_STL_VECTOR 1
#define VMA_USE_STL_UNORDERED_MAP 1 #define VMA_USE_STL_UNORDERED_MAP 1
#define VMA_USE_STL_LIST 1 #define VMA_USE_STL_LIST 1
#endif #endif
#if VMA_USE_STL_VECTOR #if VMA_USE_STL_VECTOR
#include <vector> #include <vector>
#endif #endif
#if VMA_USE_STL_UNORDERED_MAP #if VMA_USE_STL_UNORDERED_MAP
#include <unordered_map> #include <unordered_map>
#endif #endif
#if VMA_USE_STL_LIST #if VMA_USE_STL_LIST
#include <list> #include <list>
#endif #endif
/* /*
@ -726,120 +724,172 @@ remove them if not needed.
#include <malloc.h> // for aligned_alloc() #include <malloc.h> // for aligned_alloc()
#endif #endif
// Normal assert to check for programmer's errors, especially in Debug configuration.
#ifdef _DEBUG #ifndef VMA_ASSERT
// Normal assert to check for programmer's errors, especially in Debug configuration. #ifdef _DEBUG
#define VMA_ASSERT(expr) assert(expr) #define VMA_ASSERT(expr) assert(expr)
// Assert that will be called very often, like inside data structures e.g. operator[]. #else
// Making it non-empty can make program slow. #define VMA_ASSERT(expr)
#define VMA_HEAVY_ASSERT(expr) //VMA_ASSERT(expr) #endif
#else
#define VMA_ASSERT(expr)
#define VMA_HEAVY_ASSERT(expr)
#endif #endif
// Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0. // Assert that will be called very often, like inside data structures e.g. operator[].
#define VMA_NULL nullptr // Making it non-empty can make program slow.
#ifndef VMA_HEAVY_ASSERT
#define VMA_ALIGN_OF(type) (__alignof(type)) #ifdef _DEBUG
#define VMA_HEAVY_ASSERT(expr) //VMA_ASSERT(expr)
#if defined(_WIN32) #else
#define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (_aligned_malloc((size), (alignment))) #define VMA_HEAVY_ASSERT(expr)
#define VMA_SYSTEM_FREE(ptr) _aligned_free(ptr) #endif
#else
#define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (aligned_alloc((alignment), (size) ))
#define VMA_SYSTEM_FREE(ptr) free(ptr)
#endif #endif
#define VMA_MIN(v1, v2) (std::min((v1), (v2))) #ifndef VMA_NULL
#define VMA_MAX(v1, v2) (std::max((v1), (v2))) // Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0.
#define VMA_SWAP(v1, v2) std::swap((v1), (v2)) #define VMA_NULL nullptr
#endif
// You can just comment this out to use internal sorting implementation. #ifndef VMA_ALIGN_OF
//#define VMA_SORT(beg, end, cmp) std::sort(beg, end, cmp) #define VMA_ALIGN_OF(type) (__alignof(type))
#endif
#define VMA_DEBUG_LOG(format, ...) #ifndef VMA_SYSTEM_ALIGNED_MALLOC
/* #if defined(_WIN32)
#define VMA_DEBUG_LOG(format, ...) do { \ #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (_aligned_malloc((size), (alignment)))
printf(format, __VA_ARGS__); \ #else
printf("\n"); \ #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (aligned_alloc((alignment), (size) ))
} while(false) #endif
*/ #endif
#ifndef VMA_SYSTEM_FREE
#if defined(_WIN32)
#define VMA_SYSTEM_FREE(ptr) _aligned_free(ptr)
#else
#define VMA_SYSTEM_FREE(ptr) free(ptr)
#endif
#endif
#ifndef VMA_MIN
#define VMA_MIN(v1, v2) (std::min((v1), (v2)))
#endif
#ifndef VMA_MAX
#define VMA_MAX(v1, v2) (std::max((v1), (v2)))
#endif
#ifndef VMA_SWAP
#define VMA_SWAP(v1, v2) std::swap((v1), (v2))
#endif
#ifndef VMA_SORT
#define VMA_SORT(beg, end, cmp) std::sort(beg, end, cmp)
#endif
#ifndef VMA_DEBUG_LOG
#define VMA_DEBUG_LOG(format, ...)
/*
#define VMA_DEBUG_LOG(format, ...) do { \
printf(format, __VA_ARGS__); \
printf("\n"); \
} while(false)
*/
#endif
// Define this macro to 1 to enable functions: vmaBuildStatsString, vmaFreeStatsString.
#if VMA_STATS_STRING_ENABLED #if VMA_STATS_STRING_ENABLED
static inline void VmaUint32ToStr(char* outStr, size_t strLen, uint32_t num)
{
_ultoa_s(num, outStr, strLen, 10);
}
static inline void VmaUint64ToStr(char* outStr, size_t strLen, uint64_t num)
{
_ui64toa_s(num, outStr, strLen, 10);
}
#endif
static inline void VmaUint32ToStr(char* outStr, size_t strLen, uint32_t num) #ifndef VMA_MUTEX
{ class VmaMutex
_ultoa_s(num, outStr, strLen, 10); {
} public:
static inline void VmaUint64ToStr(char* outStr, size_t strLen, uint64_t num) VmaMutex() { }
{ ~VmaMutex() { }
_ui64toa_s(num, outStr, strLen, 10); void Lock() { m_Mutex.lock(); }
} void Unlock() { m_Mutex.unlock(); }
private:
std::mutex m_Mutex;
};
#define VMA_MUTEX VmaMutex
#endif
#endif // #if VMA_STATS_STRING_ENABLED #ifndef VMA_BEST_FIT
/**
Main parameter for function assessing how good is a free suballocation for a new
allocation request.
class VmaMutex - Set to 1 to use Best-Fit algorithm - prefer smaller blocks, as close to the
{ size of requested allocations as possible.
public: - Set to 0 to use Worst-Fit algorithm - prefer larger blocks, as large as
VmaMutex() { } possible.
~VmaMutex() { }
void Lock() { m_Mutex.lock(); }
void Unlock() { m_Mutex.unlock(); }
private:
std::mutex m_Mutex;
};
/* Experiments in special testing environment showed that Best-Fit algorithm is
Main parameter for function assessing how good is a free suballocation for a new better.
allocation request. */
#define VMA_BEST_FIT (1)
#endif
- Set to true to use Best-Fit algorithm - prefer smaller blocks, as close to the #ifndef VMA_DEBUG_ALWAYS_OWN_MEMORY
size of requested allocations as possible. /**
- Set to false to use Worst-Fit algorithm - prefer larger blocks, as large as Every object will have its own allocation.
possible. Define to 1 for debugging purposes only.
*/
#define VMA_DEBUG_ALWAYS_OWN_MEMORY (0)
#endif
Experiments in special testing environment showed that Best-Fit algorithm is #ifndef VMA_DEBUG_ALIGNMENT
better. /**
*/ Minimum alignment of all suballocations, in bytes.
static const bool VMA_BEST_FIT = true; Set to more than 1 for debugging purposes only. Must be power of two.
*/
#define VMA_DEBUG_ALIGNMENT (1)
#endif
/* #ifndef VMA_DEBUG_MARGIN
Every object will have its own allocation. /**
Enable for debugging purposes only. Minimum margin between suballocations, in bytes.
*/ Set nonzero for debugging purposes only.
static const bool VMA_DEBUG_ALWAYS_OWN_MEMORY = false; */
#define VMA_DEBUG_MARGIN (0)
#endif
/* #ifndef VMA_DEBUG_GLOBAL_MUTEX
Minimum alignment of all suballocations, in bytes. /**
Set to more than 1 for debugging purposes only. Must be power of two. Set this to 1 for debugging purposes only, to enable single mutex protecting all
*/ entry calls to the library. Can be useful for debugging multithreading issues.
static const VkDeviceSize VMA_DEBUG_ALIGNMENT = 1; */
#define VMA_DEBUG_GLOBAL_MUTEX (0)
#endif
/* #ifndef VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY
Minimum margin between suballocations, in bytes. /**
Set nonzero for debugging purposes only. Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity.
*/ Set to more than 1 for debugging purposes only. Must be power of two.
static const VkDeviceSize VMA_DEBUG_MARGIN = 0; */
#define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1)
#endif
/* #ifndef VMA_SMALL_HEAP_MAX_SIZE
Set this to 1 for debugging purposes only, to enable single mutex protecting all /// Maximum size of a memory heap in Vulkan to consider it "small".
entry calls to the library. Can be useful for debugging multithreading issues. #define VMA_SMALL_HEAP_MAX_SIZE (512 * 1024 * 1024)
*/ #endif
#define VMA_DEBUG_GLOBAL_MUTEX 0
/* #ifndef VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE
Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity. /// Default size of a block allocated as single VkDeviceMemory from a "large" heap.
Set to more than 1 for debugging purposes only. Must be power of two. #define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256 * 1024 * 1024)
*/ #endif
static const VkDeviceSize VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY = 1;
// Maximum size of a memory heap in Vulkan to consider it "small". #ifndef VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE
static const VkDeviceSize VMA_SMALL_HEAP_MAX_SIZE = 512 * 1024 * 1024; /// Default size of a block allocated as single VkDeviceMemory from a "small" heap.
// Default size of a block allocated as single VkDeviceMemory from a "large" heap. #define VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE (64 * 1024 * 1024)
static const VkDeviceSize VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE = 256 * 1024 * 1024; #endif
// Default size of a block allocated as single VkDeviceMemory from a "small" heap.
static const VkDeviceSize VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE = 64 * 1024 * 1024;
/******************************************************************************* /*******************************************************************************
END OF CONFIGURATION END OF CONFIGURATION
@ -989,15 +1039,15 @@ static inline bool VmaIsBufferImageGranularityConflict(
struct VmaMutexLock struct VmaMutexLock
{ {
public: public:
VmaMutexLock(VmaMutex& mutex) : m_Mutex(mutex) { mutex.Lock(); } VmaMutexLock(VMA_MUTEX& mutex) : m_Mutex(mutex) { mutex.Lock(); }
~VmaMutexLock() { m_Mutex.Unlock(); } ~VmaMutexLock() { m_Mutex.Unlock(); }
private: private:
VmaMutex& m_Mutex; VMA_MUTEX& m_Mutex;
}; };
#if VMA_DEBUG_GLOBAL_MUTEX #if VMA_DEBUG_GLOBAL_MUTEX
static VmaMutex gDebugGlobalMutex; static VMA_MUTEX gDebugGlobalMutex;
#define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex); #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex);
#else #else
#define VMA_DEBUG_GLOBAL_MUTEX_LOCK #define VMA_DEBUG_GLOBAL_MUTEX_LOCK
@ -2341,12 +2391,12 @@ struct VmaAllocator_T
hysteresis to avoid pessimistic case of alternating creation and destruction hysteresis to avoid pessimistic case of alternating creation and destruction
of a VkDeviceMemory. */ of a VkDeviceMemory. */
bool m_HasEmptyBlock[VK_MAX_MEMORY_TYPES]; bool m_HasEmptyBlock[VK_MAX_MEMORY_TYPES];
VmaMutex m_BlocksMutex[VK_MAX_MEMORY_TYPES]; VMA_MUTEX m_BlocksMutex[VK_MAX_MEMORY_TYPES];
// Each vector is sorted by memory (handle value). // Each vector is sorted by memory (handle value).
typedef VmaVector< VmaAllocation, VmaStlAllocator<VmaAllocation> > AllocationVectorType; typedef VmaVector< VmaAllocation, VmaStlAllocator<VmaAllocation> > AllocationVectorType;
AllocationVectorType* m_pOwnAllocations[VK_MAX_MEMORY_TYPES][VMA_BLOCK_VECTOR_TYPE_COUNT]; AllocationVectorType* m_pOwnAllocations[VK_MAX_MEMORY_TYPES][VMA_BLOCK_VECTOR_TYPE_COUNT];
VmaMutex m_OwnAllocationsMutex[VK_MAX_MEMORY_TYPES]; VMA_MUTEX m_OwnAllocationsMutex[VK_MAX_MEMORY_TYPES];
VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo); VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo);
~VmaAllocator_T(); ~VmaAllocator_T();
@ -2361,7 +2411,7 @@ struct VmaAllocator_T
VkDeviceSize GetBufferImageGranularity() const VkDeviceSize GetBufferImageGranularity() const
{ {
return VMA_MAX( return VMA_MAX(
VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY, static_cast<VkDeviceSize>(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY),
m_PhysicalDeviceProperties.limits.bufferImageGranularity); m_PhysicalDeviceProperties.limits.bufferImageGranularity);
} }
@ -2914,7 +2964,7 @@ bool VmaBlock::CheckAllocation(
*pOffset += VMA_DEBUG_MARGIN; *pOffset += VMA_DEBUG_MARGIN;
// Apply alignment. // Apply alignment.
const VkDeviceSize alignment = VMA_MAX(allocAlignment, VMA_DEBUG_ALIGNMENT); const VkDeviceSize alignment = VMA_MAX(allocAlignment, static_cast<VkDeviceSize>(VMA_DEBUG_ALIGNMENT));
*pOffset = VmaAlignUp(*pOffset, alignment); *pOffset = VmaAlignUp(*pOffset, alignment);
// Check previous suballocations for BufferImageGranularity conflicts. // Check previous suballocations for BufferImageGranularity conflicts.
@ -3828,9 +3878,9 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
} }
m_PreferredLargeHeapBlockSize = (pCreateInfo->preferredLargeHeapBlockSize != 0) ? m_PreferredLargeHeapBlockSize = (pCreateInfo->preferredLargeHeapBlockSize != 0) ?
pCreateInfo->preferredLargeHeapBlockSize : VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE; pCreateInfo->preferredLargeHeapBlockSize : static_cast<VkDeviceSize>(VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);
m_PreferredSmallHeapBlockSize = (pCreateInfo->preferredSmallHeapBlockSize != 0) ? m_PreferredSmallHeapBlockSize = (pCreateInfo->preferredSmallHeapBlockSize != 0) ?
pCreateInfo->preferredSmallHeapBlockSize : VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE; pCreateInfo->preferredSmallHeapBlockSize : static_cast<VkDeviceSize>(VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE);
vkGetPhysicalDeviceProperties(m_PhysicalDevice, &m_PhysicalDeviceProperties); vkGetPhysicalDeviceProperties(m_PhysicalDevice, &m_PhysicalDeviceProperties);
vkGetPhysicalDeviceMemoryProperties(m_PhysicalDevice, &m_MemProps); vkGetPhysicalDeviceMemoryProperties(m_PhysicalDevice, &m_MemProps);