1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 19:54:19 +01:00

[dxvk] Refactor sparse page allocation

Uses the new allocator directly.
This commit is contained in:
Philip Rebohle 2024-09-25 21:43:36 +02:00 committed by Philip Rebohle
parent af4a2f7973
commit 0f23a17d8f
5 changed files with 47 additions and 81 deletions

View File

@ -2683,7 +2683,7 @@ namespace dxvk {
key.offset = pageInfo.buffer.offset;
key.size = pageInfo.buffer.length;
m_cmd->bindBufferMemory(key, mapping.getHandle());
m_cmd->bindBufferMemory(key, mapping.getMemoryInfo());
} break;
case DxvkSparsePageType::Image: {
@ -2693,7 +2693,7 @@ namespace dxvk {
key.offset = pageInfo.image.offset;
key.extent = pageInfo.image.extent;
m_cmd->bindImageMemory(key, mapping.getHandle());
m_cmd->bindImageMemory(key, mapping.getMemoryInfo());
} break;
case DxvkSparsePageType::ImageMipTail: {
@ -2703,7 +2703,7 @@ namespace dxvk {
key.size = pageInfo.mipTail.resourceLength;
key.flags = 0;
m_cmd->bindImageOpaqueMemory(key, mapping.getHandle());
m_cmd->bindImageOpaqueMemory(key, mapping.getMemoryInfo());
} break;
}

View File

@ -894,6 +894,26 @@ namespace dxvk {
}
Rc<DxvkResourceAllocation> DxvkMemoryAllocator::createSparsePage() {
VkMemoryRequirements requirements = { };
requirements.size = SparseMemoryPageSize;
requirements.alignment = SparseMemoryPageSize;
requirements.memoryTypeBits = m_sparseMemoryTypes;
// Try device memory first, fall back to system memory if that fails.
// We might get an allocation with a global buffer, just ignore that.
auto allocation = allocateMemory(requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (!allocation)
allocation = allocateMemory(requirements, 0);
if (!allocation)
return nullptr;
return allocation;
}
DxvkLocalAllocationCache DxvkMemoryAllocator::createAllocationCache(
VkBufferUsageFlags bufferUsage,
VkMemoryPropertyFlags properties) {

View File

@ -1067,14 +1067,6 @@ namespace dxvk {
return m_device;
}
/**
* \brief Memory type mask for sparse resources
* \returns Sparse resource memory types
*/
uint32_t getSparseMemoryTypes() const {
return m_sparseMemoryTypes;
}
/**
* \brief Allocates device memory
*
@ -1145,6 +1137,14 @@ namespace dxvk {
VkMemoryPropertyFlags properties,
const void* next);
/**
* \brief Creates allocation for sparse binding
*
* Allocates a single page of memory for sparse binding.
* \returns Allocated memory region
*/
Rc<DxvkResourceAllocation> createSparsePage();
/**
* \brief Creates local allocation cache for buffer resources
*

View File

@ -16,7 +16,7 @@ namespace dxvk {
DxvkSparseMapping::DxvkSparseMapping(
Rc<DxvkSparsePageAllocator> allocator,
Rc<DxvkSparsePage> page)
Rc<DxvkResourceAllocation> page)
: m_pool(std::move(allocator)),
m_page(std::move(page)) {
@ -110,18 +110,18 @@ namespace dxvk {
if (!m_useCount)
m_pages.resize(pageCount);
} else if (pageCount > m_pageCount) {
std::vector<Rc<DxvkSparsePage>> newPages;
std::vector<Rc<DxvkResourceAllocation>> newPages;
newPages.reserve(pageCount - m_pageCount);
for (size_t i = 0; i < pageCount - m_pageCount; i++)
newPages.push_back(allocPage());
newPages.push_back(m_memory->createSparsePage());
// Sort page by memory and offset to enable more
// batching opportunities during page table updates
std::sort(newPages.begin(), newPages.end(),
[] (const Rc<DxvkSparsePage>& a, const Rc<DxvkSparsePage>& b) {
auto aHandle = a->getHandle();
auto bHandle = b->getHandle();
[] (const Rc<DxvkResourceAllocation>& a, const Rc<DxvkResourceAllocation>& b) {
auto aHandle = a->getMemoryInfo();
auto bHandle = b->getMemoryInfo();
// Ignore length here, the offsets cannot be the same anyway.
if (aHandle.memory < bHandle.memory) return true;
@ -138,35 +138,15 @@ namespace dxvk {
}
Rc<DxvkSparsePage> DxvkSparsePageAllocator::allocPage() {
DxvkMemoryRequirements memoryRequirements = { };
memoryRequirements.tiling = VK_IMAGE_TILING_LINEAR;
memoryRequirements.core = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 };
// We don't know what kind of resource the memory6
// might be bound to, so just guess the memory types
auto& core = memoryRequirements.core.memoryRequirements;
core.size = SparseMemoryPageSize;
core.alignment = SparseMemoryPageSize;
core.memoryTypeBits = m_memory->getSparseMemoryTypes();
DxvkMemoryProperties memoryProperties = { };
memoryProperties.flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
DxvkMemory memory = m_memory->alloc(memoryRequirements, memoryProperties);
return new DxvkSparsePage(std::move(memory));
}
void DxvkSparsePageAllocator::acquirePage(
const Rc<DxvkSparsePage>& page) {
const Rc<DxvkResourceAllocation>& page) {
std::lock_guard lock(m_mutex);
m_useCount += 1;
}
void DxvkSparsePageAllocator::releasePage(
const Rc<DxvkSparsePage>& page) {
const Rc<DxvkResourceAllocation>& page) {
std::lock_guard lock(m_mutex);
m_useCount -= 1;

View File

@ -155,38 +155,6 @@ namespace dxvk {
};
/**
* \brief Sparse memory page
*
* Stores a single reference-counted page
* of memory. The page size is 64k.
*/
class DxvkSparsePage : public DxvkResource {
public:
DxvkSparsePage(DxvkMemory&& memory)
: m_memory(std::move(memory)) { }
/**
* \brief Queries memory handle
* \returns Memory information
*/
DxvkResourceMemoryInfo getHandle() const {
DxvkResourceMemoryInfo result;
result.memory = m_memory.memory();
result.offset = m_memory.offset();
result.size = m_memory.length();
return result;
}
private:
DxvkMemory m_memory;
};
/**
* \brief Sparse page mapping
*
@ -213,11 +181,11 @@ namespace dxvk {
* \brief Queries memory handle
* \returns Memory information
*/
DxvkResourceMemoryInfo getHandle() const {
if (m_page == nullptr)
DxvkResourceMemoryInfo getMemoryInfo() const {
if (!m_page)
return DxvkResourceMemoryInfo();
return m_page->getHandle();
return m_page->getMemoryInfo();
}
bool operator == (const DxvkSparseMapping& other) const {
@ -236,11 +204,11 @@ namespace dxvk {
private:
Rc<DxvkSparsePageAllocator> m_pool;
Rc<DxvkSparsePage> m_page;
Rc<DxvkResourceAllocation> m_page;
DxvkSparseMapping(
Rc<DxvkSparsePageAllocator> allocator,
Rc<DxvkSparsePage> page);
Rc<DxvkResourceAllocation> page);
void acquire() const;
@ -294,15 +262,13 @@ namespace dxvk {
dxvk::mutex m_mutex;
uint32_t m_pageCount = 0u;
uint32_t m_useCount = 0u;
std::vector<Rc<DxvkSparsePage>> m_pages;
Rc<DxvkSparsePage> allocPage();
std::vector<Rc<DxvkResourceAllocation>> m_pages;
void acquirePage(
const Rc<DxvkSparsePage>& page);
const Rc<DxvkResourceAllocation>& page);
void releasePage(
const Rc<DxvkSparsePage>& page);
const Rc<DxvkResourceAllocation>& page);
};