mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-18 02:52:10 +01:00
[dxvk] Optimized buffer renaming
Helps applications which frequently update buffers through either Map()/Unmap() or UpdateSubresource.
This commit is contained in:
parent
ec0ff35b96
commit
a0acbeec72
@ -7,21 +7,50 @@ namespace dxvk {
|
||||
DxvkDevice* device,
|
||||
const DxvkBufferCreateInfo& createInfo,
|
||||
VkMemoryPropertyFlags memoryType)
|
||||
: m_device (device),
|
||||
m_info (createInfo),
|
||||
m_memFlags(memoryType),
|
||||
m_resource(allocateResource()) {
|
||||
: m_device (device),
|
||||
m_info (createInfo),
|
||||
m_memFlags (memoryType) {
|
||||
// Initialize a single backing bufer with one slice
|
||||
m_physBuffers[0] = this->allocPhysicalBuffer(1);
|
||||
m_physSlice = this->allocPhysicalSlice();
|
||||
}
|
||||
|
||||
|
||||
void DxvkBuffer::rename(
|
||||
const DxvkPhysicalBufferSlice& slice) {
|
||||
m_physSlice = slice;
|
||||
}
|
||||
|
||||
|
||||
DxvkPhysicalBufferSlice DxvkBuffer::allocPhysicalSlice() {
|
||||
if (m_physSliceId >= m_physBuffers[m_physBufferId]->sliceCount()) {
|
||||
m_physBufferId = (m_physBufferId + 1) % m_physBuffers.size();
|
||||
m_physSliceId = 0;
|
||||
|
||||
if ((m_physBuffers[m_physBufferId] == nullptr)
|
||||
|| (m_physBuffers[m_physBufferId]->sliceCount() < m_physSliceCount)) {
|
||||
// Make sure that all buffers have the same size. If we don't do this,
|
||||
// one of the physical buffers may grow indefinitely while the others
|
||||
// remain small, depending on the usage pattern of the application.
|
||||
m_physBuffers[m_physBufferId] = this->allocPhysicalBuffer(m_physSliceCount);
|
||||
} else if (m_physBuffers[m_physBufferId]->isInUse()) {
|
||||
// Allocate a new physical buffer if the current one is still in use.
|
||||
// This also indicates that the buffer gets updated frequently, so we
|
||||
// will double the size of the physical buffers to accomodate for it.
|
||||
if (m_physBufferId == 0)
|
||||
m_physSliceCount *= 2;
|
||||
|
||||
m_physBuffers[m_physBufferId] = this->allocPhysicalBuffer(m_physSliceCount);
|
||||
}
|
||||
}
|
||||
|
||||
return m_physBuffers[m_physBufferId]->slice(m_physSliceId++);
|
||||
}
|
||||
|
||||
|
||||
void DxvkBuffer::renameResource(const DxvkPhysicalBufferSlice& resource) {
|
||||
m_resource = resource;
|
||||
}
|
||||
|
||||
|
||||
DxvkPhysicalBufferSlice DxvkBuffer::allocateResource() {
|
||||
return m_device->allocBufferResource(m_info, m_memFlags)->slice(0);
|
||||
Rc<DxvkPhysicalBuffer> DxvkBuffer::allocPhysicalBuffer(VkDeviceSize sliceCount) const {
|
||||
TRACE(this, sliceCount);
|
||||
return m_device->allocPhysicalBuffer(m_info, sliceCount, m_memFlags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -49,7 +49,7 @@ namespace dxvk {
|
||||
* \returns Pointer to mapped memory region
|
||||
*/
|
||||
void* mapPtr(VkDeviceSize offset) const {
|
||||
return m_resource.mapPtr(offset);
|
||||
return m_physSlice.mapPtr(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,7 +62,7 @@ namespace dxvk {
|
||||
* \returns \c true if the buffer is in use
|
||||
*/
|
||||
bool isInUse() const {
|
||||
return m_resource.resource()->isInUse();
|
||||
return m_physSlice.resource()->isInUse();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,27 +72,9 @@ namespace dxvk {
|
||||
* \returns The resource object
|
||||
*/
|
||||
Rc<DxvkResource> resource() const {
|
||||
return m_resource.resource();
|
||||
return m_physSlice.resource();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Replaces backing resource
|
||||
*
|
||||
* Replaces the underlying buffer and implicitly marks
|
||||
* any buffer views using this resource as dirty. Do
|
||||
* not call this directly as this is called implicitly
|
||||
* by the context's \c invalidateBuffer method.
|
||||
* \param [in] resource The new backing resource
|
||||
*/
|
||||
void renameResource(
|
||||
const DxvkPhysicalBufferSlice& resource);
|
||||
|
||||
/**
|
||||
* \brief Allocates new backing resource
|
||||
* \returns The new buffer
|
||||
*/
|
||||
DxvkPhysicalBufferSlice allocateResource();
|
||||
|
||||
/**
|
||||
* \brief Physical buffer slice
|
||||
*
|
||||
@ -101,7 +83,7 @@ namespace dxvk {
|
||||
* \returns The backing slice
|
||||
*/
|
||||
DxvkPhysicalBufferSlice slice() const {
|
||||
return m_resource;
|
||||
return m_physSlice;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,16 +95,48 @@ namespace dxvk {
|
||||
* \returns The sub slice
|
||||
*/
|
||||
DxvkPhysicalBufferSlice subSlice(VkDeviceSize offset, VkDeviceSize length) const {
|
||||
return m_resource.subSlice(offset, length);
|
||||
return m_physSlice.subSlice(offset, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Replaces backing resource
|
||||
*
|
||||
* Replaces the underlying buffer and implicitly marks
|
||||
* any buffer views using this resource as dirty. Do
|
||||
* not call this directly as this is called implicitly
|
||||
* by the context's \c invalidateBuffer method.
|
||||
* \param [in] slice The new backing resource
|
||||
*/
|
||||
void rename(
|
||||
const DxvkPhysicalBufferSlice& slice);
|
||||
|
||||
/**
|
||||
* \brief Allocates new physical resource
|
||||
*
|
||||
* This method must not be called from multiple threads
|
||||
* simultaneously, but it can be called in parallel with
|
||||
* \ref rename and other methods of this class.
|
||||
* \returns The new backing buffer slice
|
||||
*/
|
||||
DxvkPhysicalBufferSlice allocPhysicalSlice();
|
||||
|
||||
private:
|
||||
|
||||
DxvkDevice* m_device;
|
||||
DxvkBufferCreateInfo m_info;
|
||||
VkMemoryPropertyFlags m_memFlags;
|
||||
DxvkPhysicalBufferSlice m_physSlice;
|
||||
|
||||
DxvkPhysicalBufferSlice m_resource;
|
||||
// TODO maybe align this to a cache line in order
|
||||
// to avoid false sharing once CSMT is implemented
|
||||
VkDeviceSize m_physBufferId = 0;
|
||||
VkDeviceSize m_physSliceId = 0;
|
||||
VkDeviceSize m_physSliceCount = 1;
|
||||
|
||||
std::array<Rc<DxvkPhysicalBuffer>, 2> m_physBuffers;
|
||||
|
||||
Rc<DxvkPhysicalBuffer> allocPhysicalBuffer(
|
||||
VkDeviceSize sliceCount) const;
|
||||
|
||||
};
|
||||
|
||||
|
@ -8,9 +8,10 @@ namespace dxvk {
|
||||
VkDeviceSize sliceCount,
|
||||
DxvkMemoryAllocator& memAlloc,
|
||||
VkMemoryPropertyFlags memFlags)
|
||||
: m_vkd(vkd),
|
||||
m_sliceLength(createInfo.size),
|
||||
m_sliceStride(align(createInfo.size, 256)) {
|
||||
: m_vkd (vkd),
|
||||
m_sliceCount (sliceCount),
|
||||
m_sliceLength (createInfo.size),
|
||||
m_sliceStride (align(createInfo.size, 256)) {
|
||||
|
||||
VkBufferCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
|
@ -78,6 +78,14 @@ namespace dxvk {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Number of slices
|
||||
* \returns Total slice count
|
||||
*/
|
||||
VkDeviceSize sliceCount() const {
|
||||
return m_sliceCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Map pointer
|
||||
*
|
||||
@ -108,6 +116,7 @@ namespace dxvk {
|
||||
DxvkMemory m_memory;
|
||||
VkBuffer m_handle;
|
||||
|
||||
VkDeviceSize m_sliceCount;
|
||||
VkDeviceSize m_sliceLength;
|
||||
VkDeviceSize m_sliceStride;
|
||||
|
||||
|
@ -541,8 +541,7 @@ namespace dxvk {
|
||||
|
||||
void DxvkContext::invalidateBuffer(const Rc<DxvkBuffer>& buffer) {
|
||||
// Allocate new backing resource
|
||||
buffer->renameResource(
|
||||
buffer->allocateResource());
|
||||
buffer->rename(buffer->allocPhysicalSlice());
|
||||
|
||||
// We also need to update all bindings that the buffer
|
||||
// may be bound to either directly or through views.
|
||||
|
@ -37,11 +37,12 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkPhysicalBuffer> DxvkDevice::allocBufferResource(
|
||||
Rc<DxvkPhysicalBuffer> DxvkDevice::allocPhysicalBuffer(
|
||||
const DxvkBufferCreateInfo& createInfo,
|
||||
VkDeviceSize sliceCount,
|
||||
VkMemoryPropertyFlags memoryType) {
|
||||
return new DxvkPhysicalBuffer(m_vkd,
|
||||
createInfo, 1, *m_memory, memoryType);
|
||||
createInfo, sliceCount, *m_memory, memoryType);
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,14 +101,16 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocates buffer resource
|
||||
* \brief Allocates a physical buffer
|
||||
*
|
||||
* \param [in] createInfo Buffer create info
|
||||
* \param [in] sliceCount Buffer slice count
|
||||
* \param [in] memoryType Memory property flags
|
||||
* \returns The buffer resource object
|
||||
*/
|
||||
Rc<DxvkPhysicalBuffer> allocBufferResource(
|
||||
Rc<DxvkPhysicalBuffer> allocPhysicalBuffer(
|
||||
const DxvkBufferCreateInfo& createInfo,
|
||||
VkDeviceSize sliceCount,
|
||||
VkMemoryPropertyFlags memoryType);
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user