Vulkan: Distinguish RP and outside-RP command buffer types
What goes inside and outside a render pass command buffer is largely
mutually exclusive. Moreover, the size and frequency of allocations is
different between the two.
This change distinguishes the C++ types used for inside and outside
render pass command buffers:
- The type now documents which command buffer a function is able to
receive.
- `isRenderPass` flag passing, checking and asserting is largely
removed.
- A follow up change experiments with using different (Vulkan vs ANGLE)
secondary command buffers for inside and outside RP command buffers.
- A future change could specialize the pool behaviors per command buffer
type.
Bug: angleproject:6811
Change-Id: Ia4bc669d26ac7e94e8a0dfb9b361666c82f42cc3
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3344373
Reviewed-by: Tim Van Patten <timvp@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/BufferVk.cpp b/src/libANGLE/renderer/vulkan/BufferVk.cpp
index 03d98f8..eb7759c 100644
--- a/src/libANGLE/renderer/vulkan/BufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/BufferVk.cpp
@@ -449,7 +449,7 @@
access.onBufferTransferWrite(&mBuffer);
}
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// Enqueue a copy command on the GPU.
diff --git a/src/libANGLE/renderer/vulkan/CommandProcessor.cpp b/src/libANGLE/renderer/vulkan/CommandProcessor.cpp
index d5a29fb..5914e24 100644
--- a/src/libANGLE/renderer/vulkan/CommandProcessor.cpp
+++ b/src/libANGLE/renderer/vulkan/CommandProcessor.cpp
@@ -57,6 +57,30 @@
return true;
}
+
+template <typename SecondaryCommandBufferListT>
+void ResetSecondaryCommandBuffers(VkDevice device,
+ vk::CommandPool *commandPool,
+ SecondaryCommandBufferListT *commandBuffers)
+{
+ // Nothing to do when using ANGLE secondary command buffers.
+}
+
+template <>
+ANGLE_MAYBE_UNUSED void ResetSecondaryCommandBuffers<std::vector<VulkanSecondaryCommandBuffer>>(
+ VkDevice device,
+ vk::CommandPool *commandPool,
+ std::vector<VulkanSecondaryCommandBuffer> *commandBuffers)
+{
+ // Note: we currently free the command buffers individually, but we could potentially reset the
+ // entire command pool. https://issuetracker.google.com/issues/166793850
+ for (VulkanSecondaryCommandBuffer &secondary : *commandBuffers)
+ {
+ commandPool->freeCommandBuffers(device, 1, secondary.ptr());
+ secondary.releaseHandle();
+ }
+ commandBuffers->clear();
+}
} // namespace
angle::Result FenceRecycler::newSharedFence(vk::Context *context,
@@ -98,33 +122,44 @@
// CommandProcessorTask implementation
void CommandProcessorTask::initTask()
{
- mTask = CustomTask::Invalid;
- mRenderPass = nullptr;
- mCommandBuffer = nullptr;
- mSemaphore = nullptr;
- mCommandPool = nullptr;
- mOneOffWaitSemaphore = nullptr;
- mOneOffWaitSemaphoreStageMask = 0;
- mOneOffFence = nullptr;
- mPresentInfo = {};
- mPresentInfo.pResults = nullptr;
- mPresentInfo.pSwapchains = nullptr;
- mPresentInfo.pImageIndices = nullptr;
- mPresentInfo.pNext = nullptr;
- mPresentInfo.pWaitSemaphores = nullptr;
- mOneOffCommandBufferVk = VK_NULL_HANDLE;
- mPriority = egl::ContextPriority::Medium;
- mHasProtectedContent = false;
+ mTask = CustomTask::Invalid;
+ mOutsideRenderPassCommandBuffer = nullptr;
+ mRenderPassCommandBuffer = nullptr;
+ mRenderPass = nullptr;
+ mSemaphore = nullptr;
+ mCommandPools = nullptr;
+ mOneOffWaitSemaphore = nullptr;
+ mOneOffWaitSemaphoreStageMask = 0;
+ mOneOffFence = nullptr;
+ mPresentInfo = {};
+ mPresentInfo.pResults = nullptr;
+ mPresentInfo.pSwapchains = nullptr;
+ mPresentInfo.pImageIndices = nullptr;
+ mPresentInfo.pNext = nullptr;
+ mPresentInfo.pWaitSemaphores = nullptr;
+ mOneOffCommandBufferVk = VK_NULL_HANDLE;
+ mPriority = egl::ContextPriority::Medium;
+ mHasProtectedContent = false;
}
-void CommandProcessorTask::initProcessCommands(bool hasProtectedContent,
- CommandBufferHelper *commandBuffer,
- const RenderPass *renderPass)
+void CommandProcessorTask::initOutsideRenderPassProcessCommands(
+ bool hasProtectedContent,
+ OutsideRenderPassCommandBufferHelper *commandBuffer)
{
- mTask = CustomTask::ProcessCommands;
- mCommandBuffer = commandBuffer;
- mRenderPass = renderPass;
- mHasProtectedContent = hasProtectedContent;
+ mTask = CustomTask::ProcessOutsideRenderPassCommands;
+ mOutsideRenderPassCommandBuffer = commandBuffer;
+ mHasProtectedContent = hasProtectedContent;
+}
+
+void CommandProcessorTask::initRenderPassProcessCommands(
+ bool hasProtectedContent,
+ RenderPassCommandBufferHelper *commandBuffer,
+ const RenderPass *renderPass)
+{
+ mTask = CustomTask::ProcessRenderPassCommands;
+ mRenderPassCommandBuffer = commandBuffer;
+ mRenderPass = renderPass;
+ mHasProtectedContent = hasProtectedContent;
}
void CommandProcessorTask::copyPresentInfo(const VkPresentInfoKHR &other)
@@ -218,16 +253,16 @@
const Semaphore *semaphore,
bool hasProtectedContent,
egl::ContextPriority priority,
- CommandPool *commandPool,
+ SecondaryCommandPools *commandPools,
GarbageList &¤tGarbage,
- std::vector<CommandBuffer> &&commandBuffersToReset,
+ SecondaryCommandBufferList &&commandBuffersToReset,
Serial submitQueueSerial)
{
mTask = CustomTask::FlushAndQueueSubmit;
mWaitSemaphores = waitSemaphores;
mWaitSemaphoreStageMasks = waitSemaphoreStageMasks;
mSemaphore = semaphore;
- mCommandPool = commandPool;
+ mCommandPools = commandPools;
mGarbage = std::move(currentGarbage);
mCommandBuffersToReset = std::move(commandBuffersToReset);
mPriority = priority;
@@ -261,7 +296,8 @@
}
std::swap(mRenderPass, rhs.mRenderPass);
- std::swap(mCommandBuffer, rhs.mCommandBuffer);
+ std::swap(mOutsideRenderPassCommandBuffer, rhs.mOutsideRenderPassCommandBuffer);
+ std::swap(mRenderPassCommandBuffer, rhs.mRenderPassCommandBuffer);
std::swap(mTask, rhs.mTask);
std::swap(mWaitSemaphores, rhs.mWaitSemaphores);
std::swap(mWaitSemaphoreStageMasks, rhs.mWaitSemaphoreStageMasks);
@@ -269,7 +305,7 @@
std::swap(mOneOffWaitSemaphore, rhs.mOneOffWaitSemaphore);
std::swap(mOneOffWaitSemaphoreStageMask, rhs.mOneOffWaitSemaphoreStageMask);
std::swap(mOneOffFence, rhs.mOneOffFence);
- std::swap(mCommandPool, rhs.mCommandPool);
+ std::swap(mCommandPools, rhs.mCommandPools);
std::swap(mGarbage, rhs.mGarbage);
std::swap(mCommandBuffersToReset, rhs.mCommandBuffersToReset);
std::swap(mSerial, rhs.mSerial);
@@ -286,7 +322,7 @@
}
// CommandBatch implementation.
-CommandBatch::CommandBatch() : commandPool(nullptr), hasProtectedContent(false) {}
+CommandBatch::CommandBatch() : commandPools(nullptr), hasProtectedContent(false) {}
CommandBatch::~CommandBatch() = default;
@@ -298,7 +334,7 @@
CommandBatch &CommandBatch::operator=(CommandBatch &&other)
{
std::swap(primaryCommands, other.primaryCommands);
- std::swap(commandPool, other.commandPool);
+ std::swap(commandPools, other.commandPools);
std::swap(commandBuffersToReset, other.commandBuffersToReset);
std::swap(fence, other.fence);
std::swap(serial, other.serial);
@@ -315,16 +351,10 @@
void CommandBatch::resetSecondaryCommandBuffers(VkDevice device)
{
-#if !ANGLE_USE_CUSTOM_VULKAN_CMD_BUFFERS
- for (CommandBuffer &secondary : commandBuffersToReset)
- {
- // Note: we currently free the command buffers individually, but we could potentially reset
- // the entire command pool. https://issuetracker.google.com/issues/166793850
- commandPool->freeCommandBuffers(device, 1, secondary.ptr());
- secondary.releaseHandle();
- }
- commandBuffersToReset.clear();
-#endif
+ ResetSecondaryCommandBuffers(device, &commandPools->outsideRenderPassPool,
+ &commandBuffersToReset.outsideRenderPassCommandBuffers);
+ ResetSecondaryCommandBuffers(device, &commandPools->renderPassPool,
+ &commandBuffersToReset.renderPassCommandBuffers);
}
// CommandProcessor implementation.
@@ -466,7 +496,7 @@
this, task->hasProtectedContent(), task->getPriority(), task->getWaitSemaphores(),
task->getWaitSemaphoreStageMasks(), task->getSemaphore(),
std::move(task->getGarbage()), std::move(task->getCommandBuffersToReset()),
- task->getCommandPool(), task->getQueueSerial()));
+ task->getCommandPools(), task->getQueueSerial()));
ASSERT(task->getGarbage().empty());
break;
@@ -511,25 +541,29 @@
}
break;
}
- case CustomTask::ProcessCommands:
+ case CustomTask::ProcessOutsideRenderPassCommands:
{
- ASSERT(!task->getCommandBuffer()->empty());
+ OutsideRenderPassCommandBufferHelper *commandBuffer =
+ task->getOutsideRenderPassCommandBuffer();
+ ANGLE_TRY(mCommandQueue.flushOutsideRPCommands(this, task->hasProtectedContent(),
+ &commandBuffer));
- CommandBufferHelper *commandBuffer = task->getCommandBuffer();
- if (task->getRenderPass())
- {
- ANGLE_TRY(mCommandQueue.flushRenderPassCommands(
- this, task->hasProtectedContent(), *task->getRenderPass(), &commandBuffer));
- }
- else
- {
- ANGLE_TRY(mCommandQueue.flushOutsideRPCommands(this, task->hasProtectedContent(),
- &commandBuffer));
- }
+ OutsideRenderPassCommandBufferHelper *originalCommandBuffer =
+ task->getOutsideRenderPassCommandBuffer();
+ mRenderer->recycleOutsideRenderPassCommandBufferHelper(mRenderer->getDevice(),
+ &originalCommandBuffer);
+ break;
+ }
+ case CustomTask::ProcessRenderPassCommands:
+ {
+ RenderPassCommandBufferHelper *commandBuffer = task->getRenderPassCommandBuffer();
+ ANGLE_TRY(mCommandQueue.flushRenderPassCommands(
+ this, task->hasProtectedContent(), *task->getRenderPass(), &commandBuffer));
- CommandBufferHelper *originalCommandBuffer = task->getCommandBuffer();
- ASSERT(originalCommandBuffer->empty());
- mRenderer->recycleCommandBufferHelper(mRenderer->getDevice(), &originalCommandBuffer);
+ RenderPassCommandBufferHelper *originalCommandBuffer =
+ task->getRenderPassCommandBuffer();
+ mRenderer->recycleRenderPassCommandBufferHelper(mRenderer->getDevice(),
+ &originalCommandBuffer);
break;
}
case CustomTask::CheckCompletedCommands:
@@ -689,15 +723,15 @@
const std::vector<VkPipelineStageFlags> &waitSemaphoreStageMasks,
const Semaphore *signalSemaphore,
GarbageList &¤tGarbage,
- std::vector<CommandBuffer> &&commandBuffersToReset,
- CommandPool *commandPool,
+ SecondaryCommandBufferList &&commandBuffersToReset,
+ SecondaryCommandPools *commandPools,
Serial submitQueueSerial)
{
ANGLE_TRY(checkAndPopPendingError(context));
CommandProcessorTask task;
task.initFlushAndQueueSubmit(waitSemaphores, waitSemaphoreStageMasks, signalSemaphore,
- hasProtectedContent, priority, commandPool,
+ hasProtectedContent, priority, commandPools,
std::move(currentGarbage), std::move(commandBuffersToReset),
submitQueueSerial);
@@ -757,33 +791,35 @@
return finishToSerial(context, serial, mRenderer->getMaxFenceWaitTimeNs());
}
-angle::Result CommandProcessor::flushOutsideRPCommands(Context *context,
- bool hasProtectedContent,
- CommandBufferHelper **outsideRPCommands)
+angle::Result CommandProcessor::flushOutsideRPCommands(
+ Context *context,
+ bool hasProtectedContent,
+ OutsideRenderPassCommandBufferHelper **outsideRPCommands)
{
ANGLE_TRY(checkAndPopPendingError(context));
(*outsideRPCommands)->markClosed();
CommandProcessorTask task;
- task.initProcessCommands(hasProtectedContent, *outsideRPCommands, nullptr);
+ task.initOutsideRenderPassProcessCommands(hasProtectedContent, *outsideRPCommands);
queueCommand(std::move(task));
- return mRenderer->getCommandBufferHelper(context, false, (*outsideRPCommands)->getCommandPool(),
- outsideRPCommands);
+ return mRenderer->getOutsideRenderPassCommandBufferHelper(
+ context, (*outsideRPCommands)->getCommandPool(), outsideRPCommands);
}
-angle::Result CommandProcessor::flushRenderPassCommands(Context *context,
- bool hasProtectedContent,
- const RenderPass &renderPass,
- CommandBufferHelper **renderPassCommands)
+angle::Result CommandProcessor::flushRenderPassCommands(
+ Context *context,
+ bool hasProtectedContent,
+ const RenderPass &renderPass,
+ RenderPassCommandBufferHelper **renderPassCommands)
{
ANGLE_TRY(checkAndPopPendingError(context));
(*renderPassCommands)->markClosed();
CommandProcessorTask task;
- task.initProcessCommands(hasProtectedContent, *renderPassCommands, &renderPass);
+ task.initRenderPassProcessCommands(hasProtectedContent, *renderPassCommands, &renderPass);
queueCommand(std::move(task));
- return mRenderer->getCommandBufferHelper(context, true, (*renderPassCommands)->getCommandPool(),
- renderPassCommands);
+ return mRenderer->getRenderPassCommandBufferHelper(
+ context, (*renderPassCommands)->getCommandPool(), renderPassCommands);
}
angle::Result CommandProcessor::ensureNoPendingWork(Context *context)
@@ -920,13 +956,13 @@
void CommandQueue::releaseToCommandBatch(bool hasProtectedContent,
PrimaryCommandBuffer &&commandBuffer,
- CommandPool *commandPool,
+ SecondaryCommandPools *commandPools,
CommandBatch *batch)
{
ANGLE_TRACE_EVENT0("gpu.angle", "CommandQueue::releaseToCommandBatch");
batch->primaryCommands = std::move(commandBuffer);
- batch->commandPool = commandPool;
+ batch->commandPools = commandPools;
batch->hasProtectedContent = hasProtectedContent;
}
@@ -1029,8 +1065,8 @@
const std::vector<VkPipelineStageFlags> &waitSemaphoreStageMasks,
const Semaphore *signalSemaphore,
GarbageList &¤tGarbage,
- std::vector<CommandBuffer> &&commandBuffersToReset,
- CommandPool *commandPool,
+ SecondaryCommandBufferList &&commandBuffersToReset,
+ SecondaryCommandPools *commandPools,
Serial submitQueueSerial)
{
// Start an empty primary buffer if we have an empty submit.
@@ -1076,11 +1112,11 @@
if (hasProtectedContent)
{
releaseToCommandBatch(hasProtectedContent, std::move(mProtectedPrimaryCommands),
- commandPool, &batch);
+ commandPools, &batch);
}
else
{
- releaseToCommandBatch(hasProtectedContent, std::move(mPrimaryCommands), commandPool,
+ releaseToCommandBatch(hasProtectedContent, std::move(mPrimaryCommands), commandPools,
&batch);
}
mInFlightCommands.emplace_back(scopedBatch.release());
@@ -1168,19 +1204,21 @@
return angle::Result::Continue;
}
-angle::Result CommandQueue::flushOutsideRPCommands(Context *context,
- bool hasProtectedContent,
- CommandBufferHelper **outsideRPCommands)
+angle::Result CommandQueue::flushOutsideRPCommands(
+ Context *context,
+ bool hasProtectedContent,
+ OutsideRenderPassCommandBufferHelper **outsideRPCommands)
{
ANGLE_TRY(ensurePrimaryCommandBufferValid(context, hasProtectedContent));
PrimaryCommandBuffer &commandBuffer = getCommandBuffer(hasProtectedContent);
- return (*outsideRPCommands)->flushToPrimary(context, &commandBuffer, nullptr);
+ return (*outsideRPCommands)->flushToPrimary(context, &commandBuffer);
}
-angle::Result CommandQueue::flushRenderPassCommands(Context *context,
- bool hasProtectedContent,
- const RenderPass &renderPass,
- CommandBufferHelper **renderPassCommands)
+angle::Result CommandQueue::flushRenderPassCommands(
+ Context *context,
+ bool hasProtectedContent,
+ const RenderPass &renderPass,
+ RenderPassCommandBufferHelper **renderPassCommands)
{
ANGLE_TRY(ensurePrimaryCommandBufferValid(context, hasProtectedContent));
PrimaryCommandBuffer &commandBuffer = getCommandBuffer(hasProtectedContent);
diff --git a/src/libANGLE/renderer/vulkan/CommandProcessor.h b/src/libANGLE/renderer/vulkan/CommandProcessor.h
index 77d1ad9..4f1b3cd 100644
--- a/src/libANGLE/renderer/vulkan/CommandProcessor.h
+++ b/src/libANGLE/renderer/vulkan/CommandProcessor.h
@@ -56,7 +56,8 @@
{
Invalid = 0,
// Process SecondaryCommandBuffer commands into the primary CommandBuffer.
- ProcessCommands,
+ ProcessOutsideRenderPassCommands,
+ ProcessRenderPassCommands,
// End the current command buffer and submit commands to the queue
FlushAndQueueSubmit,
// Submit custom command buffer, excludes some state management
@@ -85,9 +86,12 @@
void initTask(CustomTask command) { mTask = command; }
- void initProcessCommands(bool hasProtectedContent,
- CommandBufferHelper *commandBuffer,
- const RenderPass *renderPass);
+ void initOutsideRenderPassProcessCommands(bool hasProtectedContent,
+ OutsideRenderPassCommandBufferHelper *commandBuffer);
+
+ void initRenderPassProcessCommands(bool hasProtectedContent,
+ RenderPassCommandBufferHelper *commandBuffer,
+ const RenderPass *renderPass);
void initPresent(egl::ContextPriority priority, const VkPresentInfoKHR &presentInfo);
@@ -100,9 +104,9 @@
const Semaphore *semaphore,
bool hasProtectedContent,
egl::ContextPriority priority,
- CommandPool *commandPool,
+ SecondaryCommandPools *commandPools,
GarbageList &¤tGarbage,
- std::vector<CommandBuffer> &&commandBuffersToReset,
+ SecondaryCommandBufferList &&commandBuffersToReset,
Serial submitQueueSerial);
void initOneOffQueueSubmit(VkCommandBuffer commandBufferHandle,
@@ -130,7 +134,10 @@
}
const Semaphore *getSemaphore() { return mSemaphore; }
GarbageList &getGarbage() { return mGarbage; }
- std::vector<CommandBuffer> &getCommandBuffersToReset() { return mCommandBuffersToReset; }
+ SecondaryCommandBufferList &&getCommandBuffersToReset()
+ {
+ return std::move(mCommandBuffersToReset);
+ }
egl::ContextPriority getPriority() const { return mPriority; }
bool hasProtectedContent() const { return mHasProtectedContent; }
VkCommandBuffer getOneOffCommandBufferVk() const { return mOneOffCommandBufferVk; }
@@ -139,8 +146,15 @@
const Fence *getOneOffFence() { return mOneOffFence; }
const VkPresentInfoKHR &getPresentInfo() const { return mPresentInfo; }
const RenderPass *getRenderPass() const { return mRenderPass; }
- CommandBufferHelper *getCommandBuffer() const { return mCommandBuffer; }
- CommandPool *getCommandPool() const { return mCommandPool; }
+ OutsideRenderPassCommandBufferHelper *getOutsideRenderPassCommandBuffer() const
+ {
+ return mOutsideRenderPassCommandBuffer;
+ }
+ RenderPassCommandBufferHelper *getRenderPassCommandBuffer() const
+ {
+ return mRenderPassCommandBuffer;
+ }
+ SecondaryCommandPools *getCommandPools() const { return mCommandPools; }
private:
void copyPresentInfo(const VkPresentInfoKHR &other);
@@ -148,16 +162,17 @@
CustomTask mTask;
// ProcessCommands
+ OutsideRenderPassCommandBufferHelper *mOutsideRenderPassCommandBuffer;
+ RenderPassCommandBufferHelper *mRenderPassCommandBuffer;
const RenderPass *mRenderPass;
- CommandBufferHelper *mCommandBuffer;
// Flush data
std::vector<VkSemaphore> mWaitSemaphores;
std::vector<VkPipelineStageFlags> mWaitSemaphoreStageMasks;
const Semaphore *mSemaphore;
- CommandPool *mCommandPool;
+ SecondaryCommandPools *mCommandPools;
GarbageList mGarbage;
- std::vector<CommandBuffer> mCommandBuffersToReset;
+ SecondaryCommandBufferList mCommandBuffersToReset;
// FinishToSerial & Flush command data
Serial mSerial;
@@ -194,9 +209,9 @@
void resetSecondaryCommandBuffers(VkDevice device);
PrimaryCommandBuffer primaryCommands;
- // commandPool is for secondary CommandBuffer allocation
- CommandPool *commandPool;
- std::vector<CommandBuffer> commandBuffersToReset;
+ // commandPools is for secondary CommandBuffer allocation
+ SecondaryCommandPools *commandPools;
+ SecondaryCommandBufferList commandBuffersToReset;
Shared<Fence> fence;
Serial serial;
bool hasProtectedContent;
@@ -290,8 +305,8 @@
const std::vector<VkPipelineStageFlags> &waitSemaphoreStageMasks,
const Semaphore *signalSemaphore,
GarbageList &¤tGarbage,
- std::vector<CommandBuffer> &&commandBuffersToReset,
- CommandPool *commandPool,
+ SecondaryCommandBufferList &&commandBuffersToReset,
+ SecondaryCommandPools *commandPools,
Serial submitQueueSerial) = 0;
virtual angle::Result queueSubmitOneOff(Context *context,
bool hasProtectedContent,
@@ -315,13 +330,15 @@
// result). It would be nice if we didn't have to expose this for QueryVk::getResult.
virtual angle::Result checkCompletedCommands(Context *context) = 0;
- virtual angle::Result flushOutsideRPCommands(Context *context,
- bool hasProtectedContent,
- CommandBufferHelper **outsideRPCommands) = 0;
- virtual angle::Result flushRenderPassCommands(Context *context,
- bool hasProtectedContent,
- const RenderPass &renderPass,
- CommandBufferHelper **renderPassCommands) = 0;
+ virtual angle::Result flushOutsideRPCommands(
+ Context *context,
+ bool hasProtectedContent,
+ OutsideRenderPassCommandBufferHelper **outsideRPCommands) = 0;
+ virtual angle::Result flushRenderPassCommands(
+ Context *context,
+ bool hasProtectedContent,
+ const RenderPass &renderPass,
+ RenderPassCommandBufferHelper **renderPassCommands) = 0;
// For correct synchronization with external, in particular when asked to signal an external
// semaphore, we need to ensure that there are no pending submissions.
@@ -355,8 +372,8 @@
const std::vector<VkPipelineStageFlags> &waitSemaphoreStageMasks,
const Semaphore *signalSemaphore,
GarbageList &¤tGarbage,
- std::vector<CommandBuffer> &&commandBuffersToReset,
- CommandPool *commandPool,
+ SecondaryCommandBufferList &&commandBuffersToReset,
+ SecondaryCommandPools *commandPools,
Serial submitQueueSerial) override;
angle::Result queueSubmitOneOff(Context *context,
@@ -379,13 +396,15 @@
angle::Result checkCompletedCommands(Context *context) override;
- angle::Result flushOutsideRPCommands(Context *context,
- bool hasProtectedContent,
- CommandBufferHelper **outsideRPCommands) override;
- angle::Result flushRenderPassCommands(Context *context,
- bool hasProtectedContent,
- const RenderPass &renderPass,
- CommandBufferHelper **renderPassCommands) override;
+ angle::Result flushOutsideRPCommands(
+ Context *context,
+ bool hasProtectedContent,
+ OutsideRenderPassCommandBufferHelper **outsideRPCommands) override;
+ angle::Result flushRenderPassCommands(
+ Context *context,
+ bool hasProtectedContent,
+ const RenderPass &renderPass,
+ RenderPassCommandBufferHelper **renderPassCommands) override;
angle::Result ensureNoPendingWork(Context *context) override { return angle::Result::Continue; }
@@ -409,7 +428,7 @@
private:
void releaseToCommandBatch(bool hasProtectedContent,
PrimaryCommandBuffer &&commandBuffer,
- CommandPool *commandPool,
+ SecondaryCommandPools *commandPools,
CommandBatch *batch);
angle::Result retireFinishedCommands(Context *context, size_t finishedCount);
angle::Result ensurePrimaryCommandBufferValid(Context *context, bool hasProtectedContent);
@@ -504,8 +523,8 @@
const std::vector<VkPipelineStageFlags> &waitSemaphoreStageMasks,
const Semaphore *signalSemaphore,
GarbageList &¤tGarbage,
- std::vector<CommandBuffer> &&commandBuffersToReset,
- CommandPool *commandPool,
+ SecondaryCommandBufferList &&commandBuffersToReset,
+ SecondaryCommandPools *commandPools,
Serial submitQueueSerial) override;
angle::Result queueSubmitOneOff(Context *context,
@@ -527,13 +546,15 @@
angle::Result checkCompletedCommands(Context *context) override;
- angle::Result flushOutsideRPCommands(Context *context,
- bool hasProtectedContent,
- CommandBufferHelper **outsideRPCommands) override;
- angle::Result flushRenderPassCommands(Context *context,
- bool hasProtectedContent,
- const RenderPass &renderPass,
- CommandBufferHelper **renderPassCommands) override;
+ angle::Result flushOutsideRPCommands(
+ Context *context,
+ bool hasProtectedContent,
+ OutsideRenderPassCommandBufferHelper **outsideRPCommands) override;
+ angle::Result flushRenderPassCommands(
+ Context *context,
+ bool hasProtectedContent,
+ const RenderPass &renderPass,
+ RenderPassCommandBufferHelper **renderPassCommands) override;
angle::Result ensureNoPendingWork(Context *context) override;
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
index 00f0c85..1964001 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -209,10 +209,10 @@
*maskOut &= coverageMask;
}
-bool IsRenderPassStartedAndUsesImage(const vk::CommandBufferHelper &renderPassCommands,
+bool IsRenderPassStartedAndUsesImage(const vk::RenderPassCommandBufferHelper &renderPassCommands,
const vk::ImageHelper &image)
{
- return renderPassCommands.started() && renderPassCommands.usesImageInRenderPass(image);
+ return renderPassCommands.started() && renderPassCommands.usesImage(image);
}
// When an Android surface is rotated differently than the device's native orientation, ANGLE must
@@ -365,6 +365,153 @@
desc->append32BitValue(std::numeric_limits<uint32_t>::max());
}
+vk::ImageLayout GetImageReadLayout(TextureVk *textureVk,
+ const gl::ProgramExecutable *executable,
+ size_t textureUnit,
+ PipelineType pipelineType)
+{
+ vk::ImageHelper &image = textureVk->getImage();
+
+ if (textureVk->hasBeenBoundAsImage())
+ {
+ return pipelineType == PipelineType::Compute ? vk::ImageLayout::ComputeShaderWrite
+ : vk::ImageLayout::AllGraphicsShadersWrite;
+ }
+
+ gl::ShaderBitSet remainingShaderBits =
+ executable->getSamplerShaderBitsForTextureUnitIndex(textureUnit);
+ ASSERT(remainingShaderBits.any());
+ gl::ShaderType firstShader = remainingShaderBits.first();
+ gl::ShaderType lastShader = remainingShaderBits.last();
+ remainingShaderBits.reset(firstShader);
+ remainingShaderBits.reset(lastShader);
+
+ if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::RenderTargetAttachment))
+ {
+ // Right now we set this flag only when RenderTargetAttachment is set since we do
+ // not track all textures in the renderpass.
+ image.setRenderPassUsageFlag(vk::RenderPassUsage::TextureSampler);
+
+ if (image.isDepthOrStencil())
+ {
+ if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::ReadOnlyAttachment))
+ {
+ if (firstShader == gl::ShaderType::Fragment)
+ {
+ ASSERT(remainingShaderBits.none() && lastShader == firstShader);
+ return vk::ImageLayout::DSAttachmentReadAndFragmentShaderRead;
+ }
+ return vk::ImageLayout::DSAttachmentReadAndAllShadersRead;
+ }
+
+ return firstShader == gl::ShaderType::Fragment
+ ? vk::ImageLayout::DSAttachmentWriteAndFragmentShaderRead
+ : vk::ImageLayout::DSAttachmentWriteAndAllShadersRead;
+ }
+
+ return firstShader == gl::ShaderType::Fragment
+ ? vk::ImageLayout::ColorAttachmentAndFragmentShaderRead
+ : vk::ImageLayout::ColorAttachmentAndAllShadersRead;
+ }
+
+ if (image.isDepthOrStencil())
+ {
+ // We always use a depth-stencil read-only layout for any depth Textures to simplify
+ // our implementation's handling of depth-stencil read-only mode. We don't have to
+ // split a RenderPass to transition a depth texture from shader-read to read-only.
+ // This improves performance in Manhattan. Future optimizations are likely possible
+ // here including using specialized barriers without breaking the RenderPass.
+ if (firstShader == gl::ShaderType::Fragment)
+ {
+ ASSERT(remainingShaderBits.none() && lastShader == firstShader);
+ return vk::ImageLayout::DSAttachmentReadAndFragmentShaderRead;
+ }
+ return vk::ImageLayout::DSAttachmentReadAndAllShadersRead;
+ }
+
+ // We barrier against either:
+ // - Vertex only
+ // - Fragment only
+ // - Pre-fragment only (vertex, geometry and tessellation together)
+ if (remainingShaderBits.any() || firstShader != lastShader)
+ {
+ return lastShader == gl::ShaderType::Fragment ? vk::ImageLayout::AllGraphicsShadersReadOnly
+ : vk::ImageLayout::PreFragmentShadersReadOnly;
+ }
+
+ return kShaderReadOnlyImageLayouts[firstShader];
+}
+
+vk::ImageLayout GetImageWriteLayoutAndSubresource(const gl::ImageUnit &imageUnit,
+ vk::ImageHelper &image,
+ gl::ShaderBitSet shaderStages,
+ gl::LevelIndex *levelOut,
+ uint32_t *layerStartOut,
+ uint32_t *layerCountOut)
+{
+ *levelOut = gl::LevelIndex(static_cast<uint32_t>(imageUnit.level));
+
+ *layerStartOut = 0;
+ *layerCountOut = image.getLayerCount();
+ if (imageUnit.layered)
+ {
+ *layerStartOut = imageUnit.layered;
+ *layerCountOut = 1;
+ }
+
+ gl::ShaderType firstShader = shaderStages.first();
+ gl::ShaderType lastShader = shaderStages.last();
+ shaderStages.reset(firstShader);
+ shaderStages.reset(lastShader);
+ // We barrier against either:
+ // - Vertex only
+ // - Fragment only
+ // - Pre-fragment only (vertex, geometry and tessellation together)
+ if (shaderStages.any() || firstShader != lastShader)
+ {
+ return lastShader == gl::ShaderType::Fragment ? vk::ImageLayout::AllGraphicsShadersWrite
+ : vk::ImageLayout::PreFragmentShadersWrite;
+ }
+
+ return kShaderWriteImageLayouts[firstShader];
+}
+
+void OnTextureBufferRead(ContextVk *contextVk,
+ BufferVk *bufferVk,
+ gl::ShaderBitSet stages,
+ vk::CommandBufferHelperCommon *commandBufferHelper)
+{
+ vk::BufferHelper &buffer = bufferVk->getBuffer();
+
+ ASSERT(stages.any());
+
+ // TODO: accept multiple stages in bufferRead. http://anglebug.com/3573
+ for (gl::ShaderType stage : stages)
+ {
+ // Note: if another range of the same buffer is simultaneously used for storage,
+ // such as for transform feedback output, or SSBO, unnecessary barriers can be
+ // generated.
+ commandBufferHelper->bufferRead(contextVk, VK_ACCESS_SHADER_READ_BIT,
+ vk::GetPipelineStage(stage), &buffer);
+ }
+}
+
+void OnImageBufferWrite(ContextVk *contextVk,
+ BufferVk *bufferVk,
+ gl::ShaderBitSet stages,
+ vk::CommandBufferHelperCommon *commandBufferHelper)
+{
+ vk::BufferHelper &buffer = bufferVk->getBuffer();
+
+ // TODO: accept multiple stages in bufferWrite. http://anglebug.com/3573
+ for (gl::ShaderType stage : stages)
+ {
+ commandBufferHelper->bufferWrite(
+ contextVk, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
+ vk::GetPipelineStage(stage), vk::AliasingMode::Disallowed, &buffer);
+ }
+}
+
constexpr angle::PackedEnumMap<RenderPassClosureReason, const char *> kRenderPassClosureReason = {{
{RenderPassClosureReason::AlreadySpecifiedElsewhere, nullptr},
{RenderPassClosureReason::ContextDestruction, "Render pass closed due to context destruction"},
@@ -751,8 +898,8 @@
}
// Recycle current commands buffers.
- mRenderer->recycleCommandBufferHelper(device, &mOutsideRenderPassCommands);
- mRenderer->recycleCommandBufferHelper(device, &mRenderPassCommands);
+ mRenderer->recycleOutsideRenderPassCommandBufferHelper(device, &mOutsideRenderPassCommands);
+ mRenderer->recycleRenderPassCommandBufferHelper(device, &mRenderPassCommands);
mRenderer->releaseSharedResources(&mResourceUseList);
@@ -761,7 +908,8 @@
mRenderPassCache.destroy(mRenderer);
mShaderLibrary.destroy(device);
mGpuEventQueryPool.destroy(device);
- mCommandPool.destroy(device);
+ mCommandPools.outsideRenderPassPool.destroy(device);
+ mCommandPools.renderPassPool.destroy(device);
ASSERT(mCurrentGarbage.empty());
ASSERT(mResourceUseList.empty());
@@ -869,11 +1017,16 @@
mEmulateSeamfulCubeMapSampling = shouldEmulateSeamfulCubeMapSampling();
// Assign initial command buffers from queue
- ANGLE_TRY(vk::CommandBuffer::InitializeCommandPool(
- this, &mCommandPool, mRenderer->getDeviceQueueIndex(), hasProtectedContent()));
- ANGLE_TRY(
- mRenderer->getCommandBufferHelper(this, false, &mCommandPool, &mOutsideRenderPassCommands));
- ANGLE_TRY(mRenderer->getCommandBufferHelper(this, true, &mCommandPool, &mRenderPassCommands));
+ ANGLE_TRY(vk::OutsideRenderPassCommandBuffer::InitializeCommandPool(
+ this, &mCommandPools.outsideRenderPassPool, mRenderer->getDeviceQueueIndex(),
+ hasProtectedContent()));
+ ANGLE_TRY(vk::RenderPassCommandBuffer::InitializeCommandPool(
+ this, &mCommandPools.renderPassPool, mRenderer->getDeviceQueueIndex(),
+ hasProtectedContent()));
+ ANGLE_TRY(mRenderer->getOutsideRenderPassCommandBufferHelper(
+ this, &mCommandPools.outsideRenderPassPool, &mOutsideRenderPassCommands));
+ ANGLE_TRY(mRenderer->getRenderPassCommandBufferHelper(this, &mCommandPools.renderPassPool,
+ &mRenderPassCommands));
if (mGpuEventsEnabled)
{
@@ -1383,7 +1536,8 @@
return handleDirtyEventLogImpl(&mOutsideRenderPassCommands->getCommandBuffer());
}
-angle::Result ContextVk::handleDirtyEventLogImpl(vk::CommandBuffer *commandBuffer)
+template <typename CommandBufferT>
+angle::Result ContextVk::handleDirtyEventLogImpl(CommandBufferT *commandBuffer)
{
// This method is called when a draw or dispatch command is being processed. It's purpose is
// to call the vkCmd*DebugUtilsLabelEXT functions in order to communicate to debuggers
@@ -1597,8 +1751,9 @@
return angle::Result::Continue;
}
+template <typename CommandBufferHelperT>
ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
- vk::CommandBufferHelper *commandBufferHelper,
+ CommandBufferHelperT *commandBufferHelper,
PipelineType pipelineType)
{
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
@@ -1613,134 +1768,28 @@
// If it's a texture buffer, get the attached buffer.
if (textureVk->getBuffer().get() != nullptr)
{
- BufferVk *bufferVk = vk::GetImpl(textureVk->getBuffer().get());
- vk::BufferHelper &buffer = bufferVk->getBuffer();
-
- gl::ShaderBitSet stages =
+ BufferVk *bufferVk = vk::GetImpl(textureVk->getBuffer().get());
+ const gl::ShaderBitSet stages =
executable->getSamplerShaderBitsForTextureUnitIndex(textureUnit);
- ASSERT(stages.any());
- // TODO: accept multiple stages in bufferRead. http://anglebug.com/3573
- for (gl::ShaderType stage : stages)
- {
- // Note: if another range of the same buffer is simultaneously used for storage,
- // such as for transform feedback output, or SSBO, unnecessary barriers can be
- // generated.
- commandBufferHelper->bufferRead(this, VK_ACCESS_SHADER_READ_BIT,
- vk::GetPipelineStage(stage), &buffer);
- }
+ OnTextureBufferRead(this, bufferVk, stages, commandBufferHelper);
textureVk->retainBufferViews(&mResourceUseList);
-
continue;
}
- vk::ImageHelper &image = textureVk->getImage();
-
// The image should be flushed and ready to use at this point. There may still be
// lingering staged updates in its staging buffer for unused texture mip levels or
// layers. Therefore we can't verify it has no staged updates right here.
+ vk::ImageHelper &image = textureVk->getImage();
// Select the appropriate vk::ImageLayout depending on whether the texture is also bound as
// a GL image, and whether the program is a compute or graphics shader.
- vk::ImageLayout textureLayout;
- if (textureVk->hasBeenBoundAsImage())
- {
- textureLayout = pipelineType == PipelineType::Compute
- ? vk::ImageLayout::ComputeShaderWrite
- : vk::ImageLayout::AllGraphicsShadersWrite;
- }
- else
- {
- gl::ShaderBitSet remainingShaderBits =
- executable->getSamplerShaderBitsForTextureUnitIndex(textureUnit);
- ASSERT(remainingShaderBits.any());
- gl::ShaderType firstShader = remainingShaderBits.first();
- gl::ShaderType lastShader = remainingShaderBits.last();
- remainingShaderBits.reset(firstShader);
- remainingShaderBits.reset(lastShader);
+ const vk::ImageLayout imageLayout =
+ GetImageReadLayout(textureVk, executable, textureUnit, pipelineType);
- if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::RenderTargetAttachment))
- {
- // Right now we set this flag only when RenderTargetAttachment is set since we do
- // not track all textures in the renderpass.
- image.setRenderPassUsageFlag(vk::RenderPassUsage::TextureSampler);
-
- if (image.isDepthOrStencil())
- {
- if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::ReadOnlyAttachment))
- {
- if (firstShader == gl::ShaderType::Fragment)
- {
- ASSERT(remainingShaderBits.none() && lastShader == firstShader);
- textureLayout = vk::ImageLayout::DSAttachmentReadAndFragmentShaderRead;
- }
- else
- {
- textureLayout = vk::ImageLayout::DSAttachmentReadAndAllShadersRead;
- }
- }
- else
- {
- if (firstShader == gl::ShaderType::Fragment)
- {
- textureLayout = vk::ImageLayout::DSAttachmentWriteAndFragmentShaderRead;
- }
- else
- {
- textureLayout = vk::ImageLayout::DSAttachmentWriteAndAllShadersRead;
- }
- }
- }
- else
- {
- if (firstShader == gl::ShaderType::Fragment)
- {
- textureLayout = vk::ImageLayout::ColorAttachmentAndFragmentShaderRead;
- }
- else
- {
- textureLayout = vk::ImageLayout::ColorAttachmentAndAllShadersRead;
- }
- }
- }
- else if (image.isDepthOrStencil())
- {
- // We always use a depth-stencil read-only layout for any depth Textures to simplify
- // our implementation's handling of depth-stencil read-only mode. We don't have to
- // split a RenderPass to transition a depth texture from shader-read to read-only.
- // This improves performance in Manhattan. Future optimizations are likely possible
- // here including using specialized barriers without breaking the RenderPass.
- if (firstShader == gl::ShaderType::Fragment)
- {
- ASSERT(remainingShaderBits.none() && lastShader == firstShader);
- textureLayout = vk::ImageLayout::DSAttachmentReadAndFragmentShaderRead;
- }
- else
- {
- textureLayout = vk::ImageLayout::DSAttachmentReadAndAllShadersRead;
- }
- }
- else
- {
- // We barrier against either:
- // - Vertex only
- // - Fragment only
- // - Pre-fragment only (vertex, geometry and tessellation together)
- if (remainingShaderBits.any() || firstShader != lastShader)
- {
- textureLayout = lastShader == gl::ShaderType::Fragment
- ? vk::ImageLayout::AllGraphicsShadersReadOnly
- : vk::ImageLayout::PreFragmentShadersReadOnly;
- }
- else
- {
- textureLayout = kShaderReadOnlyImageLayouts[firstShader];
- }
- }
- }
// Ensure the image is in the desired layout
- commandBufferHelper->imageRead(this, image.getAspectFlags(), textureLayout, &image);
+ commandBufferHelper->imageRead(this, image.getAspectFlags(), imageLayout, &image);
textureVk->retainImageViews(&mResourceUseList);
}
@@ -1827,8 +1876,8 @@
return angle::Result::Continue;
}
-ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
- vk::CommandBufferHelper *commandBufferHelper)
+template <typename CommandBufferHelperT>
+angle::Result ContextVk::handleDirtyShaderResourcesImpl(CommandBufferHelperT *commandBufferHelper)
{
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
@@ -1849,6 +1898,27 @@
ANGLE_TRY(updateActiveImages(commandBufferHelper));
}
+ handleDirtyShaderBufferResourcesImpl(commandBufferHelper);
+
+ ANGLE_TRY(mExecutable->updateShaderResourcesDescriptorSet(this, mDrawFramebuffer,
+ mShaderBuffersDescriptorDesc));
+
+ // Record usage of storage buffers and images in the command buffer to aid handling of
+ // glMemoryBarrier.
+ if (hasImages || hasStorageBuffers)
+ {
+ commandBufferHelper->setHasShaderStorageOutput();
+ }
+
+ return angle::Result::Continue;
+}
+
+void ContextVk::handleDirtyShaderBufferResourcesImpl(
+ vk::CommandBufferHelperCommon *commandBufferHelper)
+{
+ const gl::ProgramExecutable *executable = mState.getProgramExecutable();
+ ASSERT(executable);
+
// Process buffer barriers.
gl::ShaderMap<const gl::ProgramState *> programStates;
mExecutable->fillProgramStateMap(this, &programStates);
@@ -1925,18 +1995,6 @@
vk::GetPipelineStage(shaderType), vk::AliasingMode::Allowed, &bufferHelper);
}
}
-
- ANGLE_TRY(mExecutable->updateShaderResourcesDescriptorSet(
- this, mDrawFramebuffer, mShaderBuffersDescriptorDesc, commandBufferHelper));
-
- // Record usage of storage buffers and images in the command buffer to aid handling of
- // glMemoryBarrier.
- if (hasImages || hasStorageBuffers)
- {
- commandBufferHelper->setHasShaderStorageOutput();
- }
-
- return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyGraphicsShaderResources(DirtyBits::Iterator *dirtyBitsIterator,
@@ -2122,12 +2180,13 @@
PipelineType::Compute);
}
-angle::Result ContextVk::handleDirtyDescriptorSetsImpl(vk::CommandBuffer *commandBuffer,
+template <typename CommandBufferT>
+angle::Result ContextVk::handleDirtyDescriptorSetsImpl(CommandBufferT *commandBuffer,
PipelineType pipelineType)
{
// When using Vulkan secondary command buffers, the descriptor sets need to be updated before
// they are bound.
- if (!vk::CommandBuffer::ExecutesInline())
+ if (!CommandBufferT::ExecutesInline())
{
flushDescriptorSetUpdates();
}
@@ -2232,7 +2291,7 @@
}
}
-void ContextVk::addOverlayUsedBuffersCount(vk::CommandBufferHelper *commandBuffer)
+void ContextVk::addOverlayUsedBuffersCount(vk::CommandBufferHelperCommon *commandBuffer)
{
const gl::OverlayType *overlay = mState.getOverlay();
if (!overlay->isEnabled())
@@ -2263,7 +2322,7 @@
}
}
- if (vk::CommandBufferHelper::kEnableCommandStreamDiagnostics)
+ if (vk::CommandBufferHelperCommon::kEnableCommandStreamDiagnostics)
{
dumpCommandStreamDiagnostics();
}
@@ -2273,7 +2332,7 @@
std::move(mWaitSemaphores),
std::move(mWaitSemaphoreStageMasks), signalSemaphore,
getShareGroupVk()->releaseResourceUseLists(),
- std::move(mCurrentGarbage), &mCommandPool, submitSerialOut));
+ std::move(mCurrentGarbage), &mCommandPools, submitSerialOut));
onRenderPassFinished(RenderPassClosureReason::AlreadySpecifiedElsewhere);
mComputeDirtyBits |= mNewComputeCommandBufferDirtyBits;
@@ -2358,9 +2417,6 @@
//
// Note: Once VK_EXT_calibrated_timestamps is ubiquitous, this should be redone.
- // Make sure nothing is running
- ASSERT(!hasRecordedCommands());
-
ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::synchronizeCpuGpuTime");
// Create a query used to receive the GPU timestamp
@@ -2486,7 +2542,7 @@
return angle::Result::Continue;
}
-angle::Result ContextVk::traceGpuEventImpl(vk::CommandBuffer *commandBuffer,
+angle::Result ContextVk::traceGpuEventImpl(vk::OutsideRenderPassCommandBuffer *commandBuffer,
char phase,
const EventName &name)
{
@@ -3167,10 +3223,14 @@
VkDebugUtilsLabelEXT label;
vk::MakeDebugUtilsLabel(source, marker, &label);
- vk::CommandBuffer *commandBuffer = hasStartedRenderPass()
- ? mRenderPassCommandBuffer
- : &mOutsideRenderPassCommands->getCommandBuffer();
- commandBuffer->insertDebugUtilsLabelEXT(label);
+ if (hasStartedRenderPass())
+ {
+ mRenderPassCommandBuffer->insertDebugUtilsLabelEXT(label);
+ }
+ else
+ {
+ mOutsideRenderPassCommands->getCommandBuffer().insertDebugUtilsLabelEXT(label);
+ }
}
angle::Result ContextVk::pushGroupMarker(GLsizei length, const char *marker)
@@ -3206,10 +3266,14 @@
VkDebugUtilsLabelEXT label;
vk::MakeDebugUtilsLabel(source, message, &label);
- vk::CommandBuffer *commandBuffer = hasStartedRenderPass()
- ? mRenderPassCommandBuffer
- : &mOutsideRenderPassCommands->getCommandBuffer();
- commandBuffer->beginDebugUtilsLabelEXT(label);
+ if (hasStartedRenderPass())
+ {
+ mRenderPassCommandBuffer->beginDebugUtilsLabelEXT(label);
+ }
+ else
+ {
+ mOutsideRenderPassCommands->getCommandBuffer().beginDebugUtilsLabelEXT(label);
+ }
return angle::Result::Continue;
}
@@ -3221,10 +3285,14 @@
return angle::Result::Continue;
}
- vk::CommandBuffer *commandBuffer = hasStartedRenderPass()
- ? mRenderPassCommandBuffer
- : &mOutsideRenderPassCommands->getCommandBuffer();
- commandBuffer->endDebugUtilsLabelEXT();
+ if (hasStartedRenderPass())
+ {
+ mRenderPassCommandBuffer->endDebugUtilsLabelEXT();
+ }
+ else
+ {
+ mOutsideRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
+ }
return angle::Result::Continue;
}
@@ -3270,16 +3338,15 @@
return;
}
- vk::CommandBuffer *commandBuffer = nullptr;
switch (mQueryEventType)
{
case GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd:
ASSERT(mOutsideRenderPassCommands);
- commandBuffer = &mOutsideRenderPassCommands->getCommandBuffer();
+ mOutsideRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
break;
case GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd:
ASSERT(mRenderPassCommands);
- commandBuffer = &mRenderPassCommands->getCommandBuffer();
+ mRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
break;
case GraphicsEventCmdBuf::NotInQueryCmd:
// The glClear* or gl*Query* command was noop'd or otherwise ended early. We could
@@ -3290,7 +3357,6 @@
default:
UNREACHABLE();
}
- commandBuffer->endDebugUtilsLabelEXT();
mQueryEventType = GraphicsEventCmdBuf::NotInQueryCmd;
}
@@ -3311,21 +3377,18 @@
mQueryEventType = queryEventType;
- vk::CommandBuffer *commandBuffer = nullptr;
switch (mQueryEventType)
{
case GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd:
ASSERT(mOutsideRenderPassCommands);
- commandBuffer = &mOutsideRenderPassCommands->getCommandBuffer();
- break;
+ return handleDirtyEventLogImpl(&mOutsideRenderPassCommands->getCommandBuffer());
case GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd:
ASSERT(mRenderPassCommands);
- commandBuffer = &mRenderPassCommands->getCommandBuffer();
- break;
+ return handleDirtyEventLogImpl(&mRenderPassCommands->getCommandBuffer());
default:
UNREACHABLE();
+ return angle::Result::Stop;
}
- return handleDirtyEventLogImpl(commandBuffer);
}
bool ContextVk::isViewportFlipEnabledForDrawFBO() const
@@ -5113,7 +5176,8 @@
PipelineType::Compute);
}
-void ContextVk::handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandBuffer,
+template <typename CommandBufferT>
+void ContextVk::handleDirtyDriverUniformsBindingImpl(CommandBufferT *commandBuffer,
VkPipelineBindPoint bindPoint,
DriverUniformsDescriptorSet *driverUniforms)
{
@@ -5399,7 +5463,8 @@
return angle::Result::Continue;
}
-angle::Result ContextVk::updateActiveImages(vk::CommandBufferHelper *commandBufferHelper)
+template <typename CommandBufferHelperT>
+angle::Result ContextVk::updateActiveImages(CommandBufferHelperT *commandBufferHelper)
{
const gl::State &glState = mState;
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
@@ -5440,19 +5505,11 @@
// Special handling of texture buffers. They have a buffer attached instead of an image.
if (texture->getType() == gl::TextureType::Buffer)
{
- BufferVk *bufferVk = vk::GetImpl(textureVk->getBuffer().get());
- vk::BufferHelper &buffer = bufferVk->getBuffer();
+ BufferVk *bufferVk = vk::GetImpl(textureVk->getBuffer().get());
- // TODO: accept multiple stages in bufferWrite. http://anglebug.com/3573
- for (gl::ShaderType stage : shaderStages)
- {
- commandBufferHelper->bufferWrite(
- this, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
- vk::GetPipelineStage(stage), vk::AliasingMode::Disallowed, &buffer);
- }
+ OnImageBufferWrite(this, bufferVk, shaderStages, commandBufferHelper);
textureVk->retainBufferViews(&mResourceUseList);
-
continue;
}
@@ -5464,50 +5521,20 @@
}
alreadyProcessed.insert(image);
- vk::ImageLayout imageLayout;
- gl::ShaderType firstShader = shaderStages.first();
- gl::ShaderType lastShader = shaderStages.last();
- shaderStages.reset(firstShader);
- shaderStages.reset(lastShader);
- // We barrier against either:
- // - Vertex only
- // - Fragment only
- // - Pre-fragment only (vertex, geometry and tessellation together)
- if (shaderStages.any() || firstShader != lastShader)
- {
- imageLayout = lastShader == gl::ShaderType::Fragment
- ? vk::ImageLayout::AllGraphicsShadersWrite
- : vk::ImageLayout::PreFragmentShadersWrite;
- }
- else
- {
- imageLayout = kShaderWriteImageLayouts[firstShader];
- }
+ gl::LevelIndex level;
+ uint32_t layerStart = 0;
+ uint32_t layerCount = 0;
+ const vk::ImageLayout imageLayout = GetImageWriteLayoutAndSubresource(
+ imageUnit, *image, shaderStages, &level, &layerStart, &layerCount);
- VkImageAspectFlags aspectFlags = image->getAspectFlags();
-
- uint32_t layerStart = 0;
- uint32_t layerCount = image->getLayerCount();
- if (imageUnit.layered)
- {
- layerStart = imageUnit.layered;
- layerCount = 1;
- }
-
- commandBufferHelper->imageWrite(
- this, gl::LevelIndex(static_cast<uint32_t>(imageUnit.level)), layerStart, layerCount,
- aspectFlags, imageLayout, vk::AliasingMode::Allowed, image);
+ commandBufferHelper->imageWrite(this, level, layerStart, layerCount,
+ image->getAspectFlags(), imageLayout,
+ vk::AliasingMode::Allowed, image);
}
return angle::Result::Continue;
}
-bool ContextVk::hasRecordedCommands()
-{
- ASSERT(mOutsideRenderPassCommands && mRenderPassCommands);
- return !mOutsideRenderPassCommands->empty() || mRenderPassCommands->started();
-}
-
angle::Result ContextVk::flushImpl(const vk::Semaphore *signalSemaphore,
RenderPassClosureReason renderPassClosureReason)
{
@@ -5640,11 +5667,6 @@
mWaitSemaphoreStageMasks.push_back(stageMask);
}
-const vk::CommandPool &ContextVk::getCommandPool() const
-{
- return mCommandPool;
-}
-
bool ContextVk::isSerialInUse(Serial serial) const
{
return serial > getLastCompletedQueueSerial();
@@ -5843,7 +5865,7 @@
const vk::PackedAttachmentCount colorAttachmentCount,
const vk::PackedAttachmentIndex depthStencilAttachmentIndex,
const vk::PackedClearValuesArray &clearValues,
- vk::CommandBuffer **commandBufferOut)
+ vk::RenderPassCommandBuffer **commandBufferOut)
{
// Next end any currently outstanding render pass. The render pass is normally closed before
// reaching here for various reasons, except typically when UtilsVk needs to start one.
@@ -5856,7 +5878,7 @@
}
angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea,
- vk::CommandBuffer **commandBufferOut,
+ vk::RenderPassCommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut)
{
ASSERT(mDrawFramebuffer == vk::GetImpl(mState.getDrawFramebuffer()));
@@ -5977,7 +5999,7 @@
ANGLE_TRY(mRenderPassCommands->endRenderPass(this));
- if (vk::CommandBufferHelper::kEnableCommandStreamDiagnostics)
+ if (vk::CommandBufferHelperCommon::kEnableCommandStreamDiagnostics)
{
mRenderPassCommands->addCommandDiagnostics(this);
}
@@ -6125,7 +6147,7 @@
addOverlayUsedBuffersCount(mOutsideRenderPassCommands);
- if (vk::CommandBufferHelper::kEnableCommandStreamDiagnostics)
+ if (vk::CommandBufferHelperCommon::kEnableCommandStreamDiagnostics)
{
mOutsideRenderPassCommands->addCommandDiagnostics(this);
}
@@ -6452,7 +6474,8 @@
{
ANGLE_TRY(flushCommandBuffersIfNecessary(access));
- vk::CommandBuffer *commandBuffer = &mOutsideRenderPassCommands->getCommandBuffer();
+ vk::OutsideRenderPassCommandBuffer *commandBuffer =
+ &mOutsideRenderPassCommands->getCommandBuffer();
for (const vk::CommandBufferImageAccess &imageAccess : access.getReadImages())
{
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.h b/src/libANGLE/renderer/vulkan/ContextVk.h
index 87f034f..3890ec8 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.h
+++ b/src/libANGLE/renderer/vulkan/ContextVk.h
@@ -446,8 +446,6 @@
void addWaitSemaphore(VkSemaphore semaphore, VkPipelineStageFlags stageMask);
- const vk::CommandPool &getCommandPool() const;
-
Serial getLastCompletedQueueSerial() const { return mRenderer->getLastCompletedQueueSerial(); }
bool isSerialInUse(Serial serial) const;
@@ -481,7 +479,7 @@
// Create Begin/End/Instant GPU trace events, which take their timestamps from GPU queries.
// The events are queued until the query results are available. Possible values for `phase`
// are TRACE_EVENT_PHASE_*
- ANGLE_INLINE angle::Result traceGpuEvent(vk::CommandBuffer *commandBuffer,
+ ANGLE_INLINE angle::Result traceGpuEvent(vk::OutsideRenderPassCommandBuffer *commandBuffer,
char phase,
const EventName &name)
{
@@ -555,10 +553,10 @@
}
}
- angle::Result getOutsideRenderPassCommandBuffer(const vk::CommandBufferAccess &access,
- vk::CommandBuffer **commandBufferOut)
+ angle::Result getOutsideRenderPassCommandBuffer(
+ const vk::CommandBufferAccess &access,
+ vk::OutsideRenderPassCommandBuffer **commandBufferOut)
{
- ASSERT(!mOutsideRenderPassCommands->hasRenderPass());
ANGLE_TRY(onResourceAccess(access));
*commandBufferOut = &mOutsideRenderPassCommands->getCommandBuffer();
return angle::Result::Continue;
@@ -571,7 +569,7 @@
const vk::PackedAttachmentCount colorAttachmentCount,
const vk::PackedAttachmentIndex depthStencilAttachmentIndex,
const vk::PackedClearValuesArray &clearValues,
- vk::CommandBuffer **commandBufferOut);
+ vk::RenderPassCommandBuffer **commandBufferOut);
// Only returns true if we have a started RP and we've run setupDraw.
bool hasStartedRenderPass() const
@@ -591,7 +589,7 @@
return hasStartedRenderPass() && !mRenderPassCommands->getCommandBuffer().empty();
}
- vk::CommandBufferHelper &getStartedRenderPassCommands()
+ vk::RenderPassCommandBufferHelper &getStartedRenderPassCommands()
{
ASSERT(mRenderPassCommands->started());
return *mRenderPassCommands;
@@ -605,7 +603,7 @@
egl::ContextPriority getContextPriority() const override { return mContextPriority; }
angle::Result startRenderPass(gl::Rectangle renderArea,
- vk::CommandBuffer **commandBufferOut,
+ vk::RenderPassCommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut);
void startNextSubpass();
angle::Result flushCommandsAndEndRenderPass(RenderPassClosureReason reason);
@@ -644,7 +642,7 @@
void syncObjectPerfCounters();
void updateOverlayOnPresent();
- void addOverlayUsedBuffersCount(vk::CommandBufferHelper *commandBuffer);
+ void addOverlayUsedBuffersCount(vk::CommandBufferHelperCommon *commandBuffer);
// DescriptorSet writes
VkDescriptorBufferInfo *allocDescriptorBufferInfos(size_t count);
@@ -836,7 +834,8 @@
void updateSurfaceRotationReadFramebuffer(const gl::State &glState);
angle::Result updateActiveTextures(const gl::Context *context, gl::Command command);
- angle::Result updateActiveImages(vk::CommandBufferHelper *commandBufferHelper);
+ template <typename CommandBufferHelperT>
+ angle::Result updateActiveImages(CommandBufferHelperT *commandBufferHelper);
angle::Result updateDefaultAttribute(size_t attribIndex);
ANGLE_INLINE void invalidateCurrentGraphicsPipeline()
@@ -917,14 +916,20 @@
// Common parts of the common dirty bit handlers.
angle::Result handleDirtyMemoryBarrierImpl(DirtyBits::Iterator *dirtyBitsIterator,
DirtyBits dirtyBitMask);
- angle::Result handleDirtyEventLogImpl(vk::CommandBuffer *commandBuffer);
- angle::Result handleDirtyTexturesImpl(vk::CommandBufferHelper *commandBufferHelper,
+ template <typename CommandBufferT>
+ angle::Result handleDirtyEventLogImpl(CommandBufferT *commandBuffer);
+ template <typename CommandBufferHelperT>
+ angle::Result handleDirtyTexturesImpl(CommandBufferHelperT *commandBufferHelper,
PipelineType pipelineType);
- angle::Result handleDirtyShaderResourcesImpl(vk::CommandBufferHelper *commandBufferHelper);
- void handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandBuffer,
+ template <typename CommandBufferHelperT>
+ angle::Result handleDirtyShaderResourcesImpl(CommandBufferHelperT *commandBufferHelper);
+ void handleDirtyShaderBufferResourcesImpl(vk::CommandBufferHelperCommon *commandBufferHelper);
+ template <typename CommandBufferT>
+ void handleDirtyDriverUniformsBindingImpl(CommandBufferT *commandBuffer,
VkPipelineBindPoint bindPoint,
DriverUniformsDescriptorSet *driverUniforms);
- angle::Result handleDirtyDescriptorSetsImpl(vk::CommandBuffer *commandBuffer,
+ template <typename CommandBufferT>
+ angle::Result handleDirtyDescriptorSetsImpl(CommandBufferT *commandBuffer,
PipelineType pipelineType);
void handleDirtyGraphicsScissorImpl(bool isPrimitivesGeneratedQueryActive);
@@ -941,7 +946,7 @@
angle::Result submitFrame(const vk::Semaphore *signalSemaphore, Serial *submitSerialOut);
angle::Result synchronizeCpuGpuTime();
- angle::Result traceGpuEventImpl(vk::CommandBuffer *commandBuffer,
+ angle::Result traceGpuEventImpl(vk::OutsideRenderPassCommandBuffer *commandBuffer,
char phase,
const EventName &name);
angle::Result checkCompletedGpuEvents();
@@ -949,7 +954,6 @@
void handleDeviceLost();
bool shouldEmulateSeamfulCubeMapSampling() const;
void clearAllGarbage();
- bool hasRecordedCommands();
void dumpCommandStreamDiagnostics();
angle::Result flushOutsideRenderPassCommands();
// Flush commands and end render pass without setting any dirty bits.
@@ -1018,7 +1022,7 @@
std::array<GraphicsDirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers;
std::array<ComputeDirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers;
- vk::CommandBuffer *mRenderPassCommandBuffer;
+ vk::RenderPassCommandBuffer *mRenderPassCommandBuffer;
vk::PipelineHelper *mCurrentGraphicsPipeline;
vk::PipelineHelper *mCurrentComputePipeline;
@@ -1130,14 +1134,14 @@
gl::AttribArray<vk::DynamicBuffer> mDefaultAttribBuffers;
// We use a single pool for recording commands. We also keep a free list for pool recycling.
- vk::CommandPool mCommandPool;
+ vk::SecondaryCommandPools mCommandPools;
vk::GarbageList mCurrentGarbage;
RenderPassCache mRenderPassCache;
- vk::CommandBufferHelper *mOutsideRenderPassCommands;
- vk::CommandBufferHelper *mRenderPassCommands;
+ vk::OutsideRenderPassCommandBufferHelper *mOutsideRenderPassCommands;
+ vk::RenderPassCommandBufferHelper *mRenderPassCommands;
// The following is used when creating debug-util markers for graphics debuggers (e.g. AGI). A
// given gl{Begin|End}Query command may result in commands being submitted to the outside or
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index 451fafc..642f135 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -859,7 +859,7 @@
access.onImageTransferRead(imageAspectMask, srcImage);
access.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
drawRenderTarget->getLayerIndex(), 1, imageAspectMask, dstImage);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkImageBlit blit = {};
@@ -1405,8 +1405,9 @@
ANGLE_TRY(drawRenderTarget->getImageView(contextVk, &resolveImageView));
vk::Framebuffer *newSrcFramebuffer = nullptr;
ANGLE_TRY(srcFramebufferVk->getFramebuffer(contextVk, &newSrcFramebuffer, resolveImageView));
- // 2. Update the CommandBufferHelper with the new framebuffer and render pass
- vk::CommandBufferHelper &commandBufferHelper = contextVk->getStartedRenderPassCommands();
+ // 2. Update the RenderPassCommandBufferHelper with the new framebuffer and render pass
+ vk::RenderPassCommandBufferHelper &commandBufferHelper =
+ contextVk->getStartedRenderPassCommands();
commandBufferHelper.updateRenderPassForResolve(contextVk, newSrcFramebuffer,
srcFramebufferVk->getRenderPassDesc());
@@ -1438,7 +1439,7 @@
&dstImage);
}
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkImageResolve resolveRegion = {};
@@ -2329,7 +2330,7 @@
}
angle::Result FramebufferVk::clearWithCommand(ContextVk *contextVk,
- vk::CommandBufferHelper *renderpassCommands,
+ vk::RenderPassCommandBufferHelper *renderpassCommands,
const gl::Rectangle &scissoredRenderArea)
{
// Clear is not affected by viewport, so ContextVk::updateScissor may have decided on a smaller
@@ -2380,11 +2381,11 @@
updateRenderPassReadOnlyDepthMode(contextVk, renderpassCommands);
}
- VkClearRect rect = {};
- rect.rect.extent.width = scissoredRenderArea.width;
- rect.rect.extent.height = scissoredRenderArea.height;
- rect.layerCount = mCurrentFramebufferDesc.getLayerCount();
- vk::CommandBuffer *renderPassCommandBuffer = &renderpassCommands->getCommandBuffer();
+ VkClearRect rect = {};
+ rect.rect.extent.width = scissoredRenderArea.width;
+ rect.rect.extent.height = scissoredRenderArea.height;
+ rect.layerCount = mCurrentFramebufferDesc.getLayerCount();
+ vk::RenderPassCommandBuffer *renderPassCommandBuffer = &renderpassCommands->getCommandBuffer();
renderPassCommandBuffer->clearAttachments(static_cast<uint32_t>(attachments.size()),
attachments.data(), 1, &rect);
@@ -2402,7 +2403,7 @@
angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
const gl::Rectangle &scissoredRenderArea,
- vk::CommandBuffer **commandBufferOut,
+ vk::RenderPassCommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut)
{
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass));
@@ -2817,7 +2818,7 @@
}
void FramebufferVk::updateRenderPassReadOnlyDepthMode(ContextVk *contextVk,
- vk::CommandBufferHelper *renderPass)
+ vk::RenderPassCommandBufferHelper *renderPass)
{
bool readOnlyDepthStencilMode =
getDepthStencilRenderTarget() && !getDepthStencilRenderTarget()->hasResolveAttachment() &&
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.h b/src/libANGLE/renderer/vulkan/FramebufferVk.h
index 5731c07..135a77f 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.h
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.h
@@ -138,7 +138,7 @@
angle::Result startNewRenderPass(ContextVk *contextVk,
const gl::Rectangle &scissoredRenderArea,
- vk::CommandBuffer **commandBufferOut,
+ vk::RenderPassCommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut);
GLint getSamples() const;
@@ -157,7 +157,7 @@
}
bool isReadOnlyDepthFeedbackLoopMode() const { return mReadOnlyDepthFeedbackLoopMode; }
void updateRenderPassReadOnlyDepthMode(ContextVk *contextVk,
- vk::CommandBufferHelper *renderPass);
+ vk::RenderPassCommandBufferHelper *renderPass);
void onSwitchProgramFramebufferFetch(ContextVk *contextVk, bool programUsesFramebufferFetch);
@@ -211,7 +211,7 @@
const VkClearDepthStencilValue &clearDepthStencilValue);
void redeferClears(ContextVk *contextVk);
angle::Result clearWithCommand(ContextVk *contextVk,
- vk::CommandBufferHelper *renderpassCommands,
+ vk::RenderPassCommandBufferHelper *renderpassCommands,
const gl::Rectangle &scissoredRenderArea);
void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a);
void updateRenderPassDesc(ContextVk *contextVk);
diff --git a/src/libANGLE/renderer/vulkan/OverlayVk.cpp b/src/libANGLE/renderer/vulkan/OverlayVk.cpp
index 4dfdeb9..a51b173 100644
--- a/src/libANGLE/renderer/vulkan/OverlayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/OverlayVk.cpp
@@ -132,7 +132,7 @@
access.onBufferTransferRead(&fontDataBuffer.get());
access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, gl::overlay::kFontCount,
VK_IMAGE_ASPECT_COLOR_BIT, &mFontImage);
- vk::CommandBuffer *fontDataUpload;
+ vk::OutsideRenderPassCommandBuffer *fontDataUpload;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &fontDataUpload));
VkBufferImageCopy copy = {};
diff --git a/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp
index 10f763c..b868bec 100644
--- a/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp
@@ -1551,8 +1551,7 @@
angle::Result ProgramExecutableVk::updateShaderResourcesDescriptorSet(
ContextVk *contextVk,
FramebufferVk *framebufferVk,
- const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc,
- vk::CommandBufferHelper *commandBufferHelper)
+ const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc)
{
const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
ASSERT(executable);
@@ -1884,8 +1883,9 @@
return angle::Result::Continue;
}
+template <typename CommandBufferT>
angle::Result ProgramExecutableVk::updateDescriptorSets(ContextVk *contextVk,
- vk::CommandBuffer *commandBuffer,
+ CommandBufferT *commandBuffer,
PipelineType pipelineType)
{
// Can probably use better dirty bits here.
@@ -1970,6 +1970,15 @@
return angle::Result::Continue;
}
+template angle::Result ProgramExecutableVk::updateDescriptorSets<vk::priv::SecondaryCommandBuffer>(
+ ContextVk *contextVk,
+ vk::priv::SecondaryCommandBuffer *commandBuffer,
+ PipelineType pipelineType);
+template angle::Result ProgramExecutableVk::updateDescriptorSets<vk::VulkanSecondaryCommandBuffer>(
+ ContextVk *contextVk,
+ vk::VulkanSecondaryCommandBuffer *commandBuffer,
+ PipelineType pipelineType);
+
// Requires that trace is enabled to see the output, which is supported with is_debug=true
void ProgramExecutableVk::outputCumulativePerfCounters()
{
diff --git a/src/libANGLE/renderer/vulkan/ProgramExecutableVk.h b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.h
index 398150e..e909181 100644
--- a/src/libANGLE/renderer/vulkan/ProgramExecutableVk.h
+++ b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.h
@@ -161,8 +161,7 @@
angle::Result updateShaderResourcesDescriptorSet(
ContextVk *contextVk,
FramebufferVk *framebufferVk,
- const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc,
- vk::CommandBufferHelper *commandBufferHelper);
+ const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc);
angle::Result updateTransformFeedbackDescriptorSet(
const gl::ProgramState &programState,
gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
@@ -174,8 +173,9 @@
ContextVk *contextVk,
FramebufferVk *framebufferVk);
+ template <typename CommandBufferT>
angle::Result updateDescriptorSets(ContextVk *contextVk,
- vk::CommandBuffer *commandBuffer,
+ CommandBufferT *commandBuffer,
PipelineType pipelineType);
void updateEarlyFragmentTestsOptimization(ContextVk *contextVk);
diff --git a/src/libANGLE/renderer/vulkan/README.md b/src/libANGLE/renderer/vulkan/README.md
index 684be1f..b515c01 100644
--- a/src/libANGLE/renderer/vulkan/README.md
+++ b/src/libANGLE/renderer/vulkan/README.md
@@ -63,7 +63,7 @@
access.onBufferTransferRead(srcBuffer);
// Get a pointer to a secondary command buffer for command recording.
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// Record the copy command into the secondary buffer. We're done!
diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
index a0fb084..840cabe 100644
--- a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
@@ -174,7 +174,7 @@
uint32_t rendererQueueFamilyIndex = contextVk->getRenderer()->getQueueFamilyIndex();
if (mImage->isQueueChangeNeccesary(rendererQueueFamilyIndex))
{
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
mImage->changeLayoutAndQueue(contextVk, aspect, vk::ImageLayout::ColorAttachment,
rendererQueueFamilyIndex, commandBuffer);
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index 2d74730..10198e2 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -1075,7 +1075,8 @@
mYuvConversionCache.destroy(this);
mVkFormatDescriptorCountMap.clear();
- mCommandBufferRecycler.onDestroy();
+ mOutsideRenderPassCommandBufferRecycler.onDestroy();
+ mRenderPassCommandBufferRecycler.onDestroy();
mBufferMemoryAllocator.destroy(this);
mAllocator.destroy();
@@ -2097,7 +2098,8 @@
// Used to support EXT_blend_func_extended
mEnabledFeatures.features.dualSrcBlend = mPhysicalDeviceFeatures.dualSrcBlend;
- if (!vk::CommandBuffer::ExecutesInline())
+ if (!vk::OutsideRenderPassCommandBuffer::ExecutesInline() ||
+ !vk::RenderPassCommandBuffer::ExecutesInline())
{
mEnabledFeatures.features.inheritedQueries = mPhysicalDeviceFeatures.inheritedQueries;
}
@@ -3006,11 +3008,12 @@
ApplyFeatureOverrides(&mFeatures, displayVk->getState());
// Disable async command queue when using Vulkan secondary command buffers temporarily to avoid
- // threading hazards with ContextVk::mCommandPool. Note that this is done even if the feature
+ // threading hazards with ContextVk::mCommandPools. Note that this is done even if the feature
// is enabled through an override.
// TODO: Investigate whether async command queue is useful with Vulkan secondary command buffers
// and enable the feature. http://anglebug.com/6811
- if (!vk::CommandBuffer::ExecutesInline())
+ if (!vk::OutsideRenderPassCommandBuffer::ExecutesInline() ||
+ !vk::RenderPassCommandBuffer::ExecutesInline())
{
mFeatures.asyncCommandQueue.enabled = false;
}
@@ -3515,20 +3518,24 @@
const vk::Semaphore *signalSemaphore,
std::vector<vk::ResourceUseList> &&resourceUseLists,
vk::GarbageList &¤tGarbage,
- vk::CommandPool *commandPool,
+ vk::SecondaryCommandPools *commandPools,
Serial *submitSerialOut)
{
std::lock_guard<std::mutex> commandQueueLock(mCommandQueueMutex);
+ vk::SecondaryCommandBufferList commandBuffersToReset = {
+ std::move(mOutsideRenderPassCommandBufferRecycler.releaseCommandBuffersToReset()),
+ std::move(mRenderPassCommandBufferRecycler.releaseCommandBuffersToReset()),
+ };
+
if (isAsyncCommandQueueEnabled())
{
*submitSerialOut = mCommandProcessor.reserveSubmitSerial();
ANGLE_TRY(mCommandProcessor.submitFrame(
context, hasProtectedContent, contextPriority, waitSemaphores, waitSemaphoreStageMasks,
- signalSemaphore, std::move(currentGarbage),
- std::move(mCommandBufferRecycler.getCommandBuffersToReset()), commandPool,
- *submitSerialOut));
+ signalSemaphore, std::move(currentGarbage), std::move(commandBuffersToReset),
+ commandPools, *submitSerialOut));
}
else
{
@@ -3536,9 +3543,8 @@
ANGLE_TRY(mCommandQueue.submitFrame(
context, hasProtectedContent, contextPriority, waitSemaphores, waitSemaphoreStageMasks,
- signalSemaphore, std::move(currentGarbage),
- std::move(mCommandBufferRecycler.getCommandBuffersToReset()), commandPool,
- *submitSerialOut));
+ signalSemaphore, std::move(currentGarbage), std::move(commandBuffersToReset),
+ commandPools, *submitSerialOut));
}
waitSemaphores.clear();
@@ -3636,10 +3642,11 @@
return angle::Result::Continue;
}
-angle::Result RendererVk::flushRenderPassCommands(vk::Context *context,
- bool hasProtectedContent,
- const vk::RenderPass &renderPass,
- vk::CommandBufferHelper **renderPassCommands)
+angle::Result RendererVk::flushRenderPassCommands(
+ vk::Context *context,
+ bool hasProtectedContent,
+ const vk::RenderPass &renderPass,
+ vk::RenderPassCommandBufferHelper **renderPassCommands)
{
ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::flushRenderPassCommands");
@@ -3658,9 +3665,10 @@
return angle::Result::Continue;
}
-angle::Result RendererVk::flushOutsideRPCommands(vk::Context *context,
- bool hasProtectedContent,
- vk::CommandBufferHelper **outsideRPCommands)
+angle::Result RendererVk::flushOutsideRPCommands(
+ vk::Context *context,
+ bool hasProtectedContent,
+ vk::OutsideRenderPassCommandBufferHelper **outsideRPCommands)
{
ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::flushOutsideRPCommands");
@@ -3703,23 +3711,44 @@
return result;
}
-angle::Result RendererVk::getCommandBufferHelper(vk::Context *context,
- bool hasRenderPass,
- vk::CommandPool *commandPool,
- vk::CommandBufferHelper **commandBufferHelperOut)
+angle::Result RendererVk::getOutsideRenderPassCommandBufferHelper(
+ vk::Context *context,
+ vk::CommandPool *commandPool,
+ vk::OutsideRenderPassCommandBufferHelper **commandBufferHelperOut)
{
- ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::getCommandBufferHelper");
+ ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::getOutsideRenderPassCommandBufferHelper");
std::unique_lock<std::mutex> lock(mCommandBufferRecyclerMutex);
- return mCommandBufferRecycler.getCommandBufferHelper(context, hasRenderPass, commandPool,
- commandBufferHelperOut);
+ return mOutsideRenderPassCommandBufferRecycler.getCommandBufferHelper(context, commandPool,
+ commandBufferHelperOut);
}
-void RendererVk::recycleCommandBufferHelper(VkDevice device,
- vk::CommandBufferHelper **commandBuffer)
+angle::Result RendererVk::getRenderPassCommandBufferHelper(
+ vk::Context *context,
+ vk::CommandPool *commandPool,
+ vk::RenderPassCommandBufferHelper **commandBufferHelperOut)
{
- ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::recycleCommandBufferHelper");
+ ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::getRenderPassCommandBufferHelper");
+ std::unique_lock<std::mutex> lock(mCommandBufferRecyclerMutex);
+ return mRenderPassCommandBufferRecycler.getCommandBufferHelper(context, commandPool,
+ commandBufferHelperOut);
+}
+
+void RendererVk::recycleOutsideRenderPassCommandBufferHelper(
+ VkDevice device,
+ vk::OutsideRenderPassCommandBufferHelper **commandBuffer)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::recycleOutsideRenderPassCommandBufferHelper");
std::lock_guard<std::mutex> lock(mCommandBufferRecyclerMutex);
- mCommandBufferRecycler.recycleCommandBufferHelper(device, commandBuffer);
+ mOutsideRenderPassCommandBufferRecycler.recycleCommandBufferHelper(device, commandBuffer);
+}
+
+void RendererVk::recycleRenderPassCommandBufferHelper(
+ VkDevice device,
+ vk::RenderPassCommandBufferHelper **commandBuffer)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::recycleRenderPassCommandBufferHelper");
+ std::lock_guard<std::mutex> lock(mCommandBufferRecyclerMutex);
+ mRenderPassCommandBufferRecycler.recycleCommandBufferHelper(device, commandBuffer);
}
void RendererVk::logCacheStats() const
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.h b/src/libANGLE/renderer/vulkan/RendererVk.h
index 3df8d13..2058826 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.h
+++ b/src/libANGLE/renderer/vulkan/RendererVk.h
@@ -297,9 +297,14 @@
bool hasProtectedContent,
vk::PrimaryCommandBuffer *commandBufferOut);
- void resetSecondaryCommandBuffer(vk::CommandBuffer &&commandBuffer)
+ void resetOutsideRenderPassCommandBuffer(vk::OutsideRenderPassCommandBuffer &&commandBuffer)
{
- mCommandBufferRecycler.resetCommandBufferHelper(std::move(commandBuffer));
+ mOutsideRenderPassCommandBufferRecycler.resetCommandBuffer(std::move(commandBuffer));
+ }
+
+ void resetRenderPassCommandBuffer(vk::RenderPassCommandBuffer &&commandBuffer)
+ {
+ mRenderPassCommandBufferRecycler.resetCommandBuffer(std::move(commandBuffer));
}
// Fire off a single command buffer immediately with default priority.
@@ -432,7 +437,7 @@
const vk::Semaphore *signalSemaphore,
std::vector<vk::ResourceUseList> &&resourceUseLists,
vk::GarbageList &¤tGarbage,
- vk::CommandPool *commandPool,
+ vk::SecondaryCommandPools *commandPools,
Serial *submitSerialOut);
void handleDeviceLost();
@@ -447,20 +452,30 @@
angle::Result flushRenderPassCommands(vk::Context *context,
bool hasProtectedContent,
const vk::RenderPass &renderPass,
- vk::CommandBufferHelper **renderPassCommands);
- angle::Result flushOutsideRPCommands(vk::Context *context,
- bool hasProtectedContent,
- vk::CommandBufferHelper **outsideRPCommands);
+ vk::RenderPassCommandBufferHelper **renderPassCommands);
+ angle::Result flushOutsideRPCommands(
+ vk::Context *context,
+ bool hasProtectedContent,
+ vk::OutsideRenderPassCommandBufferHelper **outsideRPCommands);
VkResult queuePresent(vk::Context *context,
egl::ContextPriority priority,
const VkPresentInfoKHR &presentInfo);
- angle::Result getCommandBufferHelper(vk::Context *context,
- bool hasRenderPass,
- vk::CommandPool *commandPool,
- vk::CommandBufferHelper **commandBufferHelperOut);
- void recycleCommandBufferHelper(VkDevice device, vk::CommandBufferHelper **commandBuffer);
+ angle::Result getOutsideRenderPassCommandBufferHelper(
+ vk::Context *context,
+ vk::CommandPool *commandPool,
+ vk::OutsideRenderPassCommandBufferHelper **commandBufferHelperOut);
+ angle::Result getRenderPassCommandBufferHelper(
+ vk::Context *context,
+ vk::CommandPool *commandPool,
+ vk::RenderPassCommandBufferHelper **commandBufferHelperOut);
+
+ void recycleOutsideRenderPassCommandBufferHelper(
+ VkDevice device,
+ vk::OutsideRenderPassCommandBufferHelper **commandBuffer);
+ void recycleRenderPassCommandBufferHelper(VkDevice device,
+ vk::RenderPassCommandBufferHelper **commandBuffer);
// Process GPU memory reports
void processMemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT &callbackData)
@@ -663,7 +678,11 @@
// Command buffer pool management.
std::mutex mCommandBufferRecyclerMutex;
- vk::CommandBufferRecycler mCommandBufferRecycler;
+ vk::CommandBufferRecycler<vk::OutsideRenderPassCommandBuffer,
+ vk::OutsideRenderPassCommandBufferHelper>
+ mOutsideRenderPassCommandBufferRecycler;
+ vk::CommandBufferRecycler<vk::RenderPassCommandBuffer, vk::RenderPassCommandBufferHelper>
+ mRenderPassCommandBufferRecycler;
vk::BufferMemoryAllocator mBufferMemoryAllocator;
vk::Allocator mAllocator;
diff --git a/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp b/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp
index b1fd734..ba83e75 100644
--- a/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp
+++ b/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp
@@ -81,7 +81,7 @@
BufferVk *bufferVk = vk::GetImpl(buffer);
vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
// Queue ownership transfer.
@@ -101,7 +101,7 @@
vk::ImageHelper &image = textureVk->getImage();
vk::ImageLayout layout = vk::GetImageLayoutFromGLImageLayout(textureBarrier.layout);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
// Image should not be accessed while unowned. Emulated formats may have staged updates
@@ -136,7 +136,7 @@
vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
ANGLE_TRY(contextVk->onBufferReleaseToExternal(bufferHelper));
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
// Queue ownership transfer.
@@ -166,7 +166,7 @@
ANGLE_TRY(textureVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
ANGLE_TRY(contextVk->onImageReleaseToExternal(image));
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
// Queue ownership transfer and layout transition.
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
index 464c2dc..d0168e8 100644
--- a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
+++ b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
@@ -1477,7 +1477,7 @@
// ImageLayout::Present bellow.
contextVk->finalizeImageLayout(&image.image);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
if (mColorImageMS.valid())
diff --git a/src/libANGLE/renderer/vulkan/SyncVk.cpp b/src/libANGLE/renderer/vulkan/SyncVk.cpp
index 2045639..97f8485 100644
--- a/src/libANGLE/renderer/vulkan/SyncVk.cpp
+++ b/src/libANGLE/renderer/vulkan/SyncVk.cpp
@@ -143,7 +143,7 @@
// Every resource already tracks its usage and issues the appropriate barriers, so there's
// really nothing to do here. An execution barrier is issued to strictly satisfy what the
// application asked for.
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 0,
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index b83ac3c..efdd645 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -1005,7 +1005,7 @@
access.onImageTransferWrite(level, 1, baseLayer, layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
mImage);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkImageSubresourceLayers destSubresource = srcSubresource;
@@ -1042,7 +1042,7 @@
access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
&stagingImage->get());
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkImageSubresourceLayers destSubresource = srcSubresource;
@@ -1410,7 +1410,7 @@
newLayout = vk::ImageLayout::AllGraphicsShadersReadOnly;
}
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
mImage->changeLayoutAndQueue(contextVk, mImage->getAspectFlags(), newLayout,
rendererQueueFamilyIndex, commandBuffer);
@@ -1740,7 +1740,7 @@
access.onBufferTransferRead(srcBuffer);
access.onImageTransferWrite(level, 1, layerIndex, layerCount, mImage->getAspectFlags(), mImage);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
commandBuffer->copyBufferToImage(srcBuffer->getBuffer().getHandle(), mImage->getImage(),
@@ -1799,7 +1799,7 @@
mImage->getLayerCount(), VK_IMAGE_ASPECT_COLOR_BIT,
mImage);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// Generate mipmaps for every layer separately.
@@ -2039,7 +2039,7 @@
&stagingImage->get());
access.onImageTransferRead(aspectFlags, srcImage);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkImageCopy copyRegion = {};
diff --git a/src/libANGLE/renderer/vulkan/UtilsVk.cpp b/src/libANGLE/renderer/vulkan/UtilsVk.cpp
index 94b55c1..a4c92f9 100644
--- a/src/libANGLE/renderer/vulkan/UtilsVk.cpp
+++ b/src/libANGLE/renderer/vulkan/UtilsVk.cpp
@@ -1426,82 +1426,92 @@
return angle::Result::Continue;
}
-angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
- Function function,
- vk::RefCounted<vk::ShaderAndSerial> *fsCsShader,
- vk::RefCounted<vk::ShaderAndSerial> *vsShader,
- vk::ShaderProgramHelper *program,
- const vk::GraphicsPipelineDesc *pipelineDesc,
- const VkDescriptorSet descriptorSet,
- const void *pushConstants,
- size_t pushConstantsSize,
- vk::CommandBuffer *commandBuffer)
+angle::Result UtilsVk::setupComputeProgram(ContextVk *contextVk,
+ Function function,
+ vk::RefCounted<vk::ShaderAndSerial> *csShader,
+ vk::ShaderProgramHelper *program,
+ const VkDescriptorSet descriptorSet,
+ const void *pushConstants,
+ size_t pushConstantsSize,
+ vk::OutsideRenderPassCommandBuffer *commandBuffer)
{
- RendererVk *renderer = contextVk->getRenderer();
-
- const bool isCompute = function >= Function::ComputeStartIndex;
- const VkShaderStageFlags pushConstantsShaderStage =
- isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
- const VkPipelineBindPoint pipelineBindPoint =
- isCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
-
- // If compute, vsShader and pipelineDesc should be nullptr, and if not compute they shouldn't
- // be.
- ASSERT(isCompute != (vsShader && pipelineDesc));
+ ASSERT(function >= Function::ComputeStartIndex);
const vk::BindingPointer<vk::PipelineLayout> &pipelineLayout = mPipelineLayouts[function];
- if (isCompute)
- {
- vk::PipelineHelper *pipeline;
- program->setShader(gl::ShaderType::Compute, fsCsShader);
- ANGLE_TRY(program->getComputePipeline(contextVk, pipelineLayout.get(), &pipeline));
- pipeline->retain(&contextVk->getResourceUseList());
- commandBuffer->bindComputePipeline(pipeline->getPipeline());
+ vk::PipelineHelper *pipeline;
+ program->setShader(gl::ShaderType::Compute, csShader);
+ ANGLE_TRY(program->getComputePipeline(contextVk, pipelineLayout.get(), &pipeline));
+ pipeline->retain(&contextVk->getResourceUseList());
+ commandBuffer->bindComputePipeline(pipeline->getPipeline());
- contextVk->invalidateComputePipelineBinding();
- }
- else
- {
- program->setShader(gl::ShaderType::Vertex, vsShader);
- if (fsCsShader)
- {
- program->setShader(gl::ShaderType::Fragment, fsCsShader);
- }
-
- // This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check.
- const vk::GraphicsPipelineDesc *descPtr;
- vk::PipelineHelper *helper;
- vk::PipelineCache *pipelineCache = nullptr;
- ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
- ANGLE_TRY(program->getGraphicsPipeline(contextVk, &contextVk->getRenderPassCache(),
- *pipelineCache, pipelineLayout.get(), *pipelineDesc,
- gl::AttributesMask(), gl::ComponentTypeMask(),
- gl::DrawBufferMask(), &descPtr, &helper));
- helper->retain(&contextVk->getResourceUseList());
- commandBuffer->bindGraphicsPipeline(helper->getPipeline());
-
- contextVk->invalidateGraphicsPipelineBinding();
- }
+ contextVk->invalidateComputePipelineBinding();
if (descriptorSet != VK_NULL_HANDLE)
{
- commandBuffer->bindDescriptorSets(pipelineLayout.get(), pipelineBindPoint,
+ commandBuffer->bindDescriptorSets(pipelineLayout.get(), VK_PIPELINE_BIND_POINT_COMPUTE,
DescriptorSetIndex::Internal, 1, &descriptorSet, 0,
nullptr);
- if (isCompute)
- {
- contextVk->invalidateComputeDescriptorSet(DescriptorSetIndex::Internal);
- }
- else
- {
- contextVk->invalidateGraphicsDescriptorSet(DescriptorSetIndex::Internal);
- }
+ contextVk->invalidateComputeDescriptorSet(DescriptorSetIndex::Internal);
}
if (pushConstants)
{
- commandBuffer->pushConstants(pipelineLayout.get(), pushConstantsShaderStage, 0,
+ commandBuffer->pushConstants(pipelineLayout.get(), VK_SHADER_STAGE_COMPUTE_BIT, 0,
+ static_cast<uint32_t>(pushConstantsSize), pushConstants);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result UtilsVk::setupGraphicsProgram(ContextVk *contextVk,
+ Function function,
+ vk::RefCounted<vk::ShaderAndSerial> *vsShader,
+ vk::RefCounted<vk::ShaderAndSerial> *fsShader,
+ vk::ShaderProgramHelper *program,
+ const vk::GraphicsPipelineDesc *pipelineDesc,
+ const VkDescriptorSet descriptorSet,
+ const void *pushConstants,
+ size_t pushConstantsSize,
+ vk::RenderPassCommandBuffer *commandBuffer)
+{
+ RendererVk *renderer = contextVk->getRenderer();
+
+ ASSERT(function < Function::ComputeStartIndex);
+
+ const vk::BindingPointer<vk::PipelineLayout> &pipelineLayout = mPipelineLayouts[function];
+
+ program->setShader(gl::ShaderType::Vertex, vsShader);
+ if (fsShader)
+ {
+ program->setShader(gl::ShaderType::Fragment, fsShader);
+ }
+
+ // This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check.
+ const vk::GraphicsPipelineDesc *descPtr;
+ vk::PipelineHelper *helper;
+ vk::PipelineCache *pipelineCache = nullptr;
+ ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
+ ANGLE_TRY(program->getGraphicsPipeline(contextVk, &contextVk->getRenderPassCache(),
+ *pipelineCache, pipelineLayout.get(), *pipelineDesc,
+ gl::AttributesMask(), gl::ComponentTypeMask(),
+ gl::DrawBufferMask(), &descPtr, &helper));
+ helper->retain(&contextVk->getResourceUseList());
+ commandBuffer->bindGraphicsPipeline(helper->getPipeline());
+
+ contextVk->invalidateGraphicsPipelineBinding();
+
+ if (descriptorSet != VK_NULL_HANDLE)
+ {
+ commandBuffer->bindDescriptorSets(pipelineLayout.get(), VK_PIPELINE_BIND_POINT_GRAPHICS,
+ DescriptorSetIndex::Internal, 1, &descriptorSet, 0,
+ nullptr);
+ contextVk->invalidateGraphicsDescriptorSet(DescriptorSetIndex::Internal);
+ }
+
+ if (pushConstants)
+ {
+ commandBuffer->pushConstants(pipelineLayout.get(), VK_SHADER_STAGE_FRAGMENT_BIT, 0,
static_cast<uint32_t>(pushConstantsSize), pushConstants);
}
@@ -1519,7 +1529,7 @@
access.onBufferComputeShaderRead(src);
access.onBufferComputeShaderWrite(dst);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorSet descriptorSet;
@@ -1554,9 +1564,9 @@
vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
- ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexBuffer, shader, nullptr,
- &mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
- sizeof(ConvertIndexShaderParams), commandBuffer));
+ ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexBuffer, shader,
+ &mConvertIndexPrograms[flags], descriptorSet, &shaderParams,
+ sizeof(ConvertIndexShaderParams), commandBuffer));
constexpr uint32_t kInvocationsPerGroup = 64;
constexpr uint32_t kInvocationsPerIndex = 2;
@@ -1585,7 +1595,7 @@
access.onBufferComputeShaderWrite(dstIndirectBuf);
access.onBufferComputeShaderWrite(dstIndexBuf);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorSet descriptorSet;
@@ -1625,9 +1635,9 @@
vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
- ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectBuffer, shader, nullptr,
- &mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
- sizeof(ConvertIndexIndirectShaderParams), commandBuffer));
+ ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexIndirectBuffer, shader,
+ &mConvertIndexPrograms[flags], descriptorSet, &shaderParams,
+ sizeof(ConvertIndexIndirectShaderParams), commandBuffer));
constexpr uint32_t kInvocationsPerGroup = 64;
constexpr uint32_t kInvocationsPerIndex = 2;
@@ -1657,7 +1667,7 @@
access.onBufferComputeShaderWrite(dstIndirectBuffer);
access.onBufferComputeShaderWrite(dstIndexBuffer);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorSet descriptorSet;
@@ -1697,10 +1707,10 @@
ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndexIndirectLineLoop_comp(contextVk, flags,
&shader));
- ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectLineLoopBuffer, shader, nullptr,
- &mConvertIndexIndirectLineLoopPrograms[flags], nullptr, descriptorSet,
- &shaderParams, sizeof(ConvertIndexIndirectLineLoopShaderParams),
- commandBuffer));
+ ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexIndirectLineLoopBuffer, shader,
+ &mConvertIndexIndirectLineLoopPrograms[flags], descriptorSet,
+ &shaderParams, sizeof(ConvertIndexIndirectLineLoopShaderParams),
+ commandBuffer));
commandBuffer->dispatch(1, 1, 1);
@@ -1723,7 +1733,7 @@
access.onBufferComputeShaderWrite(dstIndirectBuffer);
access.onBufferComputeShaderWrite(dstIndexBuffer);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorSet descriptorSet;
@@ -1760,10 +1770,10 @@
ANGLE_TRY(
contextVk->getShaderLibrary().getConvertIndirectLineLoop_comp(contextVk, flags, &shader));
- ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndirectLineLoopBuffer, shader, nullptr,
- &mConvertIndirectLineLoopPrograms[flags], nullptr, descriptorSet,
- &shaderParams, sizeof(ConvertIndirectLineLoopShaderParams),
- commandBuffer));
+ ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndirectLineLoopBuffer, shader,
+ &mConvertIndirectLineLoopPrograms[flags], descriptorSet,
+ &shaderParams, sizeof(ConvertIndirectLineLoopShaderParams),
+ commandBuffer));
commandBuffer->dispatch(1, 1, 1);
@@ -1781,7 +1791,7 @@
access.onBufferComputeShaderRead(src);
access.onBufferComputeShaderWrite(dst);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
ConvertVertexShaderParams shaderParams;
@@ -1886,7 +1896,7 @@
vk::BufferHelper *dst,
vk::BufferHelper *src,
uint32_t flags,
- vk::CommandBuffer *commandBuffer,
+ vk::OutsideRenderPassCommandBuffer *commandBuffer,
const ConvertVertexShaderParams &shaderParams)
{
ANGLE_TRY(ensureConvertVertexResourcesInitialized(contextVk));
@@ -1916,9 +1926,9 @@
vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
ANGLE_TRY(contextVk->getShaderLibrary().getConvertVertex_comp(contextVk, flags, &shader));
- ANGLE_TRY(setupProgram(contextVk, Function::ConvertVertexBuffer, shader, nullptr,
- &mConvertVertexPrograms[flags], nullptr, descriptorSet, &shaderParams,
- sizeof(shaderParams), commandBuffer));
+ ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertVertexBuffer, shader,
+ &mConvertVertexPrograms[flags], descriptorSet, &shaderParams,
+ sizeof(shaderParams), commandBuffer));
commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
@@ -1932,7 +1942,7 @@
const vk::ImageView *imageView,
const vk::RenderPassDesc &renderPassDesc,
const gl::Rectangle &renderArea,
- vk::CommandBuffer **commandBufferOut)
+ vk::RenderPassCommandBuffer **commandBufferOut)
{
vk::RenderPass *compatibleRenderPass = nullptr;
ANGLE_TRY(contextVk->getCompatibleRenderPass(renderPassDesc, &compatibleRenderPass));
@@ -1977,7 +1987,7 @@
const gl::Rectangle &scissoredRenderArea = params.clearArea;
vk::Framebuffer *currentFramebuffer = nullptr;
- vk::CommandBuffer *commandBuffer;
+ vk::RenderPassCommandBuffer *commandBuffer;
// Start a new render pass if not already started
ANGLE_TRY(framebuffer->getFramebuffer(contextVk, ¤tFramebuffer, nullptr));
@@ -1992,7 +2002,7 @@
if (params.clearStencil || params.clearDepth)
{
- vk::CommandBufferHelper *renderpassCommands;
+ vk::RenderPassCommandBufferHelper *renderpassCommands;
renderpassCommands = &contextVk->getStartedRenderPassCommands();
// Because clear is not affected by depth/stencil test, we have to explicitly mark
@@ -2101,9 +2111,9 @@
contextVk->getStartedRenderPassCommands().isTransformFeedbackActiveUnpaused();
contextVk->pauseTransformFeedbackIfActiveUnpaused();
- ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
- imageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
- sizeof(shaderParams), commandBuffer));
+ ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageClear, vertexShader, fragmentShader,
+ imageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
+ sizeof(shaderParams), commandBuffer));
// Make sure this draw call doesn't count towards occlusion query results.
contextVk->pauseRenderPassQueriesIfActive();
@@ -2178,7 +2188,7 @@
pipelineDesc.setRasterizationSamples(dst->getSamples());
pipelineDesc.setRenderPassDesc(renderPassDesc);
- vk::CommandBuffer *commandBuffer;
+ vk::RenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(startRenderPass(contextVk, dst, &destView.get(), renderPassDesc, renderArea,
&commandBuffer));
@@ -2203,9 +2213,9 @@
ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
- ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
- &mImageClearPrograms[flags], &pipelineDesc, VK_NULL_HANDLE,
- &shaderParams, sizeof(shaderParams), commandBuffer));
+ ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageClear, vertexShader, fragmentShader,
+ &mImageClearPrograms[flags], &pipelineDesc, VK_NULL_HANDLE,
+ &shaderParams, sizeof(shaderParams), commandBuffer));
// Note: this utility creates its own framebuffer, thus bypassing ContextVk::startRenderPass.
// As such, occlusion queries are not enabled.
@@ -2407,7 +2417,7 @@
SetStencilForShaderExport(contextVk, &pipelineDesc);
}
- vk::CommandBuffer *commandBuffer;
+ vk::RenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer, nullptr));
VkViewport viewport;
@@ -2424,7 +2434,8 @@
contextVk->onImageRenderPassRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly,
src);
- vk::CommandBufferHelper *renderPassCommands = &contextVk->getStartedRenderPassCommands();
+ vk::RenderPassCommandBufferHelper *renderPassCommands =
+ &contextVk->getStartedRenderPassCommands();
if (blitDepth)
{
// Explicitly mark a depth write because we are modifying the depth buffer.
@@ -2500,9 +2511,9 @@
ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader));
- ANGLE_TRY(setupProgram(contextVk, Function::BlitResolve, fragmentShader, vertexShader,
- &mBlitResolvePrograms[flags], &pipelineDesc, descriptorSet,
- &shaderParams, sizeof(shaderParams), commandBuffer));
+ ANGLE_TRY(setupGraphicsProgram(contextVk, Function::BlitResolve, vertexShader, fragmentShader,
+ &mBlitResolvePrograms[flags], &pipelineDesc, descriptorSet,
+ &shaderParams, sizeof(shaderParams), commandBuffer));
// Note: this utility starts the render pass directly, thus bypassing
// ContextVk::startRenderPass. As such, occlusion queries are not enabled.
@@ -2634,7 +2645,7 @@
depthStencilRenderTarget->getLayerIndex(), 1,
depthStencilImage->getAspectFlags(), depthStencilImage);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// Blit/resolve stencil into the buffer.
@@ -2678,9 +2689,9 @@
ANGLE_TRY(contextVk->getShaderLibrary().getBlitResolveStencilNoExport_comp(contextVk, flags,
&shader));
- ANGLE_TRY(setupProgram(contextVk, Function::BlitResolveStencilNoExport, shader, nullptr,
- &mBlitResolveStencilNoExportPrograms[flags], nullptr, descriptorSet,
- &shaderParams, sizeof(shaderParams), commandBuffer));
+ ANGLE_TRY(setupComputeProgram(contextVk, Function::BlitResolveStencilNoExport, shader,
+ &mBlitResolveStencilNoExportPrograms[flags], descriptorSet,
+ &shaderParams, sizeof(shaderParams), commandBuffer));
commandBuffer->dispatch(UnsignedCeilDivide(bufferRowLengthInUints, 8),
UnsignedCeilDivide(params.blitArea.height, 8), 1);
descriptorPoolBinding.reset();
@@ -2851,7 +2862,7 @@
std::swap(renderArea.width, renderArea.height);
}
- vk::CommandBuffer *commandBuffer;
+ vk::RenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(
startRenderPass(contextVk, dst, destView, renderPassDesc, renderArea, &commandBuffer));
@@ -2890,9 +2901,9 @@
ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
ANGLE_TRY(shaderLibrary.getImageCopy_frag(contextVk, flags, &fragmentShader));
- ANGLE_TRY(setupProgram(contextVk, Function::ImageCopy, fragmentShader, vertexShader,
- &mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams,
- sizeof(shaderParams), commandBuffer));
+ ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageCopy, vertexShader, fragmentShader,
+ &mImageCopyPrograms[flags], &pipelineDesc, descriptorSet,
+ &shaderParams, sizeof(shaderParams), commandBuffer));
// Note: this utility creates its own framebuffer, thus bypassing ContextVk::startRenderPass.
// As such, occlusion queries are not enabled.
@@ -2984,7 +2995,7 @@
isDst3D ? 1 : params.copyExtents[2], VK_IMAGE_ASPECT_COLOR_BIT,
dst);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// Copy src into buffer, completely packed.
@@ -3195,12 +3206,12 @@
// 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;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
- ANGLE_TRY(setupProgram(contextVk, Function::GenerateMipmap, shader, nullptr,
- &mGenerateMipmapPrograms[flags], nullptr, descriptorSet, &shaderParams,
- sizeof(shaderParams), commandBuffer));
+ ANGLE_TRY(setupComputeProgram(contextVk, Function::GenerateMipmap, shader,
+ &mGenerateMipmapPrograms[flags], descriptorSet, &shaderParams,
+ sizeof(shaderParams), commandBuffer));
commandBuffer->dispatch(workGroupX, workGroupY, 1);
descriptorPoolBinding.reset();
@@ -3301,7 +3312,7 @@
SetStencilForShaderExport(contextVk, &pipelineDesc);
}
- vk::CommandBuffer *commandBuffer =
+ vk::RenderPassCommandBuffer *commandBuffer =
&contextVk->getStartedRenderPassCommands().getCommandBuffer();
VkViewport viewport;
@@ -3365,9 +3376,9 @@
ANGLE_TRY(GetUnresolveFrag(contextVk, colorAttachmentCount, colorAttachmentTypes,
params.unresolveDepth, params.unresolveStencil, fragmentShader));
- ANGLE_TRY(setupProgram(contextVk, function, fragmentShader, vertexShader,
- &mUnresolvePrograms[flags], &pipelineDesc, descriptorSet, nullptr, 0,
- commandBuffer));
+ ANGLE_TRY(setupGraphicsProgram(contextVk, function, vertexShader, fragmentShader,
+ &mUnresolvePrograms[flags], &pipelineDesc, descriptorSet,
+ nullptr, 0, commandBuffer));
// This draw call is made before ContextVk gets a chance to start the occlusion query. As such,
// occlusion queries are not enabled.
commandBuffer->draw(3, 0);
@@ -3419,7 +3430,7 @@
access.onBufferComputeShaderRead(enabledWidgetsBuffer);
access.onImageComputeShaderWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, dst);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorImageInfo imageInfo = {};
@@ -3451,9 +3462,9 @@
vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
ANGLE_TRY(contextVk->getShaderLibrary().getOverlayCull_comp(contextVk, flags, &shader));
- ANGLE_TRY(setupProgram(contextVk, Function::OverlayCull, shader, nullptr,
- &mOverlayCullPrograms[flags], nullptr, descriptorSet, nullptr, 0,
- commandBuffer));
+ ANGLE_TRY(setupComputeProgram(contextVk, Function::OverlayCull, shader,
+ &mOverlayCullPrograms[flags], descriptorSet, nullptr, 0,
+ commandBuffer));
commandBuffer->dispatch(dst->getExtents().width, dst->getExtents().height, 1);
descriptorPoolBinding.reset();
@@ -3499,7 +3510,7 @@
access.onBufferComputeShaderRead(textWidgetsBuffer);
access.onBufferComputeShaderRead(graphWidgetsBuffer);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
VkDescriptorImageInfo imageInfos[3] = {};
@@ -3559,9 +3570,9 @@
vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
ANGLE_TRY(contextVk->getShaderLibrary().getOverlayDraw_comp(contextVk, flags, &shader));
- ANGLE_TRY(setupProgram(contextVk, Function::OverlayDraw, shader, nullptr,
- &mOverlayDrawPrograms[flags], nullptr, descriptorSet, &shaderParams,
- sizeof(shaderParams), commandBuffer));
+ ANGLE_TRY(setupComputeProgram(contextVk, Function::OverlayDraw, shader,
+ &mOverlayDrawPrograms[flags], descriptorSet, &shaderParams,
+ sizeof(shaderParams), commandBuffer));
// Every pixel of culledWidgets corresponds to one workgroup, so we can use that as dispatch
// size.
diff --git a/src/libANGLE/renderer/vulkan/UtilsVk.h b/src/libANGLE/renderer/vulkan/UtilsVk.h
index dc80611..fbc8c61 100644
--- a/src/libANGLE/renderer/vulkan/UtilsVk.h
+++ b/src/libANGLE/renderer/vulkan/UtilsVk.h
@@ -481,21 +481,26 @@
EnumCount = 22,
};
- // Common function that creates the pipeline for the specified function, binds it and prepares
- // the draw/dispatch call. If function >= ComputeStartIndex, fsCsShader is expected to be a
- // compute shader, vsShader and pipelineDesc should be nullptr, and this will set up a dispatch
- // call. Otherwise fsCsShader is expected to be a fragment shader and this will set up a draw
- // call.
- angle::Result setupProgram(ContextVk *contextVk,
- Function function,
- vk::RefCounted<vk::ShaderAndSerial> *fsCsShader,
- vk::RefCounted<vk::ShaderAndSerial> *vsShader,
- vk::ShaderProgramHelper *program,
- const vk::GraphicsPipelineDesc *pipelineDesc,
- const VkDescriptorSet descriptorSet,
- const void *pushConstants,
- size_t pushConstantsSize,
- vk::CommandBuffer *commandBuffer);
+ // Common functions that create the pipeline for the specified function, binds it and prepares
+ // the draw/dispatch call.
+ angle::Result setupComputeProgram(ContextVk *contextVk,
+ Function function,
+ vk::RefCounted<vk::ShaderAndSerial> *csShader,
+ vk::ShaderProgramHelper *program,
+ const VkDescriptorSet descriptorSet,
+ const void *pushConstants,
+ size_t pushConstantsSize,
+ vk::OutsideRenderPassCommandBuffer *commandBuffer);
+ angle::Result setupGraphicsProgram(ContextVk *contextVk,
+ Function function,
+ vk::RefCounted<vk::ShaderAndSerial> *vsShader,
+ vk::RefCounted<vk::ShaderAndSerial> *fsShader,
+ vk::ShaderProgramHelper *program,
+ const vk::GraphicsPipelineDesc *pipelineDesc,
+ const VkDescriptorSet descriptorSet,
+ const void *pushConstants,
+ size_t pushConstantsSize,
+ vk::RenderPassCommandBuffer *commandBuffer);
// Initializes descriptor set layout, pipeline layout and descriptor pool corresponding to given
// function, if not already initialized. Uses setSizes to create the layout. For example, if
@@ -533,14 +538,14 @@
const vk::ImageView *imageView,
const vk::RenderPassDesc &renderPassDesc,
const gl::Rectangle &renderArea,
- vk::CommandBuffer **commandBufferOut);
+ vk::RenderPassCommandBuffer **commandBufferOut);
// Set up descriptor set and call dispatch.
angle::Result convertVertexBufferImpl(ContextVk *contextVk,
vk::BufferHelper *dst,
vk::BufferHelper *src,
uint32_t flags,
- vk::CommandBuffer *commandBuffer,
+ vk::OutsideRenderPassCommandBuffer *commandBuffer,
const ConvertVertexShaderParams &shaderParams);
// Blits or resolves either color or depth/stencil, based on which view is given.
diff --git a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
index 7f4f8f6..85307b5 100644
--- a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
@@ -441,7 +441,8 @@
// We use secondary command buffers almost everywhere and they require a feature to be
// able to execute in the presence of queries. As a result, we won't support timestamp queries
// unless that feature is available.
- if (vk::CommandBuffer::SupportsQueries(mPhysicalDeviceFeatures))
+ if (vk::OutsideRenderPassCommandBuffer::SupportsQueries(mPhysicalDeviceFeatures) &&
+ vk::RenderPassCommandBuffer::SupportsQueries(mPhysicalDeviceFeatures))
{
mNativeExtensions.disjointTimerQueryEXT = queueFamilyProperties.timestampValidBits > 0;
mNativeCaps.queryCounterBitsTimeElapsed = queueFamilyProperties.timestampValidBits;
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
index 4d27fba..b865f06 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
@@ -85,7 +85,7 @@
VkAccessFlags srcAccessMask;
// Read or write.
ResourceAccess type;
- // CommandBufferHelper tracks an array of PipelineBarriers. This indicates which array element
+ // *CommandBufferHelper track an array of PipelineBarriers. This indicates which array element
// this should be merged into. Right now we track individual barrier for every PipelineStage. If
// layout has a single stage mask bit, we use that stage as index. If layout has multiple stage
// mask bits, we pick the lowest stage as the index since it is the first stage that needs
@@ -811,6 +811,71 @@
return sizeMismatch || releaseByPolicy;
}
+
+// Helper functions used below
+char GetLoadOpShorthand(RenderPassLoadOp loadOp)
+{
+ switch (loadOp)
+ {
+ case RenderPassLoadOp::Clear:
+ return 'C';
+ case RenderPassLoadOp::Load:
+ return 'L';
+ case RenderPassLoadOp::None:
+ return 'N';
+ default:
+ return 'D';
+ }
+}
+
+char GetStoreOpShorthand(RenderPassStoreOp storeOp)
+{
+ switch (storeOp)
+ {
+ case RenderPassStoreOp::Store:
+ return 'S';
+ case RenderPassStoreOp::None:
+ return 'N';
+ default:
+ return 'D';
+ }
+}
+
+template <typename CommandBufferHelperT>
+void RecycleCommandBufferHelper(VkDevice device,
+ std::vector<CommandBufferHelperT *> *freeList,
+ CommandBufferHelperT **commandBufferHelper,
+ priv::SecondaryCommandBuffer *commandBuffer)
+{
+ freeList->push_back(*commandBufferHelper);
+}
+
+template <typename CommandBufferHelperT>
+void RecycleCommandBufferHelper(VkDevice device,
+ std::vector<CommandBufferHelperT *> *freeList,
+ CommandBufferHelperT **commandBufferHelper,
+ VulkanSecondaryCommandBuffer *commandBuffer)
+{
+ CommandPool *pool = (*commandBufferHelper)->getCommandPool();
+
+ pool->freeCommandBuffers(device, 1, commandBuffer->ptr());
+ commandBuffer->releaseHandle();
+ SafeDelete(*commandBufferHelper);
+}
+
+ANGLE_MAYBE_UNUSED void ResetSecondaryCommandBuffer(
+ std::vector<priv::SecondaryCommandBuffer> *resetList,
+ priv::SecondaryCommandBuffer &&commandBuffer)
+{
+ commandBuffer.reset();
+}
+
+ANGLE_MAYBE_UNUSED void ResetSecondaryCommandBuffer(
+ std::vector<VulkanSecondaryCommandBuffer> *resetList,
+ VulkanSecondaryCommandBuffer &&commandBuffer)
+{
+ resetList->push_back(std::move(commandBuffer));
+}
} // anonymous namespace
// This is an arbitrary max. We can change this later if necessary.
@@ -953,45 +1018,18 @@
mValues[index.get()] = clearValue;
}
-// CommandBufferHelper implementation.
-CommandBufferHelper::CommandBufferHelper()
+// CommandBufferHelperCommon implementation.
+CommandBufferHelperCommon::CommandBufferHelperCommon()
: mPipelineBarriers(),
mPipelineBarrierMask(),
mCommandPool(nullptr),
- mCounter(0),
- mClearValues{},
- mRenderPassStarted(false),
- mTransformFeedbackCounterBuffers{},
- mValidTransformFeedbackBufferCount(0),
- mRebindTransformFeedbackBuffers(false),
- mIsTransformFeedbackActiveUnpaused(false),
- mIsRenderPassCommandBuffer(false),
mHasShaderStorageOutput(false),
- mHasGLMemoryBarrierIssued(false),
- mDepthAccess(ResourceAccess::Unused),
- mStencilAccess(ResourceAccess::Unused),
- mDepthCmdCountInvalidated(kInfiniteCmdCount),
- mDepthCmdCountDisabled(kInfiniteCmdCount),
- mStencilCmdCountInvalidated(kInfiniteCmdCount),
- mStencilCmdCountDisabled(kInfiniteCmdCount),
- mDepthStencilAttachmentIndex(kAttachmentIndexInvalid),
- mDepthStencilImage(nullptr),
- mDepthStencilResolveImage(nullptr),
- mDepthStencilLevelIndex(0),
- mDepthStencilLayerIndex(0),
- mDepthStencilLayerCount(0),
- mColorImagesCount(0),
- mImageOptimizeForPresent(nullptr)
+ mHasGLMemoryBarrierIssued(false)
{}
-CommandBufferHelper::~CommandBufferHelper()
-{
- mFramebuffer.setHandle(VK_NULL_HANDLE);
-}
+CommandBufferHelperCommon::~CommandBufferHelperCommon() {}
-angle::Result CommandBufferHelper::initialize(Context *context,
- bool isRenderPassCommandBuffer,
- CommandPool *commandPool)
+void CommandBufferHelperCommon::initializeImpl(Context *context, CommandPool *commandPool)
{
ASSERT(mUsedBuffers.empty());
constexpr size_t kInitialBufferCount = 128;
@@ -1001,82 +1039,21 @@
// Push a scope into the pool allocator so we can easily free and re-init on reset()
mAllocator.push();
- mIsRenderPassCommandBuffer = isRenderPassCommandBuffer;
- mCommandPool = commandPool;
-
- return initializeCommandBuffer(context);
+ mCommandPool = commandPool;
}
-angle::Result CommandBufferHelper::initializeCommandBuffer(Context *context)
-{
- return mCommandBuffer.initialize(context, mCommandPool, mIsRenderPassCommandBuffer,
- &mAllocator);
-}
-
-angle::Result CommandBufferHelper::reset(Context *context)
+void CommandBufferHelperCommon::resetImpl()
{
mAllocator.pop();
mAllocator.push();
- // Reset and re-initialize the command buffer
- context->getRenderer()->resetSecondaryCommandBuffer(std::move(mCommandBuffer));
- ANGLE_TRY(initializeCommandBuffer(context));
-
mUsedBuffers.clear();
-
- if (mIsRenderPassCommandBuffer)
- {
- mRenderPassStarted = false;
- mValidTransformFeedbackBufferCount = 0;
- mRebindTransformFeedbackBuffers = false;
- mHasShaderStorageOutput = false;
- mHasGLMemoryBarrierIssued = false;
- mDepthAccess = ResourceAccess::Unused;
- mStencilAccess = ResourceAccess::Unused;
- mDepthCmdCountInvalidated = kInfiniteCmdCount;
- mDepthCmdCountDisabled = kInfiniteCmdCount;
- mStencilCmdCountInvalidated = kInfiniteCmdCount;
- mStencilCmdCountDisabled = kInfiniteCmdCount;
- mColorImagesCount = PackedAttachmentCount(0);
- mDepthStencilAttachmentIndex = kAttachmentIndexInvalid;
- mDepthInvalidateArea = gl::Rectangle();
- mStencilInvalidateArea = gl::Rectangle();
- mRenderPassUsedImages.clear();
- mDepthStencilImage = nullptr;
- mDepthStencilResolveImage = nullptr;
- mColorImages.reset();
- mColorResolveImages.reset();
- mImageOptimizeForPresent = nullptr;
- }
- // This state should never change for non-renderPass command buffer
- ASSERT(mRenderPassStarted == false);
- ASSERT(mValidTransformFeedbackBufferCount == 0);
- ASSERT(!mRebindTransformFeedbackBuffers);
- ASSERT(!mIsTransformFeedbackActiveUnpaused);
- ASSERT(mRenderPassUsedImages.empty());
-
- return angle::Result::Continue;
}
-bool CommandBufferHelper::usesBuffer(const BufferHelper &buffer) const
-{
- return mUsedBuffers.contains(buffer.getBufferSerial().getValue());
-}
-
-bool CommandBufferHelper::usesBufferForWrite(const BufferHelper &buffer) const
-{
- BufferAccess access;
- if (!mUsedBuffers.get(buffer.getBufferSerial().getValue(), &access))
- {
- return false;
- }
- return access == BufferAccess::Write;
-}
-
-void CommandBufferHelper::bufferRead(ContextVk *contextVk,
- VkAccessFlags readAccessType,
- PipelineStage readStage,
- BufferHelper *buffer)
+void CommandBufferHelperCommon::bufferRead(ContextVk *contextVk,
+ VkAccessFlags readAccessType,
+ PipelineStage readStage,
+ BufferHelper *buffer)
{
VkPipelineStageFlagBits stageBits = kPipelineStageFlagBitMap[readStage];
if (buffer->recordReadBarrier(readAccessType, stageBits, &mPipelineBarriers[readStage]))
@@ -1092,11 +1069,11 @@
}
}
-void CommandBufferHelper::bufferWrite(ContextVk *contextVk,
- VkAccessFlags writeAccessType,
- PipelineStage writeStage,
- AliasingMode aliasingMode,
- BufferHelper *buffer)
+void CommandBufferHelperCommon::bufferWrite(ContextVk *contextVk,
+ VkAccessFlags writeAccessType,
+ PipelineStage writeStage,
+ AliasingMode aliasingMode,
+ BufferHelper *buffer)
{
buffer->retainReadWrite(&contextVk->getResourceUseList());
VkPipelineStageFlagBits stageBits = kPipelineStageFlagBitMap[writeStage];
@@ -1124,70 +1101,298 @@
}
}
-void CommandBufferHelper::imageRead(ContextVk *contextVk,
- VkImageAspectFlags aspectFlags,
- ImageLayout imageLayout,
- ImageHelper *image)
+bool CommandBufferHelperCommon::usesBuffer(const BufferHelper &buffer) const
+{
+ return mUsedBuffers.contains(buffer.getBufferSerial().getValue());
+}
+
+bool CommandBufferHelperCommon::usesBufferForWrite(const BufferHelper &buffer) const
+{
+ BufferAccess access;
+ if (!mUsedBuffers.get(buffer.getBufferSerial().getValue(), &access))
+ {
+ return false;
+ }
+ return access == BufferAccess::Write;
+}
+
+void CommandBufferHelperCommon::executeBarriers(const angle::FeaturesVk &features,
+ PrimaryCommandBuffer *primary)
+{
+ // make a local copy for faster access
+ PipelineStagesMask mask = mPipelineBarrierMask;
+ if (mask.none())
+ {
+ return;
+ }
+
+ if (features.preferAggregateBarrierCalls.enabled)
+ {
+ PipelineStagesMask::Iterator iter = mask.begin();
+ PipelineBarrier &barrier = mPipelineBarriers[*iter];
+ for (++iter; iter != mask.end(); ++iter)
+ {
+ barrier.merge(&mPipelineBarriers[*iter]);
+ }
+ barrier.execute(primary);
+ }
+ else
+ {
+ for (PipelineStage pipelineStage : mask)
+ {
+ PipelineBarrier &barrier = mPipelineBarriers[pipelineStage];
+ barrier.execute(primary);
+ }
+ }
+ mPipelineBarrierMask.reset();
+}
+
+void CommandBufferHelperCommon::imageReadImpl(ContextVk *contextVk,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout,
+ ImageHelper *image)
{
if (image->isReadBarrierNecessary(imageLayout))
{
updateImageLayoutAndBarrier(contextVk, image, aspectFlags, imageLayout);
}
-
- if (mIsRenderPassCommandBuffer)
- {
- // As noted in the header we don't support multiple read layouts for Images.
- // We allow duplicate uses in the RP to accommodate for normal GL sampler usage.
- if (!usesImageInRenderPass(*image))
- {
- mRenderPassUsedImages.insert(image->getImageSerial().getValue());
- image->retain(&contextVk->getResourceUseList());
- }
- }
- else
- {
- image->retain(&contextVk->getResourceUseList());
- }
}
-void CommandBufferHelper::imageWrite(ContextVk *contextVk,
- gl::LevelIndex level,
- uint32_t layerStart,
- uint32_t layerCount,
- VkImageAspectFlags aspectFlags,
- ImageLayout imageLayout,
- AliasingMode aliasingMode,
- ImageHelper *image)
+void CommandBufferHelperCommon::imageWriteImpl(ContextVk *contextVk,
+ gl::LevelIndex level,
+ uint32_t layerStart,
+ uint32_t layerCount,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout,
+ AliasingMode aliasingMode,
+ ImageHelper *image)
{
image->retain(&contextVk->getResourceUseList());
image->onWrite(level, 1, layerStart, layerCount, aspectFlags);
// Write always requires a barrier
updateImageLayoutAndBarrier(contextVk, image, aspectFlags, imageLayout);
+}
- if (mIsRenderPassCommandBuffer)
+void CommandBufferHelperCommon::updateImageLayoutAndBarrier(Context *context,
+ ImageHelper *image,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout)
+{
+ PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
+ ASSERT(barrierIndex != PipelineStage::InvalidEnum);
+ PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex];
+ if (image->updateLayoutAndBarrier(context, aspectFlags, imageLayout, barrier))
{
- // When used as a storage image we allow for aliased writes.
- if (aliasingMode == AliasingMode::Disallowed)
- {
- ASSERT(!usesImageInRenderPass(*image));
- }
- if (!usesImageInRenderPass(*image))
- {
- mRenderPassUsedImages.insert(image->getImageSerial().getValue());
- }
+ mPipelineBarrierMask.set(barrierIndex);
}
}
-void CommandBufferHelper::colorImagesDraw(ResourceUseList *resourceUseList,
- ImageHelper *image,
- ImageHelper *resolveImage,
- PackedAttachmentIndex packedAttachmentIndex)
+void CommandBufferHelperCommon::addCommandDiagnosticsCommon(std::ostringstream *out)
{
- ASSERT(mIsRenderPassCommandBuffer);
+ *out << "Memory Barrier: ";
+ for (PipelineBarrier &barrier : mPipelineBarriers)
+ {
+ if (!barrier.isEmpty())
+ {
+ barrier.addDiagnosticsString(*out);
+ }
+ }
+ *out << "\\l";
+}
+
+// OutsideRenderPassCommandBufferHelper implementation.
+OutsideRenderPassCommandBufferHelper::OutsideRenderPassCommandBufferHelper() {}
+
+OutsideRenderPassCommandBufferHelper::~OutsideRenderPassCommandBufferHelper() {}
+
+angle::Result OutsideRenderPassCommandBufferHelper::initialize(Context *context,
+ CommandPool *commandPool)
+{
+ initializeImpl(context, commandPool);
+ return initializeCommandBuffer(context);
+}
+
+angle::Result OutsideRenderPassCommandBufferHelper::initializeCommandBuffer(Context *context)
+{
+ return mCommandBuffer.initialize(context, mCommandPool, false, &mAllocator);
+}
+
+angle::Result OutsideRenderPassCommandBufferHelper::reset(Context *context)
+{
+ resetImpl();
+
+ // Reset and re-initialize the command buffer
+ context->getRenderer()->resetOutsideRenderPassCommandBuffer(std::move(mCommandBuffer));
+ return initializeCommandBuffer(context);
+}
+
+void OutsideRenderPassCommandBufferHelper::imageRead(ContextVk *contextVk,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout,
+ ImageHelper *image)
+{
+ imageReadImpl(contextVk, aspectFlags, imageLayout, image);
+ image->retain(&contextVk->getResourceUseList());
+}
+
+void OutsideRenderPassCommandBufferHelper::imageWrite(ContextVk *contextVk,
+ gl::LevelIndex level,
+ uint32_t layerStart,
+ uint32_t layerCount,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout,
+ AliasingMode aliasingMode,
+ ImageHelper *image)
+{
+ imageWriteImpl(contextVk, level, layerStart, layerCount, aspectFlags, imageLayout, aliasingMode,
+ image);
+}
+
+angle::Result OutsideRenderPassCommandBufferHelper::flushToPrimary(Context *context,
+ PrimaryCommandBuffer *primary)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "OutsideRenderPassCommandBufferHelper::flushToPrimary");
+ ASSERT(!empty());
+
+ // Commands that are added to primary before beginRenderPass command
+ executeBarriers(context->getRenderer()->getFeatures(), primary);
+
+ ANGLE_TRY(mCommandBuffer.end(context));
+ mCommandBuffer.executeCommands(primary);
+
+ // Restart the command buffer.
+ return reset(context);
+}
+
+void OutsideRenderPassCommandBufferHelper::addCommandDiagnostics(ContextVk *contextVk)
+{
+ std::ostringstream out;
+ addCommandDiagnosticsCommon(&out);
+
+ out << mCommandBuffer.dumpCommands("\\l");
+ contextVk->addCommandBufferDiagnostics(out.str());
+}
+
+// RenderPassCommandBufferHelper implementation.
+RenderPassCommandBufferHelper::RenderPassCommandBufferHelper()
+ : mCounter(0),
+ mClearValues{},
+ mRenderPassStarted(false),
+ mTransformFeedbackCounterBuffers{},
+ mValidTransformFeedbackBufferCount(0),
+ mRebindTransformFeedbackBuffers(false),
+ mIsTransformFeedbackActiveUnpaused(false),
+ mDepthAccess(ResourceAccess::Unused),
+ mStencilAccess(ResourceAccess::Unused),
+ mDepthCmdCountInvalidated(kInfiniteCmdCount),
+ mDepthCmdCountDisabled(kInfiniteCmdCount),
+ mStencilCmdCountInvalidated(kInfiniteCmdCount),
+ mStencilCmdCountDisabled(kInfiniteCmdCount),
+ mDepthStencilAttachmentIndex(kAttachmentIndexInvalid),
+ mDepthStencilImage(nullptr),
+ mDepthStencilResolveImage(nullptr),
+ mDepthStencilLevelIndex(0),
+ mDepthStencilLayerIndex(0),
+ mDepthStencilLayerCount(0),
+ mColorImagesCount(0),
+ mImageOptimizeForPresent(nullptr)
+{}
+
+RenderPassCommandBufferHelper::~RenderPassCommandBufferHelper()
+{
+ mFramebuffer.setHandle(VK_NULL_HANDLE);
+}
+
+angle::Result RenderPassCommandBufferHelper::initialize(Context *context, CommandPool *commandPool)
+{
+ initializeImpl(context, commandPool);
+ return initializeCommandBuffer(context);
+}
+
+angle::Result RenderPassCommandBufferHelper::initializeCommandBuffer(Context *context)
+{
+ return mCommandBuffer.initialize(context, mCommandPool, true, &mAllocator);
+}
+
+angle::Result RenderPassCommandBufferHelper::reset(Context *context)
+{
+ resetImpl();
+
+ mRenderPassStarted = false;
+ mValidTransformFeedbackBufferCount = 0;
+ mRebindTransformFeedbackBuffers = false;
+ mHasShaderStorageOutput = false;
+ mHasGLMemoryBarrierIssued = false;
+ mDepthAccess = ResourceAccess::Unused;
+ mStencilAccess = ResourceAccess::Unused;
+ mDepthCmdCountInvalidated = kInfiniteCmdCount;
+ mDepthCmdCountDisabled = kInfiniteCmdCount;
+ mStencilCmdCountInvalidated = kInfiniteCmdCount;
+ mStencilCmdCountDisabled = kInfiniteCmdCount;
+ mColorImagesCount = PackedAttachmentCount(0);
+ mDepthStencilAttachmentIndex = kAttachmentIndexInvalid;
+ mDepthInvalidateArea = gl::Rectangle();
+ mStencilInvalidateArea = gl::Rectangle();
+ mRenderPassUsedImages.clear();
+ mDepthStencilImage = nullptr;
+ mDepthStencilResolveImage = nullptr;
+ mColorImages.reset();
+ mColorResolveImages.reset();
+ mImageOptimizeForPresent = nullptr;
+
+ // Reset and re-initialize the command buffer
+ context->getRenderer()->resetRenderPassCommandBuffer(std::move(mCommandBuffer));
+ return initializeCommandBuffer(context);
+}
+
+void RenderPassCommandBufferHelper::imageRead(ContextVk *contextVk,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout,
+ ImageHelper *image)
+{
+ imageReadImpl(contextVk, aspectFlags, imageLayout, image);
+
+ // As noted in the header we don't support multiple read layouts for Images.
+ // We allow duplicate uses in the RP to accommodate for normal GL sampler usage.
+ if (!usesImage(*image))
+ {
+ mRenderPassUsedImages.insert(image->getImageSerial().getValue());
+ image->retain(&contextVk->getResourceUseList());
+ }
+}
+
+void RenderPassCommandBufferHelper::imageWrite(ContextVk *contextVk,
+ gl::LevelIndex level,
+ uint32_t layerStart,
+ uint32_t layerCount,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout,
+ AliasingMode aliasingMode,
+ ImageHelper *image)
+{
+ imageWriteImpl(contextVk, level, layerStart, layerCount, aspectFlags, imageLayout, aliasingMode,
+ image);
+
+ // When used as a storage image we allow for aliased writes.
+ if (aliasingMode == AliasingMode::Disallowed)
+ {
+ ASSERT(!usesImage(*image));
+ }
+ if (!usesImage(*image))
+ {
+ mRenderPassUsedImages.insert(image->getImageSerial().getValue());
+ }
+}
+
+void RenderPassCommandBufferHelper::colorImagesDraw(ResourceUseList *resourceUseList,
+ ImageHelper *image,
+ ImageHelper *resolveImage,
+ PackedAttachmentIndex packedAttachmentIndex)
+{
ASSERT(packedAttachmentIndex < mColorImagesCount);
image->retain(resourceUseList);
- if (!usesImageInRenderPass(*image))
+ if (!usesImage(*image))
{
// This is possible due to different layers of the same texture being attached to different
// attachments
@@ -1200,7 +1405,7 @@
if (resolveImage)
{
resolveImage->retain(resourceUseList);
- if (!usesImageInRenderPass(*resolveImage))
+ if (!usesImage(*resolveImage))
{
mRenderPassUsedImages.insert(resolveImage->getImageSerial().getValue());
}
@@ -1210,16 +1415,15 @@
}
}
-void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseList,
- gl::LevelIndex level,
- uint32_t layerStart,
- uint32_t layerCount,
- ImageHelper *image,
- ImageHelper *resolveImage)
+void RenderPassCommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseList,
+ gl::LevelIndex level,
+ uint32_t layerStart,
+ uint32_t layerCount,
+ ImageHelper *image,
+ ImageHelper *resolveImage)
{
- ASSERT(mIsRenderPassCommandBuffer);
- ASSERT(!usesImageInRenderPass(*image));
- ASSERT(!resolveImage || !usesImageInRenderPass(*resolveImage));
+ ASSERT(!usesImage(*image));
+ ASSERT(!resolveImage || !usesImage(*resolveImage));
// Because depthStencil buffer's read/write property can change while we build renderpass, we
// defer the image layout changes until endRenderPass time or when images going away so that we
@@ -1244,7 +1448,7 @@
}
}
-void CommandBufferHelper::onDepthAccess(ResourceAccess access)
+void RenderPassCommandBufferHelper::onDepthAccess(ResourceAccess access)
{
// Update the access for optimizing this render pass's loadOp
UpdateAccess(&mDepthAccess, access);
@@ -1257,7 +1461,7 @@
}
}
-void CommandBufferHelper::onStencilAccess(ResourceAccess access)
+void RenderPassCommandBufferHelper::onStencilAccess(ResourceAccess access)
{
// Update the access for optimizing this render pass's loadOp
UpdateAccess(&mStencilAccess, access);
@@ -1270,9 +1474,9 @@
}
}
-bool CommandBufferHelper::onDepthStencilAccess(ResourceAccess access,
- uint32_t *cmdCountInvalidated,
- uint32_t *cmdCountDisabled)
+bool RenderPassCommandBufferHelper::onDepthStencilAccess(ResourceAccess access,
+ uint32_t *cmdCountInvalidated,
+ uint32_t *cmdCountDisabled)
{
if (*cmdCountInvalidated == kInfiniteCmdCount)
{
@@ -1313,9 +1517,9 @@
}
}
-void CommandBufferHelper::updateStartedRenderPassWithDepthMode(bool readOnlyDepthStencilMode)
+void RenderPassCommandBufferHelper::updateStartedRenderPassWithDepthMode(
+ bool readOnlyDepthStencilMode)
{
- ASSERT(mIsRenderPassCommandBuffer);
ASSERT(mRenderPassStarted);
if (mDepthStencilImage)
@@ -1344,7 +1548,7 @@
}
}
-void CommandBufferHelper::restoreDepthContent()
+void RenderPassCommandBufferHelper::restoreDepthContent()
{
// Note that the image may have been deleted since the render pass has started.
if (mDepthStencilImage)
@@ -1356,7 +1560,7 @@
}
}
-void CommandBufferHelper::restoreStencilContent()
+void RenderPassCommandBufferHelper::restoreStencilContent()
{
// Note that the image may have been deleted since the render pass has started.
if (mDepthStencilImage)
@@ -1368,57 +1572,12 @@
}
}
-void CommandBufferHelper::executeBarriers(const angle::FeaturesVk &features,
- PrimaryCommandBuffer *primary)
+void RenderPassCommandBufferHelper::finalizeColorImageLayout(
+ Context *context,
+ ImageHelper *image,
+ PackedAttachmentIndex packedAttachmentIndex,
+ bool isResolveImage)
{
- // make a local copy for faster access
- PipelineStagesMask mask = mPipelineBarrierMask;
- if (mask.none())
- {
- return;
- }
-
- if (features.preferAggregateBarrierCalls.enabled)
- {
- PipelineStagesMask::Iterator iter = mask.begin();
- PipelineBarrier &barrier = mPipelineBarriers[*iter];
- for (++iter; iter != mask.end(); ++iter)
- {
- barrier.merge(&mPipelineBarriers[*iter]);
- }
- barrier.execute(primary);
- }
- else
- {
- for (PipelineStage pipelineStage : mask)
- {
- PipelineBarrier &barrier = mPipelineBarriers[pipelineStage];
- barrier.execute(primary);
- }
- }
- mPipelineBarrierMask.reset();
-}
-
-void CommandBufferHelper::updateImageLayoutAndBarrier(Context *context,
- ImageHelper *image,
- VkImageAspectFlags aspectFlags,
- ImageLayout imageLayout)
-{
- PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
- ASSERT(barrierIndex != PipelineStage::InvalidEnum);
- PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex];
- if (image->updateLayoutAndBarrier(context, aspectFlags, imageLayout, barrier))
- {
- mPipelineBarrierMask.set(barrierIndex);
- }
-}
-
-void CommandBufferHelper::finalizeColorImageLayout(Context *context,
- ImageHelper *image,
- PackedAttachmentIndex packedAttachmentIndex,
- bool isResolveImage)
-{
- ASSERT(mIsRenderPassCommandBuffer);
ASSERT(packedAttachmentIndex < mColorImagesCount);
ASSERT(image != nullptr);
@@ -1446,7 +1605,7 @@
{
ASSERT(packedAttachmentIndex == kAttachmentIndexZero);
// Use finalLayout instead of extra barrier for layout change to present
- mImageOptimizeForPresent->setCurrentImageLayout(vk::ImageLayout::Present);
+ mImageOptimizeForPresent->setCurrentImageLayout(ImageLayout::Present);
// TODO(syoussefi): We currently don't store the layout of the resolve attachments, so once
// multisampled backbuffers are optimized to use resolve attachments, this information needs
// to be stored somewhere. http://anglebug.com/4836
@@ -1458,9 +1617,8 @@
image->resetRenderPassUsageFlags();
}
-void CommandBufferHelper::finalizeDepthStencilImageLayout(Context *context)
+void RenderPassCommandBufferHelper::finalizeDepthStencilImageLayout(Context *context)
{
- ASSERT(mIsRenderPassCommandBuffer);
ASSERT(mDepthStencilImage);
// Do depth stencil layout change.
@@ -1507,9 +1665,8 @@
}
}
-void CommandBufferHelper::finalizeDepthStencilResolveImageLayout(Context *context)
+void RenderPassCommandBufferHelper::finalizeDepthStencilResolveImageLayout(Context *context)
{
- ASSERT(mIsRenderPassCommandBuffer);
ASSERT(mDepthStencilImage);
ASSERT(!mDepthStencilResolveImage->hasRenderPassUsageFlag(RenderPassUsage::ReadOnlyAttachment));
@@ -1545,10 +1702,8 @@
mDepthStencilResolveImage->resetRenderPassUsageFlags();
}
-void CommandBufferHelper::finalizeImageLayout(Context *context, const ImageHelper *image)
+void RenderPassCommandBufferHelper::finalizeImageLayout(Context *context, const ImageHelper *image)
{
- ASSERT(mIsRenderPassCommandBuffer);
-
if (image->hasRenderPassUsageFlag(RenderPassUsage::RenderTargetAttachment))
{
for (PackedAttachmentIndex index = kAttachmentIndexZero; index < mColorImagesCount; ++index)
@@ -1579,7 +1734,7 @@
}
}
-void CommandBufferHelper::finalizeDepthStencilLoadStore(Context *context)
+void RenderPassCommandBufferHelper::finalizeDepthStencilLoadStore(Context *context)
{
ASSERT(mDepthStencilAttachmentIndex != kAttachmentIndexInvalid);
@@ -1656,10 +1811,10 @@
SetBitField(dsOps.stencilStoreOp, stencilStoreOp);
}
-void CommandBufferHelper::finalizeDepthStencilLoadStoreOps(Context *context,
- ResourceAccess access,
- RenderPassLoadOp *loadOp,
- RenderPassStoreOp *storeOp)
+void RenderPassCommandBufferHelper::finalizeDepthStencilLoadStoreOps(Context *context,
+ ResourceAccess access,
+ RenderPassLoadOp *loadOp,
+ RenderPassStoreOp *storeOp)
{
// For read only depth stencil, we can use StoreOpNone if available. DontCare is still
// preferred, so do this after handling DontCare.
@@ -1696,29 +1851,28 @@
}
}
-void CommandBufferHelper::finalizeDepthStencilImageLayoutAndLoadStore(Context *context)
+void RenderPassCommandBufferHelper::finalizeDepthStencilImageLayoutAndLoadStore(Context *context)
{
finalizeDepthStencilImageLayout(context);
finalizeDepthStencilLoadStore(context);
mDepthStencilImage->resetRenderPassUsageFlags();
}
-angle::Result CommandBufferHelper::beginRenderPass(
+angle::Result RenderPassCommandBufferHelper::beginRenderPass(
ContextVk *contextVk,
const Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
const RenderPassDesc &renderPassDesc,
const AttachmentOpsArray &renderPassAttachmentOps,
- const vk::PackedAttachmentCount colorAttachmentCount,
+ const PackedAttachmentCount colorAttachmentCount,
const PackedAttachmentIndex depthStencilAttachmentIndex,
const PackedClearValuesArray &clearValues,
- CommandBuffer **commandBufferOut)
+ RenderPassCommandBuffer **commandBufferOut)
{
- ASSERT(mIsRenderPassCommandBuffer);
- ASSERT(empty());
+ ASSERT(!mRenderPassStarted);
VkCommandBufferInheritanceInfo inheritanceInfo = {};
- ANGLE_TRY(vk::CommandBuffer::InitializeRenderPassInheritanceInfo(
+ ANGLE_TRY(RenderPassCommandBuffer::InitializeRenderPassInheritanceInfo(
contextVk, framebuffer, renderPassDesc, &inheritanceInfo));
ANGLE_TRY(mCommandBuffer.begin(contextVk, inheritanceInfo));
@@ -1737,7 +1891,7 @@
return angle::Result::Continue;
}
-angle::Result CommandBufferHelper::endRenderPass(ContextVk *contextVk)
+angle::Result RenderPassCommandBufferHelper::endRenderPass(ContextVk *contextVk)
{
ANGLE_TRY(mCommandBuffer.end(contextVk));
@@ -1771,11 +1925,10 @@
return angle::Result::Continue;
}
-void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount,
- const VkBuffer *counterBuffers,
- bool rebindBuffers)
+void RenderPassCommandBufferHelper::beginTransformFeedback(size_t validBufferCount,
+ const VkBuffer *counterBuffers,
+ bool rebindBuffers)
{
- ASSERT(mIsRenderPassCommandBuffer);
mValidTransformFeedbackBufferCount = static_cast<uint32_t>(validBufferCount);
mRebindTransformFeedbackBuffers = rebindBuffers;
@@ -1785,24 +1938,23 @@
}
}
-void CommandBufferHelper::endTransformFeedback()
+void RenderPassCommandBufferHelper::endTransformFeedback()
{
- ASSERT(mIsRenderPassCommandBuffer);
pauseTransformFeedback();
mValidTransformFeedbackBufferCount = 0;
}
-void CommandBufferHelper::invalidateRenderPassColorAttachment(PackedAttachmentIndex attachmentIndex)
+void RenderPassCommandBufferHelper::invalidateRenderPassColorAttachment(
+ PackedAttachmentIndex attachmentIndex)
{
- ASSERT(mIsRenderPassCommandBuffer);
SetBitField(mAttachmentOps[attachmentIndex].storeOp, RenderPassStoreOp::DontCare);
mAttachmentOps[attachmentIndex].isInvalidated = true;
}
-void CommandBufferHelper::invalidateRenderPassDepthAttachment(const gl::DepthStencilState &dsState,
- const gl::Rectangle &invalidateArea)
+void RenderPassCommandBufferHelper::invalidateRenderPassDepthAttachment(
+ const gl::DepthStencilState &dsState,
+ const gl::Rectangle &invalidateArea)
{
- ASSERT(mIsRenderPassCommandBuffer);
// Keep track of the size of commands in the command buffer. If the size grows in the
// future, that implies that drawing occured since invalidated.
mDepthCmdCountInvalidated = mCommandBuffer.getRenderPassWriteCommandCount();
@@ -1815,11 +1967,10 @@
ExtendRenderPassInvalidateArea(invalidateArea, &mDepthInvalidateArea);
}
-void CommandBufferHelper::invalidateRenderPassStencilAttachment(
+void RenderPassCommandBufferHelper::invalidateRenderPassStencilAttachment(
const gl::DepthStencilState &dsState,
const gl::Rectangle &invalidateArea)
{
- ASSERT(mIsRenderPassCommandBuffer);
// Keep track of the size of commands in the command buffer. If the size grows in the
// future, that implies that drawing occured since invalidated.
mStencilCmdCountInvalidated = mCommandBuffer.getRenderPassWriteCommandCount();
@@ -1834,157 +1985,53 @@
ExtendRenderPassInvalidateArea(invalidateArea, &mStencilInvalidateArea);
}
-angle::Result CommandBufferHelper::flushToPrimary(Context *context,
- PrimaryCommandBuffer *primary,
- const RenderPass *renderPass)
+angle::Result RenderPassCommandBufferHelper::flushToPrimary(Context *context,
+ PrimaryCommandBuffer *primary,
+ const RenderPass *renderPass)
{
- ANGLE_TRACE_EVENT0("gpu.angle", "CommandBufferHelper::flushToPrimary");
- ASSERT(!empty());
+ ANGLE_TRACE_EVENT0("gpu.angle", "RenderPassCommandBufferHelper::flushToPrimary");
+ ASSERT(mRenderPassStarted);
// Commands that are added to primary before beginRenderPass command
executeBarriers(context->getRenderer()->getFeatures(), primary);
- if (mIsRenderPassCommandBuffer)
- {
- ASSERT(renderPass != nullptr);
+ ASSERT(renderPass != nullptr);
- VkRenderPassBeginInfo beginInfo = {};
- beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- beginInfo.renderPass = renderPass->getHandle();
- beginInfo.framebuffer = mFramebuffer.getHandle();
- beginInfo.renderArea.offset.x = static_cast<uint32_t>(mRenderArea.x);
- beginInfo.renderArea.offset.y = static_cast<uint32_t>(mRenderArea.y);
- beginInfo.renderArea.extent.width = static_cast<uint32_t>(mRenderArea.width);
- beginInfo.renderArea.extent.height = static_cast<uint32_t>(mRenderArea.height);
- beginInfo.clearValueCount = static_cast<uint32_t>(mRenderPassDesc.attachmentCount());
- beginInfo.pClearValues = mClearValues.data();
+ VkRenderPassBeginInfo beginInfo = {};
+ beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ beginInfo.renderPass = renderPass->getHandle();
+ beginInfo.framebuffer = mFramebuffer.getHandle();
+ beginInfo.renderArea.offset.x = static_cast<uint32_t>(mRenderArea.x);
+ beginInfo.renderArea.offset.y = static_cast<uint32_t>(mRenderArea.y);
+ beginInfo.renderArea.extent.width = static_cast<uint32_t>(mRenderArea.width);
+ beginInfo.renderArea.extent.height = static_cast<uint32_t>(mRenderArea.height);
+ beginInfo.clearValueCount = static_cast<uint32_t>(mRenderPassDesc.attachmentCount());
+ beginInfo.pClearValues = mClearValues.data();
- // Run commands inside the RenderPass.
- constexpr VkSubpassContents kSubpassContents =
- vk::CommandBuffer::ExecutesInline() ? VK_SUBPASS_CONTENTS_INLINE
- : VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
+ // Run commands inside the RenderPass.
+ constexpr VkSubpassContents kSubpassContents =
+ RenderPassCommandBuffer::ExecutesInline() ? VK_SUBPASS_CONTENTS_INLINE
+ : VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
- primary->beginRenderPass(beginInfo, kSubpassContents);
- mCommandBuffer.executeCommands(primary);
- primary->endRenderPass();
- }
- else
- {
- ANGLE_TRY(mCommandBuffer.end(context));
- mCommandBuffer.executeCommands(primary);
- }
+ primary->beginRenderPass(beginInfo, kSubpassContents);
+ mCommandBuffer.executeCommands(primary);
+ primary->endRenderPass();
// Restart the command buffer.
return reset(context);
}
-void CommandBufferHelper::updateRenderPassForResolve(ContextVk *contextVk,
- Framebuffer *newFramebuffer,
- const RenderPassDesc &renderPassDesc)
+void RenderPassCommandBufferHelper::updateRenderPassForResolve(ContextVk *contextVk,
+ Framebuffer *newFramebuffer,
+ const RenderPassDesc &renderPassDesc)
{
ASSERT(newFramebuffer);
mFramebuffer.setHandle(newFramebuffer->getHandle());
mRenderPassDesc = renderPassDesc;
}
-// Helper functions used below
-char GetLoadOpShorthand(RenderPassLoadOp loadOp)
+void RenderPassCommandBufferHelper::resumeTransformFeedback()
{
- switch (loadOp)
- {
- case RenderPassLoadOp::Clear:
- return 'C';
- case RenderPassLoadOp::Load:
- return 'L';
- case RenderPassLoadOp::None:
- return 'N';
- default:
- return 'D';
- }
-}
-
-char GetStoreOpShorthand(RenderPassStoreOp storeOp)
-{
- switch (storeOp)
- {
- case RenderPassStoreOp::Store:
- return 'S';
- case RenderPassStoreOp::None:
- return 'N';
- default:
- return 'D';
- }
-}
-
-void CommandBufferHelper::addCommandDiagnostics(ContextVk *contextVk)
-{
- std::ostringstream out;
-
- out << "Memory Barrier: ";
- for (PipelineBarrier &barrier : mPipelineBarriers)
- {
- if (!barrier.isEmpty())
- {
- barrier.addDiagnosticsString(out);
- }
- }
- out << "\\l";
-
- if (mIsRenderPassCommandBuffer)
- {
- size_t attachmentCount = mRenderPassDesc.attachmentCount();
- size_t depthStencilAttachmentCount = mRenderPassDesc.hasDepthStencilAttachment() ? 1 : 0;
- size_t colorAttachmentCount = attachmentCount - depthStencilAttachmentCount;
-
- PackedAttachmentIndex attachmentIndexVk(0);
- std::string loadOps, storeOps;
-
- if (colorAttachmentCount > 0)
- {
- loadOps += " Color: ";
- storeOps += " Color: ";
-
- for (size_t i = 0; i < colorAttachmentCount; ++i)
- {
- loadOps += GetLoadOpShorthand(
- static_cast<RenderPassLoadOp>(mAttachmentOps[attachmentIndexVk].loadOp));
- storeOps += GetStoreOpShorthand(
- static_cast<RenderPassStoreOp>(mAttachmentOps[attachmentIndexVk].storeOp));
- ++attachmentIndexVk;
- }
- }
-
- if (depthStencilAttachmentCount > 0)
- {
- ASSERT(depthStencilAttachmentCount == 1);
-
- loadOps += " Depth/Stencil: ";
- storeOps += " Depth/Stencil: ";
-
- loadOps += GetLoadOpShorthand(
- static_cast<RenderPassLoadOp>(mAttachmentOps[attachmentIndexVk].loadOp));
- loadOps += GetLoadOpShorthand(
- static_cast<RenderPassLoadOp>(mAttachmentOps[attachmentIndexVk].stencilLoadOp));
-
- storeOps += GetStoreOpShorthand(
- static_cast<RenderPassStoreOp>(mAttachmentOps[attachmentIndexVk].storeOp));
- storeOps += GetStoreOpShorthand(
- static_cast<RenderPassStoreOp>(mAttachmentOps[attachmentIndexVk].stencilStoreOp));
- }
-
- if (attachmentCount > 0)
- {
- out << "LoadOp: " << loadOps << "\\l";
- out << "StoreOp: " << storeOps << "\\l";
- }
- }
- out << mCommandBuffer.dumpCommands("\\l");
- contextVk->addCommandBufferDiagnostics(out.str());
-}
-
-void CommandBufferHelper::resumeTransformFeedback()
-{
- ASSERT(mIsRenderPassCommandBuffer);
ASSERT(isTransformFeedbackStarted());
uint32_t numCounterBuffers =
@@ -1997,24 +2044,24 @@
mTransformFeedbackCounterBuffers.data(), nullptr);
}
-void CommandBufferHelper::pauseTransformFeedback()
+void RenderPassCommandBufferHelper::pauseTransformFeedback()
{
- ASSERT(mIsRenderPassCommandBuffer);
ASSERT(isTransformFeedbackStarted() && isTransformFeedbackActiveUnpaused());
mIsTransformFeedbackActiveUnpaused = false;
mCommandBuffer.endTransformFeedback(0, mValidTransformFeedbackBufferCount,
mTransformFeedbackCounterBuffers.data(), nullptr);
}
-void CommandBufferHelper::updateRenderPassColorClear(PackedAttachmentIndex colorIndexVk,
- const VkClearValue &clearValue)
+void RenderPassCommandBufferHelper::updateRenderPassColorClear(PackedAttachmentIndex colorIndexVk,
+ const VkClearValue &clearValue)
{
mAttachmentOps.setClearOp(colorIndexVk);
mClearValues.store(colorIndexVk, VK_IMAGE_ASPECT_COLOR_BIT, clearValue);
}
-void CommandBufferHelper::updateRenderPassDepthStencilClear(VkImageAspectFlags aspectFlags,
- const VkClearValue &clearValue)
+void RenderPassCommandBufferHelper::updateRenderPassDepthStencilClear(
+ VkImageAspectFlags aspectFlags,
+ const VkClearValue &clearValue)
{
// Don't overwrite prior clear values for individual aspects.
VkClearValue combinedClearValue = mClearValues[mDepthStencilAttachmentIndex];
@@ -2035,10 +2082,9 @@
mClearValues.storeNoDepthStencil(mDepthStencilAttachmentIndex, combinedClearValue);
}
-void CommandBufferHelper::growRenderArea(ContextVk *contextVk, const gl::Rectangle &newRenderArea)
+void RenderPassCommandBufferHelper::growRenderArea(ContextVk *contextVk,
+ const gl::Rectangle &newRenderArea)
{
- ASSERT(mIsRenderPassCommandBuffer);
-
// The render area is grown such that it covers both the previous and the new render areas.
gl::GetEnclosingRectangle(mRenderArea, newRenderArea, &mRenderArea);
@@ -2061,13 +2107,66 @@
}
}
-// CommandBufferRecycler implementation.
-CommandBufferRecycler::CommandBufferRecycler() = default;
-CommandBufferRecycler::~CommandBufferRecycler() = default;
-
-void CommandBufferRecycler::onDestroy()
+void RenderPassCommandBufferHelper::addCommandDiagnostics(ContextVk *contextVk)
{
- for (vk::CommandBufferHelper *commandBufferHelper : mCommandBufferHelperFreeList)
+ std::ostringstream out;
+ addCommandDiagnosticsCommon(&out);
+
+ size_t attachmentCount = mRenderPassDesc.attachmentCount();
+ size_t depthStencilAttachmentCount = mRenderPassDesc.hasDepthStencilAttachment() ? 1 : 0;
+ size_t colorAttachmentCount = attachmentCount - depthStencilAttachmentCount;
+
+ PackedAttachmentIndex attachmentIndexVk(0);
+ std::string loadOps, storeOps;
+
+ if (colorAttachmentCount > 0)
+ {
+ loadOps += " Color: ";
+ storeOps += " Color: ";
+
+ for (size_t i = 0; i < colorAttachmentCount; ++i)
+ {
+ loadOps += GetLoadOpShorthand(
+ static_cast<RenderPassLoadOp>(mAttachmentOps[attachmentIndexVk].loadOp));
+ storeOps += GetStoreOpShorthand(
+ static_cast<RenderPassStoreOp>(mAttachmentOps[attachmentIndexVk].storeOp));
+ ++attachmentIndexVk;
+ }
+ }
+
+ if (depthStencilAttachmentCount > 0)
+ {
+ ASSERT(depthStencilAttachmentCount == 1);
+
+ loadOps += " Depth/Stencil: ";
+ storeOps += " Depth/Stencil: ";
+
+ loadOps += GetLoadOpShorthand(
+ static_cast<RenderPassLoadOp>(mAttachmentOps[attachmentIndexVk].loadOp));
+ loadOps += GetLoadOpShorthand(
+ static_cast<RenderPassLoadOp>(mAttachmentOps[attachmentIndexVk].stencilLoadOp));
+
+ storeOps += GetStoreOpShorthand(
+ static_cast<RenderPassStoreOp>(mAttachmentOps[attachmentIndexVk].storeOp));
+ storeOps += GetStoreOpShorthand(
+ static_cast<RenderPassStoreOp>(mAttachmentOps[attachmentIndexVk].stencilStoreOp));
+ }
+
+ if (attachmentCount > 0)
+ {
+ out << "LoadOp: " << loadOps << "\\l";
+ out << "StoreOp: " << storeOps << "\\l";
+ }
+
+ out << mCommandBuffer.dumpCommands("\\l");
+ contextVk->addCommandBufferDiagnostics(out.str());
+}
+
+// CommandBufferRecycler implementation.
+template <typename CommandBufferT, typename CommandBufferHelperT>
+void CommandBufferRecycler<CommandBufferT, CommandBufferHelperT>::onDestroy()
+{
+ for (CommandBufferHelperT *commandBufferHelper : mCommandBufferHelperFreeList)
{
SafeDelete(commandBufferHelper);
}
@@ -2076,60 +2175,68 @@
ASSERT(mSecondaryCommandBuffersToReset.empty());
}
-angle::Result CommandBufferRecycler::getCommandBufferHelper(
+template void CommandBufferRecycler<OutsideRenderPassCommandBuffer,
+ OutsideRenderPassCommandBufferHelper>::onDestroy();
+template void
+CommandBufferRecycler<RenderPassCommandBuffer, RenderPassCommandBufferHelper>::onDestroy();
+
+template <typename CommandBufferT, typename CommandBufferHelperT>
+angle::Result CommandBufferRecycler<CommandBufferT, CommandBufferHelperT>::getCommandBufferHelper(
Context *context,
- bool hasRenderPass,
CommandPool *commandPool,
- CommandBufferHelper **commandBufferHelperOut)
+ CommandBufferHelperT **commandBufferHelperOut)
{
if (mCommandBufferHelperFreeList.empty())
{
- vk::CommandBufferHelper *commandBuffer = new vk::CommandBufferHelper();
- *commandBufferHelperOut = commandBuffer;
+ CommandBufferHelperT *commandBuffer = new CommandBufferHelperT();
+ *commandBufferHelperOut = commandBuffer;
- return commandBuffer->initialize(context, hasRenderPass, commandPool);
+ return commandBuffer->initialize(context, commandPool);
}
else
{
- vk::CommandBufferHelper *commandBuffer = mCommandBufferHelperFreeList.back();
+ CommandBufferHelperT *commandBuffer = mCommandBufferHelperFreeList.back();
mCommandBufferHelperFreeList.pop_back();
- commandBuffer->setHasRenderPass(hasRenderPass);
*commandBufferHelperOut = commandBuffer;
return angle::Result::Continue;
}
}
-void CommandBufferRecycler::recycleCommandBufferHelper(VkDevice device,
- vk::CommandBufferHelper **commandBuffer)
+template angle::Result
+CommandBufferRecycler<OutsideRenderPassCommandBuffer, OutsideRenderPassCommandBufferHelper>::
+ getCommandBufferHelper(Context *context,
+ CommandPool *commandPool,
+ OutsideRenderPassCommandBufferHelper **commandBufferHelperOut);
+template angle::Result
+CommandBufferRecycler<RenderPassCommandBuffer, RenderPassCommandBufferHelper>::
+ getCommandBufferHelper(Context *context,
+ CommandPool *commandPool,
+ RenderPassCommandBufferHelper **commandBufferHelperOut);
+
+template <typename CommandBufferT, typename CommandBufferHelperT>
+void CommandBufferRecycler<CommandBufferT, CommandBufferHelperT>::recycleCommandBufferHelper(
+ VkDevice device,
+ CommandBufferHelperT **commandBuffer)
{
ASSERT((*commandBuffer)->empty());
(*commandBuffer)->markOpen();
- recycleImpl(device, commandBuffer);
+ RecycleCommandBufferHelper(device, &mCommandBufferHelperFreeList, commandBuffer,
+ &(*commandBuffer)->getCommandBuffer());
}
-#if ANGLE_USE_CUSTOM_VULKAN_CMD_BUFFERS
-void CommandBufferRecycler::recycleImpl(VkDevice device, CommandBufferHelper **commandBuffer)
-{
- mCommandBufferHelperFreeList.push_back(*commandBuffer);
-}
-void CommandBufferRecycler::resetCommandBufferHelper(CommandBuffer &&commandBuffer)
-{
- commandBuffer.reset();
-}
-#else // ANGLE_USE_CUSTOM_VULKAN_CMD_BUFFERS
-void CommandBufferRecycler::recycleImpl(VkDevice device, CommandBufferHelper **commandBuffer)
-{
- CommandPool *pool = (*commandBuffer)->getCommandPool();
+template void
+CommandBufferRecycler<OutsideRenderPassCommandBuffer, OutsideRenderPassCommandBufferHelper>::
+ recycleCommandBufferHelper(VkDevice device,
+ OutsideRenderPassCommandBufferHelper **commandBuffer);
+template void CommandBufferRecycler<RenderPassCommandBuffer, RenderPassCommandBufferHelper>::
+ recycleCommandBufferHelper(VkDevice device, RenderPassCommandBufferHelper **commandBuffer);
- pool->freeCommandBuffers(device, 1, (*commandBuffer)->getCommandBuffer().ptr());
- (*commandBuffer)->getCommandBuffer().releaseHandle();
- SafeDelete(*commandBuffer);
-}
-void CommandBufferRecycler::resetCommandBufferHelper(CommandBuffer &&commandBuffer)
+template <typename CommandBufferT, typename CommandBufferHelperT>
+void CommandBufferRecycler<CommandBufferT, CommandBufferHelperT>::resetCommandBuffer(
+ CommandBufferT &&commandBuffer)
{
- mSecondaryCommandBuffersToReset.push_back(std::move(commandBuffer));
+ ResetSecondaryCommandBuffer(&mSecondaryCommandBuffersToReset, std::move(commandBuffer));
}
-#endif // ANGLE_USE_CUSTOM_VULKAN_CMD_BUFFERS
// DynamicBuffer implementation.
DynamicBuffer::DynamicBuffer()
@@ -3152,9 +3259,10 @@
mStatus = QueryStatus::Inactive;
}
+template <typename CommandBufferT>
void QueryHelper::beginQueryImpl(ContextVk *contextVk,
- CommandBuffer *resetCommandBuffer,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *resetCommandBuffer,
+ CommandBufferT *commandBuffer)
{
ASSERT(mStatus != QueryStatus::Active);
const QueryPool &queryPool = getQueryPool();
@@ -3163,7 +3271,8 @@
mStatus = QueryStatus::Active;
}
-void QueryHelper::endQueryImpl(ContextVk *contextVk, CommandBuffer *commandBuffer)
+template <typename CommandBufferT>
+void QueryHelper::endQueryImpl(ContextVk *contextVk, CommandBufferT *commandBuffer)
{
ASSERT(mStatus != QueryStatus::Ended);
commandBuffer->endQuery(getQueryPool(), mQuery);
@@ -3181,7 +3290,7 @@
RenderPassClosureReason::BeginNonRenderPassQuery));
}
- CommandBuffer *commandBuffer;
+ OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
ANGLE_TRY(contextVk->handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd));
@@ -3199,7 +3308,7 @@
RenderPassClosureReason::EndNonRenderPassQuery));
}
- CommandBuffer *commandBuffer;
+ OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
ANGLE_TRY(contextVk->handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd));
@@ -3227,10 +3336,10 @@
angle::Result QueryHelper::beginRenderPassQuery(ContextVk *contextVk)
{
- CommandBuffer *outsideRenderPassCommandBuffer;
+ OutsideRenderPassCommandBuffer *outsideRenderPassCommandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &outsideRenderPassCommandBuffer));
- CommandBuffer *renderPassCommandBuffer =
+ RenderPassCommandBuffer *renderPassCommandBuffer =
&contextVk->getStartedRenderPassCommands().getCommandBuffer();
beginQueryImpl(contextVk, outsideRenderPassCommandBuffer, renderPassCommandBuffer);
@@ -3254,7 +3363,7 @@
contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::TimestampQuery));
}
- CommandBuffer *commandBuffer;
+ OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
writeTimestamp(contextVk, commandBuffer);
return angle::Result::Continue;
@@ -3269,7 +3378,8 @@
primary->writeTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, queryPool, mQuery);
}
-void QueryHelper::writeTimestamp(ContextVk *contextVk, CommandBuffer *commandBuffer)
+void QueryHelper::writeTimestamp(ContextVk *contextVk,
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
const QueryPool &queryPool = getQueryPool();
resetQueryPoolImpl(contextVk, queryPool, commandBuffer);
@@ -3515,7 +3625,7 @@
access.onBufferTransferWrite(&mDynamicIndexBuffer);
access.onBufferTransferRead(sourceBuffer);
- vk::CommandBuffer *commandBuffer;
+ vk::OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
commandBuffer->copyBuffer(sourceBuffer->getBuffer(), mDynamicIndexBuffer.getBuffer(),
@@ -3675,7 +3785,9 @@
}
// static
-void LineLoopHelper::Draw(uint32_t count, uint32_t baseVertex, CommandBuffer *commandBuffer)
+void LineLoopHelper::Draw(uint32_t count,
+ uint32_t baseVertex,
+ RenderPassCommandBuffer *commandBuffer)
{
// Our first index is always 0 because that's how we set it up in createIndexBuffer*.
commandBuffer->drawIndexedBaseVertex(count, baseVertex);
@@ -4048,7 +4160,7 @@
access.onBufferTransferWrite(this);
}
- CommandBuffer *commandBuffer;
+ OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
commandBuffer->copyBuffer(srcBuffer->getBuffer(), getBuffer(), regionCount, copyRegions);
@@ -4129,7 +4241,8 @@
return invalidate(renderer, 0, getSize());
}
-void BufferHelper::changeQueue(uint32_t newQueueFamilyIndex, CommandBuffer *commandBuffer)
+void BufferHelper::changeQueue(uint32_t newQueueFamilyIndex,
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
VkBufferMemoryBarrier bufferMemoryBarrier = {};
bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
@@ -4150,7 +4263,7 @@
void BufferHelper::acquireFromExternal(ContextVk *contextVk,
uint32_t externalQueueFamilyIndex,
uint32_t rendererQueueFamilyIndex,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
mCurrentQueueFamilyIndex = externalQueueFamilyIndex;
@@ -4161,7 +4274,7 @@
void BufferHelper::releaseToExternal(ContextVk *contextVk,
uint32_t rendererQueueFamilyIndex,
uint32_t externalQueueFamilyIndex,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
ASSERT(mCurrentQueueFamilyIndex == rendererQueueFamilyIndex);
@@ -5280,7 +5393,7 @@
VkImageAspectFlags aspectMask,
ImageLayout newLayout,
uint32_t newQueueFamilyIndex,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
ASSERT(isQueueChangeNeccesary(newQueueFamilyIndex));
barrierImpl(context, aspectMask, newLayout, newQueueFamilyIndex, commandBuffer);
@@ -5290,7 +5403,7 @@
uint32_t externalQueueFamilyIndex,
uint32_t rendererQueueFamilyIndex,
ImageLayout currentLayout,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
// The image must be newly allocated or have been released to the external
// queue. If this is not the case, it's an application bug, so ASSERT might
@@ -5321,7 +5434,7 @@
uint32_t rendererQueueFamilyIndex,
uint32_t externalQueueFamilyIndex,
ImageLayout desiredLayout,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
ASSERT(mCurrentQueueFamilyIndex == rendererQueueFamilyIndex);
@@ -5422,12 +5535,11 @@
mCurrentQueueFamilyIndex = newQueueFamilyIndex;
}
-template void ImageHelper::barrierImpl<rx::vk::priv::CommandBuffer>(
- Context *context,
- VkImageAspectFlags aspectMask,
- ImageLayout newLayout,
- uint32_t newQueueFamilyIndex,
- rx::vk::priv::CommandBuffer *commandBuffer);
+template void ImageHelper::barrierImpl<priv::CommandBuffer>(Context *context,
+ VkImageAspectFlags aspectMask,
+ ImageLayout newLayout,
+ uint32_t newQueueFamilyIndex,
+ priv::CommandBuffer *commandBuffer);
bool ImageHelper::updateLayoutAndBarrier(Context *context,
VkImageAspectFlags aspectMask,
@@ -5514,7 +5626,7 @@
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
ASSERT(valid());
@@ -5545,7 +5657,7 @@
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
ASSERT(valid());
@@ -5574,7 +5686,7 @@
LevelIndex mipLevel,
uint32_t baseArrayLayer,
uint32_t layerCount,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
const angle::Format &angleFormat = getActualFormat();
bool isDepthStencil = angleFormat.depthBits > 0 || angleFormat.stencilBits > 0;
@@ -5632,7 +5744,7 @@
const gl::Extents ©Size,
const VkImageSubresourceLayers &srcSubresource,
const VkImageSubresourceLayers &dstSubresource,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
ASSERT(commandBuffer->valid() && srcImage->valid() && dstImage->valid());
@@ -5717,7 +5829,7 @@
region.dstSubresource.layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
dstImage);
- CommandBuffer *commandBuffer;
+ OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
ASSERT(srcImage->valid() && dstImage->valid());
@@ -5767,7 +5879,7 @@
access.onImageTransferWrite(baseLevelGL + 1, maxLevel.get(), 0, mLayerCount,
VK_IMAGE_ASPECT_COLOR_BIT, this);
- CommandBuffer *commandBuffer;
+ OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// We are able to use blitImage since the image format we are using supports it.
@@ -5870,7 +5982,7 @@
void ImageHelper::resolve(ImageHelper *dst,
const VkImageResolve ®ion,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
ASSERT(mCurrentLayout == ImageLayout::TransferSrc ||
mCurrentLayout == ImageLayout::SharedPresent);
@@ -6991,7 +7103,7 @@
access.onImageTransferWrite(levelGLStart, 1, kMaxContentDefinedLayerCount, 0, aspectFlags,
this);
- CommandBuffer *commandBuffer;
+ OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
for (gl::LevelIndex updateMipLevelGL = levelGLStart; updateMipLevelGL < levelGLEnd;
@@ -7556,7 +7668,7 @@
access.onBufferTransferWrite(dstBuffer);
access.onImageTransferRead(aspectFlags, this);
- CommandBuffer *commandBuffer;
+ OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
commandBuffer->copyImageToBuffer(mImage, getCurrentLayout(), bufferHandle, regionCount,
@@ -7729,7 +7841,7 @@
&resolvedImage.get());
}
- CommandBuffer *commandBuffer;
+ OutsideRenderPassCommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
const angle::Format *readFormat = &getActualFormat();
@@ -7797,7 +7909,7 @@
copyAccess.onBufferTransferWrite(&packBuffer);
copyAccess.onImageTransferRead(copyAspectFlags, src);
- CommandBuffer *copyCommandBuffer;
+ OutsideRenderPassCommandBuffer *copyCommandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(copyAccess, ©CommandBuffer));
ASSERT(packPixelsParams.outputPitch % readFormat->pixelBytes == 0);
@@ -7838,7 +7950,7 @@
CommandBufferAccess readbackAccess;
readbackAccess.onBufferTransferWrite(stagingBuffer);
- CommandBuffer *readbackCommandBuffer;
+ OutsideRenderPassCommandBuffer *readbackCommandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(readbackAccess, &readbackCommandBuffer));
readbackCommandBuffer->copyImageToBuffer(src->getImage(), src->getCurrentLayout(), bufferHandle,
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.h b/src/libANGLE/renderer/vulkan/vk_helpers.h
index 733877d..fd10664 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.h
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.h
@@ -450,7 +450,8 @@
// When syncing gpu/cpu time, main thread accesses primary directly
void writeTimestampToPrimary(ContextVk *contextVk, PrimaryCommandBuffer *primary);
// All other timestamp accesses should be made on outsideRenderPassCommandBuffer
- void writeTimestamp(ContextVk *contextVk, CommandBuffer *outsideRenderPassCommandBuffer);
+ void writeTimestamp(ContextVk *contextVk,
+ OutsideRenderPassCommandBuffer *outsideRenderPassCommandBuffer);
// Whether this query helper has generated and submitted any commands.
bool hasSubmittedCommands() const;
@@ -470,10 +471,12 @@
// Reset needs to always be done outside a render pass, which may be different from the
// passed-in command buffer (which could be the render pass').
+ template <typename CommandBufferT>
void beginQueryImpl(ContextVk *contextVk,
- CommandBuffer *resetCommandBuffer,
- CommandBuffer *commandBuffer);
- void endQueryImpl(ContextVk *contextVk, CommandBuffer *commandBuffer);
+ OutsideRenderPassCommandBuffer *resetCommandBuffer,
+ CommandBufferT *commandBuffer);
+ template <typename CommandBufferT>
+ void endQueryImpl(ContextVk *contextVk, CommandBufferT *commandBuffer);
template <typename CommandBufferT>
void resetQueryPoolImpl(ContextVk *contextVk,
const QueryPool &queryPool,
@@ -792,19 +795,19 @@
angle::Result invalidate(RendererVk *renderer);
angle::Result invalidate(RendererVk *renderer, VkDeviceSize offset, VkDeviceSize size);
- void changeQueue(uint32_t newQueueFamilyIndex, CommandBuffer *commandBuffer);
+ void changeQueue(uint32_t newQueueFamilyIndex, OutsideRenderPassCommandBuffer *commandBuffer);
// Performs an ownership transfer from an external instance or API.
void acquireFromExternal(ContextVk *contextVk,
uint32_t externalQueueFamilyIndex,
uint32_t rendererQueueFamilyIndex,
- CommandBuffer *commandBuffer);
+ OutsideRenderPassCommandBuffer *commandBuffer);
// Performs an ownership transfer to an external instance or API.
void releaseToExternal(ContextVk *contextVk,
uint32_t rendererQueueFamilyIndex,
uint32_t externalQueueFamilyIndex,
- CommandBuffer *commandBuffer);
+ OutsideRenderPassCommandBuffer *commandBuffer);
// Returns true if the image is owned by an external API or instance.
bool isReleasedToExternal() const;
@@ -936,24 +939,15 @@
// This value indicates an "infinite" CmdCount that is not valid for comparing
constexpr uint32_t kInfiniteCmdCount = 0xFFFFFFFF;
-// CommandBufferHelper (CBH) class wraps ANGLE's custom command buffer
-// class, SecondaryCommandBuffer. This provides a way to temporarily
-// store Vulkan commands that be can submitted in-line to a primary
-// command buffer at a later time.
-// The current plan is for the main ANGLE thread to record commands
-// into the CBH and then pass the CBH off to a worker thread that will
-// process the commands into a primary command buffer and then submit
-// those commands to the queue.
-class CommandBufferHelper : angle::NonCopyable
+// CommandBufferHelperCommon and derivatives OutsideRenderPassCommandBufferHelper and
+// RenderPassCommandBufferHelper wrap the outside/inside render pass secondary command buffers,
+// together with other information such as barriers to issue before the command buffer, tracking of
+// resource usages, etc. When the asyncCommandQueue feature is enabled, objects of these classes
+// are handed off to the worker thread to be executed on the primary command buffer.
+class CommandBufferHelperCommon : angle::NonCopyable
{
public:
- CommandBufferHelper();
- ~CommandBufferHelper();
-
- // General Functions (non-renderPass specific)
- angle::Result initialize(Context *context,
- bool isRenderPassCommandBuffer,
- CommandPool *commandPool);
+ CommandPool *getCommandPool() { return mCommandPool; }
void bufferRead(ContextVk *contextVk,
VkAccessFlags readAccessType,
@@ -965,6 +959,151 @@
AliasingMode aliasingMode,
BufferHelper *buffer);
+ bool usesBuffer(const BufferHelper &buffer) const;
+ bool usesBufferForWrite(const BufferHelper &buffer) const;
+ size_t getUsedBuffersCount() const { return mUsedBuffers.size(); }
+
+ void executeBarriers(const angle::FeaturesVk &features, PrimaryCommandBuffer *primary);
+
+ // The markOpen and markClosed functions are to aid in proper use of the *CommandBufferHelper.
+ // saw invalid use due to threading issues that can be easily caught by marking when it's safe
+ // (open) to write to the commandbuffer.
+#if !defined(ANGLE_ENABLE_ASSERTS)
+ void markOpen() {}
+ void markClosed() {}
+#endif
+
+ void setHasShaderStorageOutput() { mHasShaderStorageOutput = true; }
+ bool hasShaderStorageOutput() const { return mHasShaderStorageOutput; }
+
+ bool hasGLMemoryBarrierIssued() const { return mHasGLMemoryBarrierIssued; }
+
+ // Dumping the command stream is disabled by default.
+ static constexpr bool kEnableCommandStreamDiagnostics = false;
+
+ protected:
+ CommandBufferHelperCommon();
+ ~CommandBufferHelperCommon();
+
+ void initializeImpl(Context *context, CommandPool *commandPool);
+
+ void resetImpl();
+
+ void imageReadImpl(ContextVk *contextVk,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout,
+ ImageHelper *image);
+ void imageWriteImpl(ContextVk *contextVk,
+ gl::LevelIndex level,
+ uint32_t layerStart,
+ uint32_t layerCount,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout,
+ AliasingMode aliasingMode,
+ ImageHelper *image);
+
+ void updateImageLayoutAndBarrier(Context *context,
+ ImageHelper *image,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout);
+
+ void addCommandDiagnosticsCommon(std::ostringstream *out);
+
+ // Allocator used by this class. Using a pool allocator per CBH to avoid threading issues
+ // that occur w/ shared allocator between multiple CBHs.
+ angle::PoolAllocator mAllocator;
+
+ // Barriers to be executed before the command buffer.
+ PipelineBarrierArray mPipelineBarriers;
+ PipelineStagesMask mPipelineBarrierMask;
+
+ // The command pool *CommandBufferHelper::mCommandBuffer is allocated from. Only used with
+ // Vulkan secondary command buffers (as opposed to ANGLE's SecondaryCommandBuffer).
+ CommandPool *mCommandPool;
+
+ // Whether the command buffers contains any draw/dispatch calls that possibly output data
+ // through storage buffers and images. This is used to determine whether glMemoryBarrier*
+ // should flush the command buffer.
+ bool mHasShaderStorageOutput;
+ // Whether glMemoryBarrier has been called while commands are recorded in this command buffer.
+ // This is used to know when to check and potentially flush the command buffer if storage
+ // buffers and images are used in it.
+ bool mHasGLMemoryBarrierIssued;
+
+ // Tracks resources used in the command buffer.
+ // For Buffers, we track the read/write access type so we can enable simultaneous reads.
+ angle::FastIntegerMap<BufferAccess> mUsedBuffers;
+};
+
+class OutsideRenderPassCommandBufferHelper final : public CommandBufferHelperCommon
+{
+ public:
+ OutsideRenderPassCommandBufferHelper();
+ ~OutsideRenderPassCommandBufferHelper();
+
+ angle::Result initialize(Context *context, CommandPool *commandPool);
+
+ angle::Result reset(Context *context);
+
+ OutsideRenderPassCommandBuffer &getCommandBuffer() { return mCommandBuffer; }
+
+ bool empty() const { return mCommandBuffer.empty(); }
+
+#if defined(ANGLE_ENABLE_ASSERTS)
+ void markOpen() { mCommandBuffer.open(); }
+ void markClosed() { mCommandBuffer.close(); }
+#endif
+
+ void imageRead(ContextVk *contextVk,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout,
+ ImageHelper *image);
+ void imageWrite(ContextVk *contextVk,
+ gl::LevelIndex level,
+ uint32_t layerStart,
+ uint32_t layerCount,
+ VkImageAspectFlags aspectFlags,
+ ImageLayout imageLayout,
+ AliasingMode aliasingMode,
+ ImageHelper *image);
+
+ angle::Result flushToPrimary(Context *context, PrimaryCommandBuffer *primary);
+
+ void setGLMemoryBarrierIssued()
+ {
+ if (!mCommandBuffer.empty())
+ {
+ mHasGLMemoryBarrierIssued = true;
+ }
+ }
+
+ void addCommandDiagnostics(ContextVk *contextVk);
+
+ private:
+ angle::Result initializeCommandBuffer(Context *context);
+
+ OutsideRenderPassCommandBuffer mCommandBuffer;
+};
+
+class RenderPassCommandBufferHelper final : public CommandBufferHelperCommon
+{
+ public:
+ RenderPassCommandBufferHelper();
+ ~RenderPassCommandBufferHelper();
+
+ angle::Result initialize(Context *context, CommandPool *commandPool);
+
+ angle::Result reset(Context *context);
+
+ RenderPassCommandBuffer &getCommandBuffer() { return mCommandBuffer; }
+
+ bool empty() const { return !started(); }
+
+#if defined(ANGLE_ENABLE_ASSERTS)
+ void markOpen() { mCommandBuffer.open(); }
+ void markClosed() { mCommandBuffer.close(); }
+#endif
+
void imageRead(ContextVk *contextVk,
VkImageAspectFlags aspectFlags,
ImageLayout imageLayout,
@@ -989,44 +1128,13 @@
ImageHelper *image,
ImageHelper *resolveImage);
- CommandBuffer &getCommandBuffer() { return mCommandBuffer; }
- CommandPool *getCommandPool() { return mCommandPool; }
+ bool usesImage(const ImageHelper &image) const;
angle::Result flushToPrimary(Context *context,
PrimaryCommandBuffer *primary,
const RenderPass *renderPass);
- void executeBarriers(const angle::FeaturesVk &features, PrimaryCommandBuffer *primary);
-
- void setHasRenderPass(bool hasRenderPass) { mIsRenderPassCommandBuffer = hasRenderPass; }
-
- // The markOpen and markClosed functions are to aid in proper use of the CommandBufferHelper.
- // saw invalid use due to threading issues that can be easily caught by marking when it's safe
- // (open) to write to the commandbuffer.
-#if defined(ANGLE_ENABLE_ASSERTS)
- void markOpen() { mCommandBuffer.open(); }
- void markClosed() { mCommandBuffer.close(); }
-#else
- void markOpen() {}
- void markClosed() {}
-#endif
-
- angle::Result reset(Context *context);
-
- // Returns true if we have no work to execute. For renderpass command buffer, even if the
- // underlying command buffer is empty, we may still have a renderpass with an empty command
- // buffer just to do the clear.
- bool empty() const
- {
- return mIsRenderPassCommandBuffer ? !mRenderPassStarted : mCommandBuffer.empty();
- }
- // RenderPass related functions. This is equivalent to !empty(), but only when you know this is
- // a RenderPass command buffer
- bool started() const
- {
- ASSERT(mIsRenderPassCommandBuffer);
- return mRenderPassStarted;
- }
+ bool started() const { return mRenderPassStarted; }
// Finalize the layout if image has any deferred layout transition.
void finalizeImageLayout(Context *context, const ImageHelper *image);
@@ -1039,7 +1147,7 @@
const vk::PackedAttachmentCount colorAttachmentCount,
const PackedAttachmentIndex depthStencilAttachmentIndex,
const PackedClearValuesArray &clearValues,
- CommandBuffer **commandBufferOut);
+ RenderPassCommandBuffer **commandBufferOut);
angle::Result endRenderPass(ContextVk *contextVk);
@@ -1059,7 +1167,6 @@
bool hasWriteAfterInvalidate(uint32_t cmdCountInvalidated, uint32_t cmdCountDisabled)
{
- ASSERT(mIsRenderPassCommandBuffer);
return (cmdCountInvalidated != kInfiniteCmdCount &&
std::min(cmdCountDisabled, mCommandBuffer.getRenderPassWriteCommandCount()) !=
cmdCountInvalidated);
@@ -1067,7 +1174,6 @@
bool isInvalidated(uint32_t cmdCountInvalidated, uint32_t cmdCountDisabled)
{
- ASSERT(mIsRenderPassCommandBuffer);
return cmdCountInvalidated != kInfiniteCmdCount &&
std::min(cmdCountDisabled, mCommandBuffer.getRenderPassWriteCommandCount()) ==
cmdCountInvalidated;
@@ -1078,11 +1184,7 @@
void updateRenderPassDepthStencilClear(VkImageAspectFlags aspectFlags,
const VkClearValue &clearValue);
- const gl::Rectangle &getRenderArea() const
- {
- ASSERT(mIsRenderPassCommandBuffer);
- return mRenderArea;
- }
+ const gl::Rectangle &getRenderArea() const { return mRenderArea; }
// If render pass is started with a small render area due to a small scissor, and if a new
// larger scissor is specified, grow the render area to accomodate it.
@@ -1095,25 +1197,12 @@
uint32_t getAndResetCounter()
{
- ASSERT(mIsRenderPassCommandBuffer);
uint32_t count = mCounter;
mCounter = 0;
return count;
}
- VkFramebuffer getFramebufferHandle() const
- {
- ASSERT(mIsRenderPassCommandBuffer);
- return mFramebuffer.getHandle();
- }
-
- bool usesBuffer(const BufferHelper &buffer) const;
- bool usesBufferForWrite(const BufferHelper &buffer) const;
- bool usesImageInRenderPass(const ImageHelper &image) const;
- size_t getUsedBuffersCount() const { return mUsedBuffers.size(); }
-
- // Dumping the command stream is disabled by default.
- static constexpr bool kEnableCommandStreamDiagnostics = false;
+ VkFramebuffer getFramebufferHandle() const { return mFramebuffer.getHandle(); }
void onDepthAccess(ResourceAccess access);
void onStencilAccess(ResourceAccess access);
@@ -1130,25 +1219,19 @@
VK_ATTACHMENT_LOAD_OP_CLEAR;
}
- void addCommandDiagnostics(ContextVk *contextVk);
-
const RenderPassDesc &getRenderPassDesc() const { return mRenderPassDesc; }
const AttachmentOpsArray &getAttachmentOps() const { return mAttachmentOps; }
- bool hasRenderPass() const { return mIsRenderPassCommandBuffer; }
-
- void setHasShaderStorageOutput() { mHasShaderStorageOutput = true; }
- bool hasShaderStorageOutput() const { return mHasShaderStorageOutput; }
+ void setImageOptimizeForPresent(ImageHelper *image) { mImageOptimizeForPresent = image; }
void setGLMemoryBarrierIssued()
{
- if (!empty())
+ if (mRenderPassStarted)
{
mHasGLMemoryBarrierIssued = true;
}
}
- bool hasGLMemoryBarrierIssued() const { return mHasGLMemoryBarrierIssued; }
- void setImageOptimizeForPresent(ImageHelper *image) { mImageOptimizeForPresent = image; }
+ void addCommandDiagnostics(ContextVk *contextVk);
private:
angle::Result initializeCommandBuffer(Context *context);
@@ -1175,22 +1258,7 @@
RenderPassStoreOp *storeOp);
void finalizeDepthStencilImageLayoutAndLoadStore(Context *context);
- void updateImageLayoutAndBarrier(Context *context,
- ImageHelper *image,
- VkImageAspectFlags aspectFlags,
- ImageLayout imageLayout);
-
- // Allocator used by this class. Using a pool allocator per CBH to avoid threading issues
- // that occur w/ shared allocator between multiple CBHs.
- angle::PoolAllocator mAllocator;
-
- // General state (non-renderPass related)
- PipelineBarrierArray mPipelineBarriers;
- PipelineStagesMask mPipelineBarrierMask;
- CommandBuffer mCommandBuffer;
- // The command pool mCommandBuffer is allocated from. Only used with Vulkan secondary command
- // buffers (as opposed to ANGLE's SecondaryCommandBuffer).
- CommandPool *mCommandPool;
+ RenderPassCommandBuffer mCommandBuffer;
// RenderPass state
uint32_t mCounter;
@@ -1207,17 +1275,6 @@
bool mRebindTransformFeedbackBuffers;
bool mIsTransformFeedbackActiveUnpaused;
- bool mIsRenderPassCommandBuffer;
-
- // Whether the command buffers contains any draw/dispatch calls that possibly output data
- // through storage buffers and images. This is used to determine whether glMemoryBarrier*
- // should flush the command buffer.
- bool mHasShaderStorageOutput;
- // Whether glMemoryBarrier has been called while commands are recorded in this command buffer.
- // This is used to know when to check and potentially flush the command buffer if storage
- // buffers and images are used in it.
- bool mHasGLMemoryBarrierIssued;
-
// State tracking for the maximum (Write been the highest) depth access during the entire
// renderpass. Note that this does not include VK_ATTACHMENT_LOAD_OP_CLEAR which is tracked
// separately. This is done this way to allow clear op to being optimized out when we find out
@@ -1239,9 +1296,8 @@
PackedAttachmentIndex mDepthStencilAttachmentIndex;
// Tracks resources used in the command buffer.
- // For Buffers, we track the read/write access type so we can enable simultaneous reads.
- // Images have unique layouts unlike buffers therefore we don't support multi-read.
- angle::FastIntegerMap<BufferAccess> mUsedBuffers;
+ // Images have unique layouts unlike buffers therefore we can't support simultaneous reads with
+ // different layout.
angle::FastIntegerSet mRenderPassUsedImages;
ImageHelper *mDepthStencilImage;
@@ -1262,33 +1318,31 @@
// The following class helps support both Vulkan and ANGLE secondary command buffers by
// encapsulating their differences.
+template <typename CommandBufferT, typename CommandBufferHelperT>
class CommandBufferRecycler
{
public:
- CommandBufferRecycler();
- ~CommandBufferRecycler();
+ CommandBufferRecycler() = default;
+ ~CommandBufferRecycler() = default;
void onDestroy();
angle::Result getCommandBufferHelper(Context *context,
- bool hasRenderPass,
CommandPool *commandPool,
- CommandBufferHelper **commandBufferHelperOut);
+ CommandBufferHelperT **commandBufferHelperOut);
- void recycleCommandBufferHelper(VkDevice device, CommandBufferHelper **commandBuffer);
+ void recycleCommandBufferHelper(VkDevice device, CommandBufferHelperT **commandBuffer);
- void resetCommandBufferHelper(CommandBuffer &&commandBuffer);
+ void resetCommandBuffer(CommandBufferT &&commandBuffer);
- SecondaryCommandBufferList &&getCommandBuffersToReset()
+ std::vector<CommandBufferT> &&releaseCommandBuffersToReset()
{
return std::move(mSecondaryCommandBuffersToReset);
}
private:
- void recycleImpl(VkDevice device, CommandBufferHelper **commandBuffer);
-
- std::vector<vk::CommandBufferHelper *> mCommandBufferHelperFreeList;
- SecondaryCommandBufferList mSecondaryCommandBuffersToReset;
+ std::vector<CommandBufferHelperT *> mCommandBufferHelperFreeList;
+ std::vector<CommandBufferT> mSecondaryCommandBuffersToReset;
};
// Imagine an image going through a few layout transitions:
@@ -1657,7 +1711,7 @@
const gl::Extents ©Size,
const VkImageSubresourceLayers &srcSubresources,
const VkImageSubresourceLayers &dstSubresources,
- CommandBuffer *commandBuffer);
+ OutsideRenderPassCommandBuffer *commandBuffer);
static angle::Result CopyImageSubData(const gl::Context *context,
ImageHelper *srcImage,
@@ -1681,7 +1735,9 @@
// Resolve this image into a destination image. This image should be in the TransferSrc layout.
// The destination image is automatically transitioned into TransferDst.
- void resolve(ImageHelper *dst, const VkImageResolve ®ion, CommandBuffer *commandBuffer);
+ void resolve(ImageHelper *dst,
+ const VkImageResolve ®ion,
+ OutsideRenderPassCommandBuffer *commandBuffer);
// Data staging
void removeSingleSubresourceStagedUpdates(ContextVk *contextVk,
@@ -1800,7 +1856,7 @@
void recordWriteBarrier(Context *context,
VkImageAspectFlags aspectMask,
ImageLayout newLayout,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
barrierImpl(context, aspectMask, newLayout, mCurrentQueueFamilyIndex, commandBuffer);
}
@@ -1818,7 +1874,7 @@
void recordReadBarrier(Context *context,
VkImageAspectFlags aspectMask,
ImageLayout newLayout,
- CommandBuffer *commandBuffer)
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
if (!isReadBarrierNecessary(newLayout))
{
@@ -1837,7 +1893,7 @@
VkImageAspectFlags aspectMask,
ImageLayout newLayout,
uint32_t newQueueFamilyIndex,
- CommandBuffer *commandBuffer);
+ OutsideRenderPassCommandBuffer *commandBuffer);
// Returns true if barrier has been generated
bool updateLayoutAndBarrier(Context *context,
@@ -1850,14 +1906,14 @@
uint32_t externalQueueFamilyIndex,
uint32_t rendererQueueFamilyIndex,
ImageLayout currentLayout,
- CommandBuffer *commandBuffer);
+ OutsideRenderPassCommandBuffer *commandBuffer);
// Performs an ownership transfer to an external instance or API.
void releaseToExternal(ContextVk *contextVk,
uint32_t rendererQueueFamilyIndex,
uint32_t externalQueueFamilyIndex,
ImageLayout desiredLayout,
- CommandBuffer *commandBuffer);
+ OutsideRenderPassCommandBuffer *commandBuffer);
// Returns true if the image is owned by an external API or instance.
bool isReleasedToExternal() const;
@@ -2093,14 +2149,14 @@
LevelIndex mipLevel,
uint32_t baseArrayLayer,
uint32_t layerCount,
- CommandBuffer *commandBuffer);
+ OutsideRenderPassCommandBuffer *commandBuffer);
void clearColor(const VkClearColorValue &color,
LevelIndex baseMipLevelVk,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
- CommandBuffer *commandBuffer);
+ OutsideRenderPassCommandBuffer *commandBuffer);
void clearDepthStencil(VkImageAspectFlags clearAspectFlags,
const VkClearDepthStencilValue &depthStencil,
@@ -2108,7 +2164,7 @@
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
- CommandBuffer *commandBuffer);
+ OutsideRenderPassCommandBuffer *commandBuffer);
angle::Result clearEmulatedChannels(ContextVk *contextVk,
VkColorComponentFlags colorMaskFlags,
@@ -2235,6 +2291,11 @@
gl::TexLevelArray<LevelContentDefinedMask> mStencilContentDefined;
};
+ANGLE_INLINE bool RenderPassCommandBufferHelper::usesImage(const ImageHelper &image) const
+{
+ return mRenderPassUsedImages.contains(image.getImageSerial().getValue());
+}
+
// A vector of image views, such as one per level or one per layer.
using ImageViewVector = std::vector<ImageView>;
@@ -2668,12 +2729,6 @@
angle::PackedEnumMap<HandleType, uint32_t> mAllocatedCounts;
};
-ANGLE_INLINE bool CommandBufferHelper::usesImageInRenderPass(const ImageHelper &image) const
-{
- 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
@@ -2839,7 +2894,7 @@
void release(ContextVk *contextVk);
void destroy(RendererVk *renderer);
- static void Draw(uint32_t count, uint32_t baseVertex, CommandBuffer *commandBuffer);
+ static void Draw(uint32_t count, uint32_t baseVertex, RenderPassCommandBuffer *commandBuffer);
private:
BufferHelper mDynamicIndexBuffer;
diff --git a/src/libANGLE/renderer/vulkan/vk_utils.h b/src/libANGLE/renderer/vulkan/vk_utils.h
index eabc62e..559fe33 100644
--- a/src/libANGLE/renderer/vulkan/vk_utils.h
+++ b/src/libANGLE/renderer/vulkan/vk_utils.h
@@ -202,12 +202,24 @@
class RenderPassDesc;
#if ANGLE_USE_CUSTOM_VULKAN_CMD_BUFFERS
-using CommandBuffer = priv::SecondaryCommandBuffer;
+using OutsideRenderPassCommandBuffer = priv::SecondaryCommandBuffer;
+using RenderPassCommandBuffer = priv::SecondaryCommandBuffer;
#else
-using CommandBuffer = VulkanSecondaryCommandBuffer;
+using OutsideRenderPassCommandBuffer = VulkanSecondaryCommandBuffer;
+using RenderPassCommandBuffer = VulkanSecondaryCommandBuffer;
#endif
-using SecondaryCommandBufferList = std::vector<CommandBuffer>;
+struct SecondaryCommandBufferList
+{
+ std::vector<OutsideRenderPassCommandBuffer> outsideRenderPassCommandBuffers;
+ std::vector<RenderPassCommandBuffer> renderPassCommandBuffers;
+};
+
+struct SecondaryCommandPools
+{
+ CommandPool outsideRenderPassPool;
+ CommandPool renderPassPool;
+};
VkImageAspectFlags GetDepthStencilAspectFlags(const angle::Format &format);
VkImageAspectFlags GetFormatAspectFlags(const angle::Format &format);