Commit 562602a3 by Tobin Ehlis Committed by Commit Bot

Vulkan: Move CommandBufferHelper to vk_helpers.h

Pull CommandBufferHelper class out of ContextVk.h/cpp and move it to vk_helpers.h/cpp. This is the natural place for it as it's a helper class. Also, this class is planned to be the interface between the main and worker threads so moving it to vk_helpers makes it easy to share between Context and Renderer. Bug: b/154030403 Change-Id: Ie5eeb864164a3787f800905ae885027834bd1a08 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2182177Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Tobin Ehlis <tobine@google.com>
parent bcd2c592
...@@ -124,9 +124,6 @@ constexpr size_t kDriverUniformsAllocatorPageSize = 4 * 1024; ...@@ -124,9 +124,6 @@ constexpr size_t kDriverUniformsAllocatorPageSize = 4 * 1024;
constexpr size_t kInFlightCommandsLimit = 100u; constexpr size_t kInFlightCommandsLimit = 100u;
// Dumping the command stream is disabled by default.
constexpr bool kEnableCommandStreamDiagnostics = false;
void InitializeSubmitInfo(VkSubmitInfo *submitInfo, void InitializeSubmitInfo(VkSubmitInfo *submitInfo,
const vk::PrimaryCommandBuffer &commandBuffer, const vk::PrimaryCommandBuffer &commandBuffer,
const std::vector<VkSemaphore> &waitSemaphores, const std::vector<VkSemaphore> &waitSemaphores,
...@@ -191,30 +188,6 @@ void ApplySampleCoverage(const gl::State &glState, ...@@ -191,30 +188,6 @@ void ApplySampleCoverage(const gl::State &glState,
*maskOut &= coverageMask; *maskOut &= coverageMask;
} }
char GetLoadOpShorthand(uint32_t loadOp)
{
switch (loadOp)
{
case VK_ATTACHMENT_LOAD_OP_CLEAR:
return 'C';
case VK_ATTACHMENT_LOAD_OP_LOAD:
return 'L';
default:
return 'D';
}
}
char GetStoreOpShorthand(uint32_t storeOp)
{
switch (storeOp)
{
case VK_ATTACHMENT_STORE_OP_STORE:
return 'S';
default:
return 'D';
}
}
// When an Android surface is rotated differently than the device's native orientation, ANGLE must // When an Android surface is rotated differently than the device's native orientation, ANGLE must
// rotate gl_Position in the vertex shader. The following are the rotation matrices used. // rotate gl_Position in the vertex shader. The following are the rotation matrices used.
// //
...@@ -1301,7 +1274,7 @@ angle::Result ContextVk::handleDirtyComputePipeline(const gl::Context *context, ...@@ -1301,7 +1274,7 @@ angle::Result ContextVk::handleDirtyComputePipeline(const gl::Context *context,
} }
ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl( ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
CommandBufferHelper *commandBufferHelper) vk::CommandBufferHelper *commandBufferHelper)
{ {
const gl::ProgramExecutable *executable = mState.getProgramExecutable(); const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable); ASSERT(executable);
...@@ -1424,7 +1397,7 @@ angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(const gl::Context *conte ...@@ -1424,7 +1397,7 @@ angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(const gl::Context *conte
ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl( ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
const gl::Context *context, const gl::Context *context,
CommandBufferHelper *commandBufferHelper) vk::CommandBufferHelper *commandBufferHelper)
{ {
const gl::ProgramExecutable *executable = mState.getProgramExecutable(); const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable); ASSERT(executable);
...@@ -1581,7 +1554,7 @@ angle::Result ContextVk::submitFrame(const VkSubmitInfo &submitInfo, ...@@ -1581,7 +1554,7 @@ angle::Result ContextVk::submitFrame(const VkSubmitInfo &submitInfo,
renderPassCount->add(mRenderPassCommands.getAndResetCounter()); renderPassCount->add(mRenderPassCommands.getAndResetCounter());
renderPassCount->next(); renderPassCount->next();
if (kEnableCommandStreamDiagnostics) if (vk::CommandBufferHelper::kEnableCommandStreamDiagnostics)
{ {
dumpCommandStreamDiagnostics(); dumpCommandStreamDiagnostics();
} }
...@@ -3646,7 +3619,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -3646,7 +3619,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
} }
angle::Result ContextVk::updateActiveImages(const gl::Context *context, angle::Result ContextVk::updateActiveImages(const gl::Context *context,
CommandBufferHelper *commandBufferHelper) vk::CommandBufferHelper *commandBufferHelper)
{ {
const gl::State &glState = mState; const gl::State &glState = mState;
const gl::ProgramExecutable *executable = glState.getProgramExecutable(); const gl::ProgramExecutable *executable = glState.getProgramExecutable();
...@@ -4378,324 +4351,4 @@ bool ContextVk::isRobustResourceInitEnabled() const ...@@ -4378,324 +4351,4 @@ bool ContextVk::isRobustResourceInitEnabled() const
return mState.isRobustResourceInitEnabled(); return mState.isRobustResourceInitEnabled();
} }
CommandBufferHelper::CommandBufferHelper(bool hasRenderPass)
: mImageBarrierSrcStageMask(0),
mImageBarrierDstStageMask(0),
mGlobalMemoryBarrierSrcAccess(0),
mGlobalMemoryBarrierDstAccess(0),
mGlobalMemoryBarrierSrcStages(0),
mGlobalMemoryBarrierDstStages(0),
mCounter(0),
mClearValues{},
mRenderPassStarted(false),
mTransformFeedbackCounterBuffers{},
mValidTransformFeedbackBufferCount(0),
mRebindTransformFeedbackBuffers(false),
mIsRenderPassCommandBuffer(hasRenderPass)
{}
CommandBufferHelper::~CommandBufferHelper()
{
mFramebuffer.setHandle(VK_NULL_HANDLE);
}
void CommandBufferHelper::initialize(angle::PoolAllocator *poolAllocator)
{
mCommandBuffer.initialize(poolAllocator);
}
void CommandBufferHelper::bufferRead(vk::ResourceUseList *resourceUseList,
VkAccessFlags readAccessType,
VkPipelineStageFlags readStage,
vk::BufferHelper *buffer)
{
buffer->retain(resourceUseList);
buffer->updateReadBarrier(readAccessType, &mGlobalMemoryBarrierSrcAccess,
&mGlobalMemoryBarrierDstAccess, readStage,
&mGlobalMemoryBarrierSrcStages, &mGlobalMemoryBarrierDstStages);
}
void CommandBufferHelper::bufferWrite(vk::ResourceUseList *resourceUseList,
VkAccessFlags writeAccessType,
VkPipelineStageFlags writeStage,
vk::BufferHelper *buffer)
{
buffer->retain(resourceUseList);
buffer->updateWriteBarrier(writeAccessType, &mGlobalMemoryBarrierSrcAccess,
&mGlobalMemoryBarrierDstAccess, writeStage,
&mGlobalMemoryBarrierSrcStages, &mGlobalMemoryBarrierDstStages);
}
void CommandBufferHelper::imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkImageMemoryBarrier &imageMemoryBarrier)
{
ASSERT(imageMemoryBarrier.pNext == nullptr);
mImageBarrierSrcStageMask |= srcStageMask;
mImageBarrierDstStageMask |= dstStageMask;
mImageMemoryBarriers.push_back(imageMemoryBarrier);
}
void CommandBufferHelper::imageRead(vk::ResourceUseList *resourceUseList,
VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image)
{
image->retain(resourceUseList);
if (image->isLayoutChangeNecessary(imageLayout))
{
image->changeLayout(aspectFlags, imageLayout, this);
}
}
void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList,
VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image)
{
image->retain(resourceUseList);
image->changeLayout(aspectFlags, imageLayout, this);
}
void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary)
{
if (mImageMemoryBarriers.empty() && mGlobalMemoryBarrierSrcAccess == 0)
{
return;
}
VkPipelineStageFlags srcStages = 0;
VkPipelineStageFlags dstStages = 0;
VkMemoryBarrier memoryBarrier = {};
uint32_t memoryBarrierCount = 0;
if (mGlobalMemoryBarrierSrcAccess != 0)
{
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.srcAccessMask = mGlobalMemoryBarrierSrcAccess;
memoryBarrier.dstAccessMask = mGlobalMemoryBarrierDstAccess;
memoryBarrierCount++;
srcStages |= mGlobalMemoryBarrierSrcStages;
dstStages |= mGlobalMemoryBarrierDstStages;
mGlobalMemoryBarrierSrcAccess = 0;
mGlobalMemoryBarrierDstAccess = 0;
mGlobalMemoryBarrierSrcStages = 0;
mGlobalMemoryBarrierDstStages = 0;
}
srcStages |= mImageBarrierSrcStageMask;
dstStages |= mImageBarrierDstStageMask;
primary->pipelineBarrier(srcStages, dstStages, 0, memoryBarrierCount, &memoryBarrier, 0,
nullptr, static_cast<uint32_t>(mImageMemoryBarriers.size()),
mImageMemoryBarriers.data());
mImageMemoryBarriers.clear();
mImageBarrierSrcStageMask = 0;
mImageBarrierDstStageMask = 0;
}
void CommandBufferHelper::beginRenderPass(const vk::Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps,
const vk::ClearValuesArray &clearValues,
vk::CommandBuffer **commandBufferOut)
{
ASSERT(mIsRenderPassCommandBuffer);
ASSERT(empty());
mRenderPassDesc = renderPassDesc;
mAttachmentOps = renderPassAttachmentOps;
mFramebuffer.setHandle(framebuffer.getHandle());
mRenderArea = renderArea;
mClearValues = clearValues;
*commandBufferOut = &mCommandBuffer;
mRenderPassStarted = true;
mCounter++;
}
void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount,
const VkBuffer *counterBuffers,
bool rebindBuffer)
{
ASSERT(mIsRenderPassCommandBuffer);
mValidTransformFeedbackBufferCount = static_cast<uint32_t>(validBufferCount);
mRebindTransformFeedbackBuffers = rebindBuffer;
for (size_t index = 0; index < validBufferCount; index++)
{
mTransformFeedbackCounterBuffers[index] = counterBuffers[index];
}
}
angle::Result CommandBufferHelper::flushToPrimary(ContextVk *contextVk,
vk::PrimaryCommandBuffer *primary)
{
ASSERT(!empty());
if (kEnableCommandStreamDiagnostics)
{
addCommandDiagnostics(contextVk);
}
// Commands that are added to primary before beginRenderPass command
executeBarriers(primary);
if (mIsRenderPassCommandBuffer)
{
mCommandBuffer.executeQueuedResetQueryPoolCommands(primary->getHandle());
// Pull a RenderPass from the cache.
RenderPassCache &renderPassCache = contextVk->getRenderPassCache();
Serial serial = contextVk->getCurrentQueueSerial();
vk::RenderPass *renderPass = nullptr;
ANGLE_TRY(renderPassCache.getRenderPassWithOps(contextVk, serial, mRenderPassDesc,
mAttachmentOps, &renderPass));
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.
primary->beginRenderPass(beginInfo, VK_SUBPASS_CONTENTS_INLINE);
mCommandBuffer.executeCommands(primary->getHandle());
primary->endRenderPass();
if (mValidTransformFeedbackBufferCount != 0)
{
// Would be better to accumulate this barrier using the command APIs.
// TODO: Clean thus up before we close http://anglebug.com/3206
VkBufferMemoryBarrier bufferBarrier = {};
bufferBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufferBarrier.pNext = nullptr;
bufferBarrier.srcAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
bufferBarrier.dstAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT;
bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferBarrier.buffer = mTransformFeedbackCounterBuffers[0];
bufferBarrier.offset = 0;
bufferBarrier.size = VK_WHOLE_SIZE;
primary->pipelineBarrier(VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0u, 0u, nullptr, 1u,
&bufferBarrier, 0u, nullptr);
}
}
else
{
mCommandBuffer.executeCommands(primary->getHandle());
}
// Restart the command buffer.
reset();
return angle::Result::Continue;
}
void CommandBufferHelper::addCommandDiagnostics(ContextVk *contextVk)
{
std::ostringstream out;
if (mGlobalMemoryBarrierSrcAccess != 0 || mGlobalMemoryBarrierDstAccess != 0)
{
out << "Memory Barrier Src: 0x" << std::hex << mGlobalMemoryBarrierSrcAccess
<< " &rarr; Dst: 0x" << std::hex << mGlobalMemoryBarrierDstAccess << "\\l";
}
if (mIsRenderPassCommandBuffer)
{
size_t attachmentCount = mRenderPassDesc.attachmentCount();
size_t depthStencilAttachmentCount = mRenderPassDesc.hasDepthStencilAttachment();
size_t colorAttachmentCount = attachmentCount - depthStencilAttachmentCount;
std::string loadOps, storeOps;
if (colorAttachmentCount > 0)
{
loadOps += " Color: ";
storeOps += " Color: ";
for (size_t i = 0; i < colorAttachmentCount; ++i)
{
loadOps += GetLoadOpShorthand(mAttachmentOps[i].loadOp);
storeOps += GetStoreOpShorthand(mAttachmentOps[i].storeOp);
}
}
if (depthStencilAttachmentCount > 0)
{
ASSERT(depthStencilAttachmentCount == 1);
loadOps += " Depth/Stencil: ";
storeOps += " Depth/Stencil: ";
size_t dsIndex = colorAttachmentCount;
loadOps += GetLoadOpShorthand(mAttachmentOps[dsIndex].loadOp);
loadOps += GetLoadOpShorthand(mAttachmentOps[dsIndex].stencilLoadOp);
storeOps += GetStoreOpShorthand(mAttachmentOps[dsIndex].storeOp);
storeOps += GetStoreOpShorthand(mAttachmentOps[dsIndex].stencilStoreOp);
}
if (attachmentCount > 0)
{
out << "LoadOp: " << loadOps << "\\l";
out << "StoreOp: " << storeOps << "\\l";
}
}
out << mCommandBuffer.dumpCommands("\\l");
contextVk->addCommandBufferDiagnostics(out.str());
}
void CommandBufferHelper::reset()
{
mCommandBuffer.reset();
if (mIsRenderPassCommandBuffer)
{
mRenderPassStarted = false;
mValidTransformFeedbackBufferCount = 0;
mRebindTransformFeedbackBuffers = false;
}
// This state should never change for non-renderPass command buffer
ASSERT(mRenderPassStarted == false);
ASSERT(mValidTransformFeedbackBufferCount == 0);
ASSERT(mRebindTransformFeedbackBuffers == false);
}
void CommandBufferHelper::resumeTransformFeedbackIfStarted()
{
ASSERT(mIsRenderPassCommandBuffer);
if (mValidTransformFeedbackBufferCount == 0)
{
return;
}
uint32_t numCounterBuffers =
mRebindTransformFeedbackBuffers ? 0 : mValidTransformFeedbackBufferCount;
mRebindTransformFeedbackBuffers = false;
mCommandBuffer.beginTransformFeedback(numCounterBuffers,
mTransformFeedbackCounterBuffers.data());
}
void CommandBufferHelper::pauseTransformFeedbackIfStarted()
{
ASSERT(mIsRenderPassCommandBuffer);
if (mValidTransformFeedbackBufferCount == 0)
{
return;
}
mCommandBuffer.endTransformFeedback(mValidTransformFeedbackBufferCount,
mTransformFeedbackCounterBuffers.data());
}
} // namespace rx } // namespace rx
...@@ -112,144 +112,6 @@ class CommandQueue final : angle::NonCopyable ...@@ -112,144 +112,6 @@ class CommandQueue final : angle::NonCopyable
vk::PersistentCommandPool mPrimaryCommandPool; vk::PersistentCommandPool mPrimaryCommandPool;
}; };
struct CommandBufferHelper : angle::NonCopyable
{
public:
CommandBufferHelper(bool canHaveRenderPass);
~CommandBufferHelper();
// General Functions (non-renderPass specific)
void initialize(angle::PoolAllocator *poolAllocator);
void bufferRead(vk::ResourceUseList *resourceUseList,
VkAccessFlags readAccessType,
VkPipelineStageFlags readStage,
vk::BufferHelper *buffer);
void bufferWrite(vk::ResourceUseList *resourceUseList,
VkAccessFlags writeAccessType,
VkPipelineStageFlags writeStage,
vk::BufferHelper *buffer);
void imageRead(vk::ResourceUseList *resourceUseList,
VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image);
void imageWrite(vk::ResourceUseList *resourceUseList,
VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image);
void imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkImageMemoryBarrier &imageMemoryBarrier);
vk::CommandBuffer &getCommandBuffer() { return mCommandBuffer; }
angle::Result flushToPrimary(ContextVk *contextVk, vk::PrimaryCommandBuffer *primary);
void executeBarriers(vk::PrimaryCommandBuffer *primary);
bool empty() const { return (!mCommandBuffer.empty() || mRenderPassStarted) ? false : true; }
void reset();
// RenderPass related functions
bool started() const
{
ASSERT(mIsRenderPassCommandBuffer);
return mRenderPassStarted;
}
void beginRenderPass(const vk::Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps,
const vk::ClearValuesArray &clearValues,
vk::CommandBuffer **commandBufferOut);
void beginTransformFeedback(size_t validBufferCount,
const VkBuffer *counterBuffers,
bool rebindBuffer);
void invalidateRenderPassColorAttachment(size_t attachmentIndex)
{
ASSERT(mIsRenderPassCommandBuffer);
SetBitField(mAttachmentOps[attachmentIndex].storeOp, VK_ATTACHMENT_STORE_OP_DONT_CARE);
}
void invalidateRenderPassDepthAttachment(size_t attachmentIndex)
{
ASSERT(mIsRenderPassCommandBuffer);
SetBitField(mAttachmentOps[attachmentIndex].storeOp, VK_ATTACHMENT_STORE_OP_DONT_CARE);
}
void invalidateRenderPassStencilAttachment(size_t attachmentIndex)
{
ASSERT(mIsRenderPassCommandBuffer);
SetBitField(mAttachmentOps[attachmentIndex].stencilStoreOp,
VK_ATTACHMENT_STORE_OP_DONT_CARE);
}
void updateRenderPassAttachmentFinalLayout(size_t attachmentIndex, vk::ImageLayout finalLayout)
{
ASSERT(mIsRenderPassCommandBuffer);
SetBitField(mAttachmentOps[attachmentIndex].finalLayout, finalLayout);
}
const gl::Rectangle &getRenderArea() const
{
ASSERT(mIsRenderPassCommandBuffer);
return mRenderArea;
}
void resumeTransformFeedbackIfStarted();
void pauseTransformFeedbackIfStarted();
uint32_t getAndResetCounter()
{
ASSERT(mIsRenderPassCommandBuffer);
uint32_t count = mCounter;
mCounter = 0;
return count;
}
VkFramebuffer getFramebufferHandle() const
{
ASSERT(mIsRenderPassCommandBuffer);
return mFramebuffer.getHandle();
}
private:
void addCommandDiagnostics(ContextVk *contextVk);
// General state (non-renderPass related)
VkPipelineStageFlags mImageBarrierSrcStageMask;
VkPipelineStageFlags mImageBarrierDstStageMask;
std::vector<VkImageMemoryBarrier> mImageMemoryBarriers;
VkFlags mGlobalMemoryBarrierSrcAccess;
VkFlags mGlobalMemoryBarrierDstAccess;
VkPipelineStageFlags mGlobalMemoryBarrierSrcStages;
VkPipelineStageFlags mGlobalMemoryBarrierDstStages;
vk::CommandBuffer mCommandBuffer;
// RenderPass state
uint32_t mCounter;
vk::RenderPassDesc mRenderPassDesc;
vk::AttachmentOpsArray mAttachmentOps;
vk::Framebuffer mFramebuffer;
gl::Rectangle mRenderArea;
vk::ClearValuesArray mClearValues;
bool mRenderPassStarted;
// Transform feedback state
gl::TransformFeedbackBuffersArray<VkBuffer> mTransformFeedbackCounterBuffers;
uint32_t mValidTransformFeedbackBufferCount;
bool mRebindTransformFeedbackBuffers;
const bool mIsRenderPassCommandBuffer;
};
static constexpr uint32_t kMaxGpuEventNameLen = 32; static constexpr uint32_t kMaxGpuEventNameLen = 32;
using EventName = std::array<char, kMaxGpuEventNameLen>; using EventName = std::array<char, kMaxGpuEventNameLen>;
...@@ -649,7 +511,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -649,7 +511,7 @@ class ContextVk : public ContextImpl, public vk::Context
bool hasStartedRenderPass() const { return !mRenderPassCommands.empty(); } bool hasStartedRenderPass() const { return !mRenderPassCommands.empty(); }
CommandBufferHelper &getStartedRenderPassCommands() vk::CommandBufferHelper &getStartedRenderPassCommands()
{ {
ASSERT(hasStartedRenderPass()); ASSERT(hasStartedRenderPass());
return mRenderPassCommands; return mRenderPassCommands;
...@@ -830,7 +692,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -830,7 +692,7 @@ class ContextVk : public ContextImpl, public vk::Context
angle::Result updateActiveTextures(const gl::Context *context); angle::Result updateActiveTextures(const gl::Context *context);
angle::Result updateActiveImages(const gl::Context *context, angle::Result updateActiveImages(const gl::Context *context,
CommandBufferHelper *commandBufferHelper); vk::CommandBufferHelper *commandBufferHelper);
angle::Result updateDefaultAttribute(size_t attribIndex); angle::Result updateDefaultAttribute(size_t attribIndex);
ANGLE_INLINE void invalidateCurrentGraphicsPipeline() ANGLE_INLINE void invalidateCurrentGraphicsPipeline()
...@@ -893,9 +755,9 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -893,9 +755,9 @@ class ContextVk : public ContextImpl, public vk::Context
vk::CommandBuffer *commandBuffer); vk::CommandBuffer *commandBuffer);
// Common parts of the common dirty bit handlers. // Common parts of the common dirty bit handlers.
angle::Result handleDirtyTexturesImpl(CommandBufferHelper *commandBufferHelper); angle::Result handleDirtyTexturesImpl(vk::CommandBufferHelper *commandBufferHelper);
angle::Result handleDirtyShaderResourcesImpl(const gl::Context *context, angle::Result handleDirtyShaderResourcesImpl(const gl::Context *context,
CommandBufferHelper *commandBufferHelper); vk::CommandBufferHelper *commandBufferHelper);
void handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandBuffer, void handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandBuffer,
VkPipelineBindPoint bindPoint, VkPipelineBindPoint bindPoint,
const DriverUniformsDescriptorSet &driverUniforms); const DriverUniformsDescriptorSet &driverUniforms);
...@@ -1066,8 +928,8 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -1066,8 +928,8 @@ class ContextVk : public ContextImpl, public vk::Context
// When the command graph is disabled we record commands completely linearly. We have plans to // When the command graph is disabled we record commands completely linearly. We have plans to
// reorder independent draws so that we can create fewer RenderPasses in some scenarios. // reorder independent draws so that we can create fewer RenderPasses in some scenarios.
CommandBufferHelper mOutsideRenderPassCommands; vk::CommandBufferHelper mOutsideRenderPassCommands;
CommandBufferHelper mRenderPassCommands; vk::CommandBufferHelper mRenderPassCommands;
vk::PrimaryCommandBuffer mPrimaryCommands; vk::PrimaryCommandBuffer mPrimaryCommands;
bool mHasPrimaryCommands; bool mHasPrimaryCommands;
......
...@@ -865,7 +865,7 @@ void ProgramExecutableVk::updateDefaultUniformsDescriptorSet( ...@@ -865,7 +865,7 @@ void ProgramExecutableVk::updateDefaultUniformsDescriptorSet(
void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk, void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
vk::ResourceUseList *resourceUseList, vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper, vk::CommandBufferHelper *commandBufferHelper,
const std::vector<gl::InterfaceBlock> &blocks, const std::vector<gl::InterfaceBlock> &blocks,
VkDescriptorType descriptorType) VkDescriptorType descriptorType)
{ {
...@@ -965,7 +965,7 @@ void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet( ...@@ -965,7 +965,7 @@ void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet(
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
ContextVk *contextVk, ContextVk *contextVk,
vk::ResourceUseList *resourceUseList, vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper) vk::CommandBufferHelper *commandBufferHelper)
{ {
const gl::State &glState = contextVk->getState(); const gl::State &glState = contextVk->getState();
const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers = const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
...@@ -1145,7 +1145,7 @@ angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramSt ...@@ -1145,7 +1145,7 @@ angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramSt
angle::Result ProgramExecutableVk::updateShaderResourcesDescriptorSet( angle::Result ProgramExecutableVk::updateShaderResourcesDescriptorSet(
ContextVk *contextVk, ContextVk *contextVk,
vk::ResourceUseList *resourceUseList, vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper) vk::CommandBufferHelper *commandBufferHelper)
{ {
const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable(); const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
ASSERT(executable); ASSERT(executable);
......
...@@ -142,7 +142,7 @@ class ProgramExecutableVk ...@@ -142,7 +142,7 @@ class ProgramExecutableVk
angle::Result updateTexturesDescriptorSet(ContextVk *contextVk); angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
angle::Result updateShaderResourcesDescriptorSet(ContextVk *contextVk, angle::Result updateShaderResourcesDescriptorSet(ContextVk *contextVk,
vk::ResourceUseList *resourceUseList, vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper); vk::CommandBufferHelper *commandBufferHelper);
angle::Result updateTransformFeedbackDescriptorSet( angle::Result updateTransformFeedbackDescriptorSet(
const gl::ProgramState &programState, const gl::ProgramState &programState,
gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks, gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
...@@ -194,14 +194,14 @@ class ProgramExecutableVk ...@@ -194,14 +194,14 @@ class ProgramExecutableVk
void updateBuffersDescriptorSet(ContextVk *contextVk, void updateBuffersDescriptorSet(ContextVk *contextVk,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
vk::ResourceUseList *resourceUseList, vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper, vk::CommandBufferHelper *commandBufferHelper,
const std::vector<gl::InterfaceBlock> &blocks, const std::vector<gl::InterfaceBlock> &blocks,
VkDescriptorType descriptorType); VkDescriptorType descriptorType);
void updateAtomicCounterBuffersDescriptorSet(const gl::ProgramState &programState, void updateAtomicCounterBuffersDescriptorSet(const gl::ProgramState &programState,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
ContextVk *contextVk, ContextVk *contextVk,
vk::ResourceUseList *resourceUseList, vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper); vk::CommandBufferHelper *commandBufferHelper);
angle::Result updateImagesDescriptorSet(const gl::ProgramState &programState, angle::Result updateImagesDescriptorSet(const gl::ProgramState &programState,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
ContextVk *contextVk); ContextVk *contextVk);
......
...@@ -453,6 +453,352 @@ VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout) ...@@ -453,6 +453,352 @@ VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout)
return kImageMemoryBarrierData[imageLayout].layout; return kImageMemoryBarrierData[imageLayout].layout;
} }
// CommandBufferHelper implementation.
CommandBufferHelper::CommandBufferHelper(bool hasRenderPass)
: mImageBarrierSrcStageMask(0),
mImageBarrierDstStageMask(0),
mGlobalMemoryBarrierSrcAccess(0),
mGlobalMemoryBarrierDstAccess(0),
mGlobalMemoryBarrierSrcStages(0),
mGlobalMemoryBarrierDstStages(0),
mCounter(0),
mClearValues{},
mRenderPassStarted(false),
mTransformFeedbackCounterBuffers{},
mValidTransformFeedbackBufferCount(0),
mRebindTransformFeedbackBuffers(false),
mIsRenderPassCommandBuffer(hasRenderPass)
{}
CommandBufferHelper::~CommandBufferHelper()
{
mFramebuffer.setHandle(VK_NULL_HANDLE);
}
void CommandBufferHelper::initialize(angle::PoolAllocator *poolAllocator)
{
mCommandBuffer.initialize(poolAllocator);
}
void CommandBufferHelper::bufferRead(vk::ResourceUseList *resourceUseList,
VkAccessFlags readAccessType,
VkPipelineStageFlags readStage,
vk::BufferHelper *buffer)
{
buffer->retain(resourceUseList);
buffer->updateReadBarrier(readAccessType, &mGlobalMemoryBarrierSrcAccess,
&mGlobalMemoryBarrierDstAccess, readStage,
&mGlobalMemoryBarrierSrcStages, &mGlobalMemoryBarrierDstStages);
}
void CommandBufferHelper::bufferWrite(vk::ResourceUseList *resourceUseList,
VkAccessFlags writeAccessType,
VkPipelineStageFlags writeStage,
vk::BufferHelper *buffer)
{
buffer->retain(resourceUseList);
buffer->updateWriteBarrier(writeAccessType, &mGlobalMemoryBarrierSrcAccess,
&mGlobalMemoryBarrierDstAccess, writeStage,
&mGlobalMemoryBarrierSrcStages, &mGlobalMemoryBarrierDstStages);
}
void CommandBufferHelper::imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkImageMemoryBarrier &imageMemoryBarrier)
{
ASSERT(imageMemoryBarrier.pNext == nullptr);
mImageBarrierSrcStageMask |= srcStageMask;
mImageBarrierDstStageMask |= dstStageMask;
mImageMemoryBarriers.push_back(imageMemoryBarrier);
}
void CommandBufferHelper::imageRead(vk::ResourceUseList *resourceUseList,
VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image)
{
image->retain(resourceUseList);
if (image->isLayoutChangeNecessary(imageLayout))
{
image->changeLayout(aspectFlags, imageLayout, this);
}
}
void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList,
VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image)
{
image->retain(resourceUseList);
image->changeLayout(aspectFlags, imageLayout, this);
}
void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary)
{
if (mImageMemoryBarriers.empty() && mGlobalMemoryBarrierSrcAccess == 0)
{
return;
}
VkPipelineStageFlags srcStages = 0;
VkPipelineStageFlags dstStages = 0;
VkMemoryBarrier memoryBarrier = {};
uint32_t memoryBarrierCount = 0;
if (mGlobalMemoryBarrierSrcAccess != 0)
{
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.srcAccessMask = mGlobalMemoryBarrierSrcAccess;
memoryBarrier.dstAccessMask = mGlobalMemoryBarrierDstAccess;
memoryBarrierCount++;
srcStages |= mGlobalMemoryBarrierSrcStages;
dstStages |= mGlobalMemoryBarrierDstStages;
mGlobalMemoryBarrierSrcAccess = 0;
mGlobalMemoryBarrierDstAccess = 0;
mGlobalMemoryBarrierSrcStages = 0;
mGlobalMemoryBarrierDstStages = 0;
}
srcStages |= mImageBarrierSrcStageMask;
dstStages |= mImageBarrierDstStageMask;
primary->pipelineBarrier(srcStages, dstStages, 0, memoryBarrierCount, &memoryBarrier, 0,
nullptr, static_cast<uint32_t>(mImageMemoryBarriers.size()),
mImageMemoryBarriers.data());
mImageMemoryBarriers.clear();
mImageBarrierSrcStageMask = 0;
mImageBarrierDstStageMask = 0;
}
void CommandBufferHelper::beginRenderPass(const vk::Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps,
const vk::ClearValuesArray &clearValues,
vk::CommandBuffer **commandBufferOut)
{
ASSERT(mIsRenderPassCommandBuffer);
ASSERT(empty());
mRenderPassDesc = renderPassDesc;
mAttachmentOps = renderPassAttachmentOps;
mFramebuffer.setHandle(framebuffer.getHandle());
mRenderArea = renderArea;
mClearValues = clearValues;
*commandBufferOut = &mCommandBuffer;
mRenderPassStarted = true;
mCounter++;
}
void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount,
const VkBuffer *counterBuffers,
bool rebindBuffer)
{
ASSERT(mIsRenderPassCommandBuffer);
mValidTransformFeedbackBufferCount = static_cast<uint32_t>(validBufferCount);
mRebindTransformFeedbackBuffers = rebindBuffer;
for (size_t index = 0; index < validBufferCount; index++)
{
mTransformFeedbackCounterBuffers[index] = counterBuffers[index];
}
}
angle::Result CommandBufferHelper::flushToPrimary(ContextVk *contextVk,
vk::PrimaryCommandBuffer *primary)
{
ASSERT(!empty());
if (kEnableCommandStreamDiagnostics)
{
addCommandDiagnostics(contextVk);
}
// Commands that are added to primary before beginRenderPass command
executeBarriers(primary);
if (mIsRenderPassCommandBuffer)
{
mCommandBuffer.executeQueuedResetQueryPoolCommands(primary->getHandle());
// Pull a RenderPass from the cache.
RenderPassCache &renderPassCache = contextVk->getRenderPassCache();
Serial serial = contextVk->getCurrentQueueSerial();
vk::RenderPass *renderPass = nullptr;
ANGLE_TRY(renderPassCache.getRenderPassWithOps(contextVk, serial, mRenderPassDesc,
mAttachmentOps, &renderPass));
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.
primary->beginRenderPass(beginInfo, VK_SUBPASS_CONTENTS_INLINE);
mCommandBuffer.executeCommands(primary->getHandle());
primary->endRenderPass();
if (mValidTransformFeedbackBufferCount != 0)
{
// Would be better to accumulate this barrier using the command APIs.
// TODO: Clean thus up before we close http://anglebug.com/3206
VkBufferMemoryBarrier bufferBarrier = {};
bufferBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufferBarrier.pNext = nullptr;
bufferBarrier.srcAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
bufferBarrier.dstAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT;
bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferBarrier.buffer = mTransformFeedbackCounterBuffers[0];
bufferBarrier.offset = 0;
bufferBarrier.size = VK_WHOLE_SIZE;
primary->pipelineBarrier(VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0u, 0u, nullptr, 1u,
&bufferBarrier, 0u, nullptr);
}
}
else
{
mCommandBuffer.executeCommands(primary->getHandle());
}
// Restart the command buffer.
reset();
return angle::Result::Continue;
}
// Helper functions used below
char GetLoadOpShorthand(uint32_t loadOp)
{
switch (loadOp)
{
case VK_ATTACHMENT_LOAD_OP_CLEAR:
return 'C';
case VK_ATTACHMENT_LOAD_OP_LOAD:
return 'L';
default:
return 'D';
}
}
char GetStoreOpShorthand(uint32_t storeOp)
{
switch (storeOp)
{
case VK_ATTACHMENT_STORE_OP_STORE:
return 'S';
default:
return 'D';
}
}
void CommandBufferHelper::addCommandDiagnostics(ContextVk *contextVk)
{
std::ostringstream out;
if (mGlobalMemoryBarrierSrcAccess != 0 || mGlobalMemoryBarrierDstAccess != 0)
{
out << "Memory Barrier Src: 0x" << std::hex << mGlobalMemoryBarrierSrcAccess
<< " &rarr; Dst: 0x" << std::hex << mGlobalMemoryBarrierDstAccess << "\\l";
}
if (mIsRenderPassCommandBuffer)
{
size_t attachmentCount = mRenderPassDesc.attachmentCount();
size_t depthStencilAttachmentCount = mRenderPassDesc.hasDepthStencilAttachment();
size_t colorAttachmentCount = attachmentCount - depthStencilAttachmentCount;
std::string loadOps, storeOps;
if (colorAttachmentCount > 0)
{
loadOps += " Color: ";
storeOps += " Color: ";
for (size_t i = 0; i < colorAttachmentCount; ++i)
{
loadOps += GetLoadOpShorthand(mAttachmentOps[i].loadOp);
storeOps += GetStoreOpShorthand(mAttachmentOps[i].storeOp);
}
}
if (depthStencilAttachmentCount > 0)
{
ASSERT(depthStencilAttachmentCount == 1);
loadOps += " Depth/Stencil: ";
storeOps += " Depth/Stencil: ";
size_t dsIndex = colorAttachmentCount;
loadOps += GetLoadOpShorthand(mAttachmentOps[dsIndex].loadOp);
loadOps += GetLoadOpShorthand(mAttachmentOps[dsIndex].stencilLoadOp);
storeOps += GetStoreOpShorthand(mAttachmentOps[dsIndex].storeOp);
storeOps += GetStoreOpShorthand(mAttachmentOps[dsIndex].stencilStoreOp);
}
if (attachmentCount > 0)
{
out << "LoadOp: " << loadOps << "\\l";
out << "StoreOp: " << storeOps << "\\l";
}
}
out << mCommandBuffer.dumpCommands("\\l");
contextVk->addCommandBufferDiagnostics(out.str());
}
void CommandBufferHelper::reset()
{
mCommandBuffer.reset();
if (mIsRenderPassCommandBuffer)
{
mRenderPassStarted = false;
mValidTransformFeedbackBufferCount = 0;
mRebindTransformFeedbackBuffers = false;
}
// This state should never change for non-renderPass command buffer
ASSERT(mRenderPassStarted == false);
ASSERT(mValidTransformFeedbackBufferCount == 0);
ASSERT(mRebindTransformFeedbackBuffers == false);
}
void CommandBufferHelper::resumeTransformFeedbackIfStarted()
{
ASSERT(mIsRenderPassCommandBuffer);
if (mValidTransformFeedbackBufferCount == 0)
{
return;
}
uint32_t numCounterBuffers =
mRebindTransformFeedbackBuffers ? 0 : mValidTransformFeedbackBufferCount;
mRebindTransformFeedbackBuffers = false;
mCommandBuffer.beginTransformFeedback(numCounterBuffers,
mTransformFeedbackCounterBuffers.data());
}
void CommandBufferHelper::pauseTransformFeedbackIfStarted()
{
ASSERT(mIsRenderPassCommandBuffer);
if (mValidTransformFeedbackBufferCount == 0)
{
return;
}
mCommandBuffer.endTransformFeedback(mValidTransformFeedbackBufferCount,
mTransformFeedbackCounterBuffers.data());
}
// DynamicBuffer implementation. // DynamicBuffer implementation.
DynamicBuffer::DynamicBuffer() DynamicBuffer::DynamicBuffer()
: mUsage(0), : mUsage(0),
......
...@@ -678,6 +678,155 @@ class BufferHelper final : public Resource ...@@ -678,6 +678,155 @@ class BufferHelper final : public Resource
VkPipelineStageFlags mCurrentReadStages; VkPipelineStageFlags mCurrentReadStages;
}; };
// 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.
struct CommandBufferHelper : angle::NonCopyable
{
public:
CommandBufferHelper(bool canHaveRenderPass);
~CommandBufferHelper();
// General Functions (non-renderPass specific)
void initialize(angle::PoolAllocator *poolAllocator);
void bufferRead(vk::ResourceUseList *resourceUseList,
VkAccessFlags readAccessType,
VkPipelineStageFlags readStage,
vk::BufferHelper *buffer);
void bufferWrite(vk::ResourceUseList *resourceUseList,
VkAccessFlags writeAccessType,
VkPipelineStageFlags writeStage,
vk::BufferHelper *buffer);
void imageRead(vk::ResourceUseList *resourceUseList,
VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image);
void imageWrite(vk::ResourceUseList *resourceUseList,
VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
vk::ImageHelper *image);
void imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkImageMemoryBarrier &imageMemoryBarrier);
vk::CommandBuffer &getCommandBuffer() { return mCommandBuffer; }
angle::Result flushToPrimary(ContextVk *contextVk, vk::PrimaryCommandBuffer *primary);
void executeBarriers(vk::PrimaryCommandBuffer *primary);
bool empty() const { return (!mCommandBuffer.empty() || mRenderPassStarted) ? false : true; }
void reset();
// RenderPass related functions
bool started() const
{
ASSERT(mIsRenderPassCommandBuffer);
return mRenderPassStarted;
}
void beginRenderPass(const vk::Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps,
const vk::ClearValuesArray &clearValues,
vk::CommandBuffer **commandBufferOut);
void beginTransformFeedback(size_t validBufferCount,
const VkBuffer *counterBuffers,
bool rebindBuffer);
void invalidateRenderPassColorAttachment(size_t attachmentIndex)
{
ASSERT(mIsRenderPassCommandBuffer);
SetBitField(mAttachmentOps[attachmentIndex].storeOp, VK_ATTACHMENT_STORE_OP_DONT_CARE);
}
void invalidateRenderPassDepthAttachment(size_t attachmentIndex)
{
ASSERT(mIsRenderPassCommandBuffer);
SetBitField(mAttachmentOps[attachmentIndex].storeOp, VK_ATTACHMENT_STORE_OP_DONT_CARE);
}
void invalidateRenderPassStencilAttachment(size_t attachmentIndex)
{
ASSERT(mIsRenderPassCommandBuffer);
SetBitField(mAttachmentOps[attachmentIndex].stencilStoreOp,
VK_ATTACHMENT_STORE_OP_DONT_CARE);
}
void updateRenderPassAttachmentFinalLayout(size_t attachmentIndex, vk::ImageLayout finalLayout)
{
ASSERT(mIsRenderPassCommandBuffer);
SetBitField(mAttachmentOps[attachmentIndex].finalLayout, finalLayout);
}
const gl::Rectangle &getRenderArea() const
{
ASSERT(mIsRenderPassCommandBuffer);
return mRenderArea;
}
void resumeTransformFeedbackIfStarted();
void pauseTransformFeedbackIfStarted();
uint32_t getAndResetCounter()
{
ASSERT(mIsRenderPassCommandBuffer);
uint32_t count = mCounter;
mCounter = 0;
return count;
}
VkFramebuffer getFramebufferHandle() const
{
ASSERT(mIsRenderPassCommandBuffer);
return mFramebuffer.getHandle();
}
// Dumping the command stream is disabled by default.
static constexpr bool kEnableCommandStreamDiagnostics = false;
private:
void addCommandDiagnostics(ContextVk *contextVk);
// General state (non-renderPass related)
VkPipelineStageFlags mImageBarrierSrcStageMask;
VkPipelineStageFlags mImageBarrierDstStageMask;
std::vector<VkImageMemoryBarrier> mImageMemoryBarriers;
VkFlags mGlobalMemoryBarrierSrcAccess;
VkFlags mGlobalMemoryBarrierDstAccess;
VkPipelineStageFlags mGlobalMemoryBarrierSrcStages;
VkPipelineStageFlags mGlobalMemoryBarrierDstStages;
vk::CommandBuffer mCommandBuffer;
// RenderPass state
uint32_t mCounter;
vk::RenderPassDesc mRenderPassDesc;
vk::AttachmentOpsArray mAttachmentOps;
vk::Framebuffer mFramebuffer;
gl::Rectangle mRenderArea;
vk::ClearValuesArray mClearValues;
bool mRenderPassStarted;
// Transform feedback state
gl::TransformFeedbackBuffersArray<VkBuffer> mTransformFeedbackCounterBuffers;
uint32_t mValidTransformFeedbackBufferCount;
bool mRebindTransformFeedbackBuffers;
const bool mIsRenderPassCommandBuffer;
};
// Imagine an image going through a few layout transitions: // Imagine an image going through a few layout transitions:
// //
// srcStage 1 dstStage 2 srcStage 2 dstStage 3 // srcStage 1 dstStage 2 srcStage 2 dstStage 3
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment