mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-18 11:52:12 +01:00
[dxvk] Implement sparse buffer creation
This commit is contained in:
parent
bc3affc264
commit
f7c255de2a
@ -16,33 +16,49 @@ namespace dxvk {
|
|||||||
m_memAlloc (&memAlloc),
|
m_memAlloc (&memAlloc),
|
||||||
m_memFlags (memFlags),
|
m_memFlags (memFlags),
|
||||||
m_shaderStages (util::shaderStages(createInfo.stages)) {
|
m_shaderStages (util::shaderStages(createInfo.stages)) {
|
||||||
// Align slices so that we don't violate any alignment
|
if (!(m_info.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)) {
|
||||||
// requirements imposed by the Vulkan device/driver
|
// Align slices so that we don't violate any alignment
|
||||||
VkDeviceSize sliceAlignment = computeSliceAlignment();
|
// requirements imposed by the Vulkan device/driver
|
||||||
m_physSliceLength = createInfo.size;
|
VkDeviceSize sliceAlignment = computeSliceAlignment();
|
||||||
m_physSliceStride = align(createInfo.size, sliceAlignment);
|
m_physSliceLength = createInfo.size;
|
||||||
m_physSliceCount = std::max<VkDeviceSize>(1, 256 / m_physSliceStride);
|
m_physSliceStride = align(createInfo.size, sliceAlignment);
|
||||||
|
m_physSliceCount = std::max<VkDeviceSize>(1, 256 / m_physSliceStride);
|
||||||
|
|
||||||
// Limit size of multi-slice buffers to reduce fragmentation
|
// Limit size of multi-slice buffers to reduce fragmentation
|
||||||
constexpr VkDeviceSize MaxBufferSize = 256 << 10;
|
constexpr VkDeviceSize MaxBufferSize = 256 << 10;
|
||||||
|
|
||||||
m_physSliceMaxCount = MaxBufferSize >= m_physSliceStride
|
m_physSliceMaxCount = MaxBufferSize >= m_physSliceStride
|
||||||
? MaxBufferSize / m_physSliceStride
|
? MaxBufferSize / m_physSliceStride
|
||||||
: 1;
|
: 1;
|
||||||
|
|
||||||
// Allocate the initial set of buffer slices. Only clear
|
// Allocate the initial set of buffer slices. Only clear
|
||||||
// buffer memory if there is more than one slice, since
|
// buffer memory if there is more than one slice, since
|
||||||
// we expect the client api to initialize the first slice.
|
// we expect the client api to initialize the first slice.
|
||||||
m_buffer = allocBuffer(m_physSliceCount, m_physSliceCount > 1);
|
m_buffer = allocBuffer(m_physSliceCount, m_physSliceCount > 1);
|
||||||
|
|
||||||
DxvkBufferSliceHandle slice;
|
m_physSlice.handle = m_buffer.buffer;
|
||||||
slice.handle = m_buffer.buffer;
|
m_physSlice.offset = 0;
|
||||||
slice.offset = 0;
|
m_physSlice.length = m_physSliceLength;
|
||||||
slice.length = m_physSliceLength;
|
m_physSlice.mapPtr = m_buffer.memory.mapPtr(0);
|
||||||
slice.mapPtr = m_buffer.memory.mapPtr(0);
|
|
||||||
|
|
||||||
m_physSlice = slice;
|
m_lazyAlloc = m_physSliceCount > 1;
|
||||||
m_lazyAlloc = m_physSliceCount > 1;
|
} else {
|
||||||
|
m_physSliceLength = createInfo.size;
|
||||||
|
m_physSliceStride = createInfo.size;
|
||||||
|
m_physSliceCount = 1;
|
||||||
|
m_physSliceMaxCount = 1;
|
||||||
|
|
||||||
|
m_buffer = createSparseBuffer();
|
||||||
|
|
||||||
|
m_physSlice.handle = m_buffer.buffer;
|
||||||
|
m_physSlice.offset = 0;
|
||||||
|
m_physSlice.length = createInfo.size;
|
||||||
|
m_physSlice.mapPtr = nullptr;
|
||||||
|
|
||||||
|
m_lazyAlloc = false;
|
||||||
|
|
||||||
|
m_sparsePageTable = DxvkSparsePageTable(device, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -59,17 +75,19 @@ namespace dxvk {
|
|||||||
auto vkd = m_device->vkd();
|
auto vkd = m_device->vkd();
|
||||||
|
|
||||||
VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||||
info.size = m_physSliceStride * sliceCount;
|
info.flags = m_info.flags;
|
||||||
info.usage = m_info.usage;
|
info.size = m_physSliceStride * sliceCount;
|
||||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
info.usage = m_info.usage;
|
||||||
|
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
|
||||||
DxvkBufferHandle handle;
|
DxvkBufferHandle handle;
|
||||||
|
|
||||||
if (vkd->vkCreateBuffer(vkd->device(), &info, nullptr, &handle.buffer)) {
|
if (vkd->vkCreateBuffer(vkd->device(), &info, nullptr, &handle.buffer)) {
|
||||||
throw DxvkError(str::format(
|
throw DxvkError(str::format(
|
||||||
"DxvkBuffer: Failed to create buffer:"
|
"DxvkBuffer: Failed to create buffer:"
|
||||||
"\n size: ", info.size,
|
"\n flags: ", std::hex, info.flags,
|
||||||
"\n usage: ", info.usage));
|
"\n size: ", std::dec, info.size,
|
||||||
|
"\n usage: ", std::hex, info.usage));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query memory requirements and whether to use a dedicated allocation
|
// Query memory requirements and whether to use a dedicated allocation
|
||||||
@ -122,6 +140,30 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkBufferHandle DxvkBuffer::createSparseBuffer() const {
|
||||||
|
auto vkd = m_device->vkd();
|
||||||
|
|
||||||
|
VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||||
|
info.flags = m_info.flags;
|
||||||
|
info.size = m_info.size;
|
||||||
|
info.usage = m_info.usage;
|
||||||
|
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
|
||||||
|
DxvkBufferHandle handle = { };
|
||||||
|
|
||||||
|
if (vkd->vkCreateBuffer(vkd->device(),
|
||||||
|
&info, nullptr, &handle.buffer) != VK_SUCCESS) {
|
||||||
|
throw DxvkError(str::format(
|
||||||
|
"DxvkBuffer: Failed to create buffer:"
|
||||||
|
"\n flags: ", std::hex, info.flags,
|
||||||
|
"\n size: ", std::dec, info.size,
|
||||||
|
"\n usage: ", std::hex, info.usage));
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VkDeviceSize DxvkBuffer::computeSliceAlignment() const {
|
VkDeviceSize DxvkBuffer::computeSliceAlignment() const {
|
||||||
const auto& devInfo = m_device->properties();
|
const auto& devInfo = m_device->properties();
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "dxvk_hash.h"
|
#include "dxvk_hash.h"
|
||||||
#include "dxvk_memory.h"
|
#include "dxvk_memory.h"
|
||||||
#include "dxvk_resource.h"
|
#include "dxvk_resource.h"
|
||||||
|
#include "dxvk_sparse.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
@ -18,6 +19,9 @@ namespace dxvk {
|
|||||||
* passed to \ref DxvkDevice::createBuffer
|
* passed to \ref DxvkDevice::createBuffer
|
||||||
*/
|
*/
|
||||||
struct DxvkBufferCreateInfo {
|
struct DxvkBufferCreateInfo {
|
||||||
|
/// Buffer create flags
|
||||||
|
VkBufferCreateFlags flags = 0;
|
||||||
|
|
||||||
/// Size of the buffer, in bytes
|
/// Size of the buffer, in bytes
|
||||||
VkDeviceSize size;
|
VkDeviceSize size;
|
||||||
|
|
||||||
@ -289,7 +293,17 @@ namespace dxvk {
|
|||||||
std::unique_lock<sync::Spinlock> swapLock(m_swapMutex);
|
std::unique_lock<sync::Spinlock> swapLock(m_swapMutex);
|
||||||
m_nextSlices.push_back(slice);
|
m_nextSlices.push_back(slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Queries sparse page table
|
||||||
|
* \returns Page table, or \c nullptr for a non-sparse resource
|
||||||
|
*/
|
||||||
|
DxvkSparsePageTable* getSparsePageTable() {
|
||||||
|
return m_info.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT
|
||||||
|
? &m_sparsePageTable
|
||||||
|
: nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
DxvkDevice* m_device;
|
DxvkDevice* m_device;
|
||||||
@ -302,6 +316,8 @@ namespace dxvk {
|
|||||||
DxvkBufferSliceHandle m_physSlice;
|
DxvkBufferSliceHandle m_physSlice;
|
||||||
uint32_t m_vertexStride = 0;
|
uint32_t m_vertexStride = 0;
|
||||||
|
|
||||||
|
DxvkSparsePageTable m_sparsePageTable;
|
||||||
|
|
||||||
alignas(CACHE_LINE_SIZE)
|
alignas(CACHE_LINE_SIZE)
|
||||||
sync::Spinlock m_freeMutex;
|
sync::Spinlock m_freeMutex;
|
||||||
|
|
||||||
@ -331,6 +347,8 @@ namespace dxvk {
|
|||||||
VkDeviceSize sliceCount,
|
VkDeviceSize sliceCount,
|
||||||
bool clear) const;
|
bool clear) const;
|
||||||
|
|
||||||
|
DxvkBufferHandle createSparseBuffer() const;
|
||||||
|
|
||||||
VkDeviceSize computeSliceAlignment() const;
|
VkDeviceSize computeSliceAlignment() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user