1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00

[dxvk] Reimplement DxvkBufferView

Instead of recreating the buffer view every single time the
underlying buffer gets invalidated, this keeps all buffer
views around until the object itself gets destroyed.
This commit is contained in:
Philip Rebohle 2019-01-09 16:17:54 +01:00
parent 61fdf4ef64
commit cc61e38b9c
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 87 additions and 44 deletions

View File

@ -81,20 +81,64 @@ namespace dxvk {
const Rc<DxvkBuffer>& buffer, const Rc<DxvkBuffer>& buffer,
const DxvkBufferViewCreateInfo& info) const DxvkBufferViewCreateInfo& info)
: m_vkd(vkd), m_info(info), m_buffer(buffer), : m_vkd(vkd), m_info(info), m_buffer(buffer),
m_physView(this->createView()), m_bufferSlice (m_buffer->getSliceHandle()),
m_revision(m_buffer->m_revision) { m_bufferView (createBufferView(m_bufferSlice)) {
} }
DxvkBufferView::~DxvkBufferView() { DxvkBufferView::~DxvkBufferView() {
if (m_views.empty()) {
m_vkd->vkDestroyBufferView(
m_vkd->device(), m_bufferView, nullptr);
} else {
for (const auto& pair : m_views) {
m_vkd->vkDestroyBufferView(
m_vkd->device(), pair.second, nullptr);
}
}
} }
Rc<DxvkPhysicalBufferView> DxvkBufferView::createView() { VkBufferView DxvkBufferView::createBufferView(
return new DxvkPhysicalBufferView( const DxvkBufferSliceHandle& slice) {
m_vkd, m_buffer->slice(), m_info); VkBufferViewCreateInfo viewInfo;
viewInfo.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
viewInfo.pNext = nullptr;
viewInfo.flags = 0;
viewInfo.buffer = slice.handle;
viewInfo.format = m_info.format;
viewInfo.offset = slice.offset;
viewInfo.range = slice.length;
VkBufferView result = VK_NULL_HANDLE;
if (m_vkd->vkCreateBufferView(m_vkd->device(),
&viewInfo, nullptr, &result) != VK_SUCCESS) {
throw DxvkError(str::format(
"DxvkBufferView: Failed to create buffer view:",
"\n Offset: ", viewInfo.offset,
"\n Range: ", viewInfo.range,
"\n Format: ", viewInfo.format));
}
return result;
}
void DxvkBufferView::updateBufferView() {
if (m_views.empty())
m_views.insert({ m_bufferSlice, m_bufferView });
m_bufferSlice = m_buffer->getSliceHandle();
auto entry = m_views.find(m_bufferSlice);
if (entry != m_views.end()) {
m_bufferView = entry->second;
} else {
m_bufferView = createBufferView(m_bufferSlice);
m_views.insert({ m_bufferSlice, m_bufferView });
}
} }

View File

@ -1,9 +1,10 @@
#pragma once #pragma once
#include <mutex> #include <unordered_map>
#include <vector> #include <vector>
#include "dxvk_buffer_res.h" #include "dxvk_buffer_res.h"
#include "dxvk_hash.h"
namespace dxvk { namespace dxvk {
@ -19,6 +20,20 @@ namespace dxvk {
VkDeviceSize offset; VkDeviceSize offset;
VkDeviceSize length; VkDeviceSize length;
void* mapPtr; void* mapPtr;
bool eq(const DxvkBufferSliceHandle& other) const {
return handle == other.handle
&& offset == other.offset
&& length == other.length;
}
size_t hash() const {
DxvkHashState result;
result.add(std::hash<VkBuffer>()(handle));
result.add(std::hash<VkDeviceSize>()(offset));
result.add(std::hash<VkDeviceSize>()(length));
return result;
}
}; };
@ -185,7 +200,6 @@ namespace dxvk {
DxvkPhysicalBufferSlice rename(const DxvkPhysicalBufferSlice& slice) { DxvkPhysicalBufferSlice rename(const DxvkPhysicalBufferSlice& slice) {
DxvkPhysicalBufferSlice prevSlice = std::move(m_physSlice); DxvkPhysicalBufferSlice prevSlice = std::move(m_physSlice);
m_physSlice = slice; m_physSlice = slice;
m_revision += 1;
return prevSlice; return prevSlice;
} }
@ -235,7 +249,6 @@ namespace dxvk {
VkMemoryPropertyFlags m_memFlags; VkMemoryPropertyFlags m_memFlags;
DxvkPhysicalBufferSlice m_physSlice; DxvkPhysicalBufferSlice m_physSlice;
uint32_t m_revision = 0;
uint32_t m_vertexStride = 0; uint32_t m_vertexStride = 0;
sync::Spinlock m_freeMutex; sync::Spinlock m_freeMutex;
@ -253,9 +266,6 @@ namespace dxvk {
Rc<DxvkPhysicalBuffer> allocPhysicalBuffer( Rc<DxvkPhysicalBuffer> allocPhysicalBuffer(
VkDeviceSize sliceCount) const; VkDeviceSize sliceCount) const;
void lock();
void unlock();
}; };
@ -437,7 +447,7 @@ namespace dxvk {
* contents like formatted pixel data. These * contents like formatted pixel data. These
* buffer views are used as texel buffers. * buffer views are used as texel buffers.
*/ */
class DxvkBufferView : public RcObject { class DxvkBufferView : public DxvkResource {
public: public:
@ -453,7 +463,7 @@ namespace dxvk {
* \returns Buffer view handle * \returns Buffer view handle
*/ */
VkBufferView handle() const { VkBufferView handle() const {
return m_physView->handle(); return m_bufferView;
} }
/** /**
@ -493,20 +503,12 @@ namespace dxvk {
return m_buffer->info(); return m_buffer->info();
} }
/**
* \brief Backing resource
* \returns Backing resource
*/
Rc<DxvkResource> viewResource() const {
return m_physView;
}
/** /**
* \brief Backing buffer resource * \brief Backing buffer resource
* \returns Backing buffer resource * \returns Backing buffer resource
*/ */
Rc<DxvkResource> bufferResource() const { Rc<DxvkResource> bufferResource() const {
return m_physView->bufferResource(); return m_buffer->resource();
} }
/** /**
@ -529,14 +531,6 @@ namespace dxvk {
m_info.rangeLength); m_info.rangeLength);
} }
/**
* \brief Underlying buffer slice
* \returns Slice backing the view
*/
DxvkPhysicalBufferSlice physicalSlice() const {
return m_physView->slice();
}
/** /**
* \brief Updates the buffer view * \brief Updates the buffer view
* *
@ -546,23 +540,28 @@ namespace dxvk {
* prior to using the buffer view handle. * prior to using the buffer view handle.
*/ */
void updateView() { void updateView() {
if (m_revision != m_buffer->m_revision) { if (!m_bufferSlice.eq(m_buffer->getSliceHandle()))
m_physView = this->createView(); this->updateBufferView();
m_revision = m_buffer->m_revision;
}
} }
private: private:
Rc<vk::DeviceFn> m_vkd; Rc<vk::DeviceFn> m_vkd;
DxvkBufferViewCreateInfo m_info; DxvkBufferViewCreateInfo m_info;
Rc<DxvkBuffer> m_buffer;
DxvkBufferSliceHandle m_bufferSlice;
VkBufferView m_bufferView;
std::unordered_map<
DxvkBufferSliceHandle,
VkBufferView,
DxvkHash, DxvkEq> m_views;
Rc<DxvkBuffer> m_buffer; VkBufferView createBufferView(
Rc<DxvkPhysicalBufferView> m_physView; const DxvkBufferSliceHandle& slice);
uint32_t m_revision = 0; void updateBufferView();
Rc<DxvkPhysicalBufferView> createView();
}; };

View File

@ -346,7 +346,7 @@ namespace dxvk {
bufferView->bufferInfo().stages, bufferView->bufferInfo().stages,
bufferView->bufferInfo().access); bufferView->bufferInfo().access);
m_cmd->trackResource(bufferView->viewResource()); m_cmd->trackResource(bufferView);
m_cmd->trackResource(bufferView->bufferResource()); m_cmd->trackResource(bufferView->bufferResource());
} }
@ -2766,7 +2766,7 @@ namespace dxvk {
res.bufferView->updateView(); res.bufferView->updateView();
m_descInfos[i].texelBuffer = res.bufferView->handle(); m_descInfos[i].texelBuffer = res.bufferView->handle();
m_cmd->trackResource(res.bufferView->viewResource()); m_cmd->trackResource(res.bufferView);
m_cmd->trackResource(res.bufferView->bufferResource()); m_cmd->trackResource(res.bufferView->bufferResource());
} else { } else {
updatePipelineState |= bindMask.setUnbound(i); updatePipelineState |= bindMask.setUnbound(i);