mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 14:52:10 +01:00
[dxvk] Use DxvkResourceAllocation internally
Changes DxvkMemory to be nothing more than a wrapper.
This commit is contained in:
parent
5dd7a29261
commit
f36a536288
@ -7,62 +7,6 @@
|
||||
#include "dxvk_sparse.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkMemory::DxvkMemory() { }
|
||||
DxvkMemory::DxvkMemory(
|
||||
DxvkMemoryAllocator* alloc,
|
||||
DxvkMemoryType* type,
|
||||
VkBuffer buffer,
|
||||
VkDeviceMemory memory,
|
||||
VkDeviceSize address,
|
||||
VkDeviceSize length,
|
||||
void* mapPtr)
|
||||
: m_alloc (alloc),
|
||||
m_type (type),
|
||||
m_buffer (buffer),
|
||||
m_memory (memory),
|
||||
m_address (address),
|
||||
m_length (length),
|
||||
m_mapPtr (mapPtr) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
DxvkMemory::DxvkMemory(DxvkMemory&& other)
|
||||
: m_alloc (std::exchange(other.m_alloc, nullptr)),
|
||||
m_type (std::exchange(other.m_type, nullptr)),
|
||||
m_buffer (std::exchange(other.m_buffer, VkBuffer(VK_NULL_HANDLE))),
|
||||
m_memory (std::exchange(other.m_memory, VkDeviceMemory(VK_NULL_HANDLE))),
|
||||
m_address (std::exchange(other.m_address, 0)),
|
||||
m_length (std::exchange(other.m_length, 0)),
|
||||
m_mapPtr (std::exchange(other.m_mapPtr, nullptr)) { }
|
||||
|
||||
|
||||
DxvkMemory& DxvkMemory::operator = (DxvkMemory&& other) {
|
||||
this->free();
|
||||
m_alloc = std::exchange(other.m_alloc, nullptr);
|
||||
m_type = std::exchange(other.m_type, nullptr);
|
||||
m_buffer = std::exchange(other.m_buffer, VkBuffer(VK_NULL_HANDLE));
|
||||
m_memory = std::exchange(other.m_memory, VkDeviceMemory(VK_NULL_HANDLE));
|
||||
m_address = std::exchange(other.m_address, 0);
|
||||
m_length = std::exchange(other.m_length, 0);
|
||||
m_mapPtr = std::exchange(other.m_mapPtr, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DxvkMemory::~DxvkMemory() {
|
||||
this->free();
|
||||
}
|
||||
|
||||
|
||||
void DxvkMemory::free() {
|
||||
if (m_alloc != nullptr)
|
||||
m_alloc->free(*this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
DxvkResourceBufferViewMap::DxvkResourceBufferViewMap(
|
||||
DxvkMemoryAllocator* allocator,
|
||||
@ -176,11 +120,6 @@ namespace dxvk {
|
||||
|
||||
|
||||
|
||||
DxvkResourceAllocation::DxvkResourceAllocation() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
DxvkResourceAllocation::~DxvkResourceAllocation() {
|
||||
if (m_buffer) {
|
||||
if (unlikely(m_bufferViews))
|
||||
@ -328,31 +267,32 @@ namespace dxvk {
|
||||
// fails, we may still fall back to a suballocation unless a
|
||||
// dedicated allocation is explicitly required.
|
||||
if (unlikely(info.dedicated.buffer || info.dedicated.image)) {
|
||||
DxvkMemory memory = allocateDedicatedMemory(
|
||||
Rc<DxvkResourceAllocation> allocation = allocateDedicatedMemory(
|
||||
req.core.memoryRequirements, info.flags, &info.dedicated);
|
||||
|
||||
if (memory)
|
||||
return memory;
|
||||
if (allocation)
|
||||
return DxvkMemory(std::move(allocation));
|
||||
|
||||
if (req.dedicated.requiresDedicatedAllocation && (info.flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) {
|
||||
return allocateDedicatedMemory(req.core.memoryRequirements,
|
||||
allocation = allocateDedicatedMemory(req.core.memoryRequirements,
|
||||
info.flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &info.dedicated);
|
||||
return DxvkMemory(std::move(allocation));
|
||||
}
|
||||
}
|
||||
|
||||
// Suballocate memory from an existing chunk
|
||||
DxvkMemory memory = allocateMemory(req.core.memoryRequirements, info.flags);
|
||||
Rc<DxvkResourceAllocation> allocation = allocateMemory(req.core.memoryRequirements, info.flags);
|
||||
|
||||
if (unlikely(!memory) && (info.flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) {
|
||||
memory = allocateMemory(req.core.memoryRequirements,
|
||||
if (unlikely(!allocation) && (info.flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) {
|
||||
allocation = allocateMemory(req.core.memoryRequirements,
|
||||
info.flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
}
|
||||
|
||||
return memory;
|
||||
return DxvkMemory(std::move(allocation));
|
||||
}
|
||||
|
||||
|
||||
DxvkMemory DxvkMemoryAllocator::allocateMemory(
|
||||
Rc<DxvkResourceAllocation> DxvkMemoryAllocator::allocateMemory(
|
||||
const VkMemoryRequirements& requirements,
|
||||
VkMemoryPropertyFlags properties) {
|
||||
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
||||
@ -375,7 +315,7 @@ namespace dxvk {
|
||||
int64_t address = selectedPool.alloc(size, requirements.alignment);
|
||||
|
||||
if (likely(address >= 0))
|
||||
return createMemory(type, selectedPool, address, size);
|
||||
return createAllocation(type, selectedPool, address, size);
|
||||
|
||||
// If the memory type is host-visible, try to find an existing chunk
|
||||
// in the other memory pool of the memory type and move over.
|
||||
@ -400,7 +340,7 @@ namespace dxvk {
|
||||
address = selectedPool.alloc(size, requirements.alignment);
|
||||
|
||||
if (likely(address >= 0))
|
||||
return createMemory(type, selectedPool, address, size);
|
||||
return createAllocation(type, selectedPool, address, size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,7 +363,7 @@ namespace dxvk {
|
||||
continue;
|
||||
|
||||
mapDeviceMemory(memory, properties);
|
||||
return createMemory(type, memory);
|
||||
return createAllocation(type, memory);
|
||||
}
|
||||
|
||||
// Try to allocate a new chunk that is large enough to hold
|
||||
@ -435,18 +375,18 @@ namespace dxvk {
|
||||
|
||||
if (allocateChunkInPool(type, selectedPool, properties, size, desiredSize)) {
|
||||
address = selectedPool.alloc(size, requirements.alignment);
|
||||
return createMemory(type, selectedPool, address, size);
|
||||
return createAllocation(type, selectedPool, address, size);
|
||||
}
|
||||
}
|
||||
|
||||
logMemoryError(requirements);
|
||||
logMemoryStats();
|
||||
|
||||
return DxvkMemory();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
DxvkMemory DxvkMemoryAllocator::allocateDedicatedMemory(
|
||||
Rc<DxvkResourceAllocation> DxvkMemoryAllocator::allocateDedicatedMemory(
|
||||
const VkMemoryRequirements& requirements,
|
||||
VkMemoryPropertyFlags properties,
|
||||
const void* next) {
|
||||
@ -460,14 +400,14 @@ namespace dxvk {
|
||||
|
||||
if (likely(memory.memory != VK_NULL_HANDLE)) {
|
||||
mapDeviceMemory(memory, properties);
|
||||
return createMemory(type, memory);
|
||||
return createAllocation(type, memory);
|
||||
}
|
||||
}
|
||||
|
||||
logMemoryError(requirements);
|
||||
logMemoryStats();
|
||||
|
||||
return DxvkMemory();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@ -612,7 +552,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxvkMemory DxvkMemoryAllocator::createMemory(
|
||||
Rc<DxvkResourceAllocation> DxvkMemoryAllocator::createAllocation(
|
||||
DxvkMemoryType& type,
|
||||
DxvkMemoryPool& pool,
|
||||
VkDeviceSize address,
|
||||
@ -624,46 +564,43 @@ namespace dxvk {
|
||||
auto& chunk = pool.chunks[chunkIndex];
|
||||
chunk.unusedTime = high_resolution_clock::time_point();
|
||||
|
||||
void* mapPtr = chunk.memory.mapPtr
|
||||
? reinterpret_cast<char*>(chunk.memory.mapPtr) + (address & DxvkPageAllocator::ChunkAddressMask)
|
||||
: nullptr;
|
||||
VkDeviceSize offset = address & DxvkPageAllocator::ChunkAddressMask;
|
||||
|
||||
return DxvkMemory(this, &type, chunk.memory.buffer,
|
||||
chunk.memory.memory, address, size, mapPtr);
|
||||
auto allocation = m_allocationPool.create(this, &type);
|
||||
allocation->m_memory = chunk.memory.memory;
|
||||
allocation->m_address = address;
|
||||
allocation->m_size = size;
|
||||
|
||||
if (chunk.memory.mapPtr)
|
||||
allocation->m_mapPtr = reinterpret_cast<char*>(chunk.memory.mapPtr) + offset;
|
||||
|
||||
if (chunk.memory.buffer) {
|
||||
allocation->m_buffer = chunk.memory.buffer;
|
||||
allocation->m_bufferOffset = offset;
|
||||
}
|
||||
|
||||
return allocation;
|
||||
}
|
||||
|
||||
|
||||
DxvkMemory DxvkMemoryAllocator::createMemory(
|
||||
Rc<DxvkResourceAllocation> DxvkMemoryAllocator::createAllocation(
|
||||
DxvkMemoryType& type,
|
||||
const DxvkDeviceMemory& memory) {
|
||||
type.stats.memoryUsed += memory.size;
|
||||
|
||||
return DxvkMemory(this, &type, memory.buffer, memory.memory,
|
||||
DedicatedChunkAddress, memory.size, memory.mapPtr);
|
||||
}
|
||||
auto allocation = m_allocationPool.create(this, &type);
|
||||
allocation->m_flags.set(DxvkAllocationFlag::OwnsMemory);
|
||||
|
||||
if (memory.buffer)
|
||||
allocation->m_flags.set(DxvkAllocationFlag::OwnsBuffer);
|
||||
|
||||
void DxvkMemoryAllocator::free(
|
||||
const DxvkMemory& memory) {
|
||||
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
||||
memory.m_type->stats.memoryUsed -= memory.m_length;
|
||||
allocation->m_memory = memory.memory;
|
||||
allocation->m_address = DedicatedChunkAddress;
|
||||
allocation->m_size = memory.size;
|
||||
allocation->m_mapPtr = memory.mapPtr;
|
||||
|
||||
if (unlikely(memory.m_address == DedicatedChunkAddress)) {
|
||||
DxvkDeviceMemory devMem;
|
||||
devMem.buffer = memory.m_buffer;
|
||||
devMem.memory = memory.m_memory;
|
||||
devMem.mapPtr = nullptr;
|
||||
devMem.size = memory.m_length;
|
||||
|
||||
this->freeDeviceMemory(*memory.m_type, devMem);
|
||||
} else {
|
||||
DxvkMemoryPool& pool = memory.m_mapPtr
|
||||
? memory.m_type->mappedPool
|
||||
: memory.m_type->devicePool;
|
||||
|
||||
if (unlikely(pool.free(memory.m_address, memory.m_length)))
|
||||
freeEmptyChunksInPool(*memory.m_type, pool, 0, high_resolution_clock::now());
|
||||
}
|
||||
allocation->m_buffer = memory.buffer;
|
||||
return allocation;
|
||||
}
|
||||
|
||||
|
||||
|
@ -433,9 +433,13 @@ namespace dxvk {
|
||||
*/
|
||||
class alignas(CACHE_LINE_SIZE) DxvkResourceAllocation {
|
||||
friend DxvkMemoryAllocator;
|
||||
friend class DxvkMemory;
|
||||
public:
|
||||
|
||||
DxvkResourceAllocation();
|
||||
DxvkResourceAllocation(
|
||||
DxvkMemoryAllocator* allocator,
|
||||
DxvkMemoryType* type)
|
||||
: m_allocator(allocator), m_type(type) { }
|
||||
|
||||
~DxvkResourceAllocation();
|
||||
|
||||
@ -650,22 +654,16 @@ namespace dxvk {
|
||||
* Represents a slice of memory that has
|
||||
* been sub-allocated from a bigger chunk.
|
||||
*/
|
||||
class DxvkMemory {
|
||||
friend class DxvkMemoryAllocator;
|
||||
public:
|
||||
|
||||
DxvkMemory();
|
||||
DxvkMemory(
|
||||
DxvkMemoryAllocator* alloc,
|
||||
DxvkMemoryType* type,
|
||||
VkBuffer buffer,
|
||||
VkDeviceMemory memory,
|
||||
VkDeviceSize address,
|
||||
VkDeviceSize length,
|
||||
void* mapPtr);
|
||||
DxvkMemory (DxvkMemory&& other);
|
||||
DxvkMemory& operator = (DxvkMemory&& other);
|
||||
~DxvkMemory();
|
||||
struct DxvkMemory {
|
||||
DxvkMemory() = default;
|
||||
|
||||
explicit DxvkMemory(Rc<DxvkResourceAllocation>&& allocation_)
|
||||
: allocation(std::move(allocation_)) { }
|
||||
|
||||
DxvkMemory(DxvkMemory&& other) = default;
|
||||
DxvkMemory& operator = (DxvkMemory&& other) = default;
|
||||
|
||||
~DxvkMemory() = default;
|
||||
|
||||
/**
|
||||
* \brief Memory object
|
||||
@ -675,7 +673,7 @@ namespace dxvk {
|
||||
* \returns Memory object
|
||||
*/
|
||||
VkDeviceMemory memory() const {
|
||||
return m_memory;
|
||||
return allocation ? allocation->m_memory : VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -685,7 +683,7 @@ namespace dxvk {
|
||||
* \returns Buffer object
|
||||
*/
|
||||
VkBuffer buffer() const {
|
||||
return m_buffer;
|
||||
return allocation ? allocation->m_buffer : VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -696,7 +694,9 @@ namespace dxvk {
|
||||
* \returns Offset into device memory
|
||||
*/
|
||||
VkDeviceSize offset() const {
|
||||
return m_address & DxvkPageAllocator::ChunkAddressMask;
|
||||
return allocation
|
||||
? allocation->m_address & DxvkPageAllocator::ChunkAddressMask
|
||||
: 0u;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -706,16 +706,17 @@ namespace dxvk {
|
||||
* \returns Pointer to mapped data
|
||||
*/
|
||||
void* mapPtr(VkDeviceSize offset) const {
|
||||
return reinterpret_cast<char*>(m_mapPtr) + offset;
|
||||
return allocation && allocation->m_mapPtr
|
||||
? reinterpret_cast<char*>(allocation->m_mapPtr) + offset
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns length of memory allocated
|
||||
*
|
||||
* \returns Memory size
|
||||
*/
|
||||
VkDeviceSize length() const {
|
||||
return m_length;
|
||||
return allocation ? allocation->m_size : 0u;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -725,7 +726,7 @@ namespace dxvk {
|
||||
* memory, and \c false if it is undefined.
|
||||
*/
|
||||
explicit operator bool () const {
|
||||
return m_memory != VK_NULL_HANDLE;
|
||||
return bool(allocation);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -733,21 +734,12 @@ namespace dxvk {
|
||||
* \returns Global buffer usage flags, if any
|
||||
*/
|
||||
VkBufferUsageFlags getBufferUsage() const {
|
||||
return m_buffer ? m_type->bufferUsage : 0u;
|
||||
return allocation && allocation->m_type
|
||||
? allocation->m_type->bufferUsage
|
||||
: 0u;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
DxvkMemoryAllocator* m_alloc = nullptr;
|
||||
DxvkMemoryType* m_type = nullptr;
|
||||
VkBuffer m_buffer = VK_NULL_HANDLE;
|
||||
VkDeviceMemory m_memory = VK_NULL_HANDLE;
|
||||
VkDeviceSize m_address = 0;
|
||||
VkDeviceSize m_length = 0;
|
||||
void* m_mapPtr = nullptr;
|
||||
|
||||
void free();
|
||||
|
||||
Rc<DxvkResourceAllocation> allocation;
|
||||
};
|
||||
|
||||
|
||||
@ -807,8 +799,9 @@ namespace dxvk {
|
||||
* \param [in] requirements Memory requirements
|
||||
* \param [in] properties Memory property flags. Some of
|
||||
* these may be ignored in case of memory pressure.
|
||||
* \returns Allocated memory
|
||||
*/
|
||||
DxvkMemory allocateMemory(
|
||||
Rc<DxvkResourceAllocation> allocateMemory(
|
||||
const VkMemoryRequirements& requirements,
|
||||
VkMemoryPropertyFlags properties);
|
||||
|
||||
@ -820,8 +813,9 @@ namespace dxvk {
|
||||
* \param [in] properties Memory property flags. Some of
|
||||
* these may be ignored in case of memory pressure.
|
||||
* \param [in] next Further memory properties
|
||||
* \returns Allocated memory
|
||||
*/
|
||||
DxvkMemory allocateDedicatedMemory(
|
||||
Rc<DxvkResourceAllocation> allocateDedicatedMemory(
|
||||
const VkMemoryRequirements& requirements,
|
||||
VkMemoryPropertyFlags properties,
|
||||
const void* next);
|
||||
@ -903,15 +897,6 @@ namespace dxvk {
|
||||
VkDeviceSize requiredSize,
|
||||
VkDeviceSize desiredSize);
|
||||
|
||||
DxvkMemory createMemory(
|
||||
DxvkMemoryType& type,
|
||||
DxvkMemoryPool& pool,
|
||||
VkDeviceSize address,
|
||||
VkDeviceSize size);
|
||||
|
||||
void free(
|
||||
const DxvkMemory& memory);
|
||||
|
||||
void freeDeviceMemory(
|
||||
DxvkMemoryType& type,
|
||||
DxvkDeviceMemory memory);
|
||||
@ -942,13 +927,13 @@ namespace dxvk {
|
||||
DxvkDeviceMemory& memory,
|
||||
VkMemoryPropertyFlags properties);
|
||||
|
||||
DxvkMemory createMemory(
|
||||
Rc<DxvkResourceAllocation> createAllocation(
|
||||
DxvkMemoryType& type,
|
||||
const DxvkMemoryPool& pool,
|
||||
DxvkMemoryPool& pool,
|
||||
VkDeviceSize address,
|
||||
VkDeviceSize size);
|
||||
|
||||
DxvkMemory createMemory(
|
||||
Rc<DxvkResourceAllocation> createAllocation(
|
||||
DxvkMemoryType& type,
|
||||
const DxvkDeviceMemory& memory);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user