mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-25 07:54:15 +01:00
[dxvk] Recreate buffer views if necessary
Fixes broken animations and artifacts in The Witcher 3.
This commit is contained in:
parent
ad017c2556
commit
360bf3ee4c
@ -21,9 +21,9 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkBuffer::rename(
|
||||
const DxvkPhysicalBufferSlice& slice) {
|
||||
void DxvkBuffer::rename(const DxvkPhysicalBufferSlice& slice) {
|
||||
m_physSlice = slice;
|
||||
m_revision += 1;
|
||||
}
|
||||
|
||||
|
||||
@ -68,36 +68,29 @@ namespace dxvk {
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
const DxvkBufferViewCreateInfo& info)
|
||||
: m_vkd(vkd), m_buffer(buffer), m_info(info) {
|
||||
this->createBufferView();
|
||||
: m_vkd(vkd), m_info(info), m_buffer(buffer),
|
||||
m_physView(this->createView()),
|
||||
m_revision(m_buffer->m_revision) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
DxvkBufferView::~DxvkBufferView() {
|
||||
this->destroyBufferView();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DxvkBufferView::createBufferView() {
|
||||
auto physicalSlice = this->slice();
|
||||
|
||||
VkBufferViewCreateInfo viewInfo;
|
||||
viewInfo.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
|
||||
viewInfo.pNext = nullptr;
|
||||
viewInfo.flags = 0;
|
||||
viewInfo.buffer = physicalSlice.handle();
|
||||
viewInfo.format = m_info.format;
|
||||
viewInfo.offset = physicalSlice.offset();
|
||||
viewInfo.range = physicalSlice.length();
|
||||
|
||||
if (m_vkd->vkCreateBufferView(m_vkd->device(), &viewInfo, nullptr, &m_view) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkBufferView::DxvkBufferView: Failed to create buffer view");
|
||||
void DxvkBufferView::updateView() {
|
||||
if (m_revision != m_buffer->m_revision) {
|
||||
m_physView = this->createView();
|
||||
m_revision = m_buffer->m_revision;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkBufferView::destroyBufferView() {
|
||||
m_vkd->vkDestroyBufferView(
|
||||
m_vkd->device(), m_view, nullptr);
|
||||
Rc<DxvkPhysicalBufferView> DxvkBufferView::createView() {
|
||||
return new DxvkPhysicalBufferView(
|
||||
m_vkd, m_buffer->slice(), m_info);
|
||||
}
|
||||
|
||||
}
|
@ -12,7 +12,7 @@ namespace dxvk {
|
||||
* if allocated on an appropriate memory type.
|
||||
*/
|
||||
class DxvkBuffer : public RcObject {
|
||||
|
||||
friend class DxvkBufferView;
|
||||
public:
|
||||
|
||||
DxvkBuffer(
|
||||
@ -126,6 +126,7 @@ namespace dxvk {
|
||||
DxvkBufferCreateInfo m_info;
|
||||
VkMemoryPropertyFlags m_memFlags;
|
||||
DxvkPhysicalBufferSlice m_physSlice;
|
||||
uint32_t m_revision = 0;
|
||||
|
||||
// TODO maybe align this to a cache line in order
|
||||
// to avoid false sharing once CSMT is implemented
|
||||
@ -150,7 +151,7 @@ namespace dxvk {
|
||||
* contents like formatted pixel data. These
|
||||
* buffer views are used as texel buffers.
|
||||
*/
|
||||
class DxvkBufferView : public DxvkResource {
|
||||
class DxvkBufferView : public RcObject {
|
||||
|
||||
public:
|
||||
|
||||
@ -166,7 +167,7 @@ namespace dxvk {
|
||||
* \returns Buffer view handle
|
||||
*/
|
||||
VkBufferView handle() const {
|
||||
return m_view;
|
||||
return m_physView->handle();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,8 +190,16 @@ namespace dxvk {
|
||||
* \brief Backing resource
|
||||
* \returns Backing resource
|
||||
*/
|
||||
Rc<DxvkResource> resource() const {
|
||||
return m_buffer->resource();
|
||||
Rc<DxvkResource> viewResource() const {
|
||||
return m_physView;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Backing buffer resource
|
||||
* \returns Backing buffer resource
|
||||
*/
|
||||
Rc<DxvkResource> bufferResource() const {
|
||||
return m_physView->slice().resource();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,21 +207,30 @@ namespace dxvk {
|
||||
* \returns Slice backing the view
|
||||
*/
|
||||
DxvkPhysicalBufferSlice slice() const {
|
||||
return m_buffer->subSlice(
|
||||
m_info.rangeOffset,
|
||||
m_info.rangeLength);
|
||||
return m_physView->slice();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Updates the buffer view
|
||||
*
|
||||
* If the buffer has been invalidated ever since
|
||||
* the view was created, the view is invalid as
|
||||
* well and needs to be re-created. Call this
|
||||
* prior to using the buffer view handle.
|
||||
*/
|
||||
void updateView();
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
Rc<DxvkBuffer> m_buffer;
|
||||
|
||||
DxvkBufferViewCreateInfo m_info;
|
||||
VkBufferView m_view;
|
||||
|
||||
void createBufferView();
|
||||
void destroyBufferView();
|
||||
Rc<DxvkBuffer> m_buffer;
|
||||
Rc<DxvkPhysicalBufferView> m_physView;
|
||||
|
||||
uint32_t m_revision = 0;
|
||||
|
||||
Rc<DxvkPhysicalBufferView> createView();
|
||||
|
||||
};
|
||||
|
||||
|
@ -1483,8 +1483,6 @@ namespace dxvk {
|
||||
|
||||
bool updatePipelineState = false;
|
||||
|
||||
// TODO recreate resource views if the underlying
|
||||
// resource was marked as dirty after invalidation
|
||||
for (uint32_t i = 0; i < layout->bindingCount(); i++) {
|
||||
const auto& binding = layout->binding(i);
|
||||
const auto& res = m_rc[binding.slot];
|
||||
@ -1534,10 +1532,11 @@ namespace dxvk {
|
||||
if (res.bufferView != nullptr) {
|
||||
updatePipelineState |= bs.setBound(i);
|
||||
|
||||
res.bufferView->updateView();
|
||||
m_descInfos[i].texelBuffer = res.bufferView->handle();
|
||||
|
||||
m_cmd->trackResource(res.bufferView);
|
||||
m_cmd->trackResource(res.bufferView->resource());
|
||||
m_cmd->trackResource(res.bufferView->viewResource());
|
||||
m_cmd->trackResource(res.bufferView->bufferResource());
|
||||
} else {
|
||||
updatePipelineState |= bs.setUnbound(i);
|
||||
m_descInfos[i].texelBuffer = m_device->dummyBufferViewDescriptor();
|
||||
|
Loading…
x
Reference in New Issue
Block a user