[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(
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);
}
}

View File

@ -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;
Rc<vk::DeviceFn> m_vkd;
DxvkBufferViewCreateInfo m_info;
DxvkBufferViewCreateInfo m_info;
VkBufferView m_view;
Rc<DxvkBuffer> m_buffer;
Rc<DxvkPhysicalBufferView> m_physView;
void createBufferView();
void destroyBufferView();
uint32_t m_revision = 0;
Rc<DxvkPhysicalBufferView> createView();
};

View File

@ -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();