1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-25 16:54:15 +01:00

[dxvk] Recreate buffer views if necessary

Fixes broken animations and artifacts in The Witcher 3.
This commit is contained in:
Philip Rebohle 2018-03-07 13:54:28 +01:00
parent ad017c2556
commit 360bf3ee4c
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 50 additions and 40 deletions

View File

@ -21,9 +21,9 @@ namespace dxvk {
} }
void DxvkBuffer::rename( void DxvkBuffer::rename(const DxvkPhysicalBufferSlice& slice) {
const DxvkPhysicalBufferSlice& slice) {
m_physSlice = slice; m_physSlice = slice;
m_revision += 1;
} }
@ -68,36 +68,29 @@ namespace dxvk {
const Rc<vk::DeviceFn>& vkd, const Rc<vk::DeviceFn>& vkd,
const Rc<DxvkBuffer>& buffer, const Rc<DxvkBuffer>& buffer,
const DxvkBufferViewCreateInfo& info) const DxvkBufferViewCreateInfo& info)
: m_vkd(vkd), m_buffer(buffer), m_info(info) { : m_vkd(vkd), m_info(info), m_buffer(buffer),
this->createBufferView(); m_physView(this->createView()),
m_revision(m_buffer->m_revision) {
} }
DxvkBufferView::~DxvkBufferView() { DxvkBufferView::~DxvkBufferView() {
this->destroyBufferView();
} }
void DxvkBufferView::createBufferView() { void DxvkBufferView::updateView() {
auto physicalSlice = this->slice(); if (m_revision != m_buffer->m_revision) {
m_physView = this->createView();
VkBufferViewCreateInfo viewInfo; m_revision = m_buffer->m_revision;
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::destroyBufferView() { Rc<DxvkPhysicalBufferView> DxvkBufferView::createView() {
m_vkd->vkDestroyBufferView( return new DxvkPhysicalBufferView(
m_vkd->device(), m_view, nullptr); m_vkd, m_buffer->slice(), m_info);
} }
} }

View File

@ -12,7 +12,7 @@ namespace dxvk {
* if allocated on an appropriate memory type. * if allocated on an appropriate memory type.
*/ */
class DxvkBuffer : public RcObject { class DxvkBuffer : public RcObject {
friend class DxvkBufferView;
public: public:
DxvkBuffer( DxvkBuffer(
@ -126,6 +126,7 @@ namespace dxvk {
DxvkBufferCreateInfo m_info; DxvkBufferCreateInfo m_info;
VkMemoryPropertyFlags m_memFlags; VkMemoryPropertyFlags m_memFlags;
DxvkPhysicalBufferSlice m_physSlice; DxvkPhysicalBufferSlice m_physSlice;
uint32_t m_revision = 0;
// TODO maybe align this to a cache line in order // TODO maybe align this to a cache line in order
// to avoid false sharing once CSMT is implemented // to avoid false sharing once CSMT is implemented
@ -150,7 +151,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 DxvkResource { class DxvkBufferView : public RcObject {
public: public:
@ -166,7 +167,7 @@ namespace dxvk {
* \returns Buffer view handle * \returns Buffer view handle
*/ */
VkBufferView handle() const { VkBufferView handle() const {
return m_view; return m_physView->handle();
} }
/** /**
@ -189,8 +190,16 @@ namespace dxvk {
* \brief Backing resource * \brief Backing resource
* \returns Backing resource * \returns Backing resource
*/ */
Rc<DxvkResource> resource() const { Rc<DxvkResource> viewResource() const {
return m_buffer->resource(); 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 * \returns Slice backing the view
*/ */
DxvkPhysicalBufferSlice slice() const { DxvkPhysicalBufferSlice slice() const {
return m_buffer->subSlice( return m_physView->slice();
m_info.rangeOffset,
m_info.rangeLength);
} }
/**
* \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: private:
Rc<vk::DeviceFn> m_vkd; Rc<vk::DeviceFn> m_vkd;
Rc<DxvkBuffer> m_buffer;
DxvkBufferViewCreateInfo m_info; DxvkBufferViewCreateInfo m_info;
VkBufferView m_view;
void createBufferView(); Rc<DxvkBuffer> m_buffer;
void destroyBufferView(); Rc<DxvkPhysicalBufferView> m_physView;
uint32_t m_revision = 0;
Rc<DxvkPhysicalBufferView> createView();
}; };

View File

@ -1483,8 +1483,6 @@ namespace dxvk {
bool updatePipelineState = false; 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++) { for (uint32_t i = 0; i < layout->bindingCount(); i++) {
const auto& binding = layout->binding(i); const auto& binding = layout->binding(i);
const auto& res = m_rc[binding.slot]; const auto& res = m_rc[binding.slot];
@ -1534,10 +1532,11 @@ namespace dxvk {
if (res.bufferView != nullptr) { if (res.bufferView != nullptr) {
updatePipelineState |= bs.setBound(i); updatePipelineState |= bs.setBound(i);
res.bufferView->updateView();
m_descInfos[i].texelBuffer = res.bufferView->handle(); m_descInfos[i].texelBuffer = res.bufferView->handle();
m_cmd->trackResource(res.bufferView); m_cmd->trackResource(res.bufferView->viewResource());
m_cmd->trackResource(res.bufferView->resource()); m_cmd->trackResource(res.bufferView->bufferResource());
} else { } else {
updatePipelineState |= bs.setUnbound(i); updatePipelineState |= bs.setUnbound(i);
m_descInfos[i].texelBuffer = m_device->dummyBufferViewDescriptor(); m_descInfos[i].texelBuffer = m_device->dummyBufferViewDescriptor();