Commit 20b1259a by Jamie Madill Committed by Commit Bot

Vulkan: Command graph linearization (Step 2).

ES 2.0 is feature complete. Passes all of the angle_end2end_tests with the new linear command recording method. Also runs the T-Rex benchmark without any obvious glitches. Likely has issues with creating too many RenderPasses. ES3 is mostly untouched. Bug: angleproject:4029 Change-Id: Ic5acf3d768495fbffd07b07bf0a6f2b5787c51f8 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2012900Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 806ba566
...@@ -229,8 +229,8 @@ angle::Result BufferVk::copySubData(const gl::Context *context, ...@@ -229,8 +229,8 @@ angle::Result BufferVk::copySubData(const gl::Context *context,
} }
else else
{ {
contextVk->onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, &sourceBuffer->getBuffer()); ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, &sourceBuffer->getBuffer()));
contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, &mBuffer); ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, &mBuffer));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer)); ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
} }
...@@ -421,8 +421,8 @@ angle::Result BufferVk::copyToBuffer(ContextVk *contextVk, ...@@ -421,8 +421,8 @@ angle::Result BufferVk::copyToBuffer(ContextVk *contextVk,
} }
else else
{ {
contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, destBuffer); ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, destBuffer));
contextVk->onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, &mBuffer); ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, &mBuffer));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer)); ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
} }
......
...@@ -786,7 +786,8 @@ angle::Result ContextVk::setupDraw(const gl::Context *context, ...@@ -786,7 +786,8 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits; mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
gl::Rectangle scissoredRenderArea = mDrawFramebuffer->getScissoredRenderArea(this); gl::Rectangle scissoredRenderArea = mDrawFramebuffer->getScissoredRenderArea(this);
if (!mDrawFramebuffer->appendToStartedRenderPass(&mResourceUseList, scissoredRenderArea, if (!commandGraphEnabled() ||
!mDrawFramebuffer->appendToStartedRenderPass(&mResourceUseList, scissoredRenderArea,
&mRenderPassCommandBuffer)) &mRenderPassCommandBuffer))
{ {
ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, scissoredRenderArea, ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, scissoredRenderArea,
...@@ -1142,19 +1143,28 @@ angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(const gl::Context *con ...@@ -1142,19 +1143,28 @@ angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(const gl::Context *con
vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer(); vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer();
// Mark all active vertex buffers as accessed by the graph. // Mark all active vertex buffers as accessed by the graph.
gl::AttributesMask attribsMask = mProgram->getState().getActiveAttribLocationsMask(); if (commandGraphEnabled())
for (size_t attribIndex : attribsMask)
{ {
vk::BufferHelper *arrayBuffer = arrayBufferResources[attribIndex]; gl::AttributesMask attribsMask = mProgram->getState().getActiveAttribLocationsMask();
if (arrayBuffer) for (size_t attribIndex : attribsMask)
{ {
if (commandGraphEnabled()) vk::BufferHelper *arrayBuffer = arrayBufferResources[attribIndex];
if (arrayBuffer)
{ {
arrayBuffer->onRead(this, framebuffer, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT); arrayBuffer->onRead(this, framebuffer, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
} }
else }
}
else
{
gl::AttributesMask attribsMask = mProgram->getState().getActiveAttribLocationsMask();
for (size_t attribIndex : attribsMask)
{
vk::BufferHelper *arrayBuffer = arrayBufferResources[attribIndex];
if (arrayBuffer)
{ {
onBufferRead(VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, arrayBuffer); mRenderPassCommands.bufferRead(&mResourceUseList,
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, arrayBuffer);
} }
} }
} }
...@@ -1179,7 +1189,8 @@ angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(const gl::Context *conte ...@@ -1179,7 +1189,8 @@ angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(const gl::Context *conte
} }
else else
{ {
onBufferRead(VK_ACCESS_INDEX_READ_BIT, elementArrayBuffer); mRenderPassCommands.bufferRead(&mResourceUseList, VK_ACCESS_INDEX_READ_BIT,
elementArrayBuffer);
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -2242,7 +2253,7 @@ void ContextVk::updateDepthRange(float nearPlane, float farPlane) ...@@ -2242,7 +2253,7 @@ void ContextVk::updateDepthRange(float nearPlane, float farPlane)
mGraphicsPipelineDesc->updateDepthRange(&mGraphicsPipelineTransition, nearPlane, farPlane); mGraphicsPipelineDesc->updateDepthRange(&mGraphicsPipelineTransition, nearPlane, farPlane);
} }
void ContextVk::updateScissor(const gl::State &glState) angle::Result ContextVk::updateScissor(const gl::State &glState)
{ {
FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer()); FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
gl::Rectangle renderArea = framebufferVk->getCompleteRenderArea(); gl::Rectangle renderArea = framebufferVk->getCompleteRenderArea();
...@@ -2260,7 +2271,39 @@ void ContextVk::updateScissor(const gl::State &glState) ...@@ -2260,7 +2271,39 @@ void ContextVk::updateScissor(const gl::State &glState)
mGraphicsPipelineDesc->updateScissor(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateScissor(&mGraphicsPipelineTransition,
gl_vk::GetRect(scissoredArea)); gl_vk::GetRect(scissoredArea));
framebufferVk->onScissorChange(this); // If the scissor has grown beyond the previous scissoredRenderArea, make sure the render pass
// is restarted. Otherwise, we can continue using the same renderpass area.
//
// Without a scissor, the render pass area covers the whole of the framebuffer. With a
// scissored clear, the render pass area could be smaller than the framebuffer size. When the
// scissor changes, if the scissor area is completely encompassed by the render pass area, it's
// possible to continue using the same render pass. However, if the current render pass area
// is too small, we need to start a new one. The latter can happen if a scissored clear starts
// a render pass, the scissor is disabled and a draw call is issued to affect the whole
// framebuffer.
gl::Rectangle scissoredRenderArea = framebufferVk->getScissoredRenderArea(this);
if (commandGraphEnabled())
{
vk::FramebufferHelper *framebuffer = framebufferVk->getFramebuffer();
framebuffer->updateCurrentAccessNodes();
if (framebuffer->hasStartedRenderPass() &&
!framebuffer->getRenderPassRenderArea().encloses(scissoredRenderArea))
{
framebuffer->finishCurrentCommands(this);
}
}
else
{
if (!mRenderPassCommands.empty())
{
if (!mRenderPassCommands.getRenderArea().encloses(scissoredRenderArea))
{
ANGLE_TRY(endRenderPass());
}
}
}
return angle::Result::Continue;
} }
angle::Result ContextVk::syncState(const gl::Context *context, angle::Result ContextVk::syncState(const gl::Context *context,
...@@ -2282,7 +2325,7 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2282,7 +2325,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
{ {
case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
case gl::State::DIRTY_BIT_SCISSOR: case gl::State::DIRTY_BIT_SCISSOR:
updateScissor(glState); ANGLE_TRY(updateScissor(glState));
break; break;
case gl::State::DIRTY_BIT_VIEWPORT: case gl::State::DIRTY_BIT_VIEWPORT:
{ {
...@@ -2290,7 +2333,7 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2290,7 +2333,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
updateViewport(framebufferVk, glState.getViewport(), glState.getNearPlane(), updateViewport(framebufferVk, glState.getViewport(), glState.getNearPlane(),
glState.getFarPlane(), isViewportFlipEnabledForDrawFBO()); glState.getFarPlane(), isViewportFlipEnabledForDrawFBO());
// Update the scissor, which will be constrained to the viewport // Update the scissor, which will be constrained to the viewport
updateScissor(glState); ANGLE_TRY(updateScissor(glState));
break; break;
} }
case gl::State::DIRTY_BIT_DEPTH_RANGE: case gl::State::DIRTY_BIT_DEPTH_RANGE:
...@@ -2465,7 +2508,7 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2465,7 +2508,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition,
glState.getRasterizerState(), glState.getRasterizerState(),
isViewportFlipEnabledForDrawFBO()); isViewportFlipEnabledForDrawFBO());
updateScissor(glState); ANGLE_TRY(updateScissor(glState));
const gl::DepthStencilState depthStencilState = glState.getDepthStencilState(); const gl::DepthStencilState depthStencilState = glState.getDepthStencilState();
mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition,
depthStencilState, drawFramebuffer); depthStencilState, drawFramebuffer);
...@@ -3266,21 +3309,20 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -3266,21 +3309,20 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
} }
// Ensure the image is in read-only layout // Ensure the image is in read-only layout
if (image.isLayoutChangeNecessary(textureLayout)) if (commandGraphEnabled())
{ {
vk::CommandBuffer *srcLayoutChange; if (image.isLayoutChangeNecessary(textureLayout))
if (commandGraphEnabled())
{ {
vk::CommandBuffer *srcLayoutChange;
VkImageAspectFlags aspectFlags = image.getAspectFlags();
ASSERT(aspectFlags != 0);
ANGLE_TRY(image.recordCommands(this, &srcLayoutChange)); ANGLE_TRY(image.recordCommands(this, &srcLayoutChange));
image.changeLayout(aspectFlags, textureLayout, srcLayoutChange);
} }
else }
{ else
ANGLE_TRY(getOutsideRenderPassCommandBuffer(&srcLayoutChange)); {
} ANGLE_TRY(onImageRead(image.getAspectFlags(), textureLayout, &image));
VkImageAspectFlags aspectFlags = image.getAspectFlags();
ASSERT(aspectFlags != 0);
image.changeLayout(aspectFlags, textureLayout, srcLayoutChange);
} }
textureVk->onImageViewUse(&mResourceUseList); textureVk->onImageViewUse(&mResourceUseList);
...@@ -3421,7 +3463,7 @@ angle::Result ContextVk::flushImpl(const vk::Semaphore *signalSemaphore) ...@@ -3421,7 +3463,7 @@ angle::Result ContextVk::flushImpl(const vk::Semaphore *signalSemaphore)
else else
{ {
mOutsideRenderPassCommands.flushToPrimary(&mPrimaryCommands); mOutsideRenderPassCommands.flushToPrimary(&mPrimaryCommands);
ANGLE_TRY(mRenderPassCommands.flushToPrimary(this, &mPrimaryCommands)); ANGLE_TRY(endRenderPass());
ANGLE_VK_TRY(this, mPrimaryCommands.end()); ANGLE_VK_TRY(this, mPrimaryCommands.end());
Serial serial = getCurrentQueueSerial(); Serial serial = getCurrentQueueSerial();
...@@ -3715,24 +3757,74 @@ bool ContextVk::shouldUseOldRewriteStructSamplers() const ...@@ -3715,24 +3757,74 @@ bool ContextVk::shouldUseOldRewriteStructSamplers() const
return mRenderer->getFeatures().forceOldRewriteStructSamplers.enabled; return mRenderer->getFeatures().forceOldRewriteStructSamplers.enabled;
} }
void ContextVk::onBufferRead(VkAccessFlags readAccessType, vk::BufferHelper *buffer) angle::Result ContextVk::onBufferRead(VkAccessFlags readAccessType, vk::BufferHelper *buffer)
{ {
ASSERT(!commandGraphEnabled());
ANGLE_TRY(endRenderPass());
if (!buffer->canAccumulateRead(this, readAccessType)) if (!buffer->canAccumulateRead(this, readAccessType))
{ {
mOutsideRenderPassCommands.flushToPrimary(&mPrimaryCommands); mOutsideRenderPassCommands.flushToPrimary(&mPrimaryCommands);
} }
mOutsideRenderPassCommands.bufferRead(readAccessType, buffer); mOutsideRenderPassCommands.bufferRead(&mResourceUseList, readAccessType, buffer);
return angle::Result::Continue;
} }
void ContextVk::onBufferWrite(VkAccessFlags writeAccessType, vk::BufferHelper *buffer) angle::Result ContextVk::onBufferWrite(VkAccessFlags writeAccessType, vk::BufferHelper *buffer)
{ {
ASSERT(!commandGraphEnabled());
ANGLE_TRY(endRenderPass());
if (!buffer->canAccumulateWrite(this, writeAccessType)) if (!buffer->canAccumulateWrite(this, writeAccessType))
{ {
mOutsideRenderPassCommands.flushToPrimary(&mPrimaryCommands); mOutsideRenderPassCommands.flushToPrimary(&mPrimaryCommands);
} }
mOutsideRenderPassCommands.bufferWrite(writeAccessType, buffer); mOutsideRenderPassCommands.bufferWrite(&mResourceUseList, writeAccessType, buffer);
return angle::Result::Continue;
}
angle::Result ContextVk::onImageRead(VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image)
{
ASSERT(!commandGraphEnabled());
ANGLE_TRY(endRenderPass());
if (image->isLayoutChangeNecessary(imageLayout))
{
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(getOutsideRenderPassCommandBuffer(&commandBuffer));
image->changeLayout(aspectFlags, imageLayout, commandBuffer);
}
image->onResourceAccess(&mResourceUseList);
return angle::Result::Continue;
}
angle::Result ContextVk::onImageWrite(VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image)
{
ASSERT(!commandGraphEnabled());
ANGLE_TRY(endRenderPass());
// Barriers are always required for image writes.
ASSERT(image->isLayoutChangeNecessary(imageLayout));
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(getOutsideRenderPassCommandBuffer(&commandBuffer));
image->changeLayout(aspectFlags, imageLayout, commandBuffer);
image->onResourceAccess(&mResourceUseList);
return angle::Result::Continue;
} }
void ContextVk::beginRenderPass(const vk::Framebuffer &framebuffer, void ContextVk::beginRenderPass(const vk::Framebuffer &framebuffer,
...@@ -3742,6 +3834,8 @@ void ContextVk::beginRenderPass(const vk::Framebuffer &framebuffer, ...@@ -3742,6 +3834,8 @@ void ContextVk::beginRenderPass(const vk::Framebuffer &framebuffer,
const std::vector<VkClearValue> &clearValues, const std::vector<VkClearValue> &clearValues,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut)
{ {
ASSERT(!commandGraphEnabled());
if (!mOutsideRenderPassCommands.empty()) if (!mOutsideRenderPassCommands.empty())
{ {
mOutsideRenderPassCommands.flushToPrimary(&mPrimaryCommands); mOutsideRenderPassCommands.flushToPrimary(&mPrimaryCommands);
...@@ -3751,62 +3845,85 @@ void ContextVk::beginRenderPass(const vk::Framebuffer &framebuffer, ...@@ -3751,62 +3845,85 @@ void ContextVk::beginRenderPass(const vk::Framebuffer &framebuffer,
renderPassAttachmentOps, clearValues, commandBufferOut); renderPassAttachmentOps, clearValues, commandBufferOut);
} }
OutsideRenderPassCommandBuffer::OutsideRenderPassCommandBuffer() angle::Result ContextVk::endRenderPass()
{
ASSERT(!commandGraphEnabled());
onRenderPassFinished();
return mRenderPassCommands.flushToPrimary(this, &mPrimaryCommands);
}
CommandBufferHelper::CommandBufferHelper()
: mGlobalMemoryBarrierSrcAccess(0), : mGlobalMemoryBarrierSrcAccess(0),
mGlobalMemoryBarrierDstAccess(0), mGlobalMemoryBarrierDstAccess(0),
mGlobalMemoryBarrierStages(0) mGlobalMemoryBarrierStages(0)
{} {}
OutsideRenderPassCommandBuffer::~OutsideRenderPassCommandBuffer() = default; CommandBufferHelper::~CommandBufferHelper() = default;
void OutsideRenderPassCommandBuffer::flushToPrimary(vk::PrimaryCommandBuffer *primary)
{
if (empty())
return;
if (mGlobalMemoryBarrierSrcAccess)
{
VkMemoryBarrier memoryBarrier = {};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.srcAccessMask = mGlobalMemoryBarrierSrcAccess;
memoryBarrier.dstAccessMask = mGlobalMemoryBarrierDstAccess;
primary->memoryBarrier(mGlobalMemoryBarrierStages, mGlobalMemoryBarrierStages,
&memoryBarrier);
}
mCommandBuffer.executeCommands(primary->getHandle());
// Restart secondary buffer.
reset();
}
void OutsideRenderPassCommandBuffer::bufferRead(VkAccessFlags readAccessType, void CommandBufferHelper::bufferRead(vk::ResourceUseList *resourceUseList,
vk::BufferHelper *buffer) VkAccessFlags readAccessType,
vk::BufferHelper *buffer)
{ {
buffer->onResourceAccess(resourceUseList);
buffer->updateReadBarrier(readAccessType, &mGlobalMemoryBarrierSrcAccess, buffer->updateReadBarrier(readAccessType, &mGlobalMemoryBarrierSrcAccess,
&mGlobalMemoryBarrierDstAccess); &mGlobalMemoryBarrierDstAccess);
mGlobalMemoryBarrierStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; mGlobalMemoryBarrierStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
} }
void OutsideRenderPassCommandBuffer::bufferWrite(VkAccessFlags writeAccessType, void CommandBufferHelper::bufferWrite(vk::ResourceUseList *resourceUseList,
vk::BufferHelper *buffer) VkAccessFlags writeAccessType,
vk::BufferHelper *buffer)
{ {
buffer->onResourceAccess(resourceUseList);
buffer->updateWriteBarrier(writeAccessType, &mGlobalMemoryBarrierSrcAccess, buffer->updateWriteBarrier(writeAccessType, &mGlobalMemoryBarrierSrcAccess,
&mGlobalMemoryBarrierDstAccess); &mGlobalMemoryBarrierDstAccess);
mGlobalMemoryBarrierStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; mGlobalMemoryBarrierStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
} }
void OutsideRenderPassCommandBuffer::reset() void CommandBufferHelper::recordBarrier(vk::PrimaryCommandBuffer *primary)
{ {
if (mGlobalMemoryBarrierSrcAccess == 0)
{
return;
}
VkMemoryBarrier memoryBarrier = {};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.srcAccessMask = mGlobalMemoryBarrierSrcAccess;
memoryBarrier.dstAccessMask = mGlobalMemoryBarrierDstAccess;
primary->memoryBarrier(mGlobalMemoryBarrierStages, mGlobalMemoryBarrierStages, &memoryBarrier);
mGlobalMemoryBarrierSrcAccess = 0; mGlobalMemoryBarrierSrcAccess = 0;
mGlobalMemoryBarrierDstAccess = 0; mGlobalMemoryBarrierDstAccess = 0;
mGlobalMemoryBarrierStages = 0; mGlobalMemoryBarrierStages = 0;
}
OutsideRenderPassCommandBuffer::OutsideRenderPassCommandBuffer() = default;
OutsideRenderPassCommandBuffer::~OutsideRenderPassCommandBuffer() = default;
void OutsideRenderPassCommandBuffer::flushToPrimary(vk::PrimaryCommandBuffer *primary)
{
if (empty())
return;
recordBarrier(primary);
mCommandBuffer.executeCommands(primary->getHandle());
// Restart secondary buffer.
reset();
}
void OutsideRenderPassCommandBuffer::reset()
{
mCommandBuffer.reset(); mCommandBuffer.reset();
} }
RenderPassCommandBuffer::RenderPassCommandBuffer() : mCounter(0) {} RenderPassCommandBuffer::RenderPassCommandBuffer()
: mCounter(0), mClearValues{}, mRenderPassStarted(false)
{}
RenderPassCommandBuffer::~RenderPassCommandBuffer() RenderPassCommandBuffer::~RenderPassCommandBuffer()
{ {
...@@ -3834,6 +3951,8 @@ void RenderPassCommandBuffer::beginRenderPass(const vk::Framebuffer &framebuffer ...@@ -3834,6 +3951,8 @@ void RenderPassCommandBuffer::beginRenderPass(const vk::Framebuffer &framebuffer
std::copy(clearValues.begin(), clearValues.end(), mClearValues.begin()); std::copy(clearValues.begin(), clearValues.end(), mClearValues.begin());
*commandBufferOut = &mCommandBuffer; *commandBufferOut = &mCommandBuffer;
mRenderPassStarted = true;
} }
angle::Result RenderPassCommandBuffer::flushToPrimary(ContextVk *contextVk, angle::Result RenderPassCommandBuffer::flushToPrimary(ContextVk *contextVk,
...@@ -3842,6 +3961,8 @@ angle::Result RenderPassCommandBuffer::flushToPrimary(ContextVk *contextVk, ...@@ -3842,6 +3961,8 @@ angle::Result RenderPassCommandBuffer::flushToPrimary(ContextVk *contextVk,
if (empty()) if (empty())
return angle::Result::Continue; return angle::Result::Continue;
recordBarrier(primary);
// Pull a RenderPass from the cache. // Pull a RenderPass from the cache.
RenderPassCache &renderPassCache = contextVk->getRenderPassCache(); RenderPassCache &renderPassCache = contextVk->getRenderPassCache();
Serial serial = contextVk->getCurrentQueueSerial(); Serial serial = contextVk->getCurrentQueueSerial();
...@@ -3875,5 +3996,6 @@ angle::Result RenderPassCommandBuffer::flushToPrimary(ContextVk *contextVk, ...@@ -3875,5 +3996,6 @@ angle::Result RenderPassCommandBuffer::flushToPrimary(ContextVk *contextVk,
void RenderPassCommandBuffer::reset() void RenderPassCommandBuffer::reset()
{ {
mCommandBuffer.reset(); mCommandBuffer.reset();
mRenderPassStarted = false;
} }
} // namespace rx } // namespace rx
...@@ -95,31 +95,43 @@ class CommandQueue final : angle::NonCopyable ...@@ -95,31 +95,43 @@ class CommandQueue final : angle::NonCopyable
vk::PersistentCommandPool mPrimaryCommandPool; vk::PersistentCommandPool mPrimaryCommandPool;
}; };
class OutsideRenderPassCommandBuffer final : angle::NonCopyable struct CommandBufferHelper : angle::NonCopyable
{ {
public: public:
OutsideRenderPassCommandBuffer(); void bufferRead(vk::ResourceUseList *resourceUseList,
~OutsideRenderPassCommandBuffer(); VkAccessFlags readAccessType,
vk::BufferHelper *buffer);
void bufferRead(VkAccessFlags readAccessType, vk::BufferHelper *buffer); void bufferWrite(vk::ResourceUseList *resourceUseList,
void bufferWrite(VkAccessFlags writeAccessType, vk::BufferHelper *buffer); VkAccessFlags writeAccessType,
vk::BufferHelper *buffer);
void flushToPrimary(vk::PrimaryCommandBuffer *primary);
vk::CommandBuffer &getCommandBuffer() { return mCommandBuffer; } vk::CommandBuffer &getCommandBuffer() { return mCommandBuffer; }
bool empty() const { return mCommandBuffer.empty(); } protected:
void reset(); CommandBufferHelper();
~CommandBufferHelper();
void recordBarrier(vk::PrimaryCommandBuffer *primary);
private:
VkFlags mGlobalMemoryBarrierSrcAccess; VkFlags mGlobalMemoryBarrierSrcAccess;
VkFlags mGlobalMemoryBarrierDstAccess; VkFlags mGlobalMemoryBarrierDstAccess;
VkPipelineStageFlags mGlobalMemoryBarrierStages; VkPipelineStageFlags mGlobalMemoryBarrierStages;
vk::CommandBuffer mCommandBuffer; vk::CommandBuffer mCommandBuffer;
}; };
class RenderPassCommandBuffer final : angle::NonCopyable class OutsideRenderPassCommandBuffer final : public CommandBufferHelper
{
public:
OutsideRenderPassCommandBuffer();
~OutsideRenderPassCommandBuffer();
void flushToPrimary(vk::PrimaryCommandBuffer *primary);
bool empty() const { return mCommandBuffer.empty(); }
void reset();
};
class RenderPassCommandBuffer final : public CommandBufferHelper
{ {
public: public:
RenderPassCommandBuffer(); RenderPassCommandBuffer();
...@@ -167,9 +179,11 @@ class RenderPassCommandBuffer final : angle::NonCopyable ...@@ -167,9 +179,11 @@ class RenderPassCommandBuffer final : angle::NonCopyable
mAttachmentOps[attachmentIndex].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; mAttachmentOps[attachmentIndex].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
} }
const gl::Rectangle &getRenderArea() const { return mRenderArea; }
angle::Result flushToPrimary(ContextVk *contextVk, vk::PrimaryCommandBuffer *primary); angle::Result flushToPrimary(ContextVk *contextVk, vk::PrimaryCommandBuffer *primary);
bool empty() const { return mCommandBuffer.empty(); } bool empty() const { return !mRenderPassStarted; }
void reset(); void reset();
uint32_t getAndResetCounter() uint32_t getAndResetCounter()
...@@ -186,7 +200,7 @@ class RenderPassCommandBuffer final : angle::NonCopyable ...@@ -186,7 +200,7 @@ class RenderPassCommandBuffer final : angle::NonCopyable
vk::Framebuffer mFramebuffer; vk::Framebuffer mFramebuffer;
gl::Rectangle mRenderArea; gl::Rectangle mRenderArea;
gl::AttachmentArray<VkClearValue> mClearValues; gl::AttachmentArray<VkClearValue> mClearValues;
vk::CommandBuffer mCommandBuffer; bool mRenderPassStarted;
}; };
class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassOwner class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassOwner
...@@ -517,7 +531,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO ...@@ -517,7 +531,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
Serial generateTextureSerial() { return mTextureSerialFactory.generate(); } Serial generateTextureSerial() { return mTextureSerialFactory.generate(); }
const vk::TextureDescriptorDesc &getActiveTexturesDesc() const { return mActiveTexturesDesc; } const vk::TextureDescriptorDesc &getActiveTexturesDesc() const { return mActiveTexturesDesc; }
void updateScissor(const gl::State &glState); angle::Result updateScissor(const gl::State &glState);
bool emulateSeamfulCubeMapSampling() const { return mEmulateSeamfulCubeMapSampling; } bool emulateSeamfulCubeMapSampling() const { return mEmulateSeamfulCubeMapSampling; }
...@@ -527,13 +541,22 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO ...@@ -527,13 +541,22 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
vk::ResourceUseList &getResourceUseList() { return mResourceUseList; } vk::ResourceUseList &getResourceUseList() { return mResourceUseList; }
void onBufferRead(VkAccessFlags readAccessType, vk::BufferHelper *buffer); angle::Result onBufferRead(VkAccessFlags readAccessType, vk::BufferHelper *buffer);
void onBufferWrite(VkAccessFlags writeAccessType, vk::BufferHelper *buffer); angle::Result onBufferWrite(VkAccessFlags writeAccessType, vk::BufferHelper *buffer);
angle::Result onImageRead(VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image);
angle::Result onImageWrite(VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image);
angle::Result getOutsideRenderPassCommandBuffer(vk::CommandBuffer **commandBufferOut) angle::Result getOutsideRenderPassCommandBuffer(vk::CommandBuffer **commandBufferOut)
{ {
if (!mRenderPassCommands.empty()) if (!mRenderPassCommands.empty())
{ {
ANGLE_TRY(mRenderPassCommands.flushToPrimary(this, &mPrimaryCommands)); ANGLE_TRY(endRenderPass());
} }
*commandBufferOut = &mOutsideRenderPassCommands.getCommandBuffer(); *commandBufferOut = &mOutsideRenderPassCommands.getCommandBuffer();
return angle::Result::Continue; return angle::Result::Continue;
...@@ -556,6 +579,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO ...@@ -556,6 +579,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
} }
egl::ContextPriority getContextPriority() const override { return mContextPriority; } egl::ContextPriority getContextPriority() const override { return mContextPriority; }
angle::Result endRenderPass();
private: private:
// Dirty bits. // Dirty bits.
......
...@@ -859,19 +859,27 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk, ...@@ -859,19 +859,27 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
const UtilsVk::BlitResolveParameters &params, const UtilsVk::BlitResolveParameters &params,
vk::ImageHelper *srcImage) vk::ImageHelper *srcImage)
{ {
if (srcImage->isLayoutChangeNecessary(vk::ImageLayout::TransferSrc)) vk::CommandBuffer *commandBuffer = nullptr;
if (contextVk->commandGraphEnabled())
{ {
vk::CommandBuffer *srcLayoutChange; if (srcImage->isLayoutChangeNecessary(vk::ImageLayout::TransferSrc))
ANGLE_TRY(srcImage->recordCommands(contextVk, &srcLayoutChange)); {
srcImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc, vk::CommandBuffer *srcLayoutChange;
srcLayoutChange); ANGLE_TRY(srcImage->recordCommands(contextVk, &srcLayoutChange));
} srcImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc,
srcLayoutChange);
}
vk::CommandBuffer *commandBuffer = nullptr; ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
// Source's layout change should happen before rendering // Source's layout change should happen before rendering
srcImage->addReadDependency(contextVk, &mFramebuffer); srcImage->addReadDependency(contextVk, &mFramebuffer);
}
else
{
ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc,
srcImage));
}
VkImageResolve resolveRegion = {}; VkImageResolve resolveRegion = {};
resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
...@@ -893,9 +901,20 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk, ...@@ -893,9 +901,20 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
for (size_t colorIndexGL : mState.getEnabledDrawBuffers()) for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{ {
RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL]; RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
vk::ImageHelper *drawImage = drawRenderTarget->getImageForWrite(contextVk, &mFramebuffer); if (contextVk->commandGraphEnabled())
drawImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst, {
commandBuffer); vk::ImageHelper *drawImage =
drawRenderTarget->getImageForWrite(contextVk, &mFramebuffer);
drawImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst,
commandBuffer);
}
else
{
ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::TransferDst,
&drawRenderTarget->getImage()));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
resolveRegion.dstSubresource.mipLevel = drawRenderTarget->getLevelIndex(); resolveRegion.dstSubresource.mipLevel = drawRenderTarget->getLevelIndex();
resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex(); resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
...@@ -1074,7 +1093,7 @@ angle::Result FramebufferVk::syncState(const gl::Context *context, ...@@ -1074,7 +1093,7 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
// The FBOs new attachment may have changed the renderable area // The FBOs new attachment may have changed the renderable area
const gl::State &glState = context->getState(); const gl::State &glState = context->getState();
contextVk->updateScissor(glState); ANGLE_TRY(contextVk->updateScissor(glState));
mActiveColorComponents = gl_vk::GetColorComponentFlags( mActiveColorComponents = gl_vk::GetColorComponentFlags(
mActiveColorComponentMasksForClear[0].any(), mActiveColorComponentMasksForClear[1].any(), mActiveColorComponentMasksForClear[0].any(), mActiveColorComponentMasksForClear[1].any(),
...@@ -1088,6 +1107,10 @@ angle::Result FramebufferVk::syncState(const gl::Context *context, ...@@ -1088,6 +1107,10 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
// create a new entry in the command graph. // create a new entry in the command graph.
mFramebuffer.finishCurrentCommands(contextVk); mFramebuffer.finishCurrentCommands(contextVk);
} }
else
{
ANGLE_TRY(contextVk->endRenderPass());
}
// Notify the ContextVk to update the pipeline desc. // Notify the ContextVk to update the pipeline desc.
updateRenderPassDesc(); updateRenderPassDesc();
...@@ -1222,7 +1245,7 @@ angle::Result FramebufferVk::clearWithRenderPassOp( ...@@ -1222,7 +1245,7 @@ angle::Result FramebufferVk::clearWithRenderPassOp(
// render pass is needed, // render pass is needed,
// - the current render area doesn't match the clear area. We need the render area to be // - the current render area doesn't match the clear area. We need the render area to be
// exactly as specified by the scissor for the loadOp to clear only that area. See // exactly as specified by the scissor for the loadOp to clear only that area. See
// onScissorChange for more information. // ContextVk::updateScissor for more information.
if (!mFramebuffer.valid() || !mFramebuffer.renderPassStartedButEmpty() || if (!mFramebuffer.valid() || !mFramebuffer.renderPassStartedButEmpty() ||
mFramebuffer.getRenderPassRenderArea() != clearArea) mFramebuffer.getRenderPassRenderArea() != clearArea)
...@@ -1468,28 +1491,6 @@ gl::Rectangle FramebufferVk::getScissoredRenderArea(ContextVk *contextVk) const ...@@ -1468,28 +1491,6 @@ gl::Rectangle FramebufferVk::getScissoredRenderArea(ContextVk *contextVk) const
return ClipRectToScissor(contextVk->getState(), renderArea, invertViewport); return ClipRectToScissor(contextVk->getState(), renderArea, invertViewport);
} }
void FramebufferVk::onScissorChange(ContextVk *contextVk)
{
gl::Rectangle scissoredRenderArea = getScissoredRenderArea(contextVk);
// If the scissor has grown beyond the previous scissoredRenderArea, make sure the render pass
// is restarted. Otherwise, we can continue using the same renderpass area.
//
// Without a scissor, the render pass area covers the whole of the framebuffer. With a
// scissored clear, the render pass area could be smaller than the framebuffer size. When the
// scissor changes, if the scissor area is completely encompassed by the render pass area, it's
// possible to continue using the same render pass. However, if the current render pass area
// is too small, we need to start a new one. The latter can happen if a scissored clear starts
// a render pass, the scissor is disabled and a draw call is issued to affect the whole
// framebuffer.
mFramebuffer.updateCurrentAccessNodes();
if (mFramebuffer.hasStartedRenderPass() &&
!mFramebuffer.getRenderPassRenderArea().encloses(scissoredRenderArea))
{
mFramebuffer.finishCurrentCommands(contextVk);
}
}
RenderTargetVk *FramebufferVk::getFirstRenderTarget() const RenderTargetVk *FramebufferVk::getFirstRenderTarget() const
{ {
for (auto *renderTarget : mRenderTargetCache.getColors()) for (auto *renderTarget : mRenderTargetCache.getColors())
......
...@@ -105,8 +105,6 @@ class FramebufferVk : public FramebufferImpl ...@@ -105,8 +105,6 @@ class FramebufferVk : public FramebufferImpl
gl::Rectangle getCompleteRenderArea() const; gl::Rectangle getCompleteRenderArea() const;
gl::Rectangle getScissoredRenderArea(ContextVk *contextVk) const; gl::Rectangle getScissoredRenderArea(ContextVk *contextVk) const;
void onScissorChange(ContextVk *contextVk);
const gl::DrawBufferMask &getEmulatedAlphaAttachmentMask() const; const gl::DrawBufferMask &getEmulatedAlphaAttachmentMask() const;
RenderTargetVk *getColorDrawRenderTarget(size_t colorIndex) const; RenderTargetVk *getColorDrawRenderTarget(size_t colorIndex) const;
RenderTargetVk *getColorReadRenderTarget() const; RenderTargetVk *getColorReadRenderTarget() const;
......
...@@ -1428,29 +1428,18 @@ void ProgramVk::updateBuffersDescriptorSet(ContextVk *contextVk, ...@@ -1428,29 +1428,18 @@ void ProgramVk::updateBuffersDescriptorSet(ContextVk *contextVk,
BufferVk *bufferVk = vk::GetImpl(bufferBinding.get()); BufferVk *bufferVk = vk::GetImpl(bufferBinding.get());
vk::BufferHelper &bufferHelper = bufferVk->getBuffer(); vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
if (isStorageBuffer) if (contextVk->getFeatures().commandGraph.enabled)
{ {
// We set the SHADER_READ_BIT to be conservative. if (isStorageBuffer)
VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
if (contextVk->getFeatures().commandGraph.enabled)
{ {
// We set the SHADER_READ_BIT to be conservative.
VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
bufferHelper.onWrite(contextVk, recorder, accessFlags); bufferHelper.onWrite(contextVk, recorder, accessFlags);
} }
else else
{ {
contextVk->onBufferWrite(accessFlags, &bufferHelper);
}
}
else
{
if (contextVk->getFeatures().commandGraph.enabled)
{
bufferHelper.onRead(contextVk, recorder, VK_ACCESS_UNIFORM_READ_BIT); bufferHelper.onRead(contextVk, recorder, VK_ACCESS_UNIFORM_READ_BIT);
} }
else
{
contextVk->onBufferRead(VK_ACCESS_UNIFORM_READ_BIT, &bufferHelper);
}
} }
++writeCount; ++writeCount;
......
...@@ -61,15 +61,19 @@ angle::Result RenderTargetVk::onColorDraw(ContextVk *contextVk, ...@@ -61,15 +61,19 @@ angle::Result RenderTargetVk::onColorDraw(ContextVk *contextVk,
ASSERT(commandBuffer->valid()); ASSERT(commandBuffer->valid());
ASSERT(!mImage->getFormat().actualImageFormat().hasDepthOrStencilBits()); ASSERT(!mImage->getFormat().actualImageFormat().hasDepthOrStencilBits());
// TODO(jmadill): Use automatic layout transition. http://anglebug.com/2361
mImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment,
commandBuffer);
if (contextVk->commandGraphEnabled()) if (contextVk->commandGraphEnabled())
{ {
mImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment,
commandBuffer);
// Set up dependencies between the RT resource and the Framebuffer. // Set up dependencies between the RT resource and the Framebuffer.
mImage->addWriteDependency(contextVk, framebufferVk); mImage->addWriteDependency(contextVk, framebufferVk);
} }
else
{
ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::ColorAttachment, mImage));
}
onImageViewAccess(contextVk); onImageViewAccess(contextVk);
...@@ -83,14 +87,21 @@ angle::Result RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk, ...@@ -83,14 +87,21 @@ angle::Result RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk,
ASSERT(commandBuffer->valid()); ASSERT(commandBuffer->valid());
ASSERT(mImage->getFormat().actualImageFormat().hasDepthOrStencilBits()); ASSERT(mImage->getFormat().actualImageFormat().hasDepthOrStencilBits());
// TODO(jmadill): Use automatic layout transition. http://anglebug.com/2361
const angle::Format &format = mImage->getFormat().actualImageFormat(); const angle::Format &format = mImage->getFormat().actualImageFormat();
VkImageAspectFlags aspectFlags = vk::GetDepthStencilAspectFlags(format); VkImageAspectFlags aspectFlags = vk::GetDepthStencilAspectFlags(format);
mImage->changeLayout(aspectFlags, vk::ImageLayout::DepthStencilAttachment, commandBuffer); if (contextVk->commandGraphEnabled())
{
mImage->changeLayout(aspectFlags, vk::ImageLayout::DepthStencilAttachment, commandBuffer);
// Set up dependencies between the RT resource and the Framebuffer. // Set up dependencies between the RT resource and the Framebuffer.
mImage->addWriteDependency(contextVk, framebufferVk); mImage->addWriteDependency(contextVk, framebufferVk);
}
else
{
ANGLE_TRY(
contextVk->onImageWrite(aspectFlags, vk::ImageLayout::DepthStencilAttachment, mImage));
}
onImageViewAccess(contextVk); onImageViewAccess(contextVk);
...@@ -180,7 +191,14 @@ angle::Result RenderTargetVk::flushStagedUpdates(ContextVk *contextVk) ...@@ -180,7 +191,14 @@ angle::Result RenderTargetVk::flushStagedUpdates(ContextVk *contextVk)
return angle::Result::Continue; return angle::Result::Continue;
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
}
else
{
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
return mImage->flushStagedUpdates(contextVk, mLevelIndex, mLevelIndex + 1, mLayerIndex, return mImage->flushStagedUpdates(contextVk, mLevelIndex, mLevelIndex + 1, mLayerIndex,
mLayerIndex + 1, commandBuffer); mLayerIndex + 1, commandBuffer);
} }
......
...@@ -1086,13 +1086,23 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk, ...@@ -1086,13 +1086,23 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
if (contextVk->commandGraphEnabled()) if (contextVk->commandGraphEnabled())
{ {
ANGLE_TRY(mColorImageMS.recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(mColorImageMS.recordCommands(contextVk, &commandBuffer));
} mColorImageMS.changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc,
commandBuffer);
mColorImageMS.changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc, image.image.changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst,
commandBuffer); commandBuffer);
// Setup graph dependency between the swapchain image and the multisampled one. // Setup graph dependency between the swapchain image and the multisampled one.
image.image.addReadDependency(contextVk, &mColorImageMS); image.image.addReadDependency(contextVk, &mColorImageMS);
ANGLE_TRY(image.image.recordCommands(contextVk, &commandBuffer));
}
else
{
ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::TransferSrc, &mColorImageMS));
ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::TransferDst, &image.image));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
VkImageResolve resolveRegion = {}; VkImageResolve resolveRegion = {};
resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
...@@ -1104,10 +1114,6 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk, ...@@ -1104,10 +1114,6 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
resolveRegion.dstOffset = {}; resolveRegion.dstOffset = {};
resolveRegion.extent = image.image.getExtents(); resolveRegion.extent = image.image.getExtents();
if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(image.image.recordCommands(contextVk, &commandBuffer));
}
mColorImageMS.resolve(&image.image, resolveRegion, commandBuffer); mColorImageMS.resolve(&image.image, resolveRegion, commandBuffer);
} }
......
...@@ -572,12 +572,20 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk, ...@@ -572,12 +572,20 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
gl::Extents extents = {sourceArea.width, sourceArea.height, 1}; gl::Extents extents = {sourceArea.width, sourceArea.height, 1};
// Change source layout if necessary // Change source layout if necessary
if (srcImage->isLayoutChangeNecessary(vk::ImageLayout::TransferSrc)) if (contextVk->commandGraphEnabled())
{ {
vk::CommandBuffer *srcLayoutChange; if (srcImage->isLayoutChangeNecessary(vk::ImageLayout::TransferSrc))
ANGLE_TRY(srcImage->recordCommands(contextVk, &srcLayoutChange)); {
srcImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc, vk::CommandBuffer *srcLayoutChange;
srcLayoutChange); ANGLE_TRY(srcImage->recordCommands(contextVk, &srcLayoutChange));
srcImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc,
srcLayoutChange);
}
}
else
{
ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc,
srcImage));
} }
VkImageSubresourceLayers srcSubresource = {}; VkImageSubresourceLayers srcSubresource = {};
...@@ -593,14 +601,23 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk, ...@@ -593,14 +601,23 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)); ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
// Change the image layout before the transfer // Change the image layout before the transfer
mImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst, mImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst,
commandBuffer); commandBuffer);
// Source's layout change should happen before the copy // Source's layout change should happen before the copy
srcImage->addReadDependency(contextVk, mImage); srcImage->addReadDependency(contextVk, mImage);
}
else
{
ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::TransferDst, mImage));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
VkImageSubresourceLayers destSubresource = srcSubresource; VkImageSubresourceLayers destSubresource = srcSubresource;
destSubresource.mipLevel = level; destSubresource.mipLevel = level;
...@@ -628,14 +645,23 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk, ...@@ -628,14 +645,23 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
destFormat, kTransferStagingImageFlags, layerCount)); destFormat, kTransferStagingImageFlags, layerCount));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(stagingImage->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(stagingImage->recordCommands(contextVk, &commandBuffer));
// Change the image layout before the transfer // Change the image layout before the transfer
stagingImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst, stagingImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst,
commandBuffer); commandBuffer);
// Source's layout change should happen before the copy // Source's layout change should happen before the copy
srcImage->addReadDependency(contextVk, stagingImage.get()); srcImage->addReadDependency(contextVk, stagingImage.get());
}
else
{
ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::TransferDst, stagingImage.get()));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
VkImageSubresourceLayers destSubresource = srcSubresource; VkImageSubresourceLayers destSubresource = srcSubresource;
destSubresource.mipLevel = 0; destSubresource.mipLevel = 0;
...@@ -1155,7 +1181,15 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context) ...@@ -1155,7 +1181,15 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
if (mImage->hasStagedUpdates()) if (mImage->hasStagedUpdates())
{ {
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
}
else
{
mImage->onResourceAccess(&contextVk->getResourceUseList());
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
ANGLE_TRY(mImage->flushStagedUpdates(contextVk, getNativeImageLevel(0), ANGLE_TRY(mImage->flushStagedUpdates(contextVk, getNativeImageLevel(0),
mImage->getLevelCount(), getNativeImageLayer(0), mImage->getLevelCount(), getNativeImageLayer(0),
mImage->getLayerCount(), commandBuffer)); mImage->getLayerCount(), commandBuffer));
...@@ -1168,9 +1202,13 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context) ...@@ -1168,9 +1202,13 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
// Create a new node for the image and add a global memory barrier for the staging buffer. // Create a new node for the image and add a global memory barrier for the staging buffer.
// It's written to and staged to be read from when ensureImageInitialized() is called. // It's written to and staged to be read from when ensureImageInitialized() is called.
mImage->finishCurrentCommands(contextVk); if (contextVk->commandGraphEnabled())
mImage->addGlobalMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, {
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); mImage->finishCurrentCommands(contextVk);
mImage->addGlobalMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
onStagingBufferChange(); onStagingBufferChange();
// Release the origin image and recreate it with new mipmap counts. // Release the origin image and recreate it with new mipmap counts.
......
...@@ -777,10 +777,19 @@ angle::Result UtilsVk::clearBuffer(ContextVk *contextVk, ...@@ -777,10 +777,19 @@ angle::Result UtilsVk::clearBuffer(ContextVk *contextVk,
ANGLE_TRY(ensureBufferClearResourcesInitialized(contextVk)); ANGLE_TRY(ensureBufferClearResourcesInitialized(contextVk));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(dest->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(dest->recordCommands(contextVk, &commandBuffer));
// Tell dest it's being written to. // Tell dest it's being written to.
dest->onSelfReadWrite(contextVk, VK_ACCESS_SHADER_WRITE_BIT); dest->onSelfReadWrite(contextVk, VK_ACCESS_SHADER_WRITE_BIT);
}
else
{
// Tell the context dest that we are writing to dest.
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dest));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
const vk::Format &destFormat = dest->getViewFormat(); const vk::Format &destFormat = dest->getViewFormat();
...@@ -829,10 +838,19 @@ angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk, ...@@ -829,10 +838,19 @@ angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk,
ANGLE_TRY(ensureConvertIndexResourcesInitialized(contextVk)); ANGLE_TRY(ensureConvertIndexResourcesInitialized(contextVk));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(dest->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(dest->recordCommands(contextVk, &commandBuffer));
// Tell src we are going to read from it and dest it's being written to. // Tell src we are going to read from it and dest it's being written to.
src->onReadByBuffer(contextVk, dest, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT); src->onReadByBuffer(contextVk, dest, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT);
}
else
{
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, src));
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dest));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
VkDescriptorSet descriptorSet; VkDescriptorSet descriptorSet;
vk::RefCountedDescriptorPoolBinding descriptorPoolBinding; vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
...@@ -892,17 +910,28 @@ angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk, ...@@ -892,17 +910,28 @@ angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk,
ANGLE_TRY(ensureConvertIndexIndirectResourcesInitialized(contextVk)); ANGLE_TRY(ensureConvertIndexIndirectResourcesInitialized(contextVk));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(dstIndexBuf->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(dstIndexBuf->recordCommands(contextVk, &commandBuffer));
// Tell src we are going to read from it and dest it's being written to. // Tell src we are going to read from it and dest it's being written to.
srcIndexBuf->onReadByBuffer(contextVk, dstIndexBuf, VK_ACCESS_SHADER_READ_BIT, srcIndexBuf->onReadByBuffer(contextVk, dstIndexBuf, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT); VK_ACCESS_SHADER_WRITE_BIT);
srcIndirectBuf->onReadByBuffer(contextVk, dstIndexBuf, VK_ACCESS_SHADER_READ_BIT, srcIndirectBuf->onReadByBuffer(contextVk, dstIndexBuf, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT); VK_ACCESS_SHADER_WRITE_BIT);
ANGLE_TRY(dstIndirectBuf->recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(dstIndirectBuf->recordCommands(contextVk, &commandBuffer));
srcIndirectBuf->onReadByBuffer(contextVk, dstIndirectBuf, VK_ACCESS_SHADER_READ_BIT, srcIndirectBuf->onReadByBuffer(contextVk, dstIndirectBuf, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT); VK_ACCESS_SHADER_WRITE_BIT);
}
else
{
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndirectBuf));
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndexBuf));
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dstIndirectBuf));
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dstIndexBuf));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
VkDescriptorSet descriptorSet; VkDescriptorSet descriptorSet;
vk::RefCountedDescriptorPoolBinding descriptorPoolBinding; vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
...@@ -966,18 +995,29 @@ angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer( ...@@ -966,18 +995,29 @@ angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer(
ANGLE_TRY(ensureConvertIndexIndirectLineLoopResourcesInitialized(contextVk)); ANGLE_TRY(ensureConvertIndexIndirectLineLoopResourcesInitialized(contextVk));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(dstIndexBuffer->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(dstIndexBuffer->recordCommands(contextVk, &commandBuffer));
// Tell src we are going to read from it and dest it's being written to. // Tell src we are going to read from it and dest it's being written to.
srcIndexBuffer->onReadByBuffer(contextVk, dstIndexBuffer, VK_ACCESS_SHADER_READ_BIT, srcIndexBuffer->onReadByBuffer(contextVk, dstIndexBuffer, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT); VK_ACCESS_SHADER_WRITE_BIT);
srcIndirectBuffer->onReadByBuffer(contextVk, dstIndexBuffer, VK_ACCESS_SHADER_READ_BIT, srcIndirectBuffer->onReadByBuffer(contextVk, dstIndexBuffer, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT); VK_ACCESS_SHADER_WRITE_BIT);
ANGLE_TRY(dstIndirectBuffer->recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(dstIndirectBuffer->recordCommands(contextVk, &commandBuffer));
srcIndirectBuffer->onReadByBuffer(contextVk, dstIndirectBuffer, VK_ACCESS_SHADER_READ_BIT, srcIndirectBuffer->onReadByBuffer(contextVk, dstIndirectBuffer, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT); VK_ACCESS_SHADER_WRITE_BIT);
}
else
{
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndirectBuffer));
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndexBuffer));
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dstIndirectBuffer));
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dstIndexBuffer));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
VkDescriptorSet descriptorSet; VkDescriptorSet descriptorSet;
vk::RefCountedDescriptorPoolBinding descriptorPoolBinding; vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
...@@ -1037,16 +1077,26 @@ angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer( ...@@ -1037,16 +1077,26 @@ angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer(
ANGLE_TRY(ensureConvertIndirectLineLoopResourcesInitialized(contextVk)); ANGLE_TRY(ensureConvertIndirectLineLoopResourcesInitialized(contextVk));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(destIndexBuffer->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(destIndexBuffer->recordCommands(contextVk, &commandBuffer));
// Tell src we are going to read from it and dest it's being written to. // Tell src we are going to read from it and dest it's being written to.
srcIndirectBuffer->onReadByBuffer(contextVk, destIndexBuffer, VK_ACCESS_SHADER_READ_BIT, srcIndirectBuffer->onReadByBuffer(contextVk, destIndexBuffer, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT); VK_ACCESS_SHADER_WRITE_BIT);
ANGLE_TRY(destIndirectBuffer->recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(destIndirectBuffer->recordCommands(contextVk, &commandBuffer));
srcIndirectBuffer->onReadByBuffer(contextVk, destIndirectBuffer, VK_ACCESS_SHADER_READ_BIT, srcIndirectBuffer->onReadByBuffer(contextVk, destIndirectBuffer, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_SHADER_WRITE_BIT); VK_ACCESS_SHADER_WRITE_BIT);
}
else
{
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndirectBuffer));
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, destIndirectBuffer));
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, destIndexBuffer));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
VkDescriptorSet descriptorSet; VkDescriptorSet descriptorSet;
vk::RefCountedDescriptorPoolBinding descriptorPoolBinding; vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
...@@ -1099,10 +1149,19 @@ angle::Result UtilsVk::convertVertexBuffer(ContextVk *contextVk, ...@@ -1099,10 +1149,19 @@ angle::Result UtilsVk::convertVertexBuffer(ContextVk *contextVk,
ANGLE_TRY(ensureConvertVertexResourcesInitialized(contextVk)); ANGLE_TRY(ensureConvertVertexResourcesInitialized(contextVk));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(dest->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(dest->recordCommands(contextVk, &commandBuffer));
// Tell src we are going to read from it and dest it's being written to. // Tell src we are going to read from it and dest it's being written to.
src->onReadByBuffer(contextVk, dest, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT); src->onReadByBuffer(contextVk, dest, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT);
}
else
{
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, src));
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dest));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
ConvertVertexShaderParams shaderParams; ConvertVertexShaderParams shaderParams;
shaderParams.Ns = params.srcFormat->channelCount; shaderParams.Ns = params.srcFormat->channelCount;
...@@ -1195,8 +1254,16 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk, ...@@ -1195,8 +1254,16 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
renderPassAttachmentOps.initWithLoadStore(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, renderPassAttachmentOps.initWithLoadStore(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
ANGLE_TRY(image->beginRenderPass(contextVk, framebuffer, renderArea, renderPassDesc, if (contextVk->commandGraphEnabled())
renderPassAttachmentOps, clearValues, commandBufferOut)); {
ANGLE_TRY(image->beginRenderPass(contextVk, framebuffer, renderArea, renderPassDesc,
renderPassAttachmentOps, clearValues, commandBufferOut));
}
else
{
contextVk->beginRenderPass(framebuffer, renderArea, renderPassDesc, renderPassAttachmentOps,
clearValues, commandBufferOut);
}
contextVk->addGarbage(&framebuffer); contextVk->addGarbage(&framebuffer);
...@@ -1432,12 +1499,20 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, ...@@ -1432,12 +1499,20 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea)); pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
// Change source layout outside render pass // Change source layout outside render pass
if (src->isLayoutChangeNecessary(vk::ImageLayout::AllGraphicsShadersReadOnly)) if (contextVk->commandGraphEnabled())
{
if (src->isLayoutChangeNecessary(vk::ImageLayout::AllGraphicsShadersReadOnly))
{
vk::CommandBuffer *srcLayoutChange;
ANGLE_TRY(src->recordCommands(contextVk, &srcLayoutChange));
src->changeLayout(src->getAspectFlags(), vk::ImageLayout::AllGraphicsShadersReadOnly,
srcLayoutChange);
}
}
else
{ {
vk::CommandBuffer *srcLayoutChange; ANGLE_TRY(contextVk->onImageRead(src->getAspectFlags(),
ANGLE_TRY(src->recordCommands(contextVk, &srcLayoutChange)); vk::ImageLayout::AllGraphicsShadersReadOnly, src));
src->changeLayout(src->getAspectFlags(), vk::ImageLayout::AllGraphicsShadersReadOnly,
srcLayoutChange);
} }
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
...@@ -1447,8 +1522,11 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, ...@@ -1447,8 +1522,11 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer)); ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer));
} }
// Source's layout change should happen before rendering if (contextVk->commandGraphEnabled())
src->addReadDependency(contextVk, framebuffer->getFramebuffer()); {
// Source's layout change should happen before rendering
src->addReadDependency(contextVk, framebuffer->getFramebuffer());
}
VkDescriptorImageInfo imageInfos[2] = {}; VkDescriptorImageInfo imageInfos[2] = {};
...@@ -1583,19 +1661,37 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk, ...@@ -1583,19 +1661,37 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
uint32_t flags = src->getLayerCount() > 1 ? BlitResolveStencilNoExport_comp::kSrcIsArray : 0; uint32_t flags = src->getLayerCount() > 1 ? BlitResolveStencilNoExport_comp::kSrcIsArray : 0;
flags |= isResolve ? BlitResolve_frag::kIsResolve : 0; flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
// Change source layout prior to computation. RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
if (src->isLayoutChangeNecessary(vk::ImageLayout::ComputeShaderReadOnly)) ASSERT(depthStencilRenderTarget != nullptr);
{ vk::ImageHelper *depthStencilImage = &depthStencilRenderTarget->getImage();
vk::CommandBuffer *srcLayoutChange;
ANGLE_TRY(src->recordCommands(contextVk, &srcLayoutChange));
src->changeLayout(src->getAspectFlags(), vk::ImageLayout::ComputeShaderReadOnly,
srcLayoutChange);
}
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(framebuffer->getFramebuffer()->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
// Change source layout prior to computation.
if (src->isLayoutChangeNecessary(vk::ImageLayout::ComputeShaderReadOnly))
{
vk::CommandBuffer *srcLayoutChange;
ANGLE_TRY(src->recordCommands(contextVk, &srcLayoutChange));
src->changeLayout(src->getAspectFlags(), vk::ImageLayout::ComputeShaderReadOnly,
srcLayoutChange);
}
src->addReadDependency(contextVk, framebuffer->getFramebuffer()); ANGLE_TRY(framebuffer->getFramebuffer()->recordCommands(contextVk, &commandBuffer));
src->addReadDependency(contextVk, framebuffer->getFramebuffer());
depthStencilImage->changeLayout(depthStencilImage->getAspectFlags(),
vk::ImageLayout::TransferDst, commandBuffer);
}
else
{
// Change source layout prior to computation.
ANGLE_TRY(contextVk->onImageRead(src->getAspectFlags(),
vk::ImageLayout::ComputeShaderReadOnly, src));
ANGLE_TRY(contextVk->onImageWrite(depthStencilImage->getAspectFlags(),
vk::ImageLayout::TransferDst, depthStencilImage));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
// Blit/resolve stencil into the buffer. // Blit/resolve stencil into the buffer.
VkDescriptorImageInfo imageInfo = {}; VkDescriptorImageInfo imageInfo = {};
...@@ -1657,13 +1753,6 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk, ...@@ -1657,13 +1753,6 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
0, nullptr); 0, nullptr);
// Copy the resulting buffer into dest. // Copy the resulting buffer into dest.
RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
ASSERT(depthStencilRenderTarget != nullptr);
vk::ImageHelper *depthStencilImage = &depthStencilRenderTarget->getImage();
depthStencilImage->changeLayout(depthStencilImage->getAspectFlags(),
vk::ImageLayout::TransferDst, commandBuffer);
VkBufferImageCopy region = {}; VkBufferImageCopy region = {};
region.bufferOffset = 0; region.bufferOffset = 0;
region.bufferRowLength = bufferRowLengthInUints * sizeof(uint32_t); region.bufferRowLength = bufferRowLengthInUints * sizeof(uint32_t);
...@@ -1761,27 +1850,40 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk, ...@@ -1761,27 +1850,40 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
pipelineDesc.setScissor(scissor); pipelineDesc.setScissor(scissor);
// Change source layout outside render pass // Change source layout outside render pass
if (src->isLayoutChangeNecessary(vk::ImageLayout::AllGraphicsShadersReadOnly)) if (contextVk->commandGraphEnabled())
{ {
vk::CommandBuffer *srcLayoutChange; if (src->isLayoutChangeNecessary(vk::ImageLayout::AllGraphicsShadersReadOnly))
ANGLE_TRY(src->recordCommands(contextVk, &srcLayoutChange)); {
src->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::AllGraphicsShadersReadOnly, vk::CommandBuffer *srcLayoutChange;
srcLayoutChange); ANGLE_TRY(src->recordCommands(contextVk, &srcLayoutChange));
} src->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::AllGraphicsShadersReadOnly, srcLayoutChange);
}
// Change destination layout outside render pass as well // Change destination layout outside render pass as well
vk::CommandBuffer *destLayoutChange; vk::CommandBuffer *destLayoutChange;
ANGLE_TRY(dest->recordCommands(contextVk, &destLayoutChange)); ANGLE_TRY(dest->recordCommands(contextVk, &destLayoutChange));
dest->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment, dest->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment,
destLayoutChange); destLayoutChange);
}
else
{
ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::AllGraphicsShadersReadOnly, src));
ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::ColorAttachment, dest));
}
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY( ANGLE_TRY(
startRenderPass(contextVk, dest, destView, renderPassDesc, renderArea, &commandBuffer)); startRenderPass(contextVk, dest, destView, renderPassDesc, renderArea, &commandBuffer));
// Source's layout change should happen before rendering if (contextVk->commandGraphEnabled())
src->addReadDependency(contextVk, dest); {
// Source's layout change should happen before rendering
src->addReadDependency(contextVk, dest);
}
VkDescriptorImageInfo imageInfo = {}; VkDescriptorImageInfo imageInfo = {};
imageInfo.imageView = srcView->getHandle(); imageInfo.imageView = srcView->getHandle();
...@@ -1843,11 +1945,21 @@ angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk, ...@@ -1843,11 +1945,21 @@ angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk,
&descriptorSet)); &descriptorSet));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(dest->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
dest->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ComputeShaderWrite, {
commandBuffer); ANGLE_TRY(dest->recordCommands(contextVk, &commandBuffer));
dest->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ComputeShaderWrite,
commandBuffer);
enabledWidgetsBuffer->onRead(contextVk, dest, VK_ACCESS_SHADER_READ_BIT); enabledWidgetsBuffer->onRead(contextVk, dest, VK_ACCESS_SHADER_READ_BIT);
}
else
{
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, enabledWidgetsBuffer));
ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::ComputeShaderWrite, dest));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
VkDescriptorImageInfo imageInfo = {}; VkDescriptorImageInfo imageInfo = {};
imageInfo.imageView = destView->getHandle(); imageInfo.imageView = destView->getHandle();
...@@ -1884,8 +1996,11 @@ angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk, ...@@ -1884,8 +1996,11 @@ angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk,
commandBuffer->dispatch(dest->getExtents().width, dest->getExtents().height, 1); commandBuffer->dispatch(dest->getExtents().width, dest->getExtents().height, 1);
descriptorPoolBinding.reset(); descriptorPoolBinding.reset();
dest->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ComputeShaderReadOnly, if (contextVk->commandGraphEnabled())
commandBuffer); {
dest->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ComputeShaderReadOnly,
commandBuffer);
}
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -1918,14 +2033,30 @@ angle::Result UtilsVk::drawOverlay(ContextVk *contextVk, ...@@ -1918,14 +2033,30 @@ angle::Result UtilsVk::drawOverlay(ContextVk *contextVk,
&descriptorSet)); &descriptorSet));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(dest->recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
dest->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ComputeShaderWrite, {
commandBuffer); ANGLE_TRY(dest->recordCommands(contextVk, &commandBuffer));
dest->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ComputeShaderWrite,
culledWidgets->addReadDependency(contextVk, dest); commandBuffer);
font->addReadDependency(contextVk, dest);
textWidgetsBuffer->onRead(contextVk, dest, VK_ACCESS_SHADER_READ_BIT); culledWidgets->addReadDependency(contextVk, dest);
graphWidgetsBuffer->onRead(contextVk, dest, VK_ACCESS_SHADER_READ_BIT); font->addReadDependency(contextVk, dest);
textWidgetsBuffer->onRead(contextVk, dest, VK_ACCESS_SHADER_READ_BIT);
graphWidgetsBuffer->onRead(contextVk, dest, VK_ACCESS_SHADER_READ_BIT);
}
else
{
ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::ComputeShaderWrite, dest));
ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::ComputeShaderReadOnly, culledWidgets));
ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::ComputeShaderReadOnly, font));
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, textWidgetsBuffer));
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, graphWidgetsBuffer));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
VkDescriptorImageInfo imageInfos[3] = {}; VkDescriptorImageInfo imageInfos[3] = {};
imageInfos[0].imageView = destView->getHandle(); imageInfos[0].imageView = destView->getHandle();
......
...@@ -108,15 +108,19 @@ void RendererVk::ensureCapsInitialized() const ...@@ -108,15 +108,19 @@ void RendererVk::ensureCapsInitialized() const
// We use secondary command buffers almost everywhere and they require a feature to be // We use secondary command buffers almost everywhere and they require a feature to be
// able to execute in the presence of queries. As a result, we won't support queries // able to execute in the presence of queries. As a result, we won't support queries
// unless that feature is available. // unless that feature is available.
// TODO(jmadill): Enable without graph. http://anglebug.com/4029
mNativeExtensions.occlusionQueryBoolean = mNativeExtensions.occlusionQueryBoolean =
vk::CommandBuffer::SupportsQueries(mPhysicalDeviceFeatures); vk::CommandBuffer::SupportsQueries(mPhysicalDeviceFeatures) &&
mFeatures.commandGraph.enabled;
// From the Vulkan specs: // From the Vulkan specs:
// > The number of valid bits in a timestamp value is determined by the // > The number of valid bits in a timestamp value is determined by the
// > VkQueueFamilyProperties::timestampValidBits property of the queue on which the timestamp is // > VkQueueFamilyProperties::timestampValidBits property of the queue on which the timestamp is
// > written. Timestamps are supported on any queue which reports a non-zero value for // > written. Timestamps are supported on any queue which reports a non-zero value for
// > timestampValidBits via vkGetPhysicalDeviceQueueFamilyProperties. // > timestampValidBits via vkGetPhysicalDeviceQueueFamilyProperties.
mNativeExtensions.disjointTimerQuery = queueFamilyProperties.timestampValidBits > 0; // TODO(jmadill): Enable without graph. http://anglebug.com/4029
mNativeExtensions.disjointTimerQuery =
queueFamilyProperties.timestampValidBits > 0 && mFeatures.commandGraph.enabled;
mNativeExtensions.queryCounterBitsTimeElapsed = queueFamilyProperties.timestampValidBits; mNativeExtensions.queryCounterBitsTimeElapsed = queueFamilyProperties.timestampValidBits;
mNativeExtensions.queryCounterBitsTimestamp = queueFamilyProperties.timestampValidBits; mNativeExtensions.queryCounterBitsTimestamp = queueFamilyProperties.timestampValidBits;
...@@ -467,7 +471,8 @@ void RendererVk::ensureCapsInitialized() const ...@@ -467,7 +471,8 @@ void RendererVk::ensureCapsInitialized() const
mNativeExtensions.pixelBufferObjectNV = true; mNativeExtensions.pixelBufferObjectNV = true;
// Enable GL_NV_fence extension. // Enable GL_NV_fence extension.
mNativeExtensions.fenceNV = true; // TODO(jmadill): Enable without graph. http://anglebug.com/4029
mNativeExtensions.fenceNV = mFeatures.commandGraph.enabled;
// Geometry shader is optional. // Geometry shader is optional.
if (mPhysicalDeviceFeatures.geometryShader) if (mPhysicalDeviceFeatures.geometryShader)
......
...@@ -1528,12 +1528,20 @@ angle::Result BufferHelper::copyFromBuffer(ContextVk *contextVk, ...@@ -1528,12 +1528,20 @@ angle::Result BufferHelper::copyFromBuffer(ContextVk *contextVk,
{ {
// 'recordCommands' will implicitly stop any reads from using the old buffer data. // 'recordCommands' will implicitly stop any reads from using the old buffer data.
CommandBuffer *commandBuffer = nullptr; CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(recordCommands(contextVk, &commandBuffer));
}
else
{
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
if (mCurrentReadAccess != 0 || mCurrentWriteAccess != 0 || bufferAccessType != 0) if (mCurrentReadAccess != 0 || mCurrentWriteAccess != 0 || bufferAccessType != 0)
{ {
// Insert a barrier to ensure reads/writes are complete. // Insert a barrier to ensure reads/writes are complete.
// Use a global memory barrier to keep things simple. // Use a global memory barrier to keep things simple.
// TODO(jmadill): Can we revisit this with http://anglebug.com/4029
VkMemoryBarrier memoryBarrier = {}; VkMemoryBarrier memoryBarrier = {};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.srcAccessMask = mCurrentReadAccess | mCurrentWriteAccess | bufferAccessType; memoryBarrier.srcAccessMask = mCurrentReadAccess | mCurrentWriteAccess | bufferAccessType;
...@@ -2192,9 +2200,18 @@ void ImageHelper::Copy(ImageHelper *srcImage, ...@@ -2192,9 +2200,18 @@ void ImageHelper::Copy(ImageHelper *srcImage,
angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, GLuint maxLevel) angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, GLuint maxLevel)
{ {
CommandBuffer *commandBuffer = nullptr; CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(recordCommands(contextVk, &commandBuffer));
changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, ImageLayout::TransferDst, commandBuffer); changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, ImageLayout::TransferDst, commandBuffer);
}
else
{
ANGLE_TRY(
contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT, ImageLayout::TransferDst, this));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
// We are able to use blitImage since the image format we are using supports it. This // We are able to use blitImage since the image format we are using supports it. This
// is a faster way we can generate the mips. // is a faster way we can generate the mips.
...@@ -2274,8 +2291,6 @@ void ImageHelper::resolve(ImageHelper *dest, ...@@ -2274,8 +2291,6 @@ void ImageHelper::resolve(ImageHelper *dest,
CommandBuffer *commandBuffer) CommandBuffer *commandBuffer)
{ {
ASSERT(mCurrentLayout == ImageLayout::TransferSrc); ASSERT(mCurrentLayout == ImageLayout::TransferSrc);
dest->changeLayout(region.dstSubresource.aspectMask, ImageLayout::TransferDst, commandBuffer);
commandBuffer->resolveImage(getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dest->getImage(), commandBuffer->resolveImage(getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dest->getImage(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
} }
...@@ -2852,7 +2867,14 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk, ...@@ -2852,7 +2867,14 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
uint64_t subresourceUploadsInProgress = 0; uint64_t subresourceUploadsInProgress = 0;
// Start in TransferDst. // Start in TransferDst.
changeLayout(aspectFlags, ImageLayout::TransferDst, commandBuffer); if (contextVk->commandGraphEnabled())
{
changeLayout(aspectFlags, ImageLayout::TransferDst, commandBuffer);
}
else
{
ANGLE_TRY(contextVk->onImageWrite(aspectFlags, ImageLayout::TransferDst, this));
}
for (SubresourceUpdate &update : mSubresourceUpdates) for (SubresourceUpdate &update : mSubresourceUpdates)
{ {
...@@ -2950,15 +2972,32 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk, ...@@ -2950,15 +2972,32 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
BufferHelper *currentBuffer = bufferUpdate.bufferHelper; BufferHelper *currentBuffer = bufferUpdate.bufferHelper;
ASSERT(currentBuffer && currentBuffer->valid()); ASSERT(currentBuffer && currentBuffer->valid());
currentBuffer->onResourceAccess(&contextVk->getResourceUseList());
if (contextVk->commandGraphEnabled())
{
currentBuffer->onResourceAccess(&contextVk->getResourceUseList());
}
else
{
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, currentBuffer));
}
commandBuffer->copyBufferToImage(currentBuffer->getBuffer().getHandle(), mImage, commandBuffer->copyBufferToImage(currentBuffer->getBuffer().getHandle(), mImage,
getCurrentLayout(), 1, &update.buffer.copyRegion); getCurrentLayout(), 1, &update.buffer.copyRegion);
} }
else else
{ {
update.image.image->changeLayout(aspectFlags, ImageLayout::TransferSrc, commandBuffer); if (contextVk->commandGraphEnabled())
update.image.image->addReadDependency(contextVk, this); {
update.image.image->changeLayout(aspectFlags, ImageLayout::TransferSrc,
commandBuffer);
update.image.image->addReadDependency(contextVk, this);
}
else
{
ANGLE_TRY(contextVk->onImageRead(aspectFlags, ImageLayout::TransferSrc,
update.image.image));
}
commandBuffer->copyImage(update.image.image->getImage(), commandBuffer->copyImage(update.image.image->getImage(),
update.image.image->getCurrentLayout(), mImage, update.image.image->getCurrentLayout(), mImage,
...@@ -2983,7 +3022,14 @@ angle::Result ImageHelper::flushAllStagedUpdates(ContextVk *contextVk) ...@@ -2983,7 +3022,14 @@ angle::Result ImageHelper::flushAllStagedUpdates(ContextVk *contextVk)
{ {
// Clear the image. // Clear the image.
CommandBuffer *commandBuffer = nullptr; CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(recordCommands(contextVk, &commandBuffer)); if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(recordCommands(contextVk, &commandBuffer));
}
else
{
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
return flushStagedUpdates(contextVk, 0, mLevelCount, 0, mLayerCount, commandBuffer); return flushStagedUpdates(contextVk, 0, mLevelCount, 0, mLayerCount, commandBuffer);
} }
...@@ -3060,17 +3106,27 @@ angle::Result ImageHelper::copyImageDataToBuffer(ContextVk *contextVk, ...@@ -3060,17 +3106,27 @@ angle::Result ImageHelper::copyImageDataToBuffer(ContextVk *contextVk,
*bufferSize = sourceArea.width * sourceArea.height * sourceArea.depth * pixelBytes * layerCount; *bufferSize = sourceArea.width * sourceArea.height * sourceArea.depth * pixelBytes * layerCount;
CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(recordCommands(contextVk, &commandBuffer));
// Transition the image to readable layout
const VkImageAspectFlags aspectFlags = getAspectFlags(); const VkImageAspectFlags aspectFlags = getAspectFlags();
changeLayout(aspectFlags, ImageLayout::TransferSrc, commandBuffer);
// Allocate staging buffer data // Allocate staging buffer data
ANGLE_TRY(allocateStagingMemory(contextVk, *bufferSize, outDataPtr, bufferOut, bufferOffsetsOut, ANGLE_TRY(allocateStagingMemory(contextVk, *bufferSize, outDataPtr, bufferOut, bufferOffsetsOut,
nullptr)); nullptr));
CommandBuffer *commandBuffer = nullptr;
if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(recordCommands(contextVk, &commandBuffer));
// Transition the image to readable layout
changeLayout(aspectFlags, ImageLayout::TransferSrc, commandBuffer);
}
else
{
ANGLE_TRY(contextVk->onImageRead(aspectFlags, ImageLayout::TransferSrc, this));
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, *bufferOut));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
VkBufferImageCopy regions[2] = {}; VkBufferImageCopy regions[2] = {};
// Default to non-combined DS case // Default to non-combined DS case
regions[0].bufferOffset = (*bufferOffsetsOut)[0]; regions[0].bufferOffset = (*bufferOffsetsOut)[0];
...@@ -3208,17 +3264,43 @@ angle::Result ImageHelper::readPixels(ContextVk *contextVk, ...@@ -3208,17 +3264,43 @@ angle::Result ImageHelper::readPixels(ContextVk *contextVk,
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
// If the source image is multisampled, we need to resolve it into a temporary image before
// performing a readback.
bool isMultisampled = mSamples > 1;
DeviceScoped<ImageHelper> resolvedImage(contextVk->getDevice());
ImageHelper *src = this;
if (isMultisampled)
{
ANGLE_TRY(resolvedImage.get().init2DStaging(
contextVk, renderer->getMemoryProperties(), gl::Extents(area.width, area.height, 1),
*mFormat, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 1));
resolvedImage.get().onResourceAccess(&contextVk->getResourceUseList());
}
// Note that although we're reading from the image, we need to update the layout below. // Note that although we're reading from the image, we need to update the layout below.
CommandBuffer *commandBuffer; CommandBuffer *commandBuffer;
if (contextVk->commandGraphEnabled()) if (contextVk->commandGraphEnabled())
{ {
ANGLE_TRY(recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(recordCommands(contextVk, &commandBuffer));
if (isMultisampled)
{
resolvedImage.get().changeLayout(copyAspectFlags, ImageLayout::TransferDst,
commandBuffer);
}
changeLayout(copyAspectFlags, ImageLayout::TransferSrc, commandBuffer);
} }
else else
{ {
if (isMultisampled)
{
ANGLE_TRY(contextVk->onImageWrite(copyAspectFlags, ImageLayout::TransferDst,
&resolvedImage.get()));
}
ANGLE_TRY(contextVk->onImageRead(copyAspectFlags, ImageLayout::TransferSrc, this));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer)); ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
} }
changeLayout(copyAspectFlags, ImageLayout::TransferSrc, commandBuffer);
const angle::Format *readFormat = &mFormat->actualImageFormat(); const angle::Format *readFormat = &mFormat->actualImageFormat();
...@@ -3245,20 +3327,8 @@ angle::Result ImageHelper::readPixels(ContextVk *contextVk, ...@@ -3245,20 +3327,8 @@ angle::Result ImageHelper::readPixels(ContextVk *contextVk,
srcSubresource.baseArrayLayer = 0; srcSubresource.baseArrayLayer = 0;
} }
// If the source image is multisampled, we need to resolve it into a temporary image before
// performing a readback.
bool isMultisampled = mSamples > 1;
DeviceScoped<ImageHelper> resolvedImage(contextVk->getDevice());
ImageHelper *src = this;
if (isMultisampled) if (isMultisampled)
{ {
ANGLE_TRY(resolvedImage.get().init2DStaging(
contextVk, renderer->getMemoryProperties(), gl::Extents(area.width, area.height, 1),
*mFormat, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 1));
resolvedImage.get().onResourceAccess(&contextVk->getResourceUseList());
// Note: resolve only works on color images (not depth/stencil). // Note: resolve only works on color images (not depth/stencil).
// //
// TODO: Currently, depth/stencil blit can perform a depth/stencil readback, but that code // TODO: Currently, depth/stencil blit can perform a depth/stencil readback, but that code
...@@ -3277,7 +3347,16 @@ angle::Result ImageHelper::readPixels(ContextVk *contextVk, ...@@ -3277,7 +3347,16 @@ angle::Result ImageHelper::readPixels(ContextVk *contextVk,
resolve(&resolvedImage.get(), resolveRegion, commandBuffer); resolve(&resolvedImage.get(), resolveRegion, commandBuffer);
resolvedImage.get().changeLayout(copyAspectFlags, ImageLayout::TransferSrc, commandBuffer); if (contextVk->commandGraphEnabled())
{
resolvedImage.get().changeLayout(copyAspectFlags, ImageLayout::TransferSrc,
commandBuffer);
}
else
{
ANGLE_TRY(contextVk->onImageRead(copyAspectFlags, ImageLayout::TransferSrc,
&resolvedImage.get()));
}
// Make the resolved image the target of buffer copy. // Make the resolved image the target of buffer copy.
src = &resolvedImage.get(); src = &resolvedImage.get();
......
...@@ -927,6 +927,9 @@ TEST_P(RobustResourceInitTest, Texture) ...@@ -927,6 +927,9 @@ TEST_P(RobustResourceInitTest, Texture)
{ {
ANGLE_SKIP_TEST_IF(!hasGLExtension()); ANGLE_SKIP_TEST_IF(!hasGLExtension());
// Flaky failure on Linux / NV / Vulkan when run in a sequence. http://anglebug.com/3416
ANGLE_SKIP_TEST_IF(IsVulkan() && IsNVIDIA() && IsLinux());
GLTexture texture; GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
......
...@@ -1080,6 +1080,6 @@ TEST_P(SimpleOperationTest, PrimitiveModeNegativeTest) ...@@ -1080,6 +1080,6 @@ TEST_P(SimpleOperationTest, PrimitiveModeNegativeTest)
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(SimpleOperationTest, WithNoCommandGraph(ES2_VULKAN())); ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(SimpleOperationTest);
} // namespace } // namespace
...@@ -118,7 +118,7 @@ struct CombinedPrintToStringParamName ...@@ -118,7 +118,7 @@ struct CombinedPrintToStringParamName
#define ANGLE_ALL_TEST_PLATFORMS_ES2 \ #define ANGLE_ALL_TEST_PLATFORMS_ES2 \
ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES(), ES2_VULKAN(), ES2_VULKAN_SWIFTSHADER(), \ ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES(), ES2_VULKAN(), ES2_VULKAN_SWIFTSHADER(), \
ES2_METAL() ES2_METAL(), WithNoCommandGraph(ES2_VULKAN())
#define ANGLE_ALL_TEST_PLATFORMS_ES3 \ #define ANGLE_ALL_TEST_PLATFORMS_ES3 \
ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(), ES3_VULKAN(), ES3_VULKAN_SWIFTSHADER() ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(), ES3_VULKAN(), ES3_VULKAN_SWIFTSHADER()
......
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