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.
@ -726,38 +724,67 @@ remove them if not needed.
#include <malloc.h> // for aligned_alloc() #include <malloc.h> // for aligned_alloc()
#endif #endif
#ifdef _DEBUG
// Normal assert to check for programmer's errors, especially in Debug configuration. // Normal assert to check for programmer's errors, especially in Debug configuration.
#ifndef VMA_ASSERT
#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[].
// Making it non-empty can make program slow.
#define VMA_HEAVY_ASSERT(expr) //VMA_ASSERT(expr)
#else #else
#define VMA_ASSERT(expr) #define VMA_ASSERT(expr)
#endif
#endif
// Assert that will be called very often, like inside data structures e.g. operator[].
// Making it non-empty can make program slow.
#ifndef VMA_HEAVY_ASSERT
#ifdef _DEBUG
#define VMA_HEAVY_ASSERT(expr) //VMA_ASSERT(expr)
#else
#define VMA_HEAVY_ASSERT(expr) #define VMA_HEAVY_ASSERT(expr)
#endif #endif
// Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0.
#define VMA_NULL nullptr
#define VMA_ALIGN_OF(type) (__alignof(type))
#if defined(_WIN32)
#define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (_aligned_malloc((size), (alignment)))
#define VMA_SYSTEM_FREE(ptr) _aligned_free(ptr)
#else
#define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (aligned_alloc((alignment), (size) ))
#define VMA_SYSTEM_FREE(ptr) free(ptr)
#endif #endif
#ifndef VMA_NULL
// Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0.
#define VMA_NULL nullptr
#endif
#ifndef VMA_ALIGN_OF
#define VMA_ALIGN_OF(type) (__alignof(type))
#endif
#ifndef VMA_SYSTEM_ALIGNED_MALLOC
#if defined(_WIN32)
#define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (_aligned_malloc((size), (alignment)))
#else
#define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (aligned_alloc((alignment), (size) ))
#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))) #define VMA_MIN(v1, v2) (std::min((v1), (v2)))
#endif
#ifndef VMA_MAX
#define VMA_MAX(v1, v2) (std::max((v1), (v2))) #define VMA_MAX(v1, v2) (std::max((v1), (v2)))
#endif
#ifndef VMA_SWAP
#define VMA_SWAP(v1, v2) std::swap((v1), (v2)) #define VMA_SWAP(v1, v2) std::swap((v1), (v2))
#endif
// You can just comment this out to use internal sorting implementation. #ifndef VMA_SORT
//#define VMA_SORT(beg, end, cmp) std::sort(beg, end, cmp) #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, ...)
/* /*
#define VMA_DEBUG_LOG(format, ...) do { \ #define VMA_DEBUG_LOG(format, ...) do { \
@ -765,9 +792,10 @@ remove them if not needed.
printf("\n"); \ printf("\n"); \
} while(false) } 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) static inline void VmaUint32ToStr(char* outStr, size_t strLen, uint32_t num)
{ {
_ultoa_s(num, outStr, strLen, 10); _ultoa_s(num, outStr, strLen, 10);
@ -776,9 +804,9 @@ static inline void VmaUint64ToStr(char* outStr, size_t strLen, uint64_t num)
{ {
_ui64toa_s(num, outStr, strLen, 10); _ui64toa_s(num, outStr, strLen, 10);
} }
#endif
#endif // #if VMA_STATS_STRING_ENABLED #ifndef VMA_MUTEX
class VmaMutex class VmaMutex
{ {
public: public:
@ -789,57 +817,79 @@ public:
private: private:
std::mutex m_Mutex; std::mutex m_Mutex;
}; };
#define VMA_MUTEX VmaMutex
#endif
/* #ifndef VMA_BEST_FIT
/**
Main parameter for function assessing how good is a free suballocation for a new Main parameter for function assessing how good is a free suballocation for a new
allocation request. allocation request.
- Set to true to use Best-Fit algorithm - prefer smaller blocks, as close to the - Set to 1 to use Best-Fit algorithm - prefer smaller blocks, as close to the
size of requested allocations as possible. size of requested allocations as possible.
- Set to false to use Worst-Fit algorithm - prefer larger blocks, as large as - Set to 0 to use Worst-Fit algorithm - prefer larger blocks, as large as
possible. possible.
Experiments in special testing environment showed that Best-Fit algorithm is Experiments in special testing environment showed that Best-Fit algorithm is
better. better.
*/ */
static const bool VMA_BEST_FIT = true; #define VMA_BEST_FIT (1)
#endif
/* #ifndef VMA_DEBUG_ALWAYS_OWN_MEMORY
/**
Every object will have its own allocation. Every object will have its own allocation.
Enable for debugging purposes only. Define to 1 for debugging purposes only.
*/ */
static const bool VMA_DEBUG_ALWAYS_OWN_MEMORY = false; #define VMA_DEBUG_ALWAYS_OWN_MEMORY (0)
#endif
/* #ifndef VMA_DEBUG_ALIGNMENT
/**
Minimum alignment of all suballocations, in bytes. Minimum alignment of all suballocations, in bytes.
Set to more than 1 for debugging purposes only. Must be power of two. Set to more than 1 for debugging purposes only. Must be power of two.
*/ */
static const VkDeviceSize VMA_DEBUG_ALIGNMENT = 1; #define VMA_DEBUG_ALIGNMENT (1)
#endif
/* #ifndef VMA_DEBUG_MARGIN
/**
Minimum margin between suballocations, in bytes. Minimum margin between suballocations, in bytes.
Set nonzero for debugging purposes only. Set nonzero for debugging purposes only.
*/ */
static const VkDeviceSize VMA_DEBUG_MARGIN = 0; #define VMA_DEBUG_MARGIN (0)
#endif
/* #ifndef VMA_DEBUG_GLOBAL_MUTEX
/**
Set this to 1 for debugging purposes only, to enable single mutex protecting all 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. entry calls to the library. Can be useful for debugging multithreading issues.
*/ */
#define VMA_DEBUG_GLOBAL_MUTEX 0 #define VMA_DEBUG_GLOBAL_MUTEX (0)
#endif
/* #ifndef VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY
/**
Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity. Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity.
Set to more than 1 for debugging purposes only. Must be power of two. Set to more than 1 for debugging purposes only. Must be power of two.
*/ */
static const VkDeviceSize VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY = 1; #define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1)
#endif
// Maximum size of a memory heap in Vulkan to consider it "small". #ifndef VMA_SMALL_HEAP_MAX_SIZE
static const VkDeviceSize VMA_SMALL_HEAP_MAX_SIZE = 512 * 1024 * 1024; /// Maximum size of a memory heap in Vulkan to consider it "small".
// Default size of a block allocated as single VkDeviceMemory from a "large" heap. #define VMA_SMALL_HEAP_MAX_SIZE (512 * 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; #ifndef VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE
/// Default size of a block allocated as single VkDeviceMemory from a "large" heap.
#define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256 * 1024 * 1024)
#endif
#ifndef VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE
/// Default size of a block allocated as single VkDeviceMemory from a "small" heap.
#define VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE (64 * 1024 * 1024)
#endif
/******************************************************************************* /*******************************************************************************
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);