Commit 9e7f08fc by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fix incorrect reordering of barriers

Take the following situation, a simple copy from image to buffer: ANGLE_TRY(contextVk->onBufferTransferWrite(buffer)); ANGLE_TRY(contextVk->onImageTransferRead(aspectFlags, image)); CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer(); commandBuffer.copyImageToBuffer(imageHandle, layout, bufferHandle, 1, regions); Both `onBufferTransferWrite` and `onImageTransferRead` may flush either the outsideRP or insideRP command buffers. If buffer is not previously used, but image is used: - onBufferTransferWrite: buffer usage is recorded in outsideRP1 - onImageTransferREad: outsiderRP1 is flushed, outsideRP2 is started - copyImageToBuffer: recorded on outsideRP2, but buffer usage not recorded there - A following command that uses the buffer and requires barrier doesn't close outsideRP2 as it believes it was not used there Bug: angleproject:5319 Change-Id: Ib8994083fbc21969a538cda3784adee57b089415 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2523388 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent 1885942d
......@@ -341,24 +341,26 @@ angle::Result BufferVk::copySubData(const gl::Context *context,
}
// Check for self-dependency.
vk::CommandBufferAccess access;
if (sourceBuffer.getBufferSerial() == mBuffer->getBufferSerial())
{
ANGLE_TRY(contextVk->onBufferSelfCopy(mBuffer));
access.onBufferSelfCopy(mBuffer);
}
else
{
ANGLE_TRY(contextVk->onBufferTransferRead(&sourceBuffer));
ANGLE_TRY(contextVk->onBufferTransferWrite(mBuffer));
access.onBufferTransferRead(&sourceBuffer);
access.onBufferTransferWrite(mBuffer);
}
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// Enqueue a copy command on the GPU.
const VkBufferCopy copyRegion = {static_cast<VkDeviceSize>(sourceOffset),
static_cast<VkDeviceSize>(destOffset),
static_cast<VkDeviceSize>(size)};
commandBuffer.copyBuffer(sourceBuffer.getBuffer(), mBuffer->getBuffer(), 1, &copyRegion);
commandBuffer->copyBuffer(sourceBuffer.getBuffer(), mBuffer->getBuffer(), 1, &copyRegion);
// The new destination buffer data may require a conversion for the next draw, so mark it dirty.
onDataChanged();
......@@ -666,13 +668,14 @@ angle::Result BufferVk::copyToBufferImpl(ContextVk *contextVk,
uint32_t copyCount,
const VkBufferCopy *copies)
{
vk::CommandBufferAccess access;
access.onBufferTransferWrite(destBuffer);
access.onBufferTransferRead(mBuffer);
ANGLE_TRY(contextVk->onBufferTransferWrite(destBuffer));
ANGLE_TRY(contextVk->onBufferTransferRead(mBuffer));
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
commandBuffer.copyBuffer(mBuffer->getBuffer(), destBuffer->getBuffer(), copyCount, copies);
commandBuffer->copyBuffer(mBuffer->getBuffer(), destBuffer->getBuffer(), copyCount, copies);
return angle::Result::Continue;
}
......
......@@ -173,6 +173,12 @@ void ApplySampleCoverage(const gl::State &glState,
*maskOut &= coverageMask;
}
bool IsRenderPassStartedAndUsesImage(const vk::CommandBufferHelper &renderPassCommands,
const vk::ImageHelper &image)
{
return renderPassCommands.started() && renderPassCommands.usesImageInRenderPass(image);
}
// When an Android surface is rotated differently than the device's native orientation, ANGLE must
// rotate gl_Position in the vertex shader and gl_FragCoord in the fragment shader. The following
// are the rotation matrices used.
......@@ -4297,114 +4303,24 @@ bool ContextVk::shouldUseOldRewriteStructSamplers() const
return mRenderer->getFeatures().forceOldRewriteStructSamplers.enabled;
}
angle::Result ContextVk::onBufferRead(VkAccessFlags readAccessType,
vk::PipelineStage readStage,
vk::BufferHelper *buffer)
{
ASSERT(!buffer->isReleasedToExternal());
if (mRenderPassCommands->usesBufferForWrite(*buffer))
{
ANGLE_TRY(flushCommandsAndEndRenderPass());
}
else if (mOutsideRenderPassCommands->usesBufferForWrite(*buffer))
{
ANGLE_TRY(flushOutsideRenderPassCommands());
}
mOutsideRenderPassCommands->bufferRead(&mResourceUseList, readAccessType, readStage, buffer);
return angle::Result::Continue;
}
angle::Result ContextVk::onBufferWrite(VkAccessFlags writeAccessType,
vk::PipelineStage writeStage,
vk::BufferHelper *buffer)
{
ASSERT(!buffer->isReleasedToExternal());
if (mRenderPassCommands->usesBuffer(*buffer))
{
ANGLE_TRY(flushCommandsAndEndRenderPass());
}
else if (mOutsideRenderPassCommands->usesBuffer(*buffer))
{
ANGLE_TRY(flushOutsideRenderPassCommands());
}
mOutsideRenderPassCommands->bufferWrite(&mResourceUseList, writeAccessType, writeStage,
vk::AliasingMode::Disallowed, buffer);
return angle::Result::Continue;
}
angle::Result ContextVk::endRenderPassIfImageUsed(const vk::ImageHelper &image)
angle::Result ContextVk::onBufferReleaseToExternal(const vk::BufferHelper &buffer)
{
if (mRenderPassCommands->started() && mRenderPassCommands->usesImageInRenderPass(image))
if (mRenderPassCommands->usesBuffer(buffer))
{
return flushCommandsAndEndRenderPass();
}
else
{
return angle::Result::Continue;
}
}
angle::Result ContextVk::onImageRead(VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image)
{
ASSERT(!image->isReleasedToExternal());
ASSERT(image->getImageSerial().valid());
// Note that different read methods are not compatible. A shader read uses a different layout
// than a transfer read. So we cannot support simultaneous read usage as easily as for Buffers.
// TODO: Don't close the render pass if the image was only used read-only in the render pass.
// http://anglebug.com/4984
ANGLE_TRY(endRenderPassIfImageUsed(*image));
image->recordReadBarrier(aspectFlags, imageLayout,
&mOutsideRenderPassCommands->getCommandBuffer());
image->retain(&mResourceUseList);
return angle::Result::Continue;
}
angle::Result ContextVk::onImageWrite(gl::LevelIndex levelStart,
uint32_t levelCount,
uint32_t layerStart,
uint32_t layerCount,
VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image)
{
ASSERT(!image->isReleasedToExternal());
ASSERT(image->getImageSerial().valid());
ANGLE_TRY(endRenderPassIfImageUsed(*image));
image->recordWriteBarrier(aspectFlags, imageLayout,
&mOutsideRenderPassCommands->getCommandBuffer());
image->retain(&mResourceUseList);
image->onWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags);
return angle::Result::Continue;
}
angle::Result ContextVk::onBufferReleaseToExternal(const vk::BufferHelper &buffer)
angle::Result ContextVk::onImageReleaseToExternal(const vk::ImageHelper &image)
{
if (mRenderPassCommands->usesBuffer(buffer))
if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, image))
{
ANGLE_TRY(flushCommandsAndEndRenderPass());
return flushCommandsAndEndRenderPass();
}
return angle::Result::Continue;
}
angle::Result ContextVk::onImageReleaseToExternal(const vk::ImageHelper &image)
{
return endRenderPassIfImageUsed(image);
}
angle::Result ContextVk::beginNewRenderPass(
const vk::Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
......@@ -4865,6 +4781,121 @@ bool ContextVk::shouldSwitchToReadOnlyDepthFeedbackLoopMode(const gl::Context *c
!mDrawFramebuffer->isReadOnlyDepthFeedbackLoopMode();
}
angle::Result ContextVk::onResourceAccess(const vk::CommandBufferAccess &access)
{
ANGLE_TRY(flushCommandBuffersIfNecessary(access));
for (const vk::CommandBufferImageAccess &imageAccess : access.getReadImages())
{
ASSERT(!IsRenderPassStartedAndUsesImage(*mRenderPassCommands, *imageAccess.image));
imageAccess.image->recordReadBarrier(imageAccess.aspectFlags, imageAccess.imageLayout,
&mOutsideRenderPassCommands->getCommandBuffer());
imageAccess.image->retain(&mResourceUseList);
}
for (const vk::CommandBufferImageWrite &imageWrite : access.getWriteImages())
{
ASSERT(!IsRenderPassStartedAndUsesImage(*mRenderPassCommands, *imageWrite.access.image));
imageWrite.access.image->recordWriteBarrier(
imageWrite.access.aspectFlags, imageWrite.access.imageLayout,
&mOutsideRenderPassCommands->getCommandBuffer());
imageWrite.access.image->retain(&mResourceUseList);
imageWrite.access.image->onWrite(imageWrite.levelStart, imageWrite.levelCount,
imageWrite.layerStart, imageWrite.layerCount,
imageWrite.access.aspectFlags);
}
for (const vk::CommandBufferBufferAccess &bufferAccess : access.getReadBuffers())
{
ASSERT(!mRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer));
ASSERT(!mOutsideRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer));
mOutsideRenderPassCommands->bufferRead(&mResourceUseList, bufferAccess.accessType,
bufferAccess.stage, bufferAccess.buffer);
}
for (const vk::CommandBufferBufferAccess &bufferAccess : access.getWriteBuffers())
{
ASSERT(!mRenderPassCommands->usesBuffer(*bufferAccess.buffer));
ASSERT(!mOutsideRenderPassCommands->usesBuffer(*bufferAccess.buffer));
mOutsideRenderPassCommands->bufferWrite(&mResourceUseList, bufferAccess.accessType,
bufferAccess.stage, vk::AliasingMode::Disallowed,
bufferAccess.buffer);
}
return angle::Result::Continue;
}
angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferAccess &access)
{
// Go over resources and decide whether the render pass needs to close, whether the outside
// render pass commands need to be flushed, or neither. Note that closing the render pass
// implies flushing the outside render pass as well, so if that needs to be done, we can close
// the render pass and immediately return from this function. Otherwise, this function keeps
// track of whether the outside render pass commands need to be closed, and if so, it will do
// that once at the end.
// Read images only need to close the render pass if they need a layout transition.
for (const vk::CommandBufferImageAccess &imageAccess : access.getReadImages())
{
// Note that different read methods are not compatible. A shader read uses a different
// layout than a transfer read. So we cannot support simultaneous read usage as easily as
// for Buffers. TODO: Don't close the render pass if the image was only used read-only in
// the render pass. http://anglebug.com/4984
if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, *imageAccess.image))
{
return flushCommandsAndEndRenderPass();
}
}
// Write images only need to close the render pass if they need a layout transition.
for (const vk::CommandBufferImageWrite &imageWrite : access.getWriteImages())
{
if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, *imageWrite.access.image))
{
return flushCommandsAndEndRenderPass();
}
}
bool shouldCloseOutsideRenderPassCommands = false;
// Read buffers only need a new command buffer if previously used for write.
for (const vk::CommandBufferBufferAccess &bufferAccess : access.getReadBuffers())
{
if (mRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer))
{
return flushCommandsAndEndRenderPass();
}
else if (mOutsideRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer))
{
shouldCloseOutsideRenderPassCommands = true;
}
}
// Write buffers always need a new command buffer if previously used.
for (const vk::CommandBufferBufferAccess &bufferAccess : access.getWriteBuffers())
{
if (mRenderPassCommands->usesBuffer(*bufferAccess.buffer))
{
return flushCommandsAndEndRenderPass();
}
else if (mOutsideRenderPassCommands->usesBuffer(*bufferAccess.buffer))
{
shouldCloseOutsideRenderPassCommands = true;
}
}
if (shouldCloseOutsideRenderPassCommands)
{
return flushOutsideRenderPassCommands();
}
return angle::Result::Continue;
}
// Requires that trace is enabled to see the output, which is supported with is_debug=true
void ContextVk::outputCumulativePerfCounters()
{
......
......@@ -425,57 +425,7 @@ class ContextVk : public ContextImpl, public vk::Context
vk::ResourceUseList &getResourceUseList() { return mResourceUseList; }
angle::Result onBufferTransferRead(vk::BufferHelper *buffer)
{
return onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, vk::PipelineStage::Transfer, buffer);
}
angle::Result onBufferTransferWrite(vk::BufferHelper *buffer)
{
return onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, vk::PipelineStage::Transfer, buffer);
}
angle::Result onBufferSelfCopy(vk::BufferHelper *buffer)
{
return onBufferWrite(VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
vk::PipelineStage::Transfer, buffer);
}
angle::Result onBufferComputeShaderRead(vk::BufferHelper *buffer)
{
return onBufferRead(VK_ACCESS_SHADER_READ_BIT, vk::PipelineStage::ComputeShader, buffer);
}
angle::Result onBufferComputeShaderWrite(vk::BufferHelper *buffer)
{
return onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, vk::PipelineStage::ComputeShader, buffer);
}
angle::Result onBufferReleaseToExternal(const vk::BufferHelper &buffer);
angle::Result onImageTransferRead(VkImageAspectFlags aspectFlags, vk::ImageHelper *image)
{
return onImageRead(aspectFlags, vk::ImageLayout::TransferSrc, image);
}
angle::Result onImageTransferWrite(gl::LevelIndex levelStart,
uint32_t levelCount,
uint32_t layerStart,
uint32_t layerCount,
VkImageAspectFlags aspectFlags,
vk::ImageHelper *image)
{
return onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags,
vk::ImageLayout::TransferDst, image);
}
angle::Result onImageComputeShaderRead(VkImageAspectFlags aspectFlags, vk::ImageHelper *image)
{
return onImageRead(aspectFlags, vk::ImageLayout::ComputeShaderReadOnly, image);
}
angle::Result onImageComputeShaderWrite(gl::LevelIndex levelStart,
uint32_t levelCount,
uint32_t layerStart,
uint32_t layerCount,
VkImageAspectFlags aspectFlags,
vk::ImageHelper *image)
{
return onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags,
vk::ImageLayout::ComputeShaderWrite, image);
}
angle::Result onImageReleaseToExternal(const vk::ImageHelper &image);
void onImageRenderPassRead(VkImageAspectFlags aspectFlags,
......@@ -516,10 +466,13 @@ class ContextVk : public ContextImpl, public vk::Context
}
}
vk::CommandBuffer &getOutsideRenderPassCommandBuffer()
angle::Result getOutsideRenderPassCommandBuffer(const vk::CommandBufferAccess &access,
vk::CommandBuffer **commandBufferOut)
{
ASSERT(!mOutsideRenderPassCommands->hasRenderPass());
return mOutsideRenderPassCommands->getCommandBuffer();
ANGLE_TRY(onResourceAccess(access));
*commandBufferOut = &mOutsideRenderPassCommands->getCommandBuffer();
return angle::Result::Continue;
}
angle::Result beginNewRenderPass(const vk::Framebuffer &framebuffer,
......@@ -881,28 +834,8 @@ class ContextVk : public ContextImpl, public vk::Context
ANGLE_INLINE void onRenderPassFinished() { mRenderPassCommandBuffer = nullptr; }
angle::Result onBufferRead(VkAccessFlags readAccessType,
vk::PipelineStage readStage,
vk::BufferHelper *buffer);
angle::Result onBufferWrite(VkAccessFlags writeAccessType,
vk::PipelineStage writeStage,
vk::BufferHelper *buffer);
angle::Result onImageRead(VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image);
angle::Result onImageWrite(gl::LevelIndex levelStart,
uint32_t levelCount,
uint32_t layerStart,
uint32_t layerCount,
VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image);
void initIndexTypeMap();
angle::Result endRenderPassIfImageUsed(const vk::ImageHelper &image);
angle::Result endRenderPassIfTransformFeedbackBuffer(const vk::BufferHelper *buffer);
void populateTransformFeedbackBufferSet(
......@@ -920,6 +853,9 @@ class ContextVk : public ContextImpl, public vk::Context
bool shouldSwitchToReadOnlyDepthFeedbackLoopMode(const gl::Context *context,
gl::Texture *texture) const;
angle::Result onResourceAccess(const vk::CommandBufferAccess &access);
angle::Result flushCommandBuffersIfNecessary(const vk::CommandBufferAccess &access);
void outputCumulativePerfCounters();
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers;
......
......@@ -823,11 +823,12 @@ angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
blitAspectMask &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
}
ANGLE_TRY(contextVk->onImageTransferRead(imageAspectMask, srcImage));
ANGLE_TRY(contextVk->onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
drawRenderTarget->getLayerIndex(), 1, imageAspectMask,
dstImage));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBufferAccess access;
access.onImageTransferRead(imageAspectMask, srcImage);
access.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
drawRenderTarget->getLayerIndex(), 1, imageAspectMask, dstImage);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkImageBlit blit = {};
blit.srcSubresource.aspectMask = blitAspectMask;
......@@ -843,9 +844,9 @@ angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
blit.dstOffsets[0] = {destArea.x0(), destArea.y0(), 0};
blit.dstOffsets[1] = {destArea.x1(), destArea.y1(), 1};
commandBuffer.blitImage(srcImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dstImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
gl_vk::GetFilter(filter));
commandBuffer->blitImage(srcImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dstImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
gl_vk::GetFilter(filter));
return angle::Result::Continue;
}
......@@ -1339,7 +1340,21 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
const UtilsVk::BlitResolveParameters &params,
vk::ImageHelper *srcImage)
{
ANGLE_TRY(contextVk->onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage));
vk::CommandBufferAccess access;
access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage);
for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{
RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
vk::ImageHelper &dstImage = drawRenderTarget->getImageForWrite();
access.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
drawRenderTarget->getLayerIndex(), 1, VK_IMAGE_ASPECT_COLOR_BIT,
&dstImage);
}
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkImageResolve resolveRegion = {};
resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
......@@ -1362,18 +1377,13 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{
RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
ANGLE_TRY(contextVk->onImageTransferWrite(
drawRenderTarget->getLevelIndex(), 1, drawRenderTarget->getLayerIndex(), 1,
VK_IMAGE_ASPECT_COLOR_BIT, &drawRenderTarget->getImageForWrite()));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::ImageHelper &dstImage = drawRenderTarget->getImageForWrite();
vk::ImageHelper &dstImage = drawRenderTarget->getImageForWrite();
vk::LevelIndex levelVk = dstImage.toVkLevel(drawRenderTarget->getLevelIndex());
vk::LevelIndex levelVk = dstImage.toVkLevel(drawRenderTarget->getLevelIndex());
resolveRegion.dstSubresource.mipLevel = levelVk.get();
resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
srcImage->resolve(&dstImage, resolveRegion, &commandBuffer);
srcImage->resolve(&dstImage, resolveRegion, commandBuffer);
perfCounters.resolveImageCommands++;
}
......
......@@ -122,10 +122,12 @@ angle::Result OverlayVk::createFont(ContextVk *contextVk)
&mFontImageView, vk::LevelIndex(0), 1));
// Copy font data from staging buffer.
ANGLE_TRY(contextVk->onBufferTransferRead(&fontDataBuffer.get()));
ANGLE_TRY(contextVk->onImageTransferWrite(gl::LevelIndex(0), 1, 0, gl::overlay::kFontCount,
VK_IMAGE_ASPECT_COLOR_BIT, &mFontImage));
vk::CommandBuffer &fontDataUpload = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBufferAccess access;
access.onBufferTransferRead(&fontDataBuffer.get());
access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, gl::overlay::kFontCount,
VK_IMAGE_ASPECT_COLOR_BIT, &mFontImage);
vk::CommandBuffer *fontDataUpload;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &fontDataUpload));
VkBufferImageCopy copy = {};
copy.bufferRowLength = gl::overlay::kFontImageWidth;
......@@ -136,9 +138,9 @@ angle::Result OverlayVk::createFont(ContextVk *contextVk)
copy.imageExtent.height = gl::overlay::kFontImageHeight;
copy.imageExtent.depth = 1;
fontDataUpload.copyBufferToImage(fontDataBuffer.get().getBuffer().getHandle(),
mFontImage.getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
&copy);
fontDataUpload->copyBufferToImage(fontDataBuffer.get().getBuffer().getHandle(),
mFontImage.getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &copy);
return angle::Result::Continue;
}
......
......@@ -24,30 +24,31 @@ of a front-end OpenGL Context. ContextVk processes state changes and handles act
## Command recording
The back-end records commands into command buffers via the the following `ContextVk` APIs:
The back-end records commands into command buffers via the following `ContextVk` APIs:
* `getOutsideRenderPassCommandBuffer`: returns a secondary command buffer *outside* a RenderPass instance.
* `flushAndBeginRenderPass`: returns a secondary command buffer *inside* a RenderPass instance.
* `beginNewRenderPass`: Writes out (aka flushes) prior pending commands into a primary command
buffer, then starts a new render pass. Returns a secondary command buffer *inside* a render pass
instance.
* `getOutsideRenderPassCommandBuffer`: May flush prior command buffers and close the render pass if
necessary, in addition to issuing the appropriate barriers. Returns a secondary command buffer
*outside* a render pass instance.
* `getStartedRenderPassCommands`: Returns a reference to the currently open render pass' commands
buffer.
*Note*: All of these commands may write out (aka flush) prior pending commands into a primary
command buffer. When a RenderPass is open `getOutsideRenderPassCommandBuffer` will flush the
pending RenderPass commands. `flushAndBeginRenderPass` will flush out pending commands outside a
RenderPass to a primary buffer. On submit ANGLE submits the primary command buffer to a `VkQueue`.
If you need to record inside a RenderPass, use `flushAndBeginRenderPass`. Otherwise, use
`getOutsideRenderPassCommandBuffer`.
The back-end (mostly) records Image and Buffer barriers through additional `ContextVk` APIs:
The back-end (mostly) records Image and Buffer barriers through additional `CommandBufferAccess`
APIs, the result of which is passed to `getOutsideRenderPassCommandBuffer`. Note that the
barriers are not actually recorded until `getOutsideRenderPassCommandBuffer` is called:
* `onBufferTransferRead` and `onBufferComputeShaderRead` accumulate `VkBuffer` read barriers.
* `onBufferTransferWrite` and `onBufferComputeShaderWrite` accumulate `VkBuffer` write barriers.
* `onBuffferSelfCopy` is a special case for `VkBuffer` self copies. It behaves the same as write.
* `onImageTransferRead` and `onImageComputerShadeRead` accumulate `VkImage` read barriers.
* `onImageTransferWrite` and `onImageComputerShadeWrite` accumulate `VkImage` write barriers.
* `onImageRenderPassRead` and `onImageRenderPassWrite` accumulate `VkImage` barriers inside a started RenderPass.
* `onImageRenderPassRead` and `onImageRenderPassWrite` accumulate `VkImage` barriers inside a
started RenderPass.
After the back-end records commands to the primary buffer we flush (e.g. on swap) or when we call
`ContextVk::finishToSerial`.
After the back-end records commands to the primary buffer and we flush (e.g. on swap) or when we call
`ContextVk::finishToSerial`, ANGLE submits the primary command buffer to a `VkQueue`.
See the [code][CommandAPIs] for more details.
......@@ -56,15 +57,16 @@ See the [code][CommandAPIs] for more details.
In this example we'll be recording a buffer copy command:
```
# Ensure that ANGLE sets proper read and write barriers for the Buffers.
ANGLE_TRY(contextVk->onBufferTransferWrite(destBuffer));
ANGLE_TRY(contextVk->onBufferTransferRead(srcBuffer));
// Ensure that ANGLE sets proper read and write barriers for the Buffers.
vk::CommandBufferAccess access;
access.onBufferTransferWrite(destBuffer);
access.onBufferTransferRead(srcBuffer);
# Get a pointer to a secondary command buffer for command recording. May "flush" the RP.
// Get a pointer to a secondary command buffer for command recording.
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
# Record the copy command into the secondary buffer. We're done!
// Record the copy command into the secondary buffer. We're done!
commandBuffer->copyBuffer(srcBuffer->getBuffer(), destBuffer->getBuffer(), copyCount, copies);
```
......
......@@ -197,9 +197,10 @@ angle::Result RenderbufferVk::setStorageEGLImageTarget(const gl::Context *contex
uint32_t rendererQueueFamilyIndex = contextVk->getRenderer()->getQueueFamilyIndex();
if (mImage->isQueueChangeNeccesary(rendererQueueFamilyIndex))
{
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
mImage->changeLayoutAndQueue(aspect, vk::ImageLayout::ColorAttachment,
rendererQueueFamilyIndex, &commandBuffer);
rendererQueueFamilyIndex, commandBuffer);
}
gl::TextureType viewType = imageVk->getImageTextureType();
......
......@@ -117,11 +117,12 @@ angle::Result SemaphoreVk::wait(gl::Context *context,
BufferVk *bufferVk = vk::GetImpl(buffer);
vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
// Queue ownership transfer.
bufferHelper.acquireFromExternal(contextVk, VK_QUEUE_FAMILY_EXTERNAL,
rendererQueueFamilyIndex, &commandBuffer);
rendererQueueFamilyIndex, commandBuffer);
}
}
......@@ -136,7 +137,8 @@ angle::Result SemaphoreVk::wait(gl::Context *context,
vk::ImageHelper &image = textureVk->getImage();
vk::ImageLayout layout = GetVulkanImageLayout(textureAndLayout.layout);
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
// Image should not be accessed while unowned. Emulated formats may have staged updates
// to clear the image after initialization.
......@@ -145,7 +147,7 @@ angle::Result SemaphoreVk::wait(gl::Context *context,
// Queue ownership transfer and layout transition.
image.acquireFromExternal(contextVk, VK_QUEUE_FAMILY_EXTERNAL, rendererQueueFamilyIndex,
layout, &commandBuffer);
layout, commandBuffer);
}
}
......@@ -170,11 +172,12 @@ angle::Result SemaphoreVk::signal(gl::Context *context,
vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
ANGLE_TRY(contextVk->onBufferReleaseToExternal(bufferHelper));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
// Queue ownership transfer.
bufferHelper.releaseToExternal(contextVk, rendererQueueFamilyIndex,
VK_QUEUE_FAMILY_EXTERNAL, &commandBuffer);
VK_QUEUE_FAMILY_EXTERNAL, commandBuffer);
}
}
......@@ -199,11 +202,12 @@ angle::Result SemaphoreVk::signal(gl::Context *context,
ANGLE_TRY(textureVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
ANGLE_TRY(contextVk->onImageReleaseToExternal(image));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
// Queue ownership transfer and layout transition.
image.releaseToExternal(contextVk, rendererQueueFamilyIndex, VK_QUEUE_FAMILY_EXTERNAL,
layout, &commandBuffer);
layout, commandBuffer);
}
}
......
......@@ -1291,15 +1291,18 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
contextVk->optimizeRenderPassForPresent(currentFramebuffer.getHandle());
}
vk::CommandBuffer *commandBuffer = &contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
if (mColorImageMS.valid())
{
// Transition the multisampled image to TRANSFER_SRC for resolve.
ANGLE_TRY(contextVk->onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, &mColorImageMS));
ANGLE_TRY(contextVk->onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1,
VK_IMAGE_ASPECT_COLOR_BIT, &image.image));
commandBuffer = &contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBufferAccess access;
access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, &mColorImageMS);
access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
&image.image);
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkImageResolve resolveRegion = {};
resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
......@@ -1317,7 +1320,7 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
if (overlayHasWidget)
{
ANGLE_TRY(drawOverlay(contextVk, &image));
commandBuffer = &contextVk->getOutsideRenderPassCommandBuffer();
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
}
// This does nothing if it's already in the requested layout
......
......@@ -57,8 +57,9 @@ angle::Result SyncHelper::initialize(ContextVk *contextVk)
mEvent = event.release();
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
commandBuffer.setEvent(mEvent.getHandle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
commandBuffer->setEvent(mEvent.getHandle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
retain(&contextVk->getResourceUseList());
contextVk->onSyncHelperInitialize();
......@@ -120,10 +121,11 @@ angle::Result SyncHelper::clientWait(Context *context,
angle::Result SyncHelper::serverWait(ContextVk *contextVk)
{
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
commandBuffer.waitEvents(1, mEvent.ptr(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, nullptr, 0, nullptr, 0,
nullptr);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
commandBuffer->waitEvents(1, mEvent.ptr(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, nullptr, 0, nullptr, 0,
nullptr);
retain(&contextVk->getResourceUseList());
return angle::Result::Continue;
}
......
......@@ -905,7 +905,8 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
gl::Extents extents = {sourceBox.width, sourceBox.height, sourceBox.depth};
// Change source layout if necessary
ANGLE_TRY(contextVk->onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage));
vk::CommandBufferAccess access;
access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage);
VkImageSubresourceLayers srcSubresource = {};
srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
......@@ -943,9 +944,11 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
// Make sure any updates to the image are already flushed.
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
ANGLE_TRY(contextVk->onImageTransferWrite(level, 1, baseLayer, layerCount,
VK_IMAGE_ASPECT_COLOR_BIT, mImage));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
access.onImageTransferWrite(level, 1, baseLayer, layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
mImage);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkImageSubresourceLayers destSubresource = srcSubresource;
destSubresource.mipLevel = mImage->toVkLevel(level).get();
......@@ -964,7 +967,7 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
}
vk::ImageHelper::Copy(srcImage, mImage, srcOffset, destOffsetModified, extents,
srcSubresource, destSubresource, &commandBuffer);
srcSubresource, destSubresource, commandBuffer);
}
else
{
......@@ -977,9 +980,11 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
gl::Extents(sourceBox.width, sourceBox.height, 1),
destFormat, kTransferStagingImageFlags, layerCount));
ANGLE_TRY(contextVk->onImageTransferWrite(gl::LevelIndex(0), 1, 0, layerCount,
VK_IMAGE_ASPECT_COLOR_BIT, stagingImage.get()));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
stagingImage.get());
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkImageSubresourceLayers destSubresource = srcSubresource;
destSubresource.mipLevel = 0;
......@@ -994,7 +999,7 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
}
vk::ImageHelper::Copy(srcImage, stagingImage.get(), srcOffset, gl::kOffsetZero, extents,
srcSubresource, destSubresource, &commandBuffer);
srcSubresource, destSubresource, commandBuffer);
// Stage the copy for when the image storage is actually created.
VkImageType imageType = gl_vk::GetImageType(mState.getType());
......@@ -1280,9 +1285,10 @@ angle::Result TextureVk::setEGLImageTarget(const gl::Context *context,
newLayout = vk::ImageLayout::AllGraphicsShadersReadOnly;
}
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
mImage->changeLayoutAndQueue(mImage->getAspectFlags(), newLayout, rendererQueueFamilyIndex,
&commandBuffer);
commandBuffer);
}
return angle::Result::Continue;
......@@ -1595,14 +1601,15 @@ angle::Result TextureVk::copyBufferDataToImage(ContextVk *contextVk,
// Make sure the source is initialized and its images are flushed.
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
ANGLE_TRY(contextVk->onBufferTransferRead(srcBuffer));
ANGLE_TRY(contextVk->onImageTransferWrite(level, 1, layerIndex, layerCount,
mImage->getAspectFlags(), mImage));
vk::CommandBufferAccess access;
access.onBufferTransferRead(srcBuffer);
access.onImageTransferWrite(level, 1, layerIndex, layerCount, mImage->getAspectFlags(), mImage);
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
commandBuffer.copyBufferToImage(srcBuffer->getBuffer().getHandle(), mImage->getImage(),
mImage->getCurrentLayout(), 1, &region);
commandBuffer->copyBufferToImage(srcBuffer->getBuffer().getHandle(), mImage->getImage(),
mImage->getCurrentLayout(), 1, &region);
return angle::Result::Continue;
}
......@@ -1648,11 +1655,16 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk)
destBaseLevelVk < vk::LevelIndex(mImage->getLevelCount());
destBaseLevelVk = destBaseLevelVk + maxGenerateLevels.get())
{
vk::CommandBufferAccess access;
uint32_t writeLevelCount =
std::min(maxGenerateLevels.get(), mImage->getLevelCount() - destBaseLevelVk.get());
ANGLE_TRY(contextVk->onImageComputeShaderWrite(mImage->toGLLevel(destBaseLevelVk),
writeLevelCount, 0, mImage->getLayerCount(),
VK_IMAGE_ASPECT_COLOR_BIT, mImage));
access.onImageComputeShaderWrite(mImage->toGLLevel(destBaseLevelVk), writeLevelCount, 0,
mImage->getLayerCount(), VK_IMAGE_ASPECT_COLOR_BIT,
mImage);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// Generate mipmaps for every layer separately.
for (uint32_t layer = 0; layer < mImage->getLayerCount(); ++layer)
......
......@@ -1027,10 +1027,12 @@ angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk,
{
ANGLE_TRY(ensureConvertIndexResourcesInitialized(contextVk));
ANGLE_TRY(contextVk->onBufferComputeShaderRead(src));
ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dest));
vk::CommandBufferAccess access;
access.onBufferComputeShaderRead(src);
access.onBufferComputeShaderWrite(dest);
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorSet descriptorSet;
vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
......@@ -1066,14 +1068,14 @@ angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk,
ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexBuffer, shader, nullptr,
&mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
sizeof(ConvertIndexShaderParams), &commandBuffer));
sizeof(ConvertIndexShaderParams), commandBuffer));
constexpr uint32_t kInvocationsPerGroup = 64;
constexpr uint32_t kInvocationsPerIndex = 2;
const uint32_t kIndexCount = params.maxIndex - params.srcOffset;
const uint32_t kGroupCount =
UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
commandBuffer.dispatch(kGroupCount, 1, 1);
commandBuffer->dispatch(kGroupCount, 1, 1);
descriptorPoolBinding.reset();
......@@ -1089,12 +1091,14 @@ angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk,
{
ANGLE_TRY(ensureConvertIndexIndirectResourcesInitialized(contextVk));
ANGLE_TRY(contextVk->onBufferComputeShaderRead(srcIndirectBuf));
ANGLE_TRY(contextVk->onBufferComputeShaderRead(srcIndexBuf));
ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dstIndirectBuf));
ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dstIndexBuf));
vk::CommandBufferAccess access;
access.onBufferComputeShaderRead(srcIndirectBuf);
access.onBufferComputeShaderRead(srcIndexBuf);
access.onBufferComputeShaderWrite(dstIndirectBuf);
access.onBufferComputeShaderWrite(dstIndexBuf);
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorSet descriptorSet;
vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
......@@ -1133,14 +1137,14 @@ angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk,
ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectBuffer, shader, nullptr,
&mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
sizeof(ConvertIndexIndirectShaderParams), &commandBuffer));
sizeof(ConvertIndexIndirectShaderParams), commandBuffer));
constexpr uint32_t kInvocationsPerGroup = 64;
constexpr uint32_t kInvocationsPerIndex = 2;
const uint32_t kIndexCount = params.maxIndex;
const uint32_t kGroupCount =
UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
commandBuffer.dispatch(kGroupCount, 1, 1);
commandBuffer->dispatch(kGroupCount, 1, 1);
descriptorPoolBinding.reset();
......@@ -1157,12 +1161,14 @@ angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer(
{
ANGLE_TRY(ensureConvertIndexIndirectLineLoopResourcesInitialized(contextVk));
ANGLE_TRY(contextVk->onBufferComputeShaderRead(srcIndirectBuffer));
ANGLE_TRY(contextVk->onBufferComputeShaderRead(srcIndexBuffer));
ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dstIndirectBuffer));
ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dstIndexBuffer));
vk::CommandBufferAccess access;
access.onBufferComputeShaderRead(srcIndirectBuffer);
access.onBufferComputeShaderRead(srcIndexBuffer);
access.onBufferComputeShaderWrite(dstIndirectBuffer);
access.onBufferComputeShaderWrite(dstIndexBuffer);
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorSet descriptorSet;
vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
......@@ -1199,9 +1205,9 @@ angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer(
ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectLineLoopBuffer, shader, nullptr,
&mConvertIndexIndirectLineLoopPrograms[flags], nullptr, descriptorSet,
&shaderParams, sizeof(ConvertIndexIndirectLineLoopShaderParams),
&commandBuffer));
commandBuffer));
commandBuffer.dispatch(1, 1, 1);
commandBuffer->dispatch(1, 1, 1);
descriptorPoolBinding.reset();
......@@ -1217,11 +1223,13 @@ angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer(
{
ANGLE_TRY(ensureConvertIndirectLineLoopResourcesInitialized(contextVk));
ANGLE_TRY(contextVk->onBufferComputeShaderRead(srcIndirectBuffer));
ANGLE_TRY(contextVk->onBufferComputeShaderWrite(destIndirectBuffer));
ANGLE_TRY(contextVk->onBufferComputeShaderWrite(destIndexBuffer));
vk::CommandBufferAccess access;
access.onBufferComputeShaderRead(srcIndirectBuffer);
access.onBufferComputeShaderWrite(destIndirectBuffer);
access.onBufferComputeShaderWrite(destIndexBuffer);
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorSet descriptorSet;
vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
......@@ -1257,9 +1265,9 @@ angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer(
ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndirectLineLoopBuffer, shader, nullptr,
&mConvertIndirectLineLoopPrograms[flags], nullptr, descriptorSet,
&shaderParams, sizeof(ConvertIndirectLineLoopShaderParams),
&commandBuffer));
commandBuffer));
commandBuffer.dispatch(1, 1, 1);
commandBuffer->dispatch(1, 1, 1);
descriptorPoolBinding.reset();
......@@ -1273,10 +1281,12 @@ angle::Result UtilsVk::convertVertexBuffer(ContextVk *contextVk,
{
ANGLE_TRY(ensureConvertVertexResourcesInitialized(contextVk));
ANGLE_TRY(contextVk->onBufferComputeShaderRead(src));
ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dest));
vk::CommandBufferAccess access;
access.onBufferComputeShaderRead(src);
access.onBufferComputeShaderWrite(dest);
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
ConvertVertexShaderParams shaderParams;
shaderParams.Ns = params.srcFormat->channelCount;
......@@ -1338,9 +1348,9 @@ angle::Result UtilsVk::convertVertexBuffer(ContextVk *contextVk,
ANGLE_TRY(setupProgram(contextVk, Function::ConvertVertexBuffer, shader, nullptr,
&mConvertVertexPrograms[flags], nullptr, descriptorSet, &shaderParams,
sizeof(shaderParams), &commandBuffer));
sizeof(shaderParams), commandBuffer));
commandBuffer.dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
descriptorPoolBinding.reset();
......@@ -1922,12 +1932,14 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
vk::ImageHelper *depthStencilImage = &depthStencilRenderTarget->getImageForWrite();
// Change source layout prior to computation.
ANGLE_TRY(contextVk->onImageComputeShaderRead(src->getAspectFlags(), src));
ANGLE_TRY(contextVk->onImageTransferWrite(
depthStencilRenderTarget->getLevelIndex(), 1, depthStencilRenderTarget->getLayerIndex(), 1,
depthStencilImage->getAspectFlags(), depthStencilImage));
vk::CommandBufferAccess access;
access.onImageComputeShaderRead(src->getAspectFlags(), src);
access.onImageTransferWrite(depthStencilRenderTarget->getLevelIndex(), 1,
depthStencilRenderTarget->getLayerIndex(), 1,
depthStencilImage->getAspectFlags(), depthStencilImage);
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// Blit/resolve stencil into the buffer.
VkDescriptorImageInfo imageInfo = {};
......@@ -1972,9 +1984,9 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
ANGLE_TRY(setupProgram(contextVk, Function::BlitResolveStencilNoExport, shader, nullptr,
&mBlitResolveStencilNoExportPrograms[flags], nullptr, descriptorSet,
&shaderParams, sizeof(shaderParams), &commandBuffer));
commandBuffer.dispatch(UnsignedCeilDivide(bufferRowLengthInUints, 8),
UnsignedCeilDivide(params.blitArea.height, 8), 1);
&shaderParams, sizeof(shaderParams), commandBuffer));
commandBuffer->dispatch(UnsignedCeilDivide(bufferRowLengthInUints, 8),
UnsignedCeilDivide(params.blitArea.height, 8), 1);
descriptorPoolBinding.reset();
// Add a barrier prior to copy.
......@@ -1984,9 +1996,9 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
// Use the all pipe stage to keep the state management simple.
commandBuffer.pipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &memoryBarrier, 0, nullptr,
0, nullptr);
commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &memoryBarrier, 0, nullptr,
0, nullptr);
// Copy the resulting buffer into dest.
VkBufferImageCopy region = {};
......@@ -2006,9 +2018,9 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
region.imageExtent.height = params.blitArea.height;
region.imageExtent.depth = 1;
commandBuffer.copyBufferToImage(blitBuffer.get().getBuffer().getHandle(),
depthStencilImage->getImage(),
depthStencilImage->getCurrentLayout(), 1, &region);
commandBuffer->copyBufferToImage(blitBuffer.get().getBuffer().getHandle(),
depthStencilImage->getImage(),
depthStencilImage->getCurrentLayout(), 1, &region);
return angle::Result::Continue;
}
......@@ -2259,13 +2271,14 @@ angle::Result UtilsVk::generateMipmap(ContextVk *contextVk,
// Note: onImageRead/onImageWrite is expected to be called by the caller. This avoids inserting
// barriers between calls for each layer of the image.
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
ANGLE_TRY(setupProgram(contextVk, Function::GenerateMipmap, shader, nullptr,
&mGenerateMipmapPrograms[flags], nullptr, descriptorSet, &shaderParams,
sizeof(shaderParams), &commandBuffer));
sizeof(shaderParams), commandBuffer));
commandBuffer.dispatch(workGroupX, workGroupY, 1);
commandBuffer->dispatch(workGroupX, workGroupY, 1);
descriptorPoolBinding.reset();
return angle::Result::Continue;
......@@ -2471,11 +2484,13 @@ angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk,
ASSERT(dest->getLevelCount() == 1 && dest->getLayerCount() == 1 &&
dest->getBaseLevel() == gl::LevelIndex(0));
ANGLE_TRY(contextVk->onBufferComputeShaderRead(enabledWidgetsBuffer));
ANGLE_TRY(contextVk->onImageComputeShaderWrite(gl::LevelIndex(0), 1, 0, 1,
VK_IMAGE_ASPECT_COLOR_BIT, dest));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBufferAccess access;
access.onBufferComputeShaderRead(enabledWidgetsBuffer);
access.onImageComputeShaderWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, dest);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorImageInfo imageInfo = {};
imageInfo.imageView = destView->getHandle();
......@@ -2508,8 +2523,8 @@ angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk,
ANGLE_TRY(setupProgram(contextVk, Function::OverlayCull, shader, nullptr,
&mOverlayCullPrograms[flags], nullptr, descriptorSet, nullptr, 0,
&commandBuffer));
commandBuffer.dispatch(dest->getExtents().width, dest->getExtents().height, 1);
commandBuffer));
commandBuffer->dispatch(dest->getExtents().width, dest->getExtents().height, 1);
descriptorPoolBinding.reset();
return angle::Result::Continue;
......@@ -2544,14 +2559,16 @@ angle::Result UtilsVk::drawOverlay(ContextVk *contextVk,
ASSERT(dest->getLevelCount() == 1 && dest->getLayerCount() == 1 &&
dest->getBaseLevel() == gl::LevelIndex(0));
ANGLE_TRY(contextVk->onImageComputeShaderWrite(gl::LevelIndex(0), 1, 0, 1,
VK_IMAGE_ASPECT_COLOR_BIT, dest));
ANGLE_TRY(contextVk->onImageComputeShaderRead(VK_IMAGE_ASPECT_COLOR_BIT, culledWidgets));
ANGLE_TRY(contextVk->onImageComputeShaderRead(VK_IMAGE_ASPECT_COLOR_BIT, font));
ANGLE_TRY(contextVk->onBufferComputeShaderRead(textWidgetsBuffer));
ANGLE_TRY(contextVk->onBufferComputeShaderRead(graphWidgetsBuffer));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBufferAccess access;
access.onImageComputeShaderWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, dest);
access.onImageComputeShaderRead(VK_IMAGE_ASPECT_COLOR_BIT, culledWidgets);
access.onImageComputeShaderRead(VK_IMAGE_ASPECT_COLOR_BIT, font);
access.onBufferComputeShaderRead(textWidgetsBuffer);
access.onBufferComputeShaderRead(graphWidgetsBuffer);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorImageInfo imageInfos[3] = {};
imageInfos[0].imageView = destView->getHandle();
......@@ -2612,12 +2629,12 @@ angle::Result UtilsVk::drawOverlay(ContextVk *contextVk,
ANGLE_TRY(setupProgram(contextVk, Function::OverlayDraw, shader, nullptr,
&mOverlayDrawPrograms[flags], nullptr, descriptorSet, &shaderParams,
sizeof(shaderParams), &commandBuffer));
sizeof(shaderParams), commandBuffer));
// Every pixel of culledWidgets corresponds to one workgroup, so we can use that as dispatch
// size.
const VkExtent3D &extents = culledWidgets->getExtents();
commandBuffer.dispatch(extents.width, extents.height, 1);
commandBuffer->dispatch(extents.width, extents.height, 1);
descriptorPoolBinding.reset();
return angle::Result::Continue;
......
......@@ -2366,10 +2366,11 @@ angle::Result QueryHelper::beginQuery(ContextVk *contextVk)
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
}
CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
const QueryPool &queryPool = getQueryPool();
commandBuffer.resetQueryPool(queryPool.getHandle(), mQuery, 1);
commandBuffer.beginQuery(queryPool.getHandle(), mQuery, 0);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
const QueryPool &queryPool = getQueryPool();
commandBuffer->resetQueryPool(queryPool.getHandle(), mQuery, 1);
commandBuffer->beginQuery(queryPool.getHandle(), mQuery, 0);
mMostRecentSerial = contextVk->getCurrentQueueSerial();
return angle::Result::Continue;
}
......@@ -2381,8 +2382,9 @@ angle::Result QueryHelper::endQuery(ContextVk *contextVk)
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
}
CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
commandBuffer.endQuery(getQueryPool().getHandle(), mQuery);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
commandBuffer->endQuery(getQueryPool().getHandle(), mQuery);
mMostRecentSerial = contextVk->getCurrentQueueSerial();
return angle::Result::Continue;
}
......@@ -2408,8 +2410,9 @@ angle::Result QueryHelper::flushAndWriteTimestamp(ContextVk *contextVk)
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
}
CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
writeTimestamp(contextVk, &commandBuffer);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
writeTimestamp(contextVk, commandBuffer);
return angle::Result::Continue;
}
......@@ -3016,11 +3019,14 @@ angle::Result BufferHelper::copyFromBuffer(ContextVk *contextVk,
uint32_t regionCount,
const VkBufferCopy *copyRegions)
{
ANGLE_TRY(contextVk->onBufferTransferRead(srcBuffer));
ANGLE_TRY(contextVk->onBufferTransferWrite(this));
vk::CommandBufferAccess access;
access.onBufferTransferRead(srcBuffer);
access.onBufferTransferWrite(this);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
commandBuffer.copyBuffer(srcBuffer->getBuffer(), mBuffer, regionCount, copyRegions);
commandBuffer->copyBuffer(srcBuffer->getBuffer(), mBuffer, regionCount, copyRegions);
return angle::Result::Continue;
}
......@@ -4267,8 +4273,6 @@ angle::Result ImageHelper::CopyImageSubData(const gl::Context *context,
const gl::LevelIndex srcLevelGL = gl::LevelIndex(srcLevel);
const gl::LevelIndex dstLevelGL = gl::LevelIndex(dstLevel);
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
srcImage->retain(&contextVk->getResourceUseList());
dstImage->retain(&contextVk->getResourceUseList());
......@@ -4294,17 +4298,21 @@ angle::Result ImageHelper::CopyImageSubData(const gl::Context *context,
region.extent.height = srcHeight;
region.extent.depth = (isSrc3D || isDst3D) ? srcDepth : 1;
ANGLE_TRY(contextVk->onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage));
ANGLE_TRY(contextVk->onImageTransferWrite(
dstLevelGL, 1, region.dstSubresource.baseArrayLayer, region.dstSubresource.layerCount,
VK_IMAGE_ASPECT_COLOR_BIT, dstImage));
vk::CommandBufferAccess access;
access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage);
access.onImageTransferWrite(dstLevelGL, 1, region.dstSubresource.baseArrayLayer,
region.dstSubresource.layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
dstImage);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
ASSERT(commandBuffer.valid() && srcImage->valid() && dstImage->valid());
ASSERT(srcImage->valid() && dstImage->valid());
ASSERT(srcImage->getCurrentLayout() == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
ASSERT(dstImage->getCurrentLayout() == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
commandBuffer.copyImage(srcImage->getImage(), srcImage->getCurrentLayout(),
dstImage->getImage(), dstImage->getCurrentLayout(), 1, &region);
commandBuffer->copyImage(srcImage->getImage(), srcImage->getCurrentLayout(),
dstImage->getImage(), dstImage->getCurrentLayout(), 1, &region);
}
else
{
......@@ -4321,10 +4329,12 @@ angle::Result ImageHelper::CopyImageSubData(const gl::Context *context,
angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, LevelIndex maxLevel)
{
ANGLE_TRY(contextVk->onImageTransferWrite(mBaseLevel + 1, maxLevel.get(), 0, mLayerCount,
VK_IMAGE_ASPECT_COLOR_BIT, this));
vk::CommandBufferAccess access;
access.onImageTransferWrite(mBaseLevel + 1, maxLevel.get(), 0, mLayerCount,
VK_IMAGE_ASPECT_COLOR_BIT, this);
CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// We are able to use blitImage since the image format we are using supports it.
int32_t mipWidth = mExtents.width;
......@@ -4358,8 +4368,8 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, LevelIn
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
// We can do it for all layers at once.
commandBuffer.imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
barrier);
commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
barrier);
VkImageBlit blit = {};
blit.srcOffsets[0] = {0, 0, 0};
blit.srcOffsets[1] = {mipWidth, mipHeight, mipDepth};
......@@ -4378,8 +4388,8 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, LevelIn
mipHeight = nextMipHeight;
mipDepth = nextMipDepth;
commandBuffer.blitImage(mImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, mImage,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, filter);
commandBuffer->blitImage(mImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, mImage,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, filter);
}
// Transition the last mip level to the same layout as all the other ones, so we can declare
......@@ -4389,8 +4399,8 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, LevelIn
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
// We can do it for all layers at once.
commandBuffer.imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
barrier);
commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
barrier);
// This is just changing the internal state of the image helper so that the next call
// to changeLayout will use this layout as the "oldLayout" argument.
mCurrentLayout = ImageLayout::TransferSrc;
......@@ -5277,9 +5287,11 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
// Start in TransferDst. Don't yet mark any subresource as having defined contents; that is
// done with fine granularity as updates are applied. This is achieved by specifying a layer
// that is outside the tracking range.
ANGLE_TRY(contextVk->onImageTransferWrite(mBaseLevel, 1, kMaxContentDefinedLayerCount, 0,
aspectFlags, this));
CommandBuffer *commandBuffer = &contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBufferAccess access;
access.onImageTransferWrite(mBaseLevel, 1, kMaxContentDefinedLayerCount, 0, aspectFlags, this);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
for (gl::LevelIndex updateMipLevelGL = levelGLStart; updateMipLevelGL < levelGLEnd;
++updateMipLevelGL)
......@@ -5385,8 +5397,10 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
BufferHelper *currentBuffer = bufferUpdate.bufferHelper;
ASSERT(currentBuffer && currentBuffer->valid());
ANGLE_TRY(contextVk->onBufferTransferRead(currentBuffer));
commandBuffer = &contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBufferAccess bufferAccess;
bufferAccess.onBufferTransferRead(currentBuffer);
ANGLE_TRY(
contextVk->getOutsideRenderPassCommandBuffer(bufferAccess, &commandBuffer));
commandBuffer->copyBufferToImage(currentBuffer->getBuffer().getHandle(), mImage,
getCurrentLayout(), 1, &update.buffer.copyRegion);
......@@ -5395,8 +5409,10 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
}
else
{
ANGLE_TRY(contextVk->onImageTransferRead(aspectFlags, update.image.image));
commandBuffer = &contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBufferAccess imageAccess;
imageAccess.onImageTransferRead(aspectFlags, update.image.image);
ANGLE_TRY(
contextVk->getOutsideRenderPassCommandBuffer(imageAccess, &commandBuffer));
commandBuffer->copyImage(update.image.image->getImage(),
update.image.image->getCurrentLayout(), mImage,
......@@ -5677,12 +5693,14 @@ angle::Result ImageHelper::copyImageDataToBuffer(ContextVk *contextVk,
regions[1].imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
}
ANGLE_TRY(contextVk->onBufferTransferWrite(*bufferOut));
ANGLE_TRY(contextVk->onImageTransferRead(aspectFlags, this));
vk::CommandBufferAccess access;
access.onBufferTransferWrite(*bufferOut);
access.onImageTransferRead(aspectFlags, this);
CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
commandBuffer.copyImageToBuffer(mImage, getCurrentLayout(), bufferHandle, 1, regions);
commandBuffer->copyImageToBuffer(mImage, getCurrentLayout(), bufferHandle, 1, regions);
return angle::Result::Continue;
}
......@@ -5825,14 +5843,16 @@ angle::Result ImageHelper::readPixels(ContextVk *contextVk,
VkImageAspectFlags layoutChangeAspectFlags = src->getAspectFlags();
// Note that although we're reading from the image, we need to update the layout below.
vk::CommandBufferAccess access;
access.onImageTransferRead(layoutChangeAspectFlags, this);
if (isMultisampled)
{
ANGLE_TRY(contextVk->onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1,
layoutChangeAspectFlags, &resolvedImage.get()));
access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, layoutChangeAspectFlags,
&resolvedImage.get());
}
ANGLE_TRY(contextVk->onImageTransferRead(layoutChangeAspectFlags, this));
CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
const angle::Format *readFormat = &mFormat->actualImageFormat();
......@@ -5874,9 +5894,11 @@ angle::Result ImageHelper::readPixels(ContextVk *contextVk,
resolveRegion.dstOffset = {};
resolveRegion.extent = srcExtent;
resolve(&resolvedImage.get(), resolveRegion, &commandBuffer);
resolve(&resolvedImage.get(), resolveRegion, commandBuffer);
ANGLE_TRY(contextVk->onImageTransferRead(layoutChangeAspectFlags, &resolvedImage.get()));
vk::CommandBufferAccess readAccess;
readAccess.onImageTransferRead(layoutChangeAspectFlags, &resolvedImage.get());
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(readAccess, &commandBuffer));
// Make the resolved image the target of buffer copy.
src = &resolvedImage.get();
......@@ -5902,8 +5924,8 @@ angle::Result ImageHelper::readPixels(ContextVk *contextVk,
region.imageOffset = srcOffset;
region.imageSubresource = srcSubresource;
commandBuffer.copyImageToBuffer(src->getImage(), src->getCurrentLayout(), bufferHandle, 1,
&region);
commandBuffer->copyImageToBuffer(src->getImage(), src->getCurrentLayout(), bufferHandle, 1,
&region);
ANGLE_PERF_WARNING(contextVk->getDebug(), GL_DEBUG_SEVERITY_HIGH,
"GPU stall due to ReadPixels");
......@@ -6600,5 +6622,48 @@ ActiveHandleCounter::ActiveHandleCounter() : mActiveCounts{}, mAllocatedCounts{}
ActiveHandleCounter::~ActiveHandleCounter() = default;
// CommandBufferAccess implementation.
CommandBufferAccess::CommandBufferAccess() = default;
CommandBufferAccess::~CommandBufferAccess() = default;
void CommandBufferAccess::onBufferRead(VkAccessFlags readAccessType,
PipelineStage readStage,
BufferHelper *buffer)
{
ASSERT(!buffer->isReleasedToExternal());
mReadBuffers.emplace_back(buffer, readAccessType, readStage);
}
void CommandBufferAccess::onBufferWrite(VkAccessFlags writeAccessType,
PipelineStage writeStage,
BufferHelper *buffer)
{
ASSERT(!buffer->isReleasedToExternal());
mWriteBuffers.emplace_back(buffer, writeAccessType, writeStage);
}
void CommandBufferAccess::onImageRead(VkImageAspectFlags aspectFlags,
ImageLayout imageLayout,
ImageHelper *image)
{
ASSERT(!image->isReleasedToExternal());
ASSERT(image->getImageSerial().valid());
mReadImages.emplace_back(image, aspectFlags, imageLayout);
}
void CommandBufferAccess::onImageWrite(gl::LevelIndex levelStart,
uint32_t levelCount,
uint32_t layerStart,
uint32_t layerCount,
VkImageAspectFlags aspectFlags,
ImageLayout imageLayout,
ImageHelper *image)
{
ASSERT(!image->isReleasedToExternal());
ASSERT(image->getImageSerial().valid());
mWriteImages.emplace_back(CommandBufferImageAccess{image, aspectFlags, imageLayout}, levelStart,
levelCount, layerStart, layerCount);
}
} // namespace vk
} // namespace rx
......@@ -2245,6 +2245,120 @@ ANGLE_INLINE bool CommandBufferHelper::usesImageInRenderPass(const ImageHelper &
ASSERT(mIsRenderPassCommandBuffer);
return mRenderPassUsedImages.contains(image.getImageSerial().getValue());
}
// Sometimes ANGLE issues a command internally, such as copies, draws and dispatches that do not
// directly correspond to the application draw/dispatch call. Before the command is recorded in the
// command buffer, the render pass may need to be broken and/or appropriate barriers may need to be
// inserted. The following struct aggregates all resources that such internal commands need.
struct CommandBufferBufferAccess
{
BufferHelper *buffer;
VkAccessFlags accessType;
PipelineStage stage;
};
struct CommandBufferImageAccess
{
ImageHelper *image;
VkImageAspectFlags aspectFlags;
ImageLayout imageLayout;
};
struct CommandBufferImageWrite
{
CommandBufferImageAccess access;
gl::LevelIndex levelStart;
uint32_t levelCount;
uint32_t layerStart;
uint32_t layerCount;
};
class CommandBufferAccess : angle::NonCopyable
{
public:
CommandBufferAccess();
~CommandBufferAccess();
void onBufferTransferRead(BufferHelper *buffer)
{
onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, PipelineStage::Transfer, buffer);
}
void onBufferTransferWrite(BufferHelper *buffer)
{
onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, PipelineStage::Transfer, buffer);
}
void onBufferSelfCopy(BufferHelper *buffer)
{
onBufferWrite(VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
PipelineStage::Transfer, buffer);
}
void onBufferComputeShaderRead(BufferHelper *buffer)
{
onBufferRead(VK_ACCESS_SHADER_READ_BIT, PipelineStage::ComputeShader, buffer);
}
void onBufferComputeShaderWrite(BufferHelper *buffer)
{
onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, PipelineStage::ComputeShader, buffer);
}
void onImageTransferRead(VkImageAspectFlags aspectFlags, ImageHelper *image)
{
onImageRead(aspectFlags, ImageLayout::TransferSrc, image);
}
void onImageTransferWrite(gl::LevelIndex levelStart,
uint32_t levelCount,
uint32_t layerStart,
uint32_t layerCount,
VkImageAspectFlags aspectFlags,
ImageHelper *image)
{
onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags,
ImageLayout::TransferDst, image);
}
void onImageComputeShaderRead(VkImageAspectFlags aspectFlags, ImageHelper *image)
{
onImageRead(aspectFlags, ImageLayout::ComputeShaderReadOnly, image);
}
void onImageComputeShaderWrite(gl::LevelIndex levelStart,
uint32_t levelCount,
uint32_t layerStart,
uint32_t layerCount,
VkImageAspectFlags aspectFlags,
ImageHelper *image)
{
onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags,
ImageLayout::ComputeShaderWrite, image);
}
// The limits reflect the current maximum concurrent usage of each resource type. ASSERTs will
// fire if this limit is exceeded in the future.
using ReadBuffers = angle::FixedVector<CommandBufferBufferAccess, 2>;
using WriteBuffers = angle::FixedVector<CommandBufferBufferAccess, 2>;
using ReadImages = angle::FixedVector<CommandBufferImageAccess, 2>;
using WriteImages = angle::FixedVector<CommandBufferImageWrite, 1>;
const ReadBuffers &getReadBuffers() const { return mReadBuffers; }
const WriteBuffers &getWriteBuffers() const { return mWriteBuffers; }
const ReadImages &getReadImages() const { return mReadImages; }
const WriteImages &getWriteImages() const { return mWriteImages; }
private:
void onBufferRead(VkAccessFlags readAccessType, PipelineStage readStage, BufferHelper *buffer);
void onBufferWrite(VkAccessFlags writeAccessType,
PipelineStage writeStage,
BufferHelper *buffer);
void onImageRead(VkImageAspectFlags aspectFlags, ImageLayout imageLayout, ImageHelper *image);
void onImageWrite(gl::LevelIndex levelStart,
uint32_t levelCount,
uint32_t layerStart,
uint32_t layerCount,
VkImageAspectFlags aspectFlags,
ImageLayout imageLayout,
ImageHelper *image);
ReadBuffers mReadBuffers;
WriteBuffers mWriteBuffers;
ReadImages mReadImages;
WriteImages mWriteImages;
};
} // namespace vk
} // namespace rx
......
......@@ -784,7 +784,6 @@ uint32_t ResourceSerialFactory::issueSerial()
}
ANGLE_VK_SERIAL_OP(ANGLE_DEFINE_GEN_VK_SERIAL)
} // namespace vk
#if !defined(ANGLE_SHARED_LIBVULKAN)
......
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