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