diff --git a/src/dxvk/dxvk_buffer.cpp b/src/dxvk/dxvk_buffer.cpp index a66d8ab1..50175937 100644 --- a/src/dxvk/dxvk_buffer.cpp +++ b/src/dxvk/dxvk_buffer.cpp @@ -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& vkd, const Rc& 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 DxvkBufferView::createView() { + return new DxvkPhysicalBufferView( + m_vkd, m_buffer->slice(), m_info); } } \ No newline at end of file diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index e0204bc1..b9aa2e0f 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -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 resource() const { - return m_buffer->resource(); + Rc viewResource() const { + return m_physView; + } + + /** + * \brief Backing buffer resource + * \returns Backing buffer resource + */ + Rc 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 m_vkd; - Rc m_buffer; + Rc m_vkd; + DxvkBufferViewCreateInfo m_info; - DxvkBufferViewCreateInfo m_info; - VkBufferView m_view; + Rc m_buffer; + Rc m_physView; - void createBufferView(); - void destroyBufferView(); + uint32_t m_revision = 0; + + Rc createView(); }; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 35ab9310..43aa8f13 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -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();