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;
}
......
......@@ -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,7 +844,7 @@ 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,
commandBuffer->blitImage(srcImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dstImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
gl_vk::GetFilter(filter));
......@@ -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::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,8 +121,9 @@ 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::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());
......
......@@ -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,13 +1601,14 @@ 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(),
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)
......
......@@ -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