From c82bddb9328153278934b0c64bfaffcc30cd810d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 26 Nov 2017 13:24:01 +0100 Subject: [PATCH] [dxvk] Added buffer copy and initial buffer barriers --- src/dxvk/dxvk_barrier.cpp | 126 ++++++++++++++++++++------------- src/dxvk/dxvk_barrier.h | 40 +++++------ src/dxvk/dxvk_cmdlist.cpp | 11 +++ src/dxvk/dxvk_cmdlist.h | 6 ++ src/dxvk/dxvk_constant_state.h | 8 +++ src/dxvk/dxvk_context.cpp | 40 +++++++++++ src/dxvk/dxvk_context.h | 19 +++++ src/dxvk/dxvk_image.h | 2 + src/dxvk/dxvk_recorder.h | 6 ++ src/dxvk/dxvk_resource.h | 7 ++ 10 files changed, 191 insertions(+), 74 deletions(-) diff --git a/src/dxvk/dxvk_barrier.cpp b/src/dxvk/dxvk_barrier.cpp index 2977bc4bf..52ebc2ee7 100644 --- a/src/dxvk/dxvk_barrier.cpp +++ b/src/dxvk/dxvk_barrier.cpp @@ -5,66 +5,90 @@ namespace dxvk { DxvkBarrierSet:: DxvkBarrierSet() { } DxvkBarrierSet::~DxvkBarrierSet() { } - bool DxvkBarrierSet::hasBarriers() const { - return (m_srcFlags | m_dstFlags) != 0; - } - - - void DxvkBarrierSet::addMemoryBarrier( - VkPipelineStageFlags srcFlags, - VkPipelineStageFlags dstFlags, - const VkMemoryBarrier& barrier) { - m_srcFlags |= srcFlags; - m_dstFlags |= dstFlags; - m_memory.push_back(barrier); - } - - - void DxvkBarrierSet::addBufferBarrier( - VkPipelineStageFlags srcFlags, - VkPipelineStageFlags dstFlags, - const VkBufferMemoryBarrier& barrier) { - m_srcFlags |= srcFlags; - m_dstFlags |= dstFlags; - m_buffer.push_back(barrier); - } - - - void DxvkBarrierSet::addImageBarrier( - VkPipelineStageFlags srcFlags, - VkPipelineStageFlags dstFlags, - const VkImageMemoryBarrier& barrier) { - m_srcFlags |= srcFlags; - m_dstFlags |= dstFlags; - m_image.push_back(barrier); + void DxvkBarrierSet::accessBuffer( + const Rc& buffer, + VkDeviceSize offset, + VkDeviceSize size, + VkPipelineStageFlags stages, + VkAccessFlags access) { + const DxvkResourceAccessTypes accessTypes + = this->getAccessTypes(access); + + m_srcStages |= stages; + m_dstStages |= buffer->info().stages; + + if (accessTypes.test(DxvkResourceAccessType::Write)) { + VkBufferMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = access; + barrier.dstAccessMask = buffer->info().access; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.buffer = buffer->handle(); + barrier.offset = offset; + barrier.size = size; + m_bufBarriers.push_back(barrier); + } } void DxvkBarrierSet::recordCommands( - DxvkRecorder& recorder) { - VkPipelineStageFlags srcFlags = m_srcFlags; - VkPipelineStageFlags dstFlags = m_dstFlags; - - if (srcFlags == 0) srcFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - if (dstFlags == 0) dstFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - - recorder.cmdPipelineBarrier( - srcFlags, dstFlags, 0, - m_memory.size(), m_memory.data(), - m_buffer.size(), m_buffer.data(), - m_image.size(), m_image.data()); - - this->reset(); + DxvkRecorder& recorder) { + if ((m_srcStages | m_dstStages) != 0) { + VkPipelineStageFlags srcFlags = m_srcStages; + VkPipelineStageFlags dstFlags = m_dstStages; + + if (srcFlags == 0) srcFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + if (dstFlags == 0) dstFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + + recorder.cmdPipelineBarrier( + srcFlags, dstFlags, 0, + m_memBarriers.size(), m_memBarriers.data(), + m_bufBarriers.size(), m_bufBarriers.data(), + m_imgBarriers.size(), m_imgBarriers.data()); + + this->reset(); + } } void DxvkBarrierSet::reset() { - m_srcFlags = 0; - m_dstFlags = 0; + m_srcStages = 0; + m_dstStages = 0; - m_memory.resize(0); - m_buffer.resize(0); - m_image .resize(0); + m_memBarriers.resize(0); + m_bufBarriers.resize(0); + m_imgBarriers.resize(0); + } + + + DxvkResourceAccessTypes DxvkBarrierSet::getAccessTypes(VkAccessFlags flags) const { + const VkAccessFlags rflags + = VK_ACCESS_INDIRECT_COMMAND_READ_BIT + | VK_ACCESS_INDEX_READ_BIT + | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT + | VK_ACCESS_UNIFORM_READ_BIT + | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT + | VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT + | VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_HOST_READ_BIT + | VK_ACCESS_MEMORY_READ_BIT; + + const VkAccessFlags wflags + = VK_ACCESS_SHADER_WRITE_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_HOST_WRITE_BIT + | VK_ACCESS_MEMORY_WRITE_BIT; + + DxvkResourceAccessTypes result; + if (flags & rflags) result.set(DxvkResourceAccessType::Read); + if (flags & wflags) result.set(DxvkResourceAccessType::Write); + return result; } } \ No newline at end of file diff --git a/src/dxvk/dxvk_barrier.h b/src/dxvk/dxvk_barrier.h index 5604a5e73..b80d60dda 100644 --- a/src/dxvk/dxvk_barrier.h +++ b/src/dxvk/dxvk_barrier.h @@ -1,5 +1,7 @@ #pragma once +#include "dxvk_buffer.h" +#include "dxvk_image.h" #include "dxvk_recorder.h" namespace dxvk { @@ -17,37 +19,29 @@ namespace dxvk { DxvkBarrierSet(); ~DxvkBarrierSet(); - - bool hasBarriers() const; - - void addMemoryBarrier( - VkPipelineStageFlags srcFlags, - VkPipelineStageFlags dstFlags, - const VkMemoryBarrier& barrier); - - void addBufferBarrier( - VkPipelineStageFlags srcFlags, - VkPipelineStageFlags dstFlags, - const VkBufferMemoryBarrier& barrier); - - void addImageBarrier( - VkPipelineStageFlags srcFlags, - VkPipelineStageFlags dstFlags, - const VkImageMemoryBarrier& barrier); + + void accessBuffer( + const Rc& buffer, + VkDeviceSize offset, + VkDeviceSize size, + VkPipelineStageFlags stages, + VkAccessFlags access); void recordCommands( - DxvkRecorder& recorder); + DxvkRecorder& recorder); void reset(); private: - VkPipelineStageFlags m_srcFlags = 0; - VkPipelineStageFlags m_dstFlags = 0; + VkPipelineStageFlags m_srcStages = 0; + VkPipelineStageFlags m_dstStages = 0; - std::vector m_memory; - std::vector m_buffer; - std::vector m_image; + std::vector m_memBarriers; + std::vector m_bufBarriers; + std::vector m_imgBarriers; + + DxvkResourceAccessTypes getAccessTypes(VkAccessFlags flags) const; }; diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index 98a79a69d..85809e15c 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -157,6 +157,17 @@ namespace dxvk { } + void DxvkCommandList::cmdCopyBuffer( + VkBuffer srcBuffer, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferCopy* pRegions) { + m_vkd->vkCmdCopyBuffer(m_buffer, + srcBuffer, dstBuffer, + regionCount, pRegions); + } + + void DxvkCommandList::cmdDispatch( uint32_t x, uint32_t y, diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index c2f1a86d1..9faf89a90 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -103,6 +103,12 @@ namespace dxvk { uint32_t rectCount, const VkClearRect* pRects) final; + void cmdCopyBuffer( + VkBuffer srcBuffer, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferCopy* pRegions) final; + void cmdDispatch( uint32_t x, uint32_t y, diff --git a/src/dxvk/dxvk_constant_state.h b/src/dxvk/dxvk_constant_state.h index ef5661409..ad03bae67 100644 --- a/src/dxvk/dxvk_constant_state.h +++ b/src/dxvk/dxvk_constant_state.h @@ -177,6 +177,14 @@ namespace dxvk { uint32_t bindingCount, const VkVertexInputBindingDescription* bindingInfo); + uint32_t vertexAttributeCount() const { + return m_attributes.size(); + } + + uint32_t vertexBindingCount() const { + return m_bindings.size(); + } + const VkPipelineVertexInputStateCreateInfo& info() const { return m_info; } diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 9715a82e1..8e2c2968b 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -102,6 +102,8 @@ namespace dxvk { void DxvkContext::bindVertexBuffer( uint32_t binding, const DxvkBufferBinding& buffer) { + TRACE(this, binding); + if (m_state.vi.vertexBuffers.at(binding) != buffer) { m_state.vi.vertexBuffers.at(binding) = buffer; m_state.flags.set(DxvkContextFlag::GpDirtyVertexBuffers); @@ -124,6 +126,43 @@ namespace dxvk { } + void DxvkContext::copyBuffer( + const Rc& dstBuffer, + VkDeviceSize dstOffset, + const Rc& srcBuffer, + VkDeviceSize srcOffset, + VkDeviceSize numBytes) { + TRACE(this, dstBuffer, dstOffset, srcBuffer, srcOffset, numBytes); + + if (numBytes != 0) { + VkBufferCopy bufferRegion; + bufferRegion.srcOffset = srcOffset; + bufferRegion.dstOffset = dstOffset; + bufferRegion.size = numBytes; + + m_cmd->cmdCopyBuffer( + srcBuffer->handle(), + dstBuffer->handle(), + 1, &bufferRegion); + + m_barriers.accessBuffer( + srcBuffer, srcOffset, numBytes, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT); + + m_barriers.accessBuffer( + dstBuffer, dstOffset, numBytes, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + + m_barriers.recordCommands(*m_cmd); + + m_cmd->trackResource(dstBuffer); + m_cmd->trackResource(srcBuffer); + } + } + + void DxvkContext::dispatch( uint32_t x, uint32_t y, @@ -361,6 +400,7 @@ namespace dxvk { void DxvkContext::commitComputeState() { + this->renderPassEnd(); this->bindComputePipeline(); } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 4143b2159..cbff55f7f 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -96,6 +96,22 @@ namespace dxvk { const VkClearAttachment& attachment, const VkClearRect& clearArea); + /** + * \brief Copies data from one buffer to another + * + * \param [in] dstBuffer Destination buffer + * \param [in] dstOffset Destination data offset + * \param [in] srcBuffer Source buffer + * \param [in] srcOffset Source data offset + * \param [in] numBytes Number of bytes to copy + */ + void copyBuffer( + const Rc& dstBuffer, + VkDeviceSize dstOffset, + const Rc& srcBuffer, + VkDeviceSize srcOffset, + VkDeviceSize numBytes); + /** * \brief Starts compute jobs * @@ -199,6 +215,7 @@ namespace dxvk { Rc m_cmd; DxvkContextState m_state; + DxvkBarrierSet m_barriers; void renderPassBegin(); void renderPassEnd(); @@ -218,6 +235,8 @@ namespace dxvk { DxvkShaderStageState* getShaderStage( VkShaderStageFlagBits stage); + + }; } \ No newline at end of file diff --git a/src/dxvk/dxvk_image.h b/src/dxvk/dxvk_image.h index 9ae67550c..cfbe9876f 100644 --- a/src/dxvk/dxvk_image.h +++ b/src/dxvk/dxvk_image.h @@ -13,6 +13,8 @@ namespace dxvk { uint32_t numLayers; uint32_t mipLevels; VkImageUsageFlags usage; + VkPipelineStageFlags stages; + VkAccessFlags access; VkImageTiling tiling; }; diff --git a/src/dxvk/dxvk_recorder.h b/src/dxvk/dxvk_recorder.h index 3ef78680a..94842885d 100644 --- a/src/dxvk/dxvk_recorder.h +++ b/src/dxvk/dxvk_recorder.h @@ -60,6 +60,12 @@ namespace dxvk { uint32_t rectCount, const VkClearRect* pRects) = 0; + virtual void cmdCopyBuffer( + VkBuffer srcBuffer, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferCopy* pRegions) = 0; + virtual void cmdDispatch( uint32_t x, uint32_t y, diff --git a/src/dxvk/dxvk_resource.h b/src/dxvk/dxvk_resource.h index e62fa11c6..38b0a97a0 100644 --- a/src/dxvk/dxvk_resource.h +++ b/src/dxvk/dxvk_resource.h @@ -4,6 +4,13 @@ namespace dxvk { + enum class DxvkResourceAccessType { + Read = 0, + Write = 1, + }; + + using DxvkResourceAccessTypes = Flags; + /** * \brief DXVK resource *