2017-10-15 14:36:41 +02:00
|
|
|
#include "dxvk_buffer.h"
|
2017-12-16 13:21:11 +01:00
|
|
|
#include "dxvk_device.h"
|
2017-10-15 14:36:41 +02:00
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
2017-12-16 13:21:11 +01:00
|
|
|
DxvkBuffer::DxvkBuffer(
|
|
|
|
DxvkDevice* device,
|
|
|
|
const DxvkBufferCreateInfo& createInfo,
|
|
|
|
VkMemoryPropertyFlags memoryType)
|
2018-01-19 00:20:05 +01:00
|
|
|
: m_device (device),
|
|
|
|
m_info (createInfo),
|
|
|
|
m_memFlags (memoryType) {
|
2018-01-29 00:01:00 +01:00
|
|
|
// Align physical buffer slices to 256 bytes, which guarantees
|
|
|
|
// that we don't violate any Vulkan alignment requirements
|
|
|
|
m_physSliceLength = createInfo.size;
|
|
|
|
m_physSliceStride = align(createInfo.size, 256);
|
|
|
|
|
2018-03-19 02:18:44 +01:00
|
|
|
// Allocate a single buffer slice
|
|
|
|
m_physSlice = this->allocPhysicalBuffer(1)
|
|
|
|
->slice(0, m_physSliceStride);
|
2017-12-20 02:58:36 +01:00
|
|
|
}
|
2018-09-29 20:19:07 +02:00
|
|
|
|
|
|
|
|
|
|
|
DxvkBuffer::~DxvkBuffer() {
|
|
|
|
|
|
|
|
}
|
2017-12-20 02:58:36 +01:00
|
|
|
|
|
|
|
|
2018-01-19 00:20:05 +01:00
|
|
|
DxvkPhysicalBufferSlice DxvkBuffer::allocPhysicalSlice() {
|
2018-07-19 09:44:58 +02:00
|
|
|
std::unique_lock<sync::Spinlock> freeLock(m_freeMutex);
|
2018-03-19 02:18:44 +01:00
|
|
|
|
2018-03-19 14:53:59 +01:00
|
|
|
// If no slices are available, swap the two free lists.
|
|
|
|
if (m_freeSlices.size() == 0) {
|
2018-07-19 09:44:58 +02:00
|
|
|
std::unique_lock<sync::Spinlock> swapLock(m_swapMutex);
|
2018-03-19 14:53:59 +01:00
|
|
|
std::swap(m_freeSlices, m_nextSlices);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there are still no slices available, create a new
|
|
|
|
// physical buffer and add all slices to the free list.
|
|
|
|
if (m_freeSlices.size() == 0) {
|
2018-07-19 09:44:58 +02:00
|
|
|
std::unique_lock<sync::Spinlock> swapLock(m_swapMutex);
|
2018-06-22 00:27:52 +02:00
|
|
|
m_physBuffer = this->allocPhysicalBuffer(m_physSliceCount);
|
2018-01-19 00:20:05 +01:00
|
|
|
|
2018-03-19 02:18:44 +01:00
|
|
|
for (uint32_t i = 0; i < m_physSliceCount; i++) {
|
2018-06-22 00:27:52 +02:00
|
|
|
m_freeSlices.push_back(m_physBuffer->slice(
|
2018-03-19 02:18:44 +01:00
|
|
|
m_physSliceStride * i,
|
|
|
|
m_physSliceLength));
|
2018-01-19 00:20:05 +01:00
|
|
|
}
|
2018-03-19 02:18:44 +01:00
|
|
|
|
|
|
|
m_physSliceCount *= 2;
|
2018-01-19 00:20:05 +01:00
|
|
|
}
|
|
|
|
|
2018-03-19 02:18:44 +01:00
|
|
|
// Take the first slice from the queue
|
2018-03-19 14:53:59 +01:00
|
|
|
DxvkPhysicalBufferSlice result = std::move(m_freeSlices.back());
|
|
|
|
m_freeSlices.pop_back();
|
2018-03-19 02:18:44 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkBuffer::freePhysicalSlice(const DxvkPhysicalBufferSlice& slice) {
|
2018-03-19 14:53:59 +01:00
|
|
|
// Add slice to a separate free list to reduce lock contention.
|
2018-07-19 09:44:58 +02:00
|
|
|
std::unique_lock<sync::Spinlock> swapLock(m_swapMutex);
|
2018-06-22 00:27:52 +02:00
|
|
|
|
|
|
|
// Discard slices allocated from other physical buffers.
|
|
|
|
// This may make descriptor set binding more efficient.
|
|
|
|
if (m_physBuffer->handle() == slice.handle())
|
|
|
|
m_nextSlices.push_back(slice);
|
2017-12-16 13:21:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-19 00:20:05 +01:00
|
|
|
Rc<DxvkPhysicalBuffer> DxvkBuffer::allocPhysicalBuffer(VkDeviceSize sliceCount) const {
|
2018-01-29 11:44:02 +01:00
|
|
|
DxvkBufferCreateInfo createInfo = m_info;
|
2018-01-29 00:01:00 +01:00
|
|
|
createInfo.size = sliceCount * m_physSliceStride;
|
|
|
|
|
|
|
|
return m_device->allocPhysicalBuffer(createInfo, m_memFlags);
|
2017-12-16 13:21:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-21 19:50:57 +01:00
|
|
|
DxvkBufferView::DxvkBufferView(
|
|
|
|
const Rc<vk::DeviceFn>& vkd,
|
|
|
|
const Rc<DxvkBuffer>& buffer,
|
|
|
|
const DxvkBufferViewCreateInfo& info)
|
2018-03-07 13:54:28 +01:00
|
|
|
: m_vkd(vkd), m_info(info), m_buffer(buffer),
|
|
|
|
m_physView(this->createView()),
|
|
|
|
m_revision(m_buffer->m_revision) {
|
|
|
|
|
2018-01-18 18:33:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DxvkBufferView::~DxvkBufferView() {
|
2018-03-07 13:54:28 +01:00
|
|
|
|
2018-01-18 18:33:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-07 13:54:28 +01:00
|
|
|
Rc<DxvkPhysicalBufferView> DxvkBufferView::createView() {
|
|
|
|
return new DxvkPhysicalBufferView(
|
|
|
|
m_vkd, m_buffer->slice(), m_info);
|
2017-11-21 19:50:57 +01:00
|
|
|
}
|
|
|
|
|
2018-03-19 02:18:44 +01:00
|
|
|
|
|
|
|
DxvkBufferTracker:: DxvkBufferTracker() { }
|
|
|
|
DxvkBufferTracker::~DxvkBufferTracker() { }
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkBufferTracker::freeBufferSlice(
|
|
|
|
const Rc<DxvkBuffer>& buffer,
|
|
|
|
const DxvkPhysicalBufferSlice& slice) {
|
|
|
|
m_entries.push_back({ buffer, slice });
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkBufferTracker::reset() {
|
|
|
|
for (const auto& e : m_entries)
|
|
|
|
e.buffer->freePhysicalSlice(e.slice);
|
|
|
|
|
|
|
|
m_entries.clear();
|
|
|
|
}
|
|
|
|
|
2017-10-15 14:36:41 +02:00
|
|
|
}
|