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:
parent
61fdf4ef64
commit
cc61e38b9c
@ -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 });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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();
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user