mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 14:52:11 +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:
parent
61fdf4ef64
commit
cc61e38b9c
@ -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 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<DxvkBuffer> m_buffer;
|
||||
Rc<DxvkPhysicalBufferView> m_physView;
|
||||
|
||||
uint32_t m_revision = 0;
|
||||
DxvkBufferSliceHandle m_bufferSlice;
|
||||
VkBufferView m_bufferView;
|
||||
|
||||
Rc<DxvkPhysicalBufferView> createView();
|
||||
std::unordered_map<
|
||||
DxvkBufferSliceHandle,
|
||||
VkBufferView,
|
||||
DxvkHash, DxvkEq> m_views;
|
||||
|
||||
VkBufferView createBufferView(
|
||||
const DxvkBufferSliceHandle& slice);
|
||||
|
||||
void updateBufferView();
|
||||
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user