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,6 +16,7 @@ namespace dxvk {
|
||||
m_memAlloc (&memAlloc),
|
||||
m_memFlags (memFlags),
|
||||
m_shaderStages (util::shaderStages(createInfo.stages)) {
|
||||
if (!(m_info.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)) {
|
||||
// Align slices so that we don't violate any alignment
|
||||
// requirements imposed by the Vulkan device/driver
|
||||
VkDeviceSize sliceAlignment = computeSliceAlignment();
|
||||
@ -35,14 +36,29 @@ namespace dxvk {
|
||||
// we expect the client api to initialize the first slice.
|
||||
m_buffer = allocBuffer(m_physSliceCount, m_physSliceCount > 1);
|
||||
|
||||
DxvkBufferSliceHandle slice;
|
||||
slice.handle = m_buffer.buffer;
|
||||
slice.offset = 0;
|
||||
slice.length = m_physSliceLength;
|
||||
slice.mapPtr = m_buffer.memory.mapPtr(0);
|
||||
m_physSlice.handle = m_buffer.buffer;
|
||||
m_physSlice.offset = 0;
|
||||
m_physSlice.length = m_physSliceLength;
|
||||
m_physSlice.mapPtr = m_buffer.memory.mapPtr(0);
|
||||
|
||||
m_physSlice = slice;
|
||||
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,6 +75,7 @@ namespace dxvk {
|
||||
auto vkd = m_device->vkd();
|
||||
|
||||
VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||
info.flags = m_info.flags;
|
||||
info.size = m_physSliceStride * sliceCount;
|
||||
info.usage = m_info.usage;
|
||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
@ -68,8 +85,9 @@ namespace dxvk {
|
||||
if (vkd->vkCreateBuffer(vkd->device(), &info, nullptr, &handle.buffer)) {
|
||||
throw DxvkError(str::format(
|
||||
"DxvkBuffer: Failed to create buffer:"
|
||||
"\n size: ", info.size,
|
||||
"\n usage: ", info.usage));
|
||||
"\n flags: ", std::hex, info.flags,
|
||||
"\n size: ", std::dec, info.size,
|
||||
"\n usage: ", std::hex, info.usage));
|
||||
}
|
||||
|
||||
// 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 {
|
||||
const auto& devInfo = m_device->properties();
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "dxvk_hash.h"
|
||||
#include "dxvk_memory.h"
|
||||
#include "dxvk_resource.h"
|
||||
#include "dxvk_sparse.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
@ -18,6 +19,9 @@ namespace dxvk {
|
||||
* passed to \ref DxvkDevice::createBuffer
|
||||
*/
|
||||
struct DxvkBufferCreateInfo {
|
||||
/// Buffer create flags
|
||||
VkBufferCreateFlags flags = 0;
|
||||
|
||||
/// Size of the buffer, in bytes
|
||||
VkDeviceSize size;
|
||||
|
||||
@ -290,6 +294,16 @@ namespace dxvk {
|
||||
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:
|
||||
|
||||
DxvkDevice* m_device;
|
||||
@ -302,6 +316,8 @@ namespace dxvk {
|
||||
DxvkBufferSliceHandle m_physSlice;
|
||||
uint32_t m_vertexStride = 0;
|
||||
|
||||
DxvkSparsePageTable m_sparsePageTable;
|
||||
|
||||
alignas(CACHE_LINE_SIZE)
|
||||
sync::Spinlock m_freeMutex;
|
||||
|
||||
@ -331,6 +347,8 @@ namespace dxvk {
|
||||
VkDeviceSize sliceCount,
|
||||
bool clear) const;
|
||||
|
||||
DxvkBufferHandle createSparseBuffer() const;
|
||||
|
||||
VkDeviceSize computeSliceAlignment() const;
|
||||
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user