Commit 3712b2e4 by Jamie Madill Committed by Commit Bot

Vulkan: Command graph linearization (Step 1).

This initial prototype introduces a new feature to the Vulkan back-end that disables the deferred command recording. The intent is to have a lower CPU overhead during submission calls which currently walk a DAG. The feature is not complete. Currently it only passes the ANGLE SimpleOperationTests. Moreover it is extremely simple and only allows use of one command buffer at a time. In the future we'll allow open command buffers for recording outside and inside render pass commands at the same time. We'll also support collapsing RenderPasses together for some use cases. Currently the prototype only passes "SimpleOperationTest". There are quite a few unimplemented features like queries, XFB, etc. Bug: angleproject:4029 Change-Id: I82760986683f55e37ac4ea559de6f4cffb6ef84e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1953485 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTobin Ehlis <tobine@google.com>
parent d5d8ffa8
......@@ -208,27 +208,36 @@ angle::Result BufferVk::copySubData(const gl::Context *context,
vk::CommandBuffer *commandBuffer = nullptr;
// Handle self-dependency especially.
if (sourceBuffer->mBuffer.getBuffer().getHandle() == mBuffer.getBuffer().getHandle())
if (contextVk->commandGraphEnabled())
{
// We set the TRANSFER_READ_BIT to be conservative.
mBuffer.onSelfReadWrite(contextVk,
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT);
// Handle self-dependency especially.
if (sourceBuffer->mBuffer.getBuffer().getHandle() == mBuffer.getBuffer().getHandle())
{
// We set the TRANSFER_READ_BIT to be conservative.
mBuffer.onSelfReadWrite(contextVk,
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT);
ANGLE_TRY(mBuffer.recordCommands(contextVk, &commandBuffer));
}
else
{
ANGLE_TRY(mBuffer.recordCommands(contextVk, &commandBuffer));
ANGLE_TRY(mBuffer.recordCommands(contextVk, &commandBuffer));
sourceBuffer->mBuffer.onReadByBuffer(contextVk, &mBuffer, VK_ACCESS_TRANSFER_READ_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
}
}
else
{
ANGLE_TRY(mBuffer.recordCommands(contextVk, &commandBuffer));
sourceBuffer->mBuffer.onReadByBuffer(contextVk, &mBuffer, VK_ACCESS_TRANSFER_READ_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
contextVk->onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, &sourceBuffer->getBuffer());
contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, &mBuffer);
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
// Enqueue a copy command on the GPU.
VkBufferCopy copyRegion = {static_cast<VkDeviceSize>(sourceOffset),
static_cast<VkDeviceSize>(destOffset),
static_cast<VkDeviceSize>(size)};
const VkBufferCopy copyRegion = {static_cast<VkDeviceSize>(sourceOffset),
static_cast<VkDeviceSize>(destOffset),
static_cast<VkDeviceSize>(size)};
commandBuffer->copyBuffer(sourceBuffer->getBuffer().getBuffer(), mBuffer.getBuffer(), 1,
&copyRegion);
......@@ -406,12 +415,24 @@ angle::Result BufferVk::copyToBuffer(ContextVk *contextVk,
const VkBufferCopy *copies)
{
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(destBuffer->recordCommands(contextVk, &commandBuffer));
commandBuffer->copyBuffer(mBuffer.getBuffer(), destBuffer->getBuffer(), copyCount, copies);
if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(destBuffer->recordCommands(contextVk, &commandBuffer));
}
else
{
contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, destBuffer);
contextVk->onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, &mBuffer);
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
mBuffer.onReadByBuffer(contextVk, destBuffer, VK_ACCESS_TRANSFER_READ_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
commandBuffer->copyBuffer(mBuffer.getBuffer(), destBuffer->getBuffer(), copyCount, copies);
if (contextVk->commandGraphEnabled())
{
mBuffer.onReadByBuffer(contextVk, destBuffer, VK_ACCESS_TRANSFER_READ_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
}
return angle::Result::Continue;
}
......
......@@ -305,6 +305,8 @@ angle::Result CommandGraphResource::finishRunningCommands(ContextVk *contextVk)
angle::Result CommandGraphResource::recordCommands(ContextVk *contextVk,
CommandBuffer **commandBufferOut)
{
ASSERT(contextVk->commandGraphEnabled());
updateCurrentAccessNodes();
if (!hasChildlessWritingNode() || hasStartedRenderPass())
......@@ -357,6 +359,8 @@ angle::Result CommandGraphResource::beginRenderPass(
void CommandGraphResource::addWriteDependency(ContextVk *contextVk,
CommandGraphResource *writingResource)
{
ASSERT(contextVk->commandGraphEnabled());
CommandGraphNode *writingNode = writingResource->mCurrentWritingNode;
ASSERT(writingNode);
......@@ -366,6 +370,8 @@ void CommandGraphResource::addWriteDependency(ContextVk *contextVk,
void CommandGraphResource::addReadDependency(ContextVk *contextVk,
CommandGraphResource *readingResource)
{
ASSERT(contextVk->commandGraphEnabled());
onResourceAccess(&contextVk->getResourceUseList());
CommandGraphNode *readingNode = readingResource->mCurrentWritingNode;
......@@ -383,11 +389,13 @@ void CommandGraphResource::addReadDependency(ContextVk *contextVk,
void CommandGraphResource::finishCurrentCommands(ContextVk *contextVk)
{
ASSERT(contextVk->commandGraphEnabled());
startNewCommands(contextVk);
}
void CommandGraphResource::startNewCommands(ContextVk *contextVk)
{
ASSERT(contextVk->commandGraphEnabled());
CommandGraphNode *newCommands =
contextVk->getCommandGraph()->allocateNode(CommandGraphNodeFunction::Generic);
newCommands->setDiagnosticInfo(mResourceType, reinterpret_cast<uintptr_t>(this));
......
......@@ -22,7 +22,7 @@
namespace angle
{
struct FeaturesVk;
}
} // namespace angle
namespace rx
{
......@@ -94,6 +94,92 @@ class CommandQueue final : angle::NonCopyable
vk::PersistentCommandPool mPrimaryCommandPool;
};
class OutsideRenderPassCommandBuffer final : angle::NonCopyable
{
public:
OutsideRenderPassCommandBuffer();
~OutsideRenderPassCommandBuffer();
void bufferRead(VkAccessFlags readAccessType, vk::BufferHelper *buffer);
void bufferWrite(VkAccessFlags writeAccessType, vk::BufferHelper *buffer);
void flushToPrimary(vk::PrimaryCommandBuffer *primary);
vk::CommandBuffer &getCommandBuffer() { return mCommandBuffer; }
bool empty() const { return mCommandBuffer.empty(); }
void reset();
private:
VkFlags mGlobalMemoryBarrierSrcAccess;
VkFlags mGlobalMemoryBarrierDstAccess;
VkPipelineStageFlags mGlobalMemoryBarrierStages;
vk::CommandBuffer mCommandBuffer;
};
class RenderPassCommandBuffer final : angle::NonCopyable
{
public:
RenderPassCommandBuffer();
~RenderPassCommandBuffer();
void initialize(angle::PoolAllocator *poolAllocator);
void beginRenderPass(const vk::Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps,
const std::vector<VkClearValue> &clearValues,
vk::CommandBuffer **commandBufferOut);
void clearRenderPassColorAttachment(size_t attachmentIndex, const VkClearColorValue &clearValue)
{
mAttachmentOps[attachmentIndex].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
mClearValues[attachmentIndex].color = clearValue;
}
void clearRenderPassDepthAttachment(size_t attachmentIndex, float depth)
{
mAttachmentOps[attachmentIndex].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
mClearValues[attachmentIndex].depthStencil.depth = depth;
}
void clearRenderPassStencilAttachment(size_t attachmentIndex, uint32_t stencil)
{
mAttachmentOps[attachmentIndex].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
mClearValues[attachmentIndex].depthStencil.stencil = stencil;
}
void invalidateRenderPassColorAttachment(size_t attachmentIndex)
{
mAttachmentOps[attachmentIndex].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
}
void invalidateRenderPassDepthAttachment(size_t attachmentIndex)
{
mAttachmentOps[attachmentIndex].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
}
void invalidateRenderPassStencilAttachment(size_t attachmentIndex)
{
mAttachmentOps[attachmentIndex].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
}
angle::Result flushToPrimary(ContextVk *contextVk, vk::PrimaryCommandBuffer *primary);
bool empty() const { return mCommandBuffer.empty(); }
void reset();
private:
vk::RenderPassDesc mRenderPassDesc;
vk::AttachmentOpsArray mAttachmentOps;
vk::Framebuffer mFramebuffer;
gl::Rectangle mRenderArea;
gl::AttachmentArray<VkClearValue> mClearValues;
vk::CommandBuffer mCommandBuffer;
};
class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassOwner
{
public:
......@@ -277,6 +363,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
VkDevice getDevice() const;
ANGLE_INLINE const angle::FeaturesVk &getFeatures() const { return mRenderer->getFeatures(); }
ANGLE_INLINE bool commandGraphEnabled() const { return getFeatures().commandGraph.enabled; }
ANGLE_INLINE void invalidateVertexAndIndexBuffers()
{
......@@ -424,6 +511,34 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
vk::ResourceUseList &getResourceUseList() { return mResourceUseList; }
void onBufferRead(VkAccessFlags readAccessType, vk::BufferHelper *buffer);
void onBufferWrite(VkAccessFlags writeAccessType, vk::BufferHelper *buffer);
angle::Result getOutsideRenderPassCommandBuffer(vk::CommandBuffer **commandBufferOut)
{
if (!mRenderPassCommands.empty())
{
ANGLE_TRY(mRenderPassCommands.flushToPrimary(this, &mPrimaryCommands));
}
*commandBufferOut = &mOutsideRenderPassCommands.getCommandBuffer();
return angle::Result::Continue;
}
void beginRenderPass(const vk::Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps,
const std::vector<VkClearValue> &clearValues,
vk::CommandBuffer **commandBufferOut);
RenderPassCommandBuffer &getRenderPassCommandBuffer()
{
if (!mOutsideRenderPassCommands.empty())
{
mOutsideRenderPassCommands.flushToPrimary(&mPrimaryCommands);
}
return mRenderPassCommands;
}
private:
// Dirty bits.
enum DirtyBitType : size_t
......@@ -673,6 +788,8 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
bool shouldUseOldRewriteStructSamplers() const;
void clearAllGarbage();
angle::Result ensureSubmitFenceInitialized();
angle::Result startPrimaryCommandBuffer();
bool hasRecordedCommands();
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers;
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers;
......@@ -783,6 +900,12 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
// See CommandGraph.h for a desription of the Command Graph.
vk::CommandGraph mCommandGraph;
// When the command graph is disabled we record commands completely linearly. We have plans to
// reorder independent draws so that we can create fewer RenderPasses in some scenarios.
OutsideRenderPassCommandBuffer mOutsideRenderPassCommands;
RenderPassCommandBuffer mRenderPassCommands;
vk::PrimaryCommandBuffer mPrimaryCommands;
// Internal shader library.
vk::ShaderLibrary mShaderLibrary;
UtilsVk mUtils;
......
......@@ -300,7 +300,10 @@ angle::Result FramebufferVk::clearImpl(const gl::Context *context,
// that case, end the render pass immediately. http://anglebug.com/2361
if (contextVk->getRenderer()->getFeatures().restartRenderPassAfterLoadOpClear.enabled)
{
mFramebuffer.finishCurrentCommands(contextVk);
if (contextVk->commandGraphEnabled())
{
mFramebuffer.finishCurrentCommands(contextVk);
}
}
// Fallback to other methods for whatever isn't cleared here.
......@@ -1089,9 +1092,12 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
mFramebuffer.release(contextVk);
// Will freeze the current set of dependencies on this FBO. The next time we render we will
// create a new entry in the command graph.
mFramebuffer.finishCurrentCommands(contextVk);
if (contextVk->commandGraphEnabled())
{
// Will freeze the current set of dependencies on this FBO. The next time we render we will
// create a new entry in the command graph.
mFramebuffer.finishCurrentCommands(contextVk);
}
// Notify the ContextVk to update the pipeline desc.
updateRenderPassDesc();
......@@ -1252,7 +1258,15 @@ angle::Result FramebufferVk::clearWithRenderPassOp(
SetEmulatedAlphaValue(renderTarget->getImageFormat(), &value);
}
mFramebuffer.clearRenderPassColorAttachment(attachmentIndexVk, value);
if (contextVk->commandGraphEnabled())
{
mFramebuffer.clearRenderPassColorAttachment(attachmentIndexVk, value);
}
else
{
contextVk->getRenderPassCommandBuffer().clearRenderPassColorAttachment(
attachmentIndexVk, value);
}
}
++attachmentIndexVk;
}
......@@ -1263,14 +1277,30 @@ angle::Result FramebufferVk::clearWithRenderPassOp(
{
if (clearDepth)
{
mFramebuffer.clearRenderPassDepthAttachment(attachmentIndexVk,
clearDepthStencilValue.depth);
if (contextVk->commandGraphEnabled())
{
mFramebuffer.clearRenderPassDepthAttachment(attachmentIndexVk,
clearDepthStencilValue.depth);
}
else
{
contextVk->getRenderPassCommandBuffer().clearRenderPassDepthAttachment(
attachmentIndexVk, clearDepthStencilValue.depth);
}
}
if (clearStencil)
{
mFramebuffer.clearRenderPassStencilAttachment(attachmentIndexVk,
clearDepthStencilValue.stencil);
if (contextVk->commandGraphEnabled())
{
mFramebuffer.clearRenderPassStencilAttachment(attachmentIndexVk,
clearDepthStencilValue.stencil);
}
else
{
contextVk->getRenderPassCommandBuffer().clearRenderPassStencilAttachment(
attachmentIndexVk, clearDepthStencilValue.stencil);
}
}
}
......@@ -1345,7 +1375,14 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
std::vector<VkClearValue> attachmentClearValues;
vk::CommandBuffer *writeCommands = nullptr;
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &writeCommands));
if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &writeCommands));
}
else
{
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&writeCommands));
}
// Initialize RenderPass info.
const auto &colorRenderTargets = mRenderTargetCache.getColors();
......@@ -1374,9 +1411,19 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
attachmentClearValues.emplace_back(kUninitializedClearValue);
}
return mFramebuffer.beginRenderPass(contextVk, *framebuffer, renderArea, mRenderPassDesc,
renderPassAttachmentOps, attachmentClearValues,
commandBufferOut);
if (contextVk->commandGraphEnabled())
{
return mFramebuffer.beginRenderPass(contextVk, *framebuffer, renderArea, mRenderPassDesc,
renderPassAttachmentOps, attachmentClearValues,
commandBufferOut);
}
else
{
contextVk->beginRenderPass(*framebuffer, renderArea, mRenderPassDesc,
renderPassAttachmentOps, attachmentClearValues,
commandBufferOut);
return angle::Result::Continue;
}
}
void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a)
......
......@@ -1389,12 +1389,26 @@ void ProgramVk::updateBuffersDescriptorSet(ContextVk *contextVk,
if (isStorageBuffer)
{
// We set the SHADER_READ_BIT to be conservative.
bufferHelper.onWrite(contextVk, recorder,
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
if (contextVk->getFeatures().commandGraph.enabled)
{
bufferHelper.onWrite(contextVk, recorder, accessFlags);
}
else
{
contextVk->onBufferWrite(accessFlags, &bufferHelper);
}
}
else
{
bufferHelper.onRead(contextVk, recorder, VK_ACCESS_UNIFORM_READ_BIT);
if (contextVk->getFeatures().commandGraph.enabled)
{
bufferHelper.onRead(contextVk, recorder, VK_ACCESS_UNIFORM_READ_BIT);
}
else
{
contextVk->onBufferRead(VK_ACCESS_UNIFORM_READ_BIT, &bufferHelper);
}
}
++writeCount;
......
......@@ -65,8 +65,11 @@ angle::Result RenderTargetVk::onColorDraw(ContextVk *contextVk,
mImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment,
commandBuffer);
// Set up dependencies between the RT resource and the Framebuffer.
mImage->addWriteDependency(contextVk, framebufferVk);
if (contextVk->commandGraphEnabled())
{
// Set up dependencies between the RT resource and the Framebuffer.
mImage->addWriteDependency(contextVk, framebufferVk);
}
onImageViewAccess(contextVk);
......
......@@ -636,6 +636,12 @@ class SecondaryCommandBuffer final : angle::NonCopyable
reinterpret_cast<CommandHeader *>(mCurrentWritePointer)->id = CommandID::Invalid;
}
void reset()
{
mCommands.clear();
initialize(mAllocator);
}
// This will cause the SecondaryCommandBuffer to become invalid by clearing its allocator
void releaseHandle() { mAllocator = nullptr; }
// The SecondaryCommandBuffer is valid if it's been initialized
......
......@@ -1025,14 +1025,22 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
SwapchainImage &image = mSwapchainImages[mCurrentSwapchainImageIndex];
vk::CommandBuffer *commandBuffer = nullptr;
if (!contextVk->commandGraphEnabled())
{
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
if (mColorImageMS.valid())
{
// Transition the multisampled image to TRANSFER_SRC for resolve.
vk::CommandBuffer *multisampledTransition = nullptr;
ANGLE_TRY(mColorImageMS.recordCommands(contextVk, &multisampledTransition));
if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(mColorImageMS.recordCommands(contextVk, &commandBuffer));
}
mColorImageMS.changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc,
multisampledTransition);
commandBuffer);
// Setup graph dependency between the swapchain image and the multisampled one.
image.image.addReadDependency(contextVk, &mColorImageMS);
......@@ -1047,17 +1055,20 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
resolveRegion.dstOffset = {};
resolveRegion.extent = image.image.getExtents();
vk::CommandBuffer *resolveCommands = nullptr;
ANGLE_TRY(image.image.recordCommands(contextVk, &resolveCommands));
mColorImageMS.resolve(&image.image, resolveRegion, resolveCommands);
if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(image.image.recordCommands(contextVk, &commandBuffer));
}
mColorImageMS.resolve(&image.image, resolveRegion, commandBuffer);
}
ANGLE_TRY(updateAndDrawOverlay(contextVk, &image));
vk::CommandBuffer *transitionCommands = nullptr;
ANGLE_TRY(image.image.recordCommands(contextVk, &transitionCommands));
image.image.changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::Present,
transitionCommands);
if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(image.image.recordCommands(contextVk, &commandBuffer));
}
image.image.changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::Present, commandBuffer);
// Knowing that the kSwapHistorySize'th submission ago has finished, we can know that the
// (kSwapHistorySize+1)'th present ago of this image is definitely finished and so its wait
......
......@@ -1429,7 +1429,14 @@ angle::Result TextureVk::ensureImageInitializedImpl(ContextVk *contextVk,
}
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
}
else
{
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
return mImage->flushStagedUpdates(contextVk, getNativeImageLevel(0), mImage->getLevelCount(),
getNativeImageLayer(0), mImage->getLayerCount(),
commandBuffer);
......
......@@ -1640,6 +1640,51 @@ void BufferHelper::changeQueue(uint32_t newQueueFamilyIndex, CommandBuffer *comm
mCurrentQueueFamilyIndex = newQueueFamilyIndex;
}
bool BufferHelper::canAccumulateRead(ContextVk *contextVk, VkAccessFlags readAccessType)
{
// We only need to start a new command buffer when we need a new barrier.
// For simplicity's sake for now we always start a new command buffer.
// TODO(jmadill): Re-use the command buffer. http://anglebug.com/4029
return false;
}
bool BufferHelper::canAccumulateWrite(ContextVk *contextVk, VkAccessFlags writeAccessType)
{
// We only need to start a new command buffer when we need a new barrier.
// For simplicity's sake for now we always start a new command buffer.
// TODO(jmadill): Re-use the command buffer. http://anglebug.com/4029
return false;
}
void BufferHelper::updateReadBarrier(VkAccessFlags readAccessType,
VkAccessFlags *barrierSrcOut,
VkAccessFlags *barrierDstOut)
{
if (mCurrentWriteAccess != 0 && (mCurrentReadAccess & readAccessType) != readAccessType)
{
*barrierSrcOut |= mCurrentWriteAccess;
*barrierDstOut |= readAccessType;
}
// Accumulate new read usage.
mCurrentReadAccess |= readAccessType;
}
void BufferHelper::updateWriteBarrier(VkAccessFlags writeAccessType,
VkAccessFlags *barrierSrcOut,
VkAccessFlags *barrierDstOut)
{
if (mCurrentReadAccess != 0 || mCurrentWriteAccess != 0)
{
*barrierSrcOut |= mCurrentWriteAccess;
*barrierDstOut |= writeAccessType;
}
// Reset usages on the new write.
mCurrentWriteAccess = writeAccessType;
mCurrentReadAccess = 0;
}
// ImageHelper implementation.
ImageHelper::ImageHelper()
: CommandGraphResource(CommandGraphResourceType::Image),
......@@ -3165,7 +3210,14 @@ angle::Result ImageHelper::readPixels(ContextVk *contextVk,
// Note that although we're reading from the image, we need to update the layout below.
CommandBuffer *commandBuffer;
ANGLE_TRY(recordCommands(contextVk, &commandBuffer));
if (contextVk->commandGraphEnabled())
{
ANGLE_TRY(recordCommands(contextVk, &commandBuffer));
}
else
{
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
}
changeLayout(copyAspectFlags, ImageLayout::TransferSrc, commandBuffer);
const angle::Format *readFormat = &mFormat->actualImageFormat();
......@@ -3638,5 +3690,24 @@ angle::Result ShaderProgramHelper::getComputePipeline(Context *context,
return angle::Result::Continue;
}
void MakeDebugUtilsLabel(GLenum source, const char *marker, VkDebugUtilsLabelEXT *label)
{
static constexpr angle::ColorF kLabelColors[6] = {
angle::ColorF(1.0f, 0.5f, 0.5f, 1.0f), // DEBUG_SOURCE_API
angle::ColorF(0.5f, 1.0f, 0.5f, 1.0f), // DEBUG_SOURCE_WINDOW_SYSTEM
angle::ColorF(0.5f, 0.5f, 1.0f, 1.0f), // DEBUG_SOURCE_SHADER_COMPILER
angle::ColorF(0.7f, 0.7f, 0.7f, 1.0f), // DEBUG_SOURCE_THIRD_PARTY
angle::ColorF(0.5f, 0.8f, 0.9f, 1.0f), // DEBUG_SOURCE_APPLICATION
angle::ColorF(0.9f, 0.8f, 0.5f, 1.0f), // DEBUG_SOURCE_OTHER
};
int colorIndex = source - GL_DEBUG_SOURCE_API;
ASSERT(colorIndex >= 0 && static_cast<size_t>(colorIndex) < ArraySize(kLabelColors));
label->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
label->pNext = nullptr;
label->pLabelName = marker;
kLabelColors[colorIndex].writeData(label->color);
}
} // namespace vk
} // namespace rx
......@@ -557,6 +557,18 @@ class BufferHelper final : public CommandGraphResource
void changeQueue(uint32_t newQueueFamilyIndex, CommandBuffer *commandBuffer);
// New methods used when the CommandGraph is disabled.
bool canAccumulateRead(ContextVk *contextVk, VkAccessFlags readAccessType);
bool canAccumulateWrite(ContextVk *contextVk, VkAccessFlags writeAccessType);
void updateReadBarrier(VkAccessFlags readAccessType,
VkAccessFlags *barrierSrcOut,
VkAccessFlags *barrierDstOut);
void updateWriteBarrier(VkAccessFlags writeAccessType,
VkAccessFlags *barrierSrcOut,
VkAccessFlags *barrierDstOut);
private:
angle::Result mapImpl(ContextVk *contextVk);
bool needsOnReadBarrier(VkAccessFlags readAccessType,
......
......@@ -1080,6 +1080,6 @@ TEST_P(SimpleOperationTest, PrimitiveModeNegativeTest)
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(SimpleOperationTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(SimpleOperationTest, WithNoCommandGraph(ES2_VULKAN()));
} // namespace
......@@ -157,6 +157,12 @@ struct CombinedPrintToStringParamName
INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
testing::PrintToStringParamName())
#define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(testName, extra) \
const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
ANGLE_ALL_TEST_PLATFORMS_ES3, extra}; \
INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
testing::PrintToStringParamName())
#define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31(testName) \
const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
ANGLE_ALL_TEST_PLATFORMS_ES3, \
......
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