2017-10-10 23:32:13 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "dxvk_adapter.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
class DxvkMemoryAllocator;
|
2018-05-29 14:48:27 +02:00
|
|
|
class DxvkMemoryChunk;
|
2017-10-10 23:32:13 +02:00
|
|
|
|
2018-04-03 15:32:00 +02:00
|
|
|
/**
|
|
|
|
* \brief Memory stats
|
|
|
|
*
|
|
|
|
* Reports the amount of device memory
|
|
|
|
* allocated and used by the application.
|
|
|
|
*/
|
|
|
|
struct DxvkMemoryStats {
|
|
|
|
VkDeviceSize memoryAllocated = 0;
|
|
|
|
VkDeviceSize memoryUsed = 0;
|
|
|
|
};
|
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
|
2018-05-29 14:48:27 +02:00
|
|
|
/**
|
|
|
|
* \brief Device memory object
|
|
|
|
*
|
|
|
|
* Stores a Vulkan memory object. If the object
|
|
|
|
* was allocated on host-visible memory, it will
|
|
|
|
* be persistently mapped.
|
|
|
|
*/
|
|
|
|
struct DxvkDeviceMemory {
|
2018-09-17 09:08:00 +02:00
|
|
|
VkDeviceMemory memHandle = VK_NULL_HANDLE;
|
|
|
|
void* memPointer = nullptr;
|
|
|
|
VkDeviceSize memSize = 0;
|
|
|
|
VkMemoryPropertyFlags memFlags = 0;
|
2019-01-30 11:38:55 +01:00
|
|
|
float priority = 0.0f;
|
2018-05-29 14:48:27 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Memory heap
|
|
|
|
*
|
|
|
|
* Corresponds to a Vulkan memory heap and stores
|
|
|
|
* its properties as well as allocation statistics.
|
|
|
|
*/
|
|
|
|
struct DxvkMemoryHeap {
|
|
|
|
VkMemoryHeap properties;
|
|
|
|
DxvkMemoryStats stats;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Memory type
|
|
|
|
*
|
|
|
|
* Corresponds to a Vulkan memory type and stores
|
|
|
|
* memory chunks used to sub-allocate memory on
|
|
|
|
* this memory type.
|
|
|
|
*/
|
|
|
|
struct DxvkMemoryType {
|
|
|
|
DxvkMemoryHeap* heap;
|
2018-11-13 12:21:53 +01:00
|
|
|
uint32_t heapId;
|
2018-05-29 14:48:27 +02:00
|
|
|
|
|
|
|
VkMemoryType memType;
|
|
|
|
uint32_t memTypeId;
|
|
|
|
|
2019-07-16 09:58:33 +02:00
|
|
|
VkDeviceSize chunkSize;
|
|
|
|
|
2018-05-29 14:48:27 +02:00
|
|
|
std::vector<Rc<DxvkMemoryChunk>> chunks;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
/**
|
|
|
|
* \brief Memory slice
|
2017-12-16 16:48:42 +01:00
|
|
|
*
|
|
|
|
* Represents a slice of memory that has
|
|
|
|
* been sub-allocated from a bigger chunk.
|
2017-10-10 23:32:13 +02:00
|
|
|
*/
|
|
|
|
class DxvkMemory {
|
2018-05-29 14:48:27 +02:00
|
|
|
friend class DxvkMemoryAllocator;
|
2017-10-10 23:32:13 +02:00
|
|
|
public:
|
|
|
|
|
|
|
|
DxvkMemory();
|
|
|
|
DxvkMemory(
|
2018-05-29 14:48:27 +02:00
|
|
|
DxvkMemoryAllocator* alloc,
|
|
|
|
DxvkMemoryChunk* chunk,
|
|
|
|
DxvkMemoryType* type,
|
|
|
|
VkDeviceMemory memory,
|
|
|
|
VkDeviceSize offset,
|
|
|
|
VkDeviceSize length,
|
|
|
|
void* mapPtr);
|
2017-10-10 23:32:13 +02:00
|
|
|
DxvkMemory (DxvkMemory&& other);
|
|
|
|
DxvkMemory& operator = (DxvkMemory&& other);
|
|
|
|
~DxvkMemory();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Memory object
|
|
|
|
*
|
|
|
|
* This information is required when
|
|
|
|
* binding memory to Vulkan objects.
|
|
|
|
* \returns Memory object
|
|
|
|
*/
|
|
|
|
VkDeviceMemory memory() const {
|
|
|
|
return m_memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-12-16 16:48:42 +01:00
|
|
|
* \brief Offset into device memory
|
2017-10-10 23:32:13 +02:00
|
|
|
*
|
|
|
|
* This information is required when
|
|
|
|
* binding memory to Vulkan objects.
|
2017-12-16 16:48:42 +01:00
|
|
|
* \returns Offset into device memory
|
2017-10-10 23:32:13 +02:00
|
|
|
*/
|
|
|
|
VkDeviceSize offset() const {
|
2017-12-16 16:48:42 +01:00
|
|
|
return m_offset;
|
2017-10-10 23:32:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Pointer to mapped data
|
2017-12-10 15:57:51 +01:00
|
|
|
*
|
|
|
|
* \param [in] offset Byte offset
|
2017-10-10 23:32:13 +02:00
|
|
|
* \returns Pointer to mapped data
|
|
|
|
*/
|
2017-12-10 15:57:51 +01:00
|
|
|
void* mapPtr(VkDeviceSize offset) const {
|
|
|
|
return reinterpret_cast<char*>(m_mapPtr) + offset;
|
2017-10-10 23:32:13 +02:00
|
|
|
}
|
2018-05-29 14:48:27 +02:00
|
|
|
|
2019-07-18 18:05:01 +01:00
|
|
|
/**
|
|
|
|
* \brief Returns length of memory allocated
|
|
|
|
*
|
|
|
|
* \returns Memory size
|
|
|
|
*/
|
|
|
|
VkDeviceSize length() const {
|
|
|
|
return m_length;
|
|
|
|
}
|
|
|
|
|
2018-05-29 14:48:27 +02:00
|
|
|
/**
|
|
|
|
* \brief Checks whether the memory slice is defined
|
|
|
|
*
|
|
|
|
* \returns \c true if this slice points to actual device
|
|
|
|
* memory, and \c false if it is undefined.
|
|
|
|
*/
|
|
|
|
operator bool () const {
|
|
|
|
return m_memory != VK_NULL_HANDLE;
|
|
|
|
}
|
2017-10-10 23:32:13 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
|
2018-05-29 14:48:27 +02:00
|
|
|
DxvkMemoryAllocator* m_alloc = nullptr;
|
|
|
|
DxvkMemoryChunk* m_chunk = nullptr;
|
|
|
|
DxvkMemoryType* m_type = nullptr;
|
|
|
|
VkDeviceMemory m_memory = VK_NULL_HANDLE;
|
|
|
|
VkDeviceSize m_offset = 0;
|
|
|
|
VkDeviceSize m_length = 0;
|
|
|
|
void* m_mapPtr = nullptr;
|
2017-12-16 16:48:42 +01:00
|
|
|
|
2018-04-03 15:32:00 +02:00
|
|
|
void free();
|
|
|
|
|
2017-12-16 16:48:42 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Memory chunk
|
|
|
|
*
|
|
|
|
* A single chunk of memory that provides a
|
|
|
|
* sub-allocator. This is not thread-safe.
|
|
|
|
*/
|
|
|
|
class DxvkMemoryChunk : public RcObject {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
DxvkMemoryChunk(
|
2018-05-29 14:48:27 +02:00
|
|
|
DxvkMemoryAllocator* alloc,
|
|
|
|
DxvkMemoryType* type,
|
|
|
|
DxvkDeviceMemory memory);
|
2017-12-16 16:48:42 +01:00
|
|
|
|
|
|
|
~DxvkMemoryChunk();
|
2018-09-17 09:08:00 +02:00
|
|
|
|
2017-12-16 16:48:42 +01:00
|
|
|
/**
|
|
|
|
* \brief Allocates memory from the chunk
|
|
|
|
*
|
|
|
|
* On failure, this returns a slice with
|
|
|
|
* \c VK_NULL_HANDLE as the memory handle.
|
2018-09-17 09:08:00 +02:00
|
|
|
* \param [in] flags Requested memory flags
|
2017-12-16 16:48:42 +01:00
|
|
|
* \param [in] size Number of bytes to allocate
|
|
|
|
* \param [in] align Required alignment
|
2019-01-30 11:38:55 +01:00
|
|
|
* \param [in] priority Requested priority
|
2017-12-16 16:48:42 +01:00
|
|
|
* \returns The allocated memory slice
|
|
|
|
*/
|
|
|
|
DxvkMemory alloc(
|
2018-09-17 09:08:00 +02:00
|
|
|
VkMemoryPropertyFlags flags,
|
|
|
|
VkDeviceSize size,
|
2019-01-30 11:38:55 +01:00
|
|
|
VkDeviceSize align,
|
|
|
|
float priority);
|
2017-12-16 16:48:42 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Frees memory
|
|
|
|
*
|
|
|
|
* Returns a slice back to the chunk.
|
|
|
|
* Called automatically when a memory
|
|
|
|
* slice runs out of scope.
|
|
|
|
* \param [in] offset Slice offset
|
|
|
|
* \param [in] length Slice length
|
|
|
|
*/
|
|
|
|
void free(
|
|
|
|
VkDeviceSize offset,
|
|
|
|
VkDeviceSize length);
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
struct FreeSlice {
|
|
|
|
VkDeviceSize offset;
|
|
|
|
VkDeviceSize length;
|
|
|
|
};
|
|
|
|
|
2018-05-29 14:48:27 +02:00
|
|
|
DxvkMemoryAllocator* m_alloc;
|
|
|
|
DxvkMemoryType* m_type;
|
|
|
|
DxvkDeviceMemory m_memory;
|
2018-03-20 22:36:02 +01:00
|
|
|
|
2017-12-16 16:48:42 +01:00
|
|
|
std::vector<FreeSlice> m_freeList;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
/**
|
|
|
|
* \brief Memory allocator
|
|
|
|
*
|
|
|
|
* Allocates device memory for Vulkan resources.
|
|
|
|
* Memory objects will be destroyed automatically.
|
|
|
|
*/
|
2019-07-30 20:06:59 +02:00
|
|
|
class DxvkMemoryAllocator {
|
2017-10-10 23:32:13 +02:00
|
|
|
friend class DxvkMemory;
|
2018-05-29 14:48:27 +02:00
|
|
|
friend class DxvkMemoryChunk;
|
2017-10-10 23:32:13 +02:00
|
|
|
public:
|
|
|
|
|
2018-08-07 16:42:21 +02:00
|
|
|
DxvkMemoryAllocator(const DxvkDevice* device);
|
2017-10-10 23:32:13 +02:00
|
|
|
~DxvkMemoryAllocator();
|
|
|
|
|
2018-03-20 20:24:11 +01:00
|
|
|
/**
|
|
|
|
* \brief Buffer-image granularity
|
|
|
|
*
|
|
|
|
* The granularity between linear and non-linear
|
|
|
|
* resources in adjacent memory locations. See
|
|
|
|
* section 11.6 of the Vulkan spec for details.
|
|
|
|
* \returns Buffer-image granularity
|
|
|
|
*/
|
|
|
|
VkDeviceSize bufferImageGranularity() const {
|
|
|
|
return m_devProps.limits.bufferImageGranularity;
|
|
|
|
}
|
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
/**
|
|
|
|
* \brief Allocates device memory
|
|
|
|
*
|
|
|
|
* \param [in] req Memory requirements
|
2019-06-20 10:32:00 +02:00
|
|
|
* \param [in] dedAllocReq Dedicated allocation requirements
|
2019-01-30 11:38:55 +01:00
|
|
|
* \param [in] dedAllocInfo Dedicated allocation info
|
|
|
|
* \param [in] flags Memory type flags
|
|
|
|
* \param [in] priority Device-local memory priority
|
2017-10-10 23:32:13 +02:00
|
|
|
* \returns Allocated memory slice
|
|
|
|
*/
|
|
|
|
DxvkMemory alloc(
|
2018-06-24 02:55:42 -06:00
|
|
|
const VkMemoryRequirements* req,
|
2019-06-20 10:32:00 +02:00
|
|
|
const VkMemoryDedicatedRequirements& dedAllocReq,
|
|
|
|
const VkMemoryDedicatedAllocateInfoKHR& dedAllocInfo,
|
2019-01-30 11:38:55 +01:00
|
|
|
VkMemoryPropertyFlags flags,
|
|
|
|
float priority);
|
2017-10-10 23:32:13 +02:00
|
|
|
|
2019-12-13 11:15:52 +01:00
|
|
|
/**
|
|
|
|
* \brief Queries memory stats
|
|
|
|
*
|
|
|
|
* Returns the total amount of memory
|
|
|
|
* allocated and used for a given heap.
|
|
|
|
* \param [in] heap Heap index
|
|
|
|
* \returns Memory stats for this heap
|
|
|
|
*/
|
|
|
|
DxvkMemoryStats getMemoryStats(uint32_t heap) const {
|
|
|
|
return m_memHeaps[heap].stats;
|
|
|
|
}
|
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
private:
|
2018-05-29 14:48:27 +02:00
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
const Rc<vk::DeviceFn> m_vkd;
|
2019-01-30 13:13:46 +01:00
|
|
|
const DxvkDevice* m_device;
|
2018-03-20 20:24:11 +01:00
|
|
|
const VkPhysicalDeviceProperties m_devProps;
|
2017-10-10 23:32:13 +02:00
|
|
|
const VkPhysicalDeviceMemoryProperties m_memProps;
|
|
|
|
|
2018-05-29 14:48:27 +02:00
|
|
|
std::mutex m_mutex;
|
|
|
|
std::array<DxvkMemoryHeap, VK_MAX_MEMORY_HEAPS> m_memHeaps;
|
|
|
|
std::array<DxvkMemoryType, VK_MAX_MEMORY_TYPES> m_memTypes;
|
2017-10-10 23:32:13 +02:00
|
|
|
|
2018-02-27 12:36:44 +01:00
|
|
|
DxvkMemory tryAlloc(
|
2018-06-24 02:55:42 -06:00
|
|
|
const VkMemoryRequirements* req,
|
|
|
|
const VkMemoryDedicatedAllocateInfoKHR* dedAllocInfo,
|
2019-01-30 11:38:55 +01:00
|
|
|
VkMemoryPropertyFlags flags,
|
|
|
|
float priority);
|
2018-02-27 12:36:44 +01:00
|
|
|
|
2018-05-29 14:48:27 +02:00
|
|
|
DxvkMemory tryAllocFromType(
|
2018-06-24 02:55:42 -06:00
|
|
|
DxvkMemoryType* type,
|
2018-09-17 09:08:00 +02:00
|
|
|
VkMemoryPropertyFlags flags,
|
2018-06-24 02:55:42 -06:00
|
|
|
VkDeviceSize size,
|
|
|
|
VkDeviceSize align,
|
2019-01-30 11:38:55 +01:00
|
|
|
float priority,
|
2018-06-24 02:55:42 -06:00
|
|
|
const VkMemoryDedicatedAllocateInfoKHR* dedAllocInfo);
|
2018-05-29 14:48:27 +02:00
|
|
|
|
|
|
|
DxvkDeviceMemory tryAllocDeviceMemory(
|
2018-06-24 02:55:42 -06:00
|
|
|
DxvkMemoryType* type,
|
2018-09-17 09:08:00 +02:00
|
|
|
VkMemoryPropertyFlags flags,
|
2018-06-24 02:55:42 -06:00
|
|
|
VkDeviceSize size,
|
2019-01-30 11:38:55 +01:00
|
|
|
float priority,
|
2018-06-24 02:55:42 -06:00
|
|
|
const VkMemoryDedicatedAllocateInfoKHR* dedAllocInfo);
|
2018-05-29 14:48:27 +02:00
|
|
|
|
|
|
|
void free(
|
|
|
|
const DxvkMemory& memory);
|
|
|
|
|
|
|
|
void freeChunkMemory(
|
|
|
|
DxvkMemoryType* type,
|
|
|
|
DxvkMemoryChunk* chunk,
|
|
|
|
VkDeviceSize offset,
|
|
|
|
VkDeviceSize length);
|
|
|
|
|
|
|
|
void freeDeviceMemory(
|
|
|
|
DxvkMemoryType* type,
|
|
|
|
DxvkDeviceMemory memory);
|
2018-07-09 19:18:39 +02:00
|
|
|
|
|
|
|
VkDeviceSize pickChunkSize(
|
2019-07-16 09:58:33 +02:00
|
|
|
uint32_t memTypeId) const;
|
2018-05-29 14:48:27 +02:00
|
|
|
|
2017-10-10 23:32:13 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|