[dxvk] Reimplement DxvkBuffer

Avoids the DxvkPhysicalBuffer indirection and keeps all buffer
objects alive until the DxvkBuffer itself gets destroyed.
This commit is contained in:
Philip Rebohle 2019-01-09 17:56:53 +01:00
parent cc61e38b9c
commit 8b5db80fbd
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
14 changed files with 203 additions and 228 deletions

View File

@ -98,7 +98,7 @@ namespace dxvk {
// Create the buffer and set the entire buffer slice as mapped,
// so that we only have to update it when invalidating th buffer
m_buffer = m_device->GetDXVKDevice()->createBuffer(info, memoryFlags);
m_mapped = m_buffer->slice();
m_mapped = m_buffer->getSliceHandle();
// For Stream Output buffers we need a counter
if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT)

View File

@ -79,12 +79,12 @@ namespace dxvk {
return m_soCounter;
}
DxvkPhysicalBufferSlice DiscardSlice() {
m_mapped = m_buffer->allocPhysicalSlice();
DxvkBufferSliceHandle DiscardSlice() {
m_mapped = m_buffer->allocSlice();
return m_mapped;
}
DxvkPhysicalBufferSlice GetMappedSlice() const {
DxvkBufferSliceHandle GetMappedSlice() const {
return m_mapped;
}
@ -99,7 +99,7 @@ namespace dxvk {
Rc<DxvkBuffer> m_buffer;
DxvkBufferSlice m_soCounter;
DxvkPhysicalBufferSlice m_mapped;
DxvkBufferSliceHandle m_mapped;
D3D10Buffer m_d3d10;

View File

@ -181,9 +181,9 @@ namespace dxvk {
if (pBuffer->Desc()->Usage == D3D11_USAGE_DYNAMIC && m_csFlags.test(DxvkCsChunkFlag::SingleUse)) {
// For resources that cannot be written by the GPU,
// we may write to the buffer resource directly and
// just swap in the physical buffer slice as needed.
pMapEntry->BufferSlice = buffer->allocPhysicalSlice();
pMapEntry->MapPointer = pMapEntry->BufferSlice.mapPtr(0);
// just swap in the buffer slice as needed.
pMapEntry->BufferSlice = buffer->allocSlice();
pMapEntry->MapPointer = pMapEntry->BufferSlice.mapPtr;
} else {
// For GPU-writable resources, we need a data slice
// to perform the update operation at execution time.
@ -257,8 +257,8 @@ namespace dxvk {
cDstBuffer = pBuffer->GetBuffer(),
cDataSlice = pMapEntry->DataSlice
] (DxvkContext* ctx) {
DxvkPhysicalBufferSlice slice = cDstBuffer->allocPhysicalSlice();
std::memcpy(slice.mapPtr(0), cDataSlice.ptr(), cDataSlice.length());
DxvkBufferSliceHandle slice = cDstBuffer->allocSlice();
std::memcpy(slice.mapPtr, cDataSlice.ptr(), cDataSlice.length());
ctx->invalidateBuffer(cDstBuffer, slice);
});
}

View File

@ -17,7 +17,7 @@ namespace dxvk {
UINT RowPitch;
UINT DepthPitch;
DxvkDataSlice DataSlice;
DxvkPhysicalBufferSlice BufferSlice;
DxvkBufferSliceHandle BufferSlice;
void* MapPointer;
};

View File

@ -351,32 +351,32 @@ namespace dxvk {
// Allocate a new backing slice for the buffer and set
// it as the 'new' mapped slice. This assumes that the
// only way to invalidate a buffer is by mapping it.
auto physicalSlice = pResource->DiscardSlice();
pMappedResource->pData = physicalSlice.mapPtr(0);
auto physSlice = pResource->DiscardSlice();
pMappedResource->pData = physSlice.mapPtr;
pMappedResource->RowPitch = pResource->Desc()->ByteWidth;
pMappedResource->DepthPitch = pResource->Desc()->ByteWidth;
EmitCs([
cBuffer = std::move(buffer),
cPhysicalSlice = std::move(physicalSlice)
cBuffer = std::move(buffer),
cBufferSlice = std::move(physSlice)
] (DxvkContext* ctx) {
ctx->invalidateBuffer(cBuffer, cPhysicalSlice);
ctx->invalidateBuffer(cBuffer, cBufferSlice);
});
return S_OK;
} else {
// Wait until the resource is no longer in use
if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) {
if (!WaitForResource(buffer->resource(), MapFlags))
if (!WaitForResource(buffer, MapFlags))
return DXGI_ERROR_WAS_STILL_DRAWING;
}
// Use map pointer from previous map operation. This
// way we don't have to synchronize with the CS thread
// if the map mode is D3D11_MAP_WRITE_NO_OVERWRITE.
DxvkPhysicalBufferSlice physicalSlice = pResource->GetMappedSlice();
DxvkBufferSliceHandle physSlice = pResource->GetMappedSlice();
pMappedResource->pData = physicalSlice.mapPtr(0);
pMappedResource->pData = physSlice.mapPtr;
pMappedResource->RowPitch = pResource->Desc()->ByteWidth;
pMappedResource->DepthPitch = pResource->Desc()->ByteWidth;
return S_OK;
@ -449,10 +449,10 @@ namespace dxvk {
cImageBuffer, 0, cImage, layers, offset, extent, cFormat);
});
WaitForResource(mappedBuffer->resource(), 0);
WaitForResource(mappedBuffer, 0);
DxvkPhysicalBufferSlice physicalSlice = mappedBuffer->slice();
pMappedResource->pData = physicalSlice.mapPtr(0);
DxvkBufferSliceHandle physSlice = mappedBuffer->getSliceHandle();
pMappedResource->pData = physSlice.mapPtr;
pMappedResource->RowPitch = packFormatInfo->elementSize * levelExtent.width;
pMappedResource->DepthPitch = packFormatInfo->elementSize * levelExtent.width * levelExtent.height;
return S_OK;
@ -460,18 +460,18 @@ namespace dxvk {
VkExtent3D levelExtent = mappedImage->mipLevelExtent(subresource.mipLevel);
VkExtent3D blockCount = util::computeBlockCount(levelExtent, formatInfo->blockSize);
DxvkPhysicalBufferSlice physicalSlice;
DxvkBufferSliceHandle physSlice;
if (MapType == D3D11_MAP_WRITE_DISCARD) {
// We do not have to preserve the contents of the
// buffer if the entire image gets discarded.
physicalSlice = mappedBuffer->allocPhysicalSlice();
physSlice = mappedBuffer->allocSlice();
EmitCs([
cImageBuffer = mappedBuffer,
cPhysicalSlice = physicalSlice
cImageBuffer = mappedBuffer,
cBufferSlice = physSlice
] (DxvkContext* ctx) {
ctx->invalidateBuffer(cImageBuffer, cPhysicalSlice);
ctx->invalidateBuffer(cImageBuffer, cBufferSlice);
});
} else {
// When using any map mode which requires the image contents
@ -495,12 +495,12 @@ namespace dxvk {
});
}
WaitForResource(mappedBuffer->resource(), 0);
physicalSlice = mappedBuffer->slice();
WaitForResource(mappedBuffer, 0);
physSlice = mappedBuffer->getSliceHandle();
}
// Set up map pointer. Data is tightly packed within the mapped buffer.
pMappedResource->pData = physicalSlice.mapPtr(0);
pMappedResource->pData = physSlice.mapPtr;
pMappedResource->RowPitch = formatInfo->elementSize * blockCount.width;
pMappedResource->DepthPitch = formatInfo->elementSize * blockCount.width * blockCount.height;
return S_OK;

View File

@ -6,27 +6,37 @@ namespace dxvk {
DxvkBuffer::DxvkBuffer(
DxvkDevice* device,
const DxvkBufferCreateInfo& createInfo,
VkMemoryPropertyFlags memoryType)
DxvkMemoryAllocator& memAlloc,
VkMemoryPropertyFlags memFlags)
: m_device (device),
m_info (createInfo),
m_memFlags (memoryType) {
// Align physical buffer slices to 256 bytes, which guarantees
// that we don't violate any Vulkan alignment requirements
m_memAlloc (&memAlloc),
m_memFlags (memFlags) {
// Align 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);
// Allocate a single buffer slice
m_physSlice = this->allocPhysicalBuffer(1)
->slice(0, m_physSliceStride);
m_buffer = allocBuffer(1);
m_physSlice.handle = m_buffer.buffer;
m_physSlice.offset = 0;
m_physSlice.length = m_physSliceLength;
m_physSlice.mapPtr = m_buffer.memory.mapPtr(0);
}
DxvkBuffer::~DxvkBuffer() {
auto vkd = m_device->vkd();
for (const auto& buffer : m_buffers)
vkd->vkDestroyBuffer(vkd->device(), buffer.buffer, nullptr);
vkd->vkDestroyBuffer(vkd->device(), m_buffer.buffer, nullptr);
}
DxvkPhysicalBufferSlice DxvkBuffer::allocPhysicalSlice() {
DxvkBufferSliceHandle DxvkBuffer::allocSlice() {
std::unique_lock<sync::Spinlock> freeLock(m_freeMutex);
// If no slices are available, swap the two free lists.
@ -34,47 +44,99 @@ namespace dxvk {
std::unique_lock<sync::Spinlock> swapLock(m_swapMutex);
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.
// backing buffer and add all slices to the free list.
if (m_freeSlices.size() == 0) {
std::unique_lock<sync::Spinlock> swapLock(m_swapMutex);
m_physBuffer = this->allocPhysicalBuffer(m_physSliceCount);
DxvkBufferHandle handle = allocBuffer(m_physSliceCount);
for (uint32_t i = 0; i < m_physSliceCount; i++) {
m_freeSlices.push_back(m_physBuffer->slice(
m_physSliceStride * i,
m_physSliceLength));
DxvkBufferSliceHandle slice;
slice.handle = handle.buffer;
slice.offset = m_physSliceStride * i;
slice.length = m_physSliceLength;
slice.mapPtr = handle.memory.mapPtr(slice.offset);
m_freeSlices.push_back(slice);
}
m_buffers.push_back(std::move(handle));
m_physSliceCount *= 2;
}
// Take the first slice from the queue
DxvkPhysicalBufferSlice result = std::move(m_freeSlices.back());
DxvkBufferSliceHandle result = std::move(m_freeSlices.back());
m_freeSlices.pop_back();
return result;
}
void DxvkBuffer::freePhysicalSlice(const DxvkPhysicalBufferSlice& slice) {
void DxvkBuffer::freeSlice(const DxvkBufferSliceHandle& slice) {
// Add slice to a separate free list to reduce lock contention.
std::unique_lock<sync::Spinlock> swapLock(m_swapMutex);
m_nextSlices.push_back(slice);
}
DxvkBufferHandle DxvkBuffer::allocBuffer(VkDeviceSize sliceCount) const {
auto vkd = m_device->vkd();
// 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);
}
Rc<DxvkPhysicalBuffer> DxvkBuffer::allocPhysicalBuffer(VkDeviceSize sliceCount) const {
DxvkBufferCreateInfo createInfo = m_info;
createInfo.size = sliceCount * m_physSliceStride;
VkBufferCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
info.pNext = nullptr;
info.flags = 0;
info.size = m_physSliceStride * sliceCount;
info.usage = m_info.usage;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
info.queueFamilyIndexCount = 0;
info.pQueueFamilyIndices = nullptr;
return m_device->allocPhysicalBuffer(createInfo, m_memFlags);
DxvkBufferHandle handle;
if (vkd->vkCreateBuffer(vkd->device(),
&info, nullptr, &handle.buffer) != VK_SUCCESS) {
throw DxvkError(str::format(
"DxvkBuffer: Failed to create buffer:"
"\n size: ", info.size,
"\n usage: ", info.usage));
}
VkMemoryDedicatedRequirementsKHR dedicatedRequirements;
dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR;
dedicatedRequirements.pNext = VK_NULL_HANDLE;
dedicatedRequirements.prefersDedicatedAllocation = VK_FALSE;
dedicatedRequirements.requiresDedicatedAllocation = VK_FALSE;
VkMemoryRequirements2KHR memReq;
memReq.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR;
memReq.pNext = &dedicatedRequirements;
VkBufferMemoryRequirementsInfo2KHR memReqInfo;
memReqInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR;
memReqInfo.buffer = handle.buffer;
memReqInfo.pNext = VK_NULL_HANDLE;
VkMemoryDedicatedAllocateInfoKHR dedMemoryAllocInfo;
dedMemoryAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR;
dedMemoryAllocInfo.pNext = VK_NULL_HANDLE;
dedMemoryAllocInfo.buffer = handle.buffer;
dedMemoryAllocInfo.image = VK_NULL_HANDLE;
vkd->vkGetBufferMemoryRequirements2KHR(
vkd->device(), &memReqInfo, &memReq);
bool useDedicated = dedicatedRequirements.prefersDedicatedAllocation;
handle.memory = m_memAlloc->alloc(&memReq.memoryRequirements,
useDedicated ? &dedMemoryAllocInfo : nullptr, m_memFlags);
if (vkd->vkBindBufferMemory(vkd->device(), handle.buffer,
handle.memory.memory(), handle.memory.offset()) != VK_SUCCESS)
throw DxvkError("DxvkBuffer: Failed to bind device memory");
return handle;
}
DxvkBufferView::DxvkBufferView(
const Rc<vk::DeviceFn>& vkd,
@ -132,7 +194,7 @@ namespace dxvk {
m_bufferSlice = m_buffer->getSliceHandle();
auto entry = m_views.find(m_bufferSlice);
if (entry != m_views.end()) {
m_bufferView = entry->second;
} else {
@ -147,15 +209,15 @@ namespace dxvk {
void DxvkBufferTracker::freeBufferSlice(
const Rc<DxvkBuffer>& buffer,
const DxvkPhysicalBufferSlice& slice) {
const Rc<DxvkBuffer>& buffer,
const DxvkBufferSliceHandle& slice) {
m_entries.push_back({ buffer, slice });
}
void DxvkBufferTracker::reset() {
for (const auto& e : m_entries)
e.buffer->freePhysicalSlice(e.slice);
e.buffer->freeSlice(e.slice);
m_entries.clear();
}

View File

@ -8,6 +8,18 @@
namespace dxvk {
/**
* \brief Buffer info
*
* Stores a Vulkan buffer handle and the
* memory object that is bound to the buffer.
*/
struct DxvkBufferHandle {
VkBuffer buffer = VK_NULL_HANDLE;
DxvkMemory memory;
};
/**
* \brief Buffer slice info
*
@ -44,14 +56,15 @@ namespace dxvk {
* unformatted data. Can be accessed by the host
* if allocated on an appropriate memory type.
*/
class DxvkBuffer : public RcObject {
class DxvkBuffer : public DxvkResource {
friend class DxvkBufferView;
public:
DxvkBuffer(
DxvkDevice* device,
const DxvkBufferCreateInfo& createInfo,
VkMemoryPropertyFlags memoryType);
DxvkMemoryAllocator& memAlloc,
VkMemoryPropertyFlags memFlags);
~DxvkBuffer();
@ -84,33 +97,15 @@ namespace dxvk {
* \returns Pointer to mapped memory region
*/
void* mapPtr(VkDeviceSize offset) const {
return m_physSlice.mapPtr(offset);
return reinterpret_cast<char*>(m_physSlice.mapPtr) + offset;
}
/**
* \brief Checks whether the buffer is in use
*
* Returns \c true if the underlying buffer resource
* is in use. If it is, it should not be accessed by
* the host for reading or writing, but reallocating
* the buffer is a valid strategy to overcome this.
* \returns \c true if the buffer is in use
*/
bool isInUse() const {
return m_physSlice.resource()->isInUse();
}
/**
* \brief Retrieves slice handle
* \returns Buffer slice handle
*/
DxvkBufferSliceHandle getSliceHandle() const {
DxvkBufferSliceHandle result;
result.handle = m_physSlice.handle();
result.offset = m_physSlice.offset();
result.length = m_physSlice.length();
result.mapPtr = m_physSlice.mapPtr(0);
return result;
return m_physSlice;
}
/**
@ -122,10 +117,10 @@ namespace dxvk {
*/
DxvkBufferSliceHandle getSliceHandle(VkDeviceSize offset, VkDeviceSize length) const {
DxvkBufferSliceHandle result;
result.handle = m_physSlice.handle();
result.offset = m_physSlice.offset() + offset;
result.handle = m_physSlice.handle;
result.offset = m_physSlice.offset + offset;
result.length = length;
result.mapPtr = m_physSlice.mapPtr(offset);
result.mapPtr = mapPtr(offset);
return result;
}
@ -138,8 +133,8 @@ namespace dxvk {
*/
DxvkDescriptorInfo getDescriptor(VkDeviceSize offset, VkDeviceSize length) const {
DxvkDescriptorInfo result;
result.buffer.buffer = m_physSlice.handle();
result.buffer.offset = m_physSlice.offset() + offset;
result.buffer.buffer = m_physSlice.handle;
result.buffer.offset = m_physSlice.offset + offset;
result.buffer.range = length;
return result;
}
@ -148,43 +143,10 @@ namespace dxvk {
* \brief Retrieves dynamic offset
*
* \param [in] offset Offset into the buffer
* \returns Physical buffer slice offset
* \returns Offset for dynamic descriptors
*/
VkDeviceSize getDynamicOffset(VkDeviceSize offset) const {
return m_physSlice.offset() + offset;
}
/**
* \brief Underlying buffer resource
*
* Use this for lifetime tracking.
* \returns The resource object
*/
Rc<DxvkResource> resource() const {
return m_physSlice.resource();
}
/**
* \brief Physical buffer slice
*
* Retrieves a slice into the physical
* buffer which backs this buffer.
* \returns The backing slice
*/
DxvkPhysicalBufferSlice slice() const {
return m_physSlice;
}
/**
* \brief Physical buffer sub slice
*
* Retrieves a sub slice into the backing buffer.
* \param [in] offset Offset into the buffer
* \param [in] length Length of the slice
* \returns The sub slice
*/
DxvkPhysicalBufferSlice subSlice(VkDeviceSize offset, VkDeviceSize length) const {
return m_physSlice.subSlice(offset, length);
return m_physSlice.offset + offset;
}
/**
@ -197,10 +159,8 @@ namespace dxvk {
* \param [in] slice The new backing resource
* \returns Previous buffer slice
*/
DxvkPhysicalBufferSlice rename(const DxvkPhysicalBufferSlice& slice) {
DxvkPhysicalBufferSlice prevSlice = std::move(m_physSlice);
m_physSlice = slice;
return prevSlice;
DxvkBufferSliceHandle rename(const DxvkBufferSliceHandle& slice) {
return std::exchange(m_physSlice, slice);
}
/**
@ -226,45 +186,47 @@ namespace dxvk {
}
/**
* \brief Allocates new physical resource
* \returns The new backing buffer slice
* \brief Allocates new buffer slice
* \returns The new buffer slice
*/
DxvkPhysicalBufferSlice allocPhysicalSlice();
DxvkBufferSliceHandle allocSlice();
/**
* \brief Frees a physical buffer slice
* \brief Frees a buffer slice
*
* Marks the slice as free so that it can be used for
* subsequent allocations. Called automatically when
* the slice is no longer needed by the GPU.
* \param [in] slice The buffer slice to free
*/
void freePhysicalSlice(
const DxvkPhysicalBufferSlice& slice);
void freeSlice(
const DxvkBufferSliceHandle& slice);
private:
DxvkDevice* m_device;
DxvkBufferCreateInfo m_info;
DxvkMemoryAllocator* m_memAlloc;
VkMemoryPropertyFlags m_memFlags;
DxvkPhysicalBufferSlice m_physSlice;
DxvkBufferHandle m_buffer;
DxvkBufferSliceHandle m_physSlice;
uint32_t m_vertexStride = 0;
sync::Spinlock m_freeMutex;
sync::Spinlock m_swapMutex;
std::vector<DxvkPhysicalBufferSlice> m_freeSlices;
std::vector<DxvkPhysicalBufferSlice> m_nextSlices;
std::vector<DxvkBufferHandle> m_buffers;
std::vector<DxvkBufferSliceHandle> m_freeSlices;
std::vector<DxvkBufferSliceHandle> m_nextSlices;
VkDeviceSize m_physSliceLength = 0;
VkDeviceSize m_physSliceStride = 0;
VkDeviceSize m_physSliceCount = 2;
Rc<DxvkPhysicalBuffer> m_physBuffer;
Rc<DxvkPhysicalBuffer> allocPhysicalBuffer(
VkDeviceSize sliceCount) const;
DxvkBufferHandle allocBuffer(
VkDeviceSize sliceCount) const;
};
@ -365,20 +327,6 @@ namespace dxvk {
: DxvkBufferSliceHandle();
}
/**
* \brief Physical slice
*
* Retrieves the physical slice that currently
* backs the virtual slice. This may change
* when the virtual buffer gets invalidated.
* \returns The physical buffer slice
*/
DxvkPhysicalBufferSlice physicalSlice() const {
return m_buffer != nullptr
? m_buffer->subSlice(m_offset, m_length)
: DxvkPhysicalBufferSlice();
}
/**
* \brief Retrieves descriptor info
* \returns Buffer slice descriptor
@ -409,14 +357,6 @@ namespace dxvk {
: nullptr;
}
/**
* \brief Resource pointer
* \returns Resource pointer
*/
Rc<DxvkResource> resource() const {
return m_buffer->resource();
}
/**
* \brief Checks whether two slices are equal
*
@ -502,14 +442,6 @@ namespace dxvk {
const DxvkBufferCreateInfo& bufferInfo() const {
return m_buffer->info();
}
/**
* \brief Backing buffer resource
* \returns Backing buffer resource
*/
Rc<DxvkResource> bufferResource() const {
return m_buffer->resource();
}
/**
* \brief Retrieves buffer slice handle
@ -581,16 +513,16 @@ namespace dxvk {
~DxvkBufferTracker();
void freeBufferSlice(
const Rc<DxvkBuffer>& buffer,
const DxvkPhysicalBufferSlice& slice);
const Rc<DxvkBuffer>& buffer,
const DxvkBufferSliceHandle& slice);
void reset();
private:
struct Entry {
Rc<DxvkBuffer> buffer;
DxvkPhysicalBufferSlice slice;
Rc<DxvkBuffer> buffer;
DxvkBufferSliceHandle slice;
};
std::vector<Entry> m_entries;

View File

@ -108,17 +108,17 @@ namespace dxvk {
void endRecording();
/**
* \brief Frees physical buffer slice
* \brief Frees buffer slice
*
* After the command buffer execution has finished,
* the given physical slice will be released to the
* the given buffer slice will be released to the
* virtual buffer object so that it can be reused.
* \param [in] buffer The virtual buffer object
* \param [in] slice The physical buffer slice
* \param [in] slice The buffer slice handle
*/
void freePhysicalBufferSlice(
void freeBufferSlice(
const Rc<DxvkBuffer>& buffer,
const DxvkPhysicalBufferSlice& slice) {
const DxvkBufferSliceHandle& slice) {
m_bufferTracker.freeBufferSlice(buffer, slice);
}

View File

@ -276,7 +276,7 @@ namespace dxvk {
buffer->info().stages,
buffer->info().access);
m_cmd->trackResource(buffer->resource());
m_cmd->trackResource(buffer);
}
@ -347,7 +347,7 @@ namespace dxvk {
bufferView->bufferInfo().access);
m_cmd->trackResource(bufferView);
m_cmd->trackResource(bufferView->bufferResource());
m_cmd->trackResource(bufferView->buffer());
}
@ -657,8 +657,8 @@ namespace dxvk {
dstBuffer->info().stages,
dstBuffer->info().access);
m_cmd->trackResource(dstBuffer->resource());
m_cmd->trackResource(srcBuffer->resource());
m_cmd->trackResource(dstBuffer);
m_cmd->trackResource(srcBuffer);
}
@ -761,7 +761,7 @@ namespace dxvk {
srcBuffer->info().access);
m_cmd->trackResource(dstImage);
m_cmd->trackResource(srcBuffer->resource());
m_cmd->trackResource(srcBuffer);
}
@ -920,7 +920,7 @@ namespace dxvk {
dstBuffer->info().access);
m_cmd->trackResource(srcImage);
m_cmd->trackResource(dstBuffer->resource());
m_cmd->trackResource(dstBuffer);
}
@ -1030,14 +1030,14 @@ namespace dxvk {
m_cmd->trackResource(sView);
m_cmd->trackResource(srcImage);
m_cmd->trackResource(dstBuffer->resource());
m_cmd->trackResource(dstBuffer);
}
void DxvkContext::discardBuffer(
const Rc<DxvkBuffer>& buffer) {
if (m_barriers.isBufferDirty(buffer->getSliceHandle(), DxvkAccess::Write))
this->invalidateBuffer(buffer, buffer->allocPhysicalSlice());
this->invalidateBuffer(buffer, buffer->allocSlice());
}
@ -1343,10 +1343,10 @@ namespace dxvk {
void DxvkContext::invalidateBuffer(
const Rc<DxvkBuffer>& buffer,
const DxvkPhysicalBufferSlice& slice) {
const DxvkBufferSliceHandle& slice) {
// Allocate new backing resource
DxvkPhysicalBufferSlice prevSlice = buffer->rename(slice);
m_cmd->freePhysicalBufferSlice(buffer, prevSlice);
DxvkBufferSliceHandle prevSlice = buffer->rename(slice);
m_cmd->freeBufferSlice(buffer, prevSlice);
// We also need to update all bindings that the buffer
// may be bound to either directly or through views.
@ -1372,7 +1372,7 @@ namespace dxvk {
if (usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) {
if (prevSlice.handle() != slice.handle()) {
if (prevSlice.handle != slice.handle) {
m_flags.set(DxvkContextFlag::GpDirtyResources,
DxvkContextFlag::CpDirtyResources);
} else {
@ -1473,7 +1473,7 @@ namespace dxvk {
buffer->info().stages,
buffer->info().access);
m_cmd->trackResource(buffer->resource());
m_cmd->trackResource(buffer);
}
@ -2464,7 +2464,7 @@ namespace dxvk {
ctrOffsets[i] = physSlice.offset;
if (physSlice.handle != VK_NULL_HANDLE)
m_cmd->trackResource(m_state.xfb.counters[i].resource());
m_cmd->trackResource(m_state.xfb.counters[i].buffer());
}
m_cmd->cmdBeginTransformFeedback(
@ -2490,7 +2490,7 @@ namespace dxvk {
ctrOffsets[i] = physSlice.offset;
if (physSlice.handle != VK_NULL_HANDLE)
m_cmd->trackResource(m_state.xfb.counters[i].resource());
m_cmd->trackResource(m_state.xfb.counters[i].buffer());
}
m_queries.endQueries(m_cmd,
@ -2767,7 +2767,7 @@ namespace dxvk {
m_descInfos[i].texelBuffer = res.bufferView->handle();
m_cmd->trackResource(res.bufferView);
m_cmd->trackResource(res.bufferView->bufferResource());
m_cmd->trackResource(res.bufferView->buffer());
} else {
updatePipelineState |= bindMask.setUnbound(i);
m_descInfos[i].texelBuffer = m_device->dummyBufferViewDescriptor();
@ -2779,7 +2779,7 @@ namespace dxvk {
updatePipelineState |= bindMask.setBound(i);
m_descInfos[i] = res.bufferSlice.getDescriptor();
m_cmd->trackResource(res.bufferSlice.resource());
m_cmd->trackResource(res.bufferSlice.buffer());
} else {
updatePipelineState |= bindMask.setUnbound(i);
m_descInfos[i].buffer = m_device->dummyBufferDescriptor();
@ -2792,7 +2792,7 @@ namespace dxvk {
m_descInfos[i] = res.bufferSlice.getDescriptor();
m_descInfos[i].buffer.offset = 0;
m_cmd->trackResource(res.bufferSlice.resource());
m_cmd->trackResource(res.bufferSlice.buffer());
} else {
updatePipelineState |= bindMask.setUnbound(i);
m_descInfos[i].buffer = m_device->dummyBufferDescriptor();
@ -2887,7 +2887,7 @@ namespace dxvk {
bufferInfo.buffer.offset,
m_state.vi.indexType);
m_cmd->trackResource(
m_state.vi.indexBuffer.resource());
m_state.vi.indexBuffer.buffer());
} else {
m_cmd->cmdBindIndexBuffer(
m_device->dummyBufferHandle(),
@ -2920,7 +2920,7 @@ namespace dxvk {
bindingMask |= 1u << binding;
m_cmd->trackResource(m_state.vi.vertexBuffers[binding].resource());
m_cmd->trackResource(m_state.vi.vertexBuffers[binding].buffer());
}
}
@ -2975,7 +2975,7 @@ namespace dxvk {
auto buffer = m_state.xfb.buffers[i].buffer();
buffer->setXfbVertexStride(gsOptions.xfbStrides[i]);
m_cmd->trackResource(buffer->resource());
m_cmd->trackResource(buffer);
}
}
@ -3291,7 +3291,7 @@ namespace dxvk {
m_flags.clr(DxvkContextFlag::DirtyDrawBuffer);
if (m_state.id.argBuffer.defined())
m_cmd->trackResource(m_state.id.argBuffer.resource());
m_cmd->trackResource(m_state.id.argBuffer.buffer());
}
}

View File

@ -575,11 +575,11 @@ namespace dxvk {
* \warning If the buffer is used by another context,
* invalidating it will result in undefined behaviour.
* \param [in] buffer The buffer to invalidate
* \param [in] slice New physical buffer slice
* \param [in] slice New buffer slice handle
*/
void invalidateBuffer(
const Rc<DxvkBuffer>& buffer,
const DxvkPhysicalBufferSlice& slice);
const DxvkBufferSliceHandle& slice);
/**
* \brief Resolves a multisampled image resource

View File

@ -52,14 +52,6 @@ namespace dxvk {
}
Rc<DxvkPhysicalBuffer> DxvkDevice::allocPhysicalBuffer(
const DxvkBufferCreateInfo& createInfo,
VkMemoryPropertyFlags memoryType) {
return new DxvkPhysicalBuffer(m_vkd,
createInfo, *m_memory, memoryType);
}
Rc<DxvkStagingBuffer> DxvkDevice::allocStagingBuffer(VkDeviceSize size) {
// In case we need a standard-size staging buffer, try
// to recycle an old one that has been returned earlier
@ -155,7 +147,7 @@ namespace dxvk {
Rc<DxvkBuffer> DxvkDevice::createBuffer(
const DxvkBufferCreateInfo& createInfo,
VkMemoryPropertyFlags memoryType) {
return new DxvkBuffer(this, createInfo, memoryType);
return new DxvkBuffer(this, createInfo, *m_memory, memoryType);
}

View File

@ -139,17 +139,6 @@ namespace dxvk {
*/
DxvkDeviceOptions options() const;
/**
* \brief Allocates a physical buffer
*
* \param [in] createInfo Buffer create info
* \param [in] memoryType Memory property flags
* \returns The buffer resource object
*/
Rc<DxvkPhysicalBuffer> allocPhysicalBuffer(
const DxvkBufferCreateInfo& createInfo,
VkMemoryPropertyFlags memoryType);
/**
* \brief Allocates a staging buffer
*

View File

@ -103,8 +103,8 @@ namespace dxvk::hud {
void Hud::updateUniformBuffer(const Rc<DxvkContext>& ctx, const HudUniformData& data) {
auto slice = m_uniformBuffer->allocPhysicalSlice();
std::memcpy(slice.mapPtr(0), &data, sizeof(data));
auto slice = m_uniformBuffer->allocSlice();
std::memcpy(slice.mapPtr, &data, sizeof(data));
ctx->invalidateBuffer(m_uniformBuffer, slice);
}

View File

@ -26,7 +26,7 @@ namespace dxvk::hud {
void HudRenderer::beginFrame(const Rc<DxvkContext>& context) {
auto vertexSlice = m_vertexBuffer->allocPhysicalSlice();
auto vertexSlice = m_vertexBuffer->allocSlice();
context->invalidateBuffer(m_vertexBuffer, vertexSlice);
const std::array<DxvkVertexAttribute, 3> ilAttributes = {{