Commit 03d1a5ed by Jamie Madill Committed by Commit Bot

Vulkan: Use global buffer barriers.

This switches from using resource barriers for buffers to using global barriers. This matches the general advised best practice. It also allows us to combine multiple barriers into one. On a draw we might combine all the vertex and index barriers into a single barrier call. We implement this using a bit of extra state tracking in BufferHelper. Bug: angleproject:2828 Change-Id: I196b368804ff50e60d085687a643e5566ba1c5b6 Reviewed-on: https://chromium-review.googlesource.com/c/1309977 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 48f63f90
...@@ -213,43 +213,8 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk, ...@@ -213,43 +213,8 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk,
stagingBuffer.getDeviceMemory().unmap(device); stagingBuffer.getDeviceMemory().unmap(device);
// Enqueue a copy command on the GPU. // Enqueue a copy command on the GPU.
// 'beginWriteResource' will stop any subsequent rendering from using the old buffer data,
// by marking any current read operations / command buffers as 'finished'.
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mBuffer.recordCommands(contextVk, &commandBuffer));
// Insert a barrier to ensure reads from the buffer are complete.
// TODO(jmadill): Insert minimal barriers.
VkBufferMemoryBarrier bufferBarrier = {};
bufferBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufferBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
bufferBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
bufferBarrier.srcQueueFamilyIndex = 0;
bufferBarrier.dstQueueFamilyIndex = 0;
bufferBarrier.buffer = mBuffer.getBuffer().getHandle();
bufferBarrier.offset = offset;
bufferBarrier.size = static_cast<VkDeviceSize>(size);
commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1,
&bufferBarrier, 0, nullptr);
VkBufferCopy copyRegion = {0, offset, size}; VkBufferCopy copyRegion = {0, offset, size};
commandBuffer->copyBuffer(stagingBuffer.getBuffer(), mBuffer.getBuffer(), 1, &copyRegion); ANGLE_TRY(mBuffer.copyFromBuffer(contextVk, stagingBuffer.getBuffer(), copyRegion));
// Insert a barrier to ensure copy has done.
// TODO(jie.a.chen@intel.com): Insert minimal barriers.
bufferBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
bufferBarrier.dstAccessMask =
VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_INDEX_READ_BIT |
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT |
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT;
commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1,
&bufferBarrier, 0, nullptr);
// Immediately release staging buffer. We should probably be using a DynamicBuffer here. // Immediately release staging buffer. We should probably be using a DynamicBuffer here.
renderer->releaseObject(renderer->getCurrentQueueSerial(), &stagingBuffer); renderer->releaseObject(renderer->getCurrentQueueSerial(), &stagingBuffer);
......
...@@ -33,17 +33,17 @@ angle::Result InitAndBeginCommandBuffer(vk::Context *context, ...@@ -33,17 +33,17 @@ angle::Result InitAndBeginCommandBuffer(vk::Context *context,
ASSERT(!commandBuffer->valid()); ASSERT(!commandBuffer->valid());
VkCommandBufferAllocateInfo createInfo = {}; VkCommandBufferAllocateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
createInfo.commandPool = commandPool.getHandle(); createInfo.commandPool = commandPool.getHandle();
createInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; createInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
createInfo.commandBufferCount = 1; createInfo.commandBufferCount = 1;
ANGLE_TRY(commandBuffer->init(context, createInfo)); ANGLE_TRY(commandBuffer->init(context, createInfo));
VkCommandBufferBeginInfo beginInfo = {}; VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = flags | VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; beginInfo.flags = flags | VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
beginInfo.pInheritanceInfo = &inheritanceInfo; beginInfo.pInheritanceInfo = &inheritanceInfo;
ANGLE_TRY(commandBuffer->begin(context, beginInfo)); ANGLE_TRY(commandBuffer->begin(context, beginInfo));
return angle::Result::Continue(); return angle::Result::Continue();
...@@ -297,7 +297,9 @@ CommandGraphNode::CommandGraphNode(CommandGraphNodeFunction function) ...@@ -297,7 +297,9 @@ CommandGraphNode::CommandGraphNode(CommandGraphNodeFunction function)
mQueryPool(VK_NULL_HANDLE), mQueryPool(VK_NULL_HANDLE),
mQueryIndex(0), mQueryIndex(0),
mHasChildren(false), mHasChildren(false),
mVisitedState(VisitedState::Unvisited) mVisitedState(VisitedState::Unvisited),
mGlobalMemoryBarrierSrcAccess(0),
mGlobalMemoryBarrierDstAccess(0)
{ {
} }
...@@ -323,14 +325,14 @@ angle::Result CommandGraphNode::beginOutsideRenderPassRecording(Context *context ...@@ -323,14 +325,14 @@ angle::Result CommandGraphNode::beginOutsideRenderPassRecording(Context *context
ASSERT(!mHasChildren); ASSERT(!mHasChildren);
VkCommandBufferInheritanceInfo inheritanceInfo = {}; VkCommandBufferInheritanceInfo inheritanceInfo = {};
inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
inheritanceInfo.renderPass = VK_NULL_HANDLE; inheritanceInfo.renderPass = VK_NULL_HANDLE;
inheritanceInfo.subpass = 0; inheritanceInfo.subpass = 0;
inheritanceInfo.framebuffer = VK_NULL_HANDLE; inheritanceInfo.framebuffer = VK_NULL_HANDLE;
inheritanceInfo.occlusionQueryEnable = inheritanceInfo.occlusionQueryEnable =
context->getRenderer()->getPhysicalDeviceFeatures().inheritedQueries; context->getRenderer()->getPhysicalDeviceFeatures().inheritedQueries;
inheritanceInfo.queryFlags = 0; inheritanceInfo.queryFlags = 0;
inheritanceInfo.pipelineStatistics = 0; inheritanceInfo.pipelineStatistics = 0;
ANGLE_TRY(InitAndBeginCommandBuffer(context, commandPool, inheritanceInfo, 0, ANGLE_TRY(InitAndBeginCommandBuffer(context, commandPool, inheritanceInfo, 0,
&mOutsideRenderPassCommands)); &mOutsideRenderPassCommands));
...@@ -351,14 +353,14 @@ angle::Result CommandGraphNode::beginInsideRenderPassRecording(Context *context, ...@@ -351,14 +353,14 @@ angle::Result CommandGraphNode::beginInsideRenderPassRecording(Context *context,
&compatibleRenderPass)); &compatibleRenderPass));
VkCommandBufferInheritanceInfo inheritanceInfo = {}; VkCommandBufferInheritanceInfo inheritanceInfo = {};
inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
inheritanceInfo.renderPass = compatibleRenderPass->getHandle(); inheritanceInfo.renderPass = compatibleRenderPass->getHandle();
inheritanceInfo.subpass = 0; inheritanceInfo.subpass = 0;
inheritanceInfo.framebuffer = mRenderPassFramebuffer.getHandle(); inheritanceInfo.framebuffer = mRenderPassFramebuffer.getHandle();
inheritanceInfo.occlusionQueryEnable = inheritanceInfo.occlusionQueryEnable =
context->getRenderer()->getPhysicalDeviceFeatures().inheritedQueries; context->getRenderer()->getPhysicalDeviceFeatures().inheritedQueries;
inheritanceInfo.queryFlags = 0; inheritanceInfo.queryFlags = 0;
inheritanceInfo.pipelineStatistics = 0; inheritanceInfo.pipelineStatistics = 0;
ANGLE_TRY(InitAndBeginCommandBuffer( ANGLE_TRY(InitAndBeginCommandBuffer(
context, context->getRenderer()->getCommandPool(), inheritanceInfo, context, context->getRenderer()->getCommandPool(), inheritanceInfo,
...@@ -429,6 +431,12 @@ void CommandGraphNode::setQueryPool(const QueryPool *queryPool, uint32_t queryIn ...@@ -429,6 +431,12 @@ void CommandGraphNode::setQueryPool(const QueryPool *queryPool, uint32_t queryIn
mQueryIndex = queryIndex; mQueryIndex = queryIndex;
} }
void CommandGraphNode::addGlobalMemoryBarrier(VkFlags srcAccess, VkFlags dstAccess)
{
mGlobalMemoryBarrierSrcAccess |= srcAccess;
mGlobalMemoryBarrierDstAccess |= dstAccess;
}
void CommandGraphNode::setHasChildren() void CommandGraphNode::setHasChildren()
{ {
mHasChildren = true; mHasChildren = true;
...@@ -480,6 +488,21 @@ angle::Result CommandGraphNode::visitAndExecute(vk::Context *context, ...@@ -480,6 +488,21 @@ angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
case CommandGraphNodeFunction::Generic: case CommandGraphNodeFunction::Generic:
ASSERT(mQueryPool == VK_NULL_HANDLE); ASSERT(mQueryPool == VK_NULL_HANDLE);
// Record the deferred pipeline barrier if necessary.
ASSERT((mGlobalMemoryBarrierDstAccess == 0) == (mGlobalMemoryBarrierSrcAccess == 0));
if (mGlobalMemoryBarrierSrcAccess)
{
VkMemoryBarrier memoryBarrier = {};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.srcAccessMask = mGlobalMemoryBarrierSrcAccess;
memoryBarrier.dstAccessMask = mGlobalMemoryBarrierDstAccess;
// Use the top of pipe stage to keep the state management simple.
primaryCommandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 1,
&memoryBarrier, 0, nullptr, 0, nullptr);
}
if (mOutsideRenderPassCommands.valid()) if (mOutsideRenderPassCommands.valid())
{ {
ANGLE_TRY(mOutsideRenderPassCommands.end(context)); ANGLE_TRY(mOutsideRenderPassCommands.end(context));
...@@ -630,10 +653,10 @@ angle::Result CommandGraph::submitCommands(Context *context, ...@@ -630,10 +653,10 @@ angle::Result CommandGraph::submitCommands(Context *context,
mLastBarrierIndex = kInvalidNodeIndex; mLastBarrierIndex = kInvalidNodeIndex;
VkCommandBufferAllocateInfo primaryInfo = {}; VkCommandBufferAllocateInfo primaryInfo = {};
primaryInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; primaryInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
primaryInfo.commandPool = commandPool->getHandle(); primaryInfo.commandPool = commandPool->getHandle();
primaryInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; primaryInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
primaryInfo.commandBufferCount = 1; primaryInfo.commandBufferCount = 1;
ANGLE_TRY(primaryCommandBufferOut->init(context, primaryInfo)); ANGLE_TRY(primaryCommandBufferOut->init(context, primaryInfo));
......
...@@ -107,6 +107,8 @@ class CommandGraphNode final : angle::NonCopyable ...@@ -107,6 +107,8 @@ class CommandGraphNode final : angle::NonCopyable
void setQueryPool(const QueryPool *queryPool, uint32_t queryIndex); void setQueryPool(const QueryPool *queryPool, uint32_t queryIndex);
void addGlobalMemoryBarrier(VkFlags srcAccess, VkFlags dstAccess);
private: private:
void setHasChildren(); void setHasChildren();
...@@ -142,6 +144,10 @@ class CommandGraphNode final : angle::NonCopyable ...@@ -142,6 +144,10 @@ class CommandGraphNode final : angle::NonCopyable
// Additional diagnostic information. // Additional diagnostic information.
CommandGraphResourceType mResourceType; CommandGraphResourceType mResourceType;
uintptr_t mResourceID; uintptr_t mResourceID;
// For global memory barriers.
VkFlags mGlobalMemoryBarrierSrcAccess;
VkFlags mGlobalMemoryBarrierDstAccess;
}; };
// This is a helper class for back-end objects used in Vk command buffers. It records a serial // This is a helper class for back-end objects used in Vk command buffers. It records a serial
...@@ -214,11 +220,17 @@ class RecordableGraphResource : public CommandGraphResource ...@@ -214,11 +220,17 @@ class RecordableGraphResource : public CommandGraphResource
// Called when 'this' object changes, but we'd like to start a new command buffer later. // Called when 'this' object changes, but we'd like to start a new command buffer later.
void finishCurrentCommands(RendererVk *renderer); void finishCurrentCommands(RendererVk *renderer);
// Store a deferred memory barrier. Will be recorded into a primary command buffer at submit.
void addGlobalMemoryBarrier(VkFlags srcAccess, VkFlags dstAccess)
{
ASSERT(mCurrentWritingNode);
mCurrentWritingNode->addGlobalMemoryBarrier(srcAccess, dstAccess);
}
protected: protected:
explicit RecordableGraphResource(CommandGraphResourceType resourceType); explicit RecordableGraphResource(CommandGraphResourceType resourceType);
private: private:
// Returns true if this node has a current writing node with no children. // Returns true if this node has a current writing node with no children.
bool hasChildlessWritingNode() const bool hasChildlessWritingNode() const
{ {
......
...@@ -428,14 +428,19 @@ angle::Result ContextVk::handleDirtyVertexBuffers(const gl::Context *context, ...@@ -428,14 +428,19 @@ angle::Result ContextVk::handleDirtyVertexBuffers(const gl::Context *context,
mProgram->getState().getMaxActiveAttribLocation(), mProgram->getState().getMaxActiveAttribLocation(),
mVertexArray->getCurrentArrayBufferHandles(), mVertexArray->getCurrentArrayBufferOffsets()); mVertexArray->getCurrentArrayBufferHandles(), mVertexArray->getCurrentArrayBufferOffsets());
const auto &arrayBufferResources = mVertexArray->getCurrentArrayBufferResources(); const auto &arrayBufferResources = mVertexArray->getCurrentArrayBuffers();
vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer();
for (size_t attribIndex : context->getStateCache().getActiveBufferedAttribsMask()) for (size_t attribIndex : context->getStateCache().getActiveBufferedAttribsMask())
{ {
if (arrayBufferResources[attribIndex]) vk::BufferHelper *arrayBuffer = arrayBufferResources[attribIndex];
arrayBufferResources[attribIndex]->addReadDependency( if (arrayBuffer)
mDrawFramebuffer->getFramebuffer()); {
arrayBuffer->onFramebufferRead(framebuffer, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
}
} }
return angle::Result::Continue(); return angle::Result::Continue();
} }
...@@ -446,11 +451,11 @@ angle::Result ContextVk::handleDirtyIndexBuffer(const gl::Context *context, ...@@ -446,11 +451,11 @@ angle::Result ContextVk::handleDirtyIndexBuffer(const gl::Context *context,
mVertexArray->getCurrentElementArrayBufferOffset(), mVertexArray->getCurrentElementArrayBufferOffset(),
gl_vk::GetIndexType(mCurrentDrawElementsType)); gl_vk::GetIndexType(mCurrentDrawElementsType));
vk::RecordableGraphResource *elementArrayBufferResource = vk::BufferHelper *elementArrayBuffer = mVertexArray->getCurrentElementArrayBuffer();
mVertexArray->getCurrentElementArrayBufferResource(); if (elementArrayBuffer)
if (elementArrayBufferResource)
{ {
elementArrayBufferResource->addReadDependency(mDrawFramebuffer->getFramebuffer()); vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer();
elementArrayBuffer->onFramebufferRead(framebuffer, VK_ACCESS_INDEX_READ_BIT);
} }
return angle::Result::Continue(); return angle::Result::Continue();
} }
......
...@@ -64,7 +64,7 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend ...@@ -64,7 +64,7 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend
: VertexArrayImpl(state), : VertexArrayImpl(state),
mCurrentArrayBufferHandles{}, mCurrentArrayBufferHandles{},
mCurrentArrayBufferOffsets{}, mCurrentArrayBufferOffsets{},
mCurrentArrayBufferResources{}, mCurrentArrayBuffers{},
mCurrentArrayBufferFormats{}, mCurrentArrayBufferFormats{},
mCurrentArrayBufferStrides{}, mCurrentArrayBufferStrides{},
mCurrentArrayBufferConversion{{ mCurrentArrayBufferConversion{{
...@@ -74,7 +74,7 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend ...@@ -74,7 +74,7 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend
mCurrentArrayBufferConversionCanRelease{}, mCurrentArrayBufferConversionCanRelease{},
mCurrentElementArrayBufferHandle(VK_NULL_HANDLE), mCurrentElementArrayBufferHandle(VK_NULL_HANDLE),
mCurrentElementArrayBufferOffset(0), mCurrentElementArrayBufferOffset(0),
mCurrentElementArrayBufferResource(nullptr), mCurrentElementArrayBuffer(nullptr),
mPackedInputBindings{}, mPackedInputBindings{},
mPackedInputAttributes{}, mPackedInputAttributes{},
mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize), mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize),
...@@ -85,7 +85,7 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend ...@@ -85,7 +85,7 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend
{ {
mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE); mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
mCurrentArrayBufferOffsets.fill(0); mCurrentArrayBufferOffsets.fill(0);
mCurrentArrayBufferResources.fill(nullptr); mCurrentArrayBuffers.fill(nullptr);
for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion) for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
{ {
...@@ -253,15 +253,15 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context, ...@@ -253,15 +253,15 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context,
gl::Buffer *bufferGL = mState.getElementArrayBuffer(); gl::Buffer *bufferGL = mState.getElementArrayBuffer();
if (bufferGL) if (bufferGL)
{ {
BufferVk *bufferVk = vk::GetImpl(bufferGL); BufferVk *bufferVk = vk::GetImpl(bufferGL);
mCurrentElementArrayBufferResource = &bufferVk->getBuffer(); mCurrentElementArrayBuffer = &bufferVk->getBuffer();
mCurrentElementArrayBufferHandle = mCurrentElementArrayBufferHandle =
bufferVk->getBuffer().getBuffer().getHandle(); bufferVk->getBuffer().getBuffer().getHandle();
} }
else else
{ {
mCurrentElementArrayBufferResource = nullptr; mCurrentElementArrayBuffer = nullptr;
mCurrentElementArrayBufferHandle = VK_NULL_HANDLE; mCurrentElementArrayBufferHandle = VK_NULL_HANDLE;
} }
mCurrentElementArrayBufferOffset = 0; mCurrentElementArrayBufferOffset = 0;
...@@ -326,12 +326,12 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -326,12 +326,12 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
ANGLE_TRY(convertVertexBuffer(contextVk, bufferVk, binding, attribIndex)); ANGLE_TRY(convertVertexBuffer(contextVk, bufferVk, binding, attribIndex));
mCurrentArrayBufferResources[attribIndex] = nullptr; mCurrentArrayBuffers[attribIndex] = nullptr;
releaseConversion = false; releaseConversion = false;
} }
else else
{ {
mCurrentArrayBufferResources[attribIndex] = &bufferVk->getBuffer(); mCurrentArrayBuffers[attribIndex] = &bufferVk->getBuffer();
mCurrentArrayBufferHandles[attribIndex] = mCurrentArrayBufferHandles[attribIndex] =
bufferVk->getBuffer().getBuffer().getHandle(); bufferVk->getBuffer().getBuffer().getHandle();
mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset(); mCurrentArrayBufferOffsets[attribIndex] = binding.getOffset();
...@@ -340,9 +340,9 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -340,9 +340,9 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
} }
else else
{ {
mCurrentArrayBufferResources[attribIndex] = nullptr; mCurrentArrayBuffers[attribIndex] = nullptr;
mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE; mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
mCurrentArrayBufferOffsets[attribIndex] = 0; mCurrentArrayBufferOffsets[attribIndex] = 0;
mCurrentArrayBufferStrides[attribIndex] = mCurrentArrayBufferStrides[attribIndex] =
mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes; mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
} }
...@@ -352,10 +352,10 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -352,10 +352,10 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
contextVk->invalidateDefaultAttribute(attribIndex); contextVk->invalidateDefaultAttribute(attribIndex);
// These will be filled out by the ContextVk. // These will be filled out by the ContextVk.
mCurrentArrayBufferResources[attribIndex] = nullptr; mCurrentArrayBuffers[attribIndex] = nullptr;
mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE; mCurrentArrayBufferHandles[attribIndex] = VK_NULL_HANDLE;
mCurrentArrayBufferOffsets[attribIndex] = 0; mCurrentArrayBufferOffsets[attribIndex] = 0;
mCurrentArrayBufferStrides[attribIndex] = 0; mCurrentArrayBufferStrides[attribIndex] = 0;
mCurrentArrayBufferFormats[attribIndex] = mCurrentArrayBufferFormats[attribIndex] =
&renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT); &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
} }
...@@ -582,10 +582,10 @@ void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer, ...@@ -582,10 +582,10 @@ void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
{ {
if (!mState.getEnabledAttributesMask().test(attribIndex)) if (!mState.getEnabledAttributesMask().test(attribIndex))
{ {
mCurrentArrayBufferHandles[attribIndex] = bufferHandle; mCurrentArrayBufferHandles[attribIndex] = bufferHandle;
mCurrentArrayBufferOffsets[attribIndex] = offset; mCurrentArrayBufferOffsets[attribIndex] = offset;
mCurrentArrayBufferResources[attribIndex] = nullptr; mCurrentArrayBuffers[attribIndex] = nullptr;
mCurrentArrayBufferStrides[attribIndex] = 0; mCurrentArrayBufferStrides[attribIndex] = 0;
mCurrentArrayBufferFormats[attribIndex] = mCurrentArrayBufferFormats[attribIndex] =
&renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED); &renderer->getFormat(angle::FormatID::R32G32B32A32_FIXED);
mDirtyPackedInputs.set(attribIndex); mDirtyPackedInputs.set(attribIndex);
......
...@@ -65,9 +65,9 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -65,9 +65,9 @@ class VertexArrayVk : public VertexArrayImpl
return mCurrentArrayBufferOffsets; return mCurrentArrayBufferOffsets;
} }
const gl::AttribArray<vk::RecordableGraphResource *> &getCurrentArrayBufferResources() const const gl::AttribArray<vk::BufferHelper *> &getCurrentArrayBuffers() const
{ {
return mCurrentArrayBufferResources; return mCurrentArrayBuffers;
} }
VkBuffer getCurrentElementArrayBufferHandle() const { return mCurrentElementArrayBufferHandle; } VkBuffer getCurrentElementArrayBufferHandle() const { return mCurrentElementArrayBufferHandle; }
...@@ -82,10 +82,7 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -82,10 +82,7 @@ class VertexArrayVk : public VertexArrayImpl
mCurrentElementArrayBufferOffset = reinterpret_cast<VkDeviceSize>(offset); mCurrentElementArrayBufferOffset = reinterpret_cast<VkDeviceSize>(offset);
} }
vk::RecordableGraphResource *getCurrentElementArrayBufferResource() const vk::BufferHelper *getCurrentElementArrayBuffer() const { return mCurrentElementArrayBuffer; }
{
return mCurrentElementArrayBufferResource;
}
angle::Result updateIndexTranslation(ContextVk *contextVk, angle::Result updateIndexTranslation(ContextVk *contextVk,
GLsizei indexCount, GLsizei indexCount,
...@@ -121,14 +118,14 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -121,14 +118,14 @@ class VertexArrayVk : public VertexArrayImpl
gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles; gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles;
gl::AttribArray<VkDeviceSize> mCurrentArrayBufferOffsets; gl::AttribArray<VkDeviceSize> mCurrentArrayBufferOffsets;
gl::AttribArray<vk::RecordableGraphResource *> mCurrentArrayBufferResources; gl::AttribArray<vk::BufferHelper *> mCurrentArrayBuffers;
gl::AttribArray<const vk::Format *> mCurrentArrayBufferFormats; gl::AttribArray<const vk::Format *> mCurrentArrayBufferFormats;
gl::AttribArray<GLuint> mCurrentArrayBufferStrides; gl::AttribArray<GLuint> mCurrentArrayBufferStrides;
gl::AttribArray<vk::DynamicBuffer> mCurrentArrayBufferConversion; gl::AttribArray<vk::DynamicBuffer> mCurrentArrayBufferConversion;
gl::AttribArray<bool> mCurrentArrayBufferConversionCanRelease; gl::AttribArray<bool> mCurrentArrayBufferConversionCanRelease;
VkBuffer mCurrentElementArrayBufferHandle; VkBuffer mCurrentElementArrayBufferHandle;
VkDeviceSize mCurrentElementArrayBufferOffset; VkDeviceSize mCurrentElementArrayBufferOffset;
vk::RecordableGraphResource *mCurrentElementArrayBufferResource; vk::BufferHelper *mCurrentElementArrayBuffer;
// Keep a cache of binding and attribute descriptions for easy pipeline updates. // Keep a cache of binding and attribute descriptions for easy pipeline updates.
// This is copied out of here into the pipeline description on a Context state change. // This is copied out of here into the pipeline description on a Context state change.
......
...@@ -887,7 +887,10 @@ void LineLoopHelper::Draw(uint32_t count, CommandBuffer *commandBuffer) ...@@ -887,7 +887,10 @@ void LineLoopHelper::Draw(uint32_t count, CommandBuffer *commandBuffer)
// BufferHelper implementation. // BufferHelper implementation.
BufferHelper::BufferHelper() BufferHelper::BufferHelper()
: RecordableGraphResource(CommandGraphResourceType::Buffer), mMemoryPropertyFlags{} : RecordableGraphResource(CommandGraphResourceType::Buffer),
mMemoryPropertyFlags{},
mCurrentWriteAccess(0),
mCurrentReadAccess(0)
{ {
} }
...@@ -908,6 +911,47 @@ void BufferHelper::release(RendererVk *renderer) ...@@ -908,6 +911,47 @@ void BufferHelper::release(RendererVk *renderer)
renderer->releaseObject(getStoredQueueSerial(), &mDeviceMemory); renderer->releaseObject(getStoredQueueSerial(), &mDeviceMemory);
} }
void BufferHelper::onFramebufferRead(FramebufferHelper *framebuffer, VkAccessFlagBits accessType)
{
addReadDependency(framebuffer);
if ((mCurrentWriteAccess != 0) && ((mCurrentReadAccess & accessType) == 0))
{
framebuffer->addGlobalMemoryBarrier(mCurrentWriteAccess, accessType);
mCurrentReadAccess |= accessType;
}
}
angle::Result BufferHelper::copyFromBuffer(ContextVk *contextVk,
const Buffer &buffer,
const VkBufferCopy &copyRegion)
{
// 'recordCommands' will implicitly stop any reads from using the old buffer data.
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(recordCommands(contextVk, &commandBuffer));
if (mCurrentReadAccess != 0 || mCurrentWriteAccess != 0)
{
// Insert a barrier to ensure reads/writes are complete.
// Use a global memory barrier to keep things simple.
VkMemoryBarrier memoryBarrier = {};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.srcAccessMask = mCurrentReadAccess;
memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &memoryBarrier, 0,
nullptr, 0, nullptr);
mCurrentWriteAccess = VK_ACCESS_TRANSFER_WRITE_BIT;
mCurrentReadAccess = 0;
}
commandBuffer->copyBuffer(buffer, mBuffer, 1, &copyRegion);
return angle::Result::Continue();
}
// ImageHelper implementation. // ImageHelper implementation.
ImageHelper::ImageHelper() ImageHelper::ImageHelper()
: RecordableGraphResource(CommandGraphResourceType::Image), : RecordableGraphResource(CommandGraphResourceType::Image),
......
...@@ -369,6 +369,8 @@ class LineLoopHelper final : angle::NonCopyable ...@@ -369,6 +369,8 @@ class LineLoopHelper final : angle::NonCopyable
DynamicBuffer mDynamicIndexBuffer; DynamicBuffer mDynamicIndexBuffer;
}; };
class FramebufferHelper;
class BufferHelper final : public RecordableGraphResource class BufferHelper final : public RecordableGraphResource
{ {
public: public:
...@@ -384,6 +386,14 @@ class BufferHelper final : public RecordableGraphResource ...@@ -384,6 +386,14 @@ class BufferHelper final : public RecordableGraphResource
const Buffer &getBuffer() const { return mBuffer; } const Buffer &getBuffer() const { return mBuffer; }
const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; } const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; }
// Helper for setting the graph dependencies *and* setting the appropriate barrier.
void onFramebufferRead(FramebufferHelper *framebuffer, VkAccessFlagBits accessType);
// Also implicitly sets up the correct barriers.
angle::Result copyFromBuffer(ContextVk *contextVk,
const Buffer &buffer,
const VkBufferCopy &copyRegion);
private: private:
// Vulkan objects. // Vulkan objects.
Buffer mBuffer; Buffer mBuffer;
...@@ -391,6 +401,10 @@ class BufferHelper final : public RecordableGraphResource ...@@ -391,6 +401,10 @@ class BufferHelper final : public RecordableGraphResource
// Cached properties. // Cached properties.
VkMemoryPropertyFlags mMemoryPropertyFlags; VkMemoryPropertyFlags mMemoryPropertyFlags;
// For memory barriers.
VkFlags mCurrentWriteAccess;
VkFlags mCurrentReadAccess;
}; };
class ImageHelper final : public RecordableGraphResource class ImageHelper final : public RecordableGraphResource
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment