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

View File

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