Commit 45a493ea by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Use a dirty bit to start the render pass

Some dirty bits need to run before the render pass starts. An upcoming change for example needs to break the render pass when the program pipeline is changed while transform feedback is active. Another upcoming change may need to do the same based on a preceding glMemoryBarrier. This change adds a new dirty bit to start the render pass after some dirty bits have already been processed. Bug: angleproject:5528 Change-Id: I993c9efefed4c8fee268b218a8dd66a582d4e7cd Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2678863 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent dccec125
...@@ -311,6 +311,7 @@ ANGLE_INLINE void ContextVk::onRenderPassFinished() ...@@ -311,6 +311,7 @@ ANGLE_INLINE void ContextVk::onRenderPassFinished()
pauseRenderPassQueriesIfActive(); pauseRenderPassQueriesIfActive();
mRenderPassCommandBuffer = nullptr; mRenderPassCommandBuffer = nullptr;
mGraphicsDirtyBits.set(DIRTY_BIT_RENDER_PASS);
} }
// ContextVk::ScopedDescriptorSetUpdates implementation. // ContextVk::ScopedDescriptorSetUpdates implementation.
...@@ -366,7 +367,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -366,7 +367,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mDrawFramebuffer(nullptr), mDrawFramebuffer(nullptr),
mProgram(nullptr), mProgram(nullptr),
mExecutable(nullptr), mExecutable(nullptr),
mLastIndexBufferOffset(0), mLastIndexBufferOffset(nullptr),
mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum), mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum),
mXfbBaseVertex(0), mXfbBaseVertex(0),
mXfbVertexCountPerInstance(0), mXfbVertexCountPerInstance(0),
...@@ -407,7 +408,8 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -407,7 +408,8 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
// Note that currently these dirty bits are set every time a new render pass command buffer is // Note that currently these dirty bits are set every time a new render pass command buffer is
// begun. However, using ANGLE's SecondaryCommandBuffer, the Vulkan command buffer (which is // begun. However, using ANGLE's SecondaryCommandBuffer, the Vulkan command buffer (which is
// the primary command buffer) is not ended, so technically we don't need to rebind these. // the primary command buffer) is not ended, so technically we don't need to rebind these.
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_PIPELINE); mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_RENDER_PASS);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TEXTURES); mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TEXTURES);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS); mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_INDEX_BUFFER); mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
...@@ -419,7 +421,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -419,7 +421,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS); mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
} }
mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_PIPELINE); mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_TEXTURES); mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_TEXTURES);
mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES); mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS); mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
...@@ -428,7 +430,11 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -428,7 +430,11 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mGraphicsDirtyBitHandlers[DIRTY_BIT_EVENT_LOG] = &ContextVk::handleDirtyGraphicsEventLog; mGraphicsDirtyBitHandlers[DIRTY_BIT_EVENT_LOG] = &ContextVk::handleDirtyGraphicsEventLog;
mGraphicsDirtyBitHandlers[DIRTY_BIT_DEFAULT_ATTRIBS] = mGraphicsDirtyBitHandlers[DIRTY_BIT_DEFAULT_ATTRIBS] =
&ContextVk::handleDirtyGraphicsDefaultAttribs; &ContextVk::handleDirtyGraphicsDefaultAttribs;
mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE] = &ContextVk::handleDirtyGraphicsPipeline; mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE_DESC] =
&ContextVk::handleDirtyGraphicsPipelineDesc;
mGraphicsDirtyBitHandlers[DIRTY_BIT_RENDER_PASS] = &ContextVk::handleDirtyGraphicsRenderPass;
mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE_BINDING] =
&ContextVk::handleDirtyGraphicsPipelineBinding;
mGraphicsDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyGraphicsTextures; mGraphicsDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyGraphicsTextures;
mGraphicsDirtyBitHandlers[DIRTY_BIT_VERTEX_BUFFERS] = mGraphicsDirtyBitHandlers[DIRTY_BIT_VERTEX_BUFFERS] =
&ContextVk::handleDirtyGraphicsVertexBuffers; &ContextVk::handleDirtyGraphicsVertexBuffers;
...@@ -454,18 +460,22 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -454,18 +460,22 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
&ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation; &ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation;
} }
mGraphicsDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] = &ContextVk::handleDirtyDescriptorSets; mGraphicsDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] =
&ContextVk::handleDirtyGraphicsDescriptorSets;
mComputeDirtyBitHandlers[DIRTY_BIT_EVENT_LOG] = &ContextVk::handleDirtyGraphicsEventLog; mComputeDirtyBitHandlers[DIRTY_BIT_EVENT_LOG] = &ContextVk::handleDirtyComputeEventLog;
mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE] = &ContextVk::handleDirtyComputePipeline; mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE_DESC] = &ContextVk::handleDirtyComputePipelineDesc;
mComputeDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyComputeTextures; mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE_BINDING] =
&ContextVk::handleDirtyComputePipelineBinding;
mComputeDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyComputeTextures;
mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] = mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] =
&ContextVk::handleDirtyComputeDriverUniforms; &ContextVk::handleDirtyComputeDriverUniforms;
mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS_BINDING] = mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS_BINDING] =
&ContextVk::handleDirtyComputeDriverUniformsBinding; &ContextVk::handleDirtyComputeDriverUniformsBinding;
mComputeDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] = mComputeDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] =
&ContextVk::handleDirtyComputeShaderResources; &ContextVk::handleDirtyComputeShaderResources;
mComputeDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] = &ContextVk::handleDirtyDescriptorSets; mComputeDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] =
&ContextVk::handleDirtyComputeDescriptorSets;
mGraphicsDirtyBits = mNewGraphicsCommandBufferDirtyBits; mGraphicsDirtyBits = mNewGraphicsCommandBufferDirtyBits;
mComputeDirtyBits = mNewComputeCommandBufferDirtyBits; mComputeDirtyBits = mNewComputeCommandBufferDirtyBits;
...@@ -478,8 +488,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -478,8 +488,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
// - READ_FRAMEBUFFER_BINDING only affects operations that read from said framebuffer, // - READ_FRAMEBUFFER_BINDING only affects operations that read from said framebuffer,
// - CLEAR_* only affect following clear calls, // - CLEAR_* only affect following clear calls,
// - PACK/UNPACK_STATE only affect texture data upload/download, // - PACK/UNPACK_STATE only affect texture data upload/download,
// - *_BINDING only affect descriptor sets, // - *_BINDING only affect descriptor sets.
// - CURRENT_VALUES only affects (default) vertex attributes.
// //
mPipelineDirtyBitsMask.set(); mPipelineDirtyBitsMask.set();
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING); mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
...@@ -491,7 +500,6 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -491,7 +500,6 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_PACK_STATE); mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_PACK_STATE);
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_PACK_BUFFER_BINDING); mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_PACK_BUFFER_BINDING);
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_RENDERBUFFER_BINDING); mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_RENDERBUFFER_BINDING);
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING); mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING);
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING); mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING);
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_SAMPLER_BINDINGS); mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_SAMPLER_BINDINGS);
...@@ -501,7 +509,6 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -501,7 +509,6 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS); mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING); mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING); mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_CURRENT_VALUES);
// Reserve reasonable amount of spaces so that for majority of apps we don't need to grow at all // Reserve reasonable amount of spaces so that for majority of apps we don't need to grow at all
mDescriptorBufferInfos.reserve(kDescriptorBufferInfosInitialSize); mDescriptorBufferInfos.reserve(kDescriptorBufferInfosInitialSize);
...@@ -766,8 +773,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context, ...@@ -766,8 +773,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
GLsizei instanceCount, GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid, gl::DrawElementsType indexTypeOrInvalid,
const void *indices, const void *indices,
DirtyBits dirtyBitMask, DirtyBits dirtyBitMask)
vk::CommandBuffer **commandBufferOut)
{ {
// Set any dirty bits that depend on draw call parameters or other objects. // Set any dirty bits that depend on draw call parameters or other objects.
if (mode != mCurrentDrawMode) if (mode != mCurrentDrawMode)
...@@ -788,23 +794,6 @@ angle::Result ContextVk::setupDraw(const gl::Context *context, ...@@ -788,23 +794,6 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS); mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
} }
// This could be improved using a dirty bit. But currently it's slower to use a handler
// function than an inlined if. We should probably replace the dirty bit dispatch table
// with a switch with inlined handler functions.
// TODO(jmadill): Use dirty bit. http://anglebug.com/3014
if (!mRenderPassCommandBuffer)
{
gl::Rectangle scissoredRenderArea = mDrawFramebuffer->getRotatedScissoredRenderArea(this);
ANGLE_TRY(startRenderPass(scissoredRenderArea, nullptr));
}
// We keep a local copy of the command buffer. It's possible that some state changes could
// trigger a command buffer invalidation. The local copy ensures we retain the reference.
// Command buffers are pool allocated and only deleted after submit. Thus we know the
// command buffer will still be valid for the duration of this API call.
*commandBufferOut = mRenderPassCommandBuffer;
ASSERT(*commandBufferOut);
// Create a local object to ensure we flush the descriptor updates to device when we leave this // Create a local object to ensure we flush the descriptor updates to device when we leave this
// function // function
ScopedDescriptorSetUpdates descriptorSetUpdates(this); ScopedDescriptorSetUpdates descriptorSetUpdates(this);
...@@ -836,18 +825,30 @@ angle::Result ContextVk::setupDraw(const gl::Context *context, ...@@ -836,18 +825,30 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
if (dirtyBits.none()) if (dirtyBits.none())
{ {
ASSERT(mRenderPassCommandBuffer);
return angle::Result::Continue; return angle::Result::Continue;
} }
// If the render pass needs to be recreated, close it before processing dirty bits. This
// operation may add many dirty bits.
if (mRenderPassCommandBuffer == nullptr)
{
ANGLE_TRY(flushCommandsAndEndRenderPass());
}
// Flush any relevant dirty bits. // Flush any relevant dirty bits.
for (size_t dirtyBit : dirtyBits) for (DirtyBits::Iterator dirtyBitIter = dirtyBits.begin(); dirtyBitIter != dirtyBits.end();
++dirtyBitIter)
{ {
ASSERT(mGraphicsDirtyBitHandlers[dirtyBit]); ASSERT(mGraphicsDirtyBitHandlers[*dirtyBitIter]);
ANGLE_TRY((this->*mGraphicsDirtyBitHandlers[dirtyBit])(context, *commandBufferOut)); ANGLE_TRY((this->*mGraphicsDirtyBitHandlers[*dirtyBitIter])(&dirtyBitIter));
} }
mGraphicsDirtyBits &= ~dirtyBitMask; mGraphicsDirtyBits &= ~dirtyBitMask;
// Render pass must be always available at this point.
ASSERT(mRenderPassCommandBuffer);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -856,8 +857,7 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context, ...@@ -856,8 +857,7 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
GLsizei indexCount, GLsizei indexCount,
GLsizei instanceCount, GLsizei instanceCount,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
const void *indices, const void *indices)
vk::CommandBuffer **commandBufferOut)
{ {
ASSERT(mode != gl::PrimitiveMode::LineLoop); ASSERT(mode != gl::PrimitiveMode::LineLoop);
...@@ -909,15 +909,14 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context, ...@@ -909,15 +909,14 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
} }
return setupDraw(context, mode, 0, indexCount, instanceCount, indexType, indices, return setupDraw(context, mode, 0, indexCount, instanceCount, indexType, indices,
mIndexedDirtyBitsMask, commandBufferOut); mIndexedDirtyBitsMask);
} }
angle::Result ContextVk::setupIndirectDraw(const gl::Context *context, angle::Result ContextVk::setupIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
DirtyBits dirtyBitMask, DirtyBits dirtyBitMask,
vk::BufferHelper *indirectBuffer, vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset, VkDeviceSize indirectBufferOffset)
vk::CommandBuffer **commandBufferOut)
{ {
GLint firstVertex = -1; GLint firstVertex = -1;
GLsizei vertexCount = 0; GLsizei vertexCount = 0;
...@@ -933,8 +932,7 @@ angle::Result ContextVk::setupIndirectDraw(const gl::Context *context, ...@@ -933,8 +932,7 @@ angle::Result ContextVk::setupIndirectDraw(const gl::Context *context,
vk::PipelineStage::DrawIndirect, indirectBuffer); vk::PipelineStage::DrawIndirect, indirectBuffer);
ANGLE_TRY(setupDraw(context, mode, firstVertex, vertexCount, instanceCount, ANGLE_TRY(setupDraw(context, mode, firstVertex, vertexCount, instanceCount,
gl::DrawElementsType::InvalidEnum, nullptr, dirtyBitMask, gl::DrawElementsType::InvalidEnum, nullptr, dirtyBitMask));
commandBufferOut));
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -943,8 +941,7 @@ angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context, ...@@ -943,8 +941,7 @@ angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
vk::BufferHelper *indirectBuffer, vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset, VkDeviceSize indirectBufferOffset)
vk::CommandBuffer **commandBufferOut)
{ {
ASSERT(mode != gl::PrimitiveMode::LineLoop); ASSERT(mode != gl::PrimitiveMode::LineLoop);
...@@ -955,7 +952,7 @@ angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context, ...@@ -955,7 +952,7 @@ angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context,
} }
return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBuffer, return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBuffer,
indirectBufferOffset, commandBufferOut); indirectBufferOffset);
} }
angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *context, angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *context,
...@@ -963,7 +960,6 @@ angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *con ...@@ -963,7 +960,6 @@ angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *con
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
vk::BufferHelper *srcIndirectBuf, vk::BufferHelper *srcIndirectBuf,
VkDeviceSize indirectBufferOffset, VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut,
vk::BufferHelper **indirectBufferOut, vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut) VkDeviceSize *indirectBufferOffsetOut)
{ {
...@@ -986,14 +982,13 @@ angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *con ...@@ -986,14 +982,13 @@ angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *con
} }
return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, dstIndirectBuf, return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, dstIndirectBuf,
dstIndirectBufOffset, commandBufferOut); dstIndirectBufOffset);
} }
angle::Result ContextVk::setupLineLoopIndirectDraw(const gl::Context *context, angle::Result ContextVk::setupLineLoopIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
vk::BufferHelper *indirectBuffer, vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset, VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut,
vk::BufferHelper **indirectBufferOut, vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut) VkDeviceSize *indirectBufferOffsetOut)
{ {
...@@ -1014,7 +1009,7 @@ angle::Result ContextVk::setupLineLoopIndirectDraw(const gl::Context *context, ...@@ -1014,7 +1009,7 @@ angle::Result ContextVk::setupLineLoopIndirectDraw(const gl::Context *context,
} }
return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBufferHelperOut, return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBufferHelperOut,
*indirectBufferOffsetOut, commandBufferOut); *indirectBufferOffsetOut);
} }
angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context, angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
...@@ -1023,7 +1018,6 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context, ...@@ -1023,7 +1018,6 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
GLsizei vertexOrIndexCount, GLsizei vertexOrIndexCount,
gl::DrawElementsType indexTypeOrInvalid, gl::DrawElementsType indexTypeOrInvalid,
const void *indices, const void *indices,
vk::CommandBuffer **commandBufferOut,
uint32_t *numIndicesOut) uint32_t *numIndicesOut)
{ {
ANGLE_TRY(mVertexArray->handleLineLoop(this, firstVertex, vertexOrIndexCount, ANGLE_TRY(mVertexArray->handleLineLoop(this, firstVertex, vertexOrIndexCount,
...@@ -1033,17 +1027,15 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context, ...@@ -1033,17 +1027,15 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
? indexTypeOrInvalid ? indexTypeOrInvalid
: gl::DrawElementsType::UnsignedInt; : gl::DrawElementsType::UnsignedInt;
return setupDraw(context, mode, firstVertex, vertexOrIndexCount, 1, indexTypeOrInvalid, indices, return setupDraw(context, mode, firstVertex, vertexOrIndexCount, 1, indexTypeOrInvalid, indices,
mIndexedDirtyBitsMask, commandBufferOut); mIndexedDirtyBitsMask);
} }
angle::Result ContextVk::setupDispatch(const gl::Context *context, angle::Result ContextVk::setupDispatch(const gl::Context *context)
vk::CommandBuffer **commandBufferOut)
{ {
// |setupDispatch| and |setupDraw| are special in that they flush dirty bits. Therefore they // |setupDispatch| and |setupDraw| are special in that they flush dirty bits. Therefore they
// don't use the same APIs to record commands as the functions outside ContextVk. // don't use the same APIs to record commands as the functions outside ContextVk.
// The following ensures prior commands are flushed before we start processing dirty bits. // The following ensures prior commands are flushed before we start processing dirty bits.
ANGLE_TRY(flushCommandsAndEndRenderPass()); ANGLE_TRY(flushCommandsAndEndRenderPass());
*commandBufferOut = &mOutsideRenderPassCommands->getCommandBuffer();
// Create a local object to ensure we flush the descriptor updates to device when we leave this // Create a local object to ensure we flush the descriptor updates to device when we leave this
// function // function
...@@ -1066,7 +1058,7 @@ angle::Result ContextVk::setupDispatch(const gl::Context *context, ...@@ -1066,7 +1058,7 @@ angle::Result ContextVk::setupDispatch(const gl::Context *context,
for (size_t dirtyBit : dirtyBits) for (size_t dirtyBit : dirtyBits)
{ {
ASSERT(mComputeDirtyBitHandlers[dirtyBit]); ASSERT(mComputeDirtyBitHandlers[dirtyBit]);
ANGLE_TRY((this->*mComputeDirtyBitHandlers[dirtyBit])(context, *commandBufferOut)); ANGLE_TRY((this->*mComputeDirtyBitHandlers[dirtyBit])());
} }
mComputeDirtyBits.reset(); mComputeDirtyBits.reset();
...@@ -1074,8 +1066,17 @@ angle::Result ContextVk::setupDispatch(const gl::Context *context, ...@@ -1074,8 +1066,17 @@ angle::Result ContextVk::setupDispatch(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::handleDirtyGraphicsEventLog(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsEventLog(DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer) {
return handleDirtyEventLogImpl(mRenderPassCommandBuffer);
}
angle::Result ContextVk::handleDirtyComputeEventLog()
{
return handleDirtyEventLogImpl(&mOutsideRenderPassCommands->getCommandBuffer());
}
angle::Result ContextVk::handleDirtyEventLogImpl(vk::CommandBuffer *commandBuffer)
{ {
if (mEventLog.empty()) if (mEventLog.empty())
{ {
...@@ -1125,8 +1126,7 @@ angle::Result ContextVk::handleDirtyGraphicsEventLog(const gl::Context *context, ...@@ -1125,8 +1126,7 @@ angle::Result ContextVk::handleDirtyGraphicsEventLog(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer)
{ {
ASSERT(mDirtyDefaultAttribsMask.any()); ASSERT(mDirtyDefaultAttribsMask.any());
...@@ -1139,9 +1139,12 @@ angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(const gl::Context *co ...@@ -1139,9 +1139,12 @@ angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(const gl::Context *co
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer)
{ {
const VkPipeline previousPipeline = mCurrentGraphicsPipeline
? mCurrentGraphicsPipeline->getPipeline().getHandle()
: VK_NULL_HANDLE;
ASSERT(mExecutable); ASSERT(mExecutable);
if (!mCurrentGraphicsPipeline) if (!mCurrentGraphicsPipeline)
...@@ -1156,8 +1159,8 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context, ...@@ -1156,8 +1159,8 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
// Draw call shader patching, shader compilation, and pipeline cache query. // Draw call shader patching, shader compilation, and pipeline cache query.
ANGLE_TRY(mExecutable->getGraphicsPipeline( ANGLE_TRY(mExecutable->getGraphicsPipeline(
this, mCurrentDrawMode, *mGraphicsPipelineDesc, this, mCurrentDrawMode, *mGraphicsPipelineDesc,
context->getState().getProgramExecutable()->getNonBuiltinAttribLocationsMask(), mState.getProgramExecutable()->getNonBuiltinAttribLocationsMask(), &descPtr,
&descPtr, &mCurrentGraphicsPipeline)); &mCurrentGraphicsPipeline));
mGraphicsPipelineTransition.reset(); mGraphicsPipelineTransition.reset();
} }
else if (mGraphicsPipelineTransition.any()) else if (mGraphicsPipelineTransition.any())
...@@ -1170,8 +1173,8 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context, ...@@ -1170,8 +1173,8 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
ANGLE_TRY(mExecutable->getGraphicsPipeline( ANGLE_TRY(mExecutable->getGraphicsPipeline(
this, mCurrentDrawMode, *mGraphicsPipelineDesc, this, mCurrentDrawMode, *mGraphicsPipelineDesc,
context->getState().getProgramExecutable()->getNonBuiltinAttribLocationsMask(), mState.getProgramExecutable()->getNonBuiltinAttribLocationsMask(), &descPtr,
&descPtr, &mCurrentGraphicsPipeline)); &mCurrentGraphicsPipeline));
oldPipeline->addTransition(mGraphicsPipelineTransition, descPtr, oldPipeline->addTransition(mGraphicsPipelineTransition, descPtr,
mCurrentGraphicsPipeline); mCurrentGraphicsPipeline);
...@@ -1179,20 +1182,63 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context, ...@@ -1179,20 +1182,63 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
mGraphicsPipelineTransition.reset(); mGraphicsPipelineTransition.reset();
} }
pauseTransformFeedbackIfStarted({});
commandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline());
// Update the queue serial for the pipeline object. // Update the queue serial for the pipeline object.
ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid()); ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid());
// TODO: https://issuetracker.google.com/issues/169788986: Need to change this so that we get // TODO: https://issuetracker.google.com/issues/169788986: Need to change this so that we get
// the actual serial used when this work is submitted. // the actual serial used when this work is submitted.
mCurrentGraphicsPipeline->updateSerial(getCurrentQueueSerial()); mCurrentGraphicsPipeline->updateSerial(getCurrentQueueSerial());
const VkPipeline newPipeline = mCurrentGraphicsPipeline->getPipeline().getHandle();
// If there's no change in pipeline, avoid rebinding it later. If the rebind is due to a new
// command buffer or UtilsVk, it will happen anyway with DIRTY_BIT_PIPELINE_BINDING.
if (newPipeline == previousPipeline)
{
return angle::Result::Continue;
}
pauseTransformFeedbackIfStarted({});
// The pipeline needs to rebind because it's changed.
dirtyBitsIterator->setLaterBit(DIRTY_BIT_PIPELINE_BINDING);
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::handleDirtyComputePipeline(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer) {
ASSERT(mRenderPassCommandBuffer == nullptr);
// Closing a render pass can affect the pipeline (by setting subpass to 0), and sets dirty bits.
// As such, it's expected that the render pass is closed before dirty bits are handled.
ASSERT(!mRenderPassCommands->started());
gl::Rectangle scissoredRenderArea = mDrawFramebuffer->getRotatedScissoredRenderArea(this);
bool renderPassDescChanged = false;
ANGLE_TRY(startRenderPass(scissoredRenderArea, nullptr, &renderPassDescChanged));
// The render pass desc can change when starting the render pass, for example due to
// multisampled-render-to-texture needs based on loadOps. In that case, recreate the graphics
// pipeline.
if (renderPassDescChanged)
{
ANGLE_TRY(handleDirtyGraphicsPipelineDesc(dirtyBitsIterator));
}
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyGraphicsPipelineBinding(DirtyBits::Iterator *dirtyBitsIterator)
{
ASSERT(mCurrentGraphicsPipeline);
mRenderPassCommandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline());
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyComputePipelineDesc()
{ {
if (!mCurrentComputePipeline) if (!mCurrentComputePipeline)
{ {
...@@ -1200,7 +1246,17 @@ angle::Result ContextVk::handleDirtyComputePipeline(const gl::Context *context, ...@@ -1200,7 +1246,17 @@ angle::Result ContextVk::handleDirtyComputePipeline(const gl::Context *context,
ANGLE_TRY(mExecutable->getComputePipeline(this, &mCurrentComputePipeline)); ANGLE_TRY(mExecutable->getComputePipeline(this, &mCurrentComputePipeline));
} }
commandBuffer->bindComputePipeline(mCurrentComputePipeline->get()); ASSERT(mComputeDirtyBits.test(DIRTY_BIT_PIPELINE_BINDING));
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyComputePipelineBinding()
{
ASSERT(mCurrentComputePipeline);
mOutsideRenderPassCommands->getCommandBuffer().bindComputePipeline(
mCurrentComputePipeline->get());
// TODO: https://issuetracker.google.com/issues/169788986: Need to change this so that we get // TODO: https://issuetracker.google.com/issues/169788986: Need to change this so that we get
// the actual serial used when this work is submitted. // the actual serial used when this work is submitted.
mCurrentComputePipeline->updateSerial(getCurrentQueueSerial()); mCurrentComputePipeline->updateSerial(getCurrentQueueSerial());
...@@ -1306,33 +1362,31 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl( ...@@ -1306,33 +1362,31 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::handleDirtyGraphicsTextures(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsTextures(DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer)
{ {
return handleDirtyTexturesImpl(mRenderPassCommands); return handleDirtyTexturesImpl(mRenderPassCommands);
} }
angle::Result ContextVk::handleDirtyComputeTextures(const gl::Context *context, angle::Result ContextVk::handleDirtyComputeTextures()
vk::CommandBuffer *commandBuffer)
{ {
return handleDirtyTexturesImpl(mOutsideRenderPassCommands); return handleDirtyTexturesImpl(mOutsideRenderPassCommands);
} }
angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer)
{ {
uint32_t maxAttrib = context->getState().getProgramExecutable()->getMaxActiveAttribLocation(); uint32_t maxAttrib = mState.getProgramExecutable()->getMaxActiveAttribLocation();
const gl::AttribArray<VkBuffer> &bufferHandles = mVertexArray->getCurrentArrayBufferHandles(); const gl::AttribArray<VkBuffer> &bufferHandles = mVertexArray->getCurrentArrayBufferHandles();
const gl::AttribArray<VkDeviceSize> &bufferOffsets = const gl::AttribArray<VkDeviceSize> &bufferOffsets =
mVertexArray->getCurrentArrayBufferOffsets(); mVertexArray->getCurrentArrayBufferOffsets();
commandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(), bufferOffsets.data()); mRenderPassCommandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(),
bufferOffsets.data());
const gl::AttribArray<vk::BufferHelper *> &arrayBufferResources = const gl::AttribArray<vk::BufferHelper *> &arrayBufferResources =
mVertexArray->getCurrentArrayBuffers(); mVertexArray->getCurrentArrayBuffers();
// Mark all active vertex buffers as accessed. // Mark all active vertex buffers as accessed.
const gl::ProgramExecutable *executable = context->getState().getProgramExecutable(); const gl::ProgramExecutable *executable = mState.getProgramExecutable();
gl::AttributesMask attribsMask = executable->getActiveAttribLocationsMask(); gl::AttributesMask attribsMask = executable->getActiveAttribLocationsMask();
for (size_t attribIndex : attribsMask) for (size_t attribIndex : attribsMask)
{ {
...@@ -1347,15 +1401,14 @@ angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(const gl::Context *con ...@@ -1347,15 +1401,14 @@ angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(const gl::Context *con
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer)
{ {
vk::BufferHelper *elementArrayBuffer = mVertexArray->getCurrentElementArrayBuffer(); vk::BufferHelper *elementArrayBuffer = mVertexArray->getCurrentElementArrayBuffer();
ASSERT(elementArrayBuffer != nullptr); ASSERT(elementArrayBuffer != nullptr);
commandBuffer->bindIndexBuffer(elementArrayBuffer->getBuffer(), mRenderPassCommandBuffer->bindIndexBuffer(elementArrayBuffer->getBuffer(),
mVertexArray->getCurrentElementArrayBufferOffset(), mVertexArray->getCurrentElementArrayBufferOffset(),
getVkIndexType(mCurrentDrawElementsType)); getVkIndexType(mCurrentDrawElementsType));
mRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_INDEX_READ_BIT, mRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_INDEX_READ_BIT,
vk::PipelineStage::VertexInput, elementArrayBuffer); vk::PipelineStage::VertexInput, elementArrayBuffer);
...@@ -1364,7 +1417,6 @@ angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(const gl::Context *conte ...@@ -1364,7 +1417,6 @@ angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(const gl::Context *conte
} }
ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl( ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
const gl::Context *context,
vk::CommandBufferHelper *commandBufferHelper) vk::CommandBufferHelper *commandBufferHelper)
{ {
const gl::ProgramExecutable *executable = mState.getProgramExecutable(); const gl::ProgramExecutable *executable = mState.getProgramExecutable();
...@@ -1372,7 +1424,7 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl( ...@@ -1372,7 +1424,7 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
if (executable->hasImages()) if (executable->hasImages())
{ {
ANGLE_TRY(updateActiveImages(context, commandBufferHelper)); ANGLE_TRY(updateActiveImages(commandBufferHelper));
} }
if (executable->hasUniformBuffers() || executable->hasStorageBuffers() || if (executable->hasUniformBuffers() || executable->hasStorageBuffers() ||
...@@ -1384,21 +1436,18 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl( ...@@ -1384,21 +1436,18 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::handleDirtyGraphicsShaderResources(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsShaderResources(DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer)
{ {
return handleDirtyShaderResourcesImpl(context, mRenderPassCommands); return handleDirtyShaderResourcesImpl(mRenderPassCommands);
} }
angle::Result ContextVk::handleDirtyComputeShaderResources(const gl::Context *context, angle::Result ContextVk::handleDirtyComputeShaderResources()
vk::CommandBuffer *commandBuffer)
{ {
return handleDirtyShaderResourcesImpl(context, mOutsideRenderPassCommands); return handleDirtyShaderResourcesImpl(mOutsideRenderPassCommands);
} }
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation( angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
const gl::Context *context, DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer)
{ {
const gl::ProgramExecutable *executable = mState.getProgramExecutable(); const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable); ASSERT(executable);
...@@ -1438,8 +1487,7 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation( ...@@ -1438,8 +1487,7 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
} }
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension( angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
const gl::Context *context, DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer)
{ {
const gl::ProgramExecutable *executable = mState.getProgramExecutable(); const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable); ASSERT(executable);
...@@ -1471,15 +1519,15 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension( ...@@ -1471,15 +1519,15 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferSizes = const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferSizes =
transformFeedbackVk->getBufferSizes(); transformFeedbackVk->getBufferSizes();
commandBuffer->bindTransformFeedbackBuffers(static_cast<uint32_t>(bufferCount), mRenderPassCommandBuffer->bindTransformFeedbackBuffers(
bufferHandles.data(), bufferOffsets.data(), static_cast<uint32_t>(bufferCount), bufferHandles.data(), bufferOffsets.data(),
bufferSizes.data()); bufferSizes.data());
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(
vk::CommandBuffer *commandBuffer) DirtyBits::Iterator *dirtyBitsIterator)
{ {
const gl::ProgramExecutable *executable = mState.getProgramExecutable(); const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable); ASSERT(executable);
...@@ -1505,8 +1553,7 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Con ...@@ -1505,8 +1553,7 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Con
} }
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume( angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume(
const gl::Context *context, DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer)
{ {
if (mRenderPassCommands->isTransformFeedbackStarted()) if (mRenderPassCommands->isTransformFeedbackStarted())
{ {
...@@ -1515,11 +1562,19 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume( ...@@ -1515,11 +1562,19 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume(
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::handleDirtyDescriptorSets(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsDescriptorSets(DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer)
{ {
ANGLE_TRY(mExecutable->updateDescriptorSets(this, commandBuffer)); return handleDirtyDescriptorSetsImpl(mRenderPassCommandBuffer);
return angle::Result::Continue; }
angle::Result ContextVk::handleDirtyComputeDescriptorSets()
{
return handleDirtyDescriptorSetsImpl(&mOutsideRenderPassCommands->getCommandBuffer());
}
angle::Result ContextVk::handleDirtyDescriptorSetsImpl(vk::CommandBuffer *commandBuffer)
{
return mExecutable->updateDescriptorSets(this, commandBuffer);
} }
void ContextVk::updateOverlayOnPresent() void ContextVk::updateOverlayOnPresent()
...@@ -1977,21 +2032,20 @@ angle::Result ContextVk::drawArrays(const gl::Context *context, ...@@ -1977,21 +2032,20 @@ angle::Result ContextVk::drawArrays(const gl::Context *context,
GLint first, GLint first,
GLsizei count) GLsizei count)
{ {
vk::CommandBuffer *commandBuffer = nullptr; uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
uint32_t numIndices; uint32_t numIndices;
ANGLE_TRY(setupLineLoopDraw(context, mode, first, count, gl::DrawElementsType::InvalidEnum, ANGLE_TRY(setupLineLoopDraw(context, mode, first, count, gl::DrawElementsType::InvalidEnum,
nullptr, &commandBuffer, &numIndices)); nullptr, &numIndices));
vk::LineLoopHelper::Draw(numIndices, 0, commandBuffer); vk::LineLoopHelper::Draw(numIndices, 0, mRenderPassCommandBuffer);
} }
else else
{ {
ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum, ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer)); nullptr, mNonIndexedDirtyBitsMask));
commandBuffer->draw(clampedVertexCount, first); mRenderPassCommandBuffer->draw(clampedVertexCount, first);
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -2003,22 +2057,20 @@ angle::Result ContextVk::drawArraysInstanced(const gl::Context *context, ...@@ -2003,22 +2057,20 @@ angle::Result ContextVk::drawArraysInstanced(const gl::Context *context,
GLsizei count, GLsizei count,
GLsizei instances) GLsizei instances)
{ {
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count); uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
uint32_t numIndices; uint32_t numIndices;
ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount, ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
gl::DrawElementsType::InvalidEnum, nullptr, &commandBuffer, gl::DrawElementsType::InvalidEnum, nullptr, &numIndices));
&numIndices)); mRenderPassCommandBuffer->drawIndexedInstanced(numIndices, instances);
commandBuffer->drawIndexedInstanced(numIndices, instances);
return angle::Result::Continue; return angle::Result::Continue;
} }
ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum, ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer)); nullptr, mNonIndexedDirtyBitsMask));
commandBuffer->drawInstanced(gl::GetClampedVertexCount<uint32_t>(count), instances, first); mRenderPassCommandBuffer->drawInstanced(gl::GetClampedVertexCount<uint32_t>(count), instances,
first);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -2029,24 +2081,21 @@ angle::Result ContextVk::drawArraysInstancedBaseInstance(const gl::Context *cont ...@@ -2029,24 +2081,21 @@ angle::Result ContextVk::drawArraysInstancedBaseInstance(const gl::Context *cont
GLsizei instances, GLsizei instances,
GLuint baseInstance) GLuint baseInstance)
{ {
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count); uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
uint32_t numIndices; uint32_t numIndices;
ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount, ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
gl::DrawElementsType::InvalidEnum, nullptr, &commandBuffer, gl::DrawElementsType::InvalidEnum, nullptr, &numIndices));
&numIndices)); mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(numIndices, instances,
commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(numIndices, instances, 0, 0, 0, 0, baseInstance);
baseInstance);
return angle::Result::Continue; return angle::Result::Continue;
} }
ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum, ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer)); nullptr, mNonIndexedDirtyBitsMask));
commandBuffer->drawInstancedBaseInstance(gl::GetClampedVertexCount<uint32_t>(count), instances, mRenderPassCommandBuffer->drawInstancedBaseInstance(gl::GetClampedVertexCount<uint32_t>(count),
first, baseInstance); instances, first, baseInstance);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -2056,18 +2105,16 @@ angle::Result ContextVk::drawElements(const gl::Context *context, ...@@ -2056,18 +2105,16 @@ angle::Result ContextVk::drawElements(const gl::Context *context,
gl::DrawElementsType type, gl::DrawElementsType type,
const void *indices) const void *indices)
{ {
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
uint32_t indexCount; uint32_t indexCount;
ANGLE_TRY( ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount)); vk::LineLoopHelper::Draw(indexCount, 0, mRenderPassCommandBuffer);
vk::LineLoopHelper::Draw(indexCount, 0, commandBuffer);
} }
else else
{ {
ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer)); ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
commandBuffer->drawIndexed(count); mRenderPassCommandBuffer->drawIndexed(count);
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -2080,18 +2127,16 @@ angle::Result ContextVk::drawElementsBaseVertex(const gl::Context *context, ...@@ -2080,18 +2127,16 @@ angle::Result ContextVk::drawElementsBaseVertex(const gl::Context *context,
const void *indices, const void *indices,
GLint baseVertex) GLint baseVertex)
{ {
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
uint32_t indexCount; uint32_t indexCount;
ANGLE_TRY( ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount)); vk::LineLoopHelper::Draw(indexCount, baseVertex, mRenderPassCommandBuffer);
vk::LineLoopHelper::Draw(indexCount, baseVertex, commandBuffer);
} }
else else
{ {
ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer)); ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
commandBuffer->drawIndexedBaseVertex(count, baseVertex); mRenderPassCommandBuffer->drawIndexedBaseVertex(count, baseVertex);
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -2104,21 +2149,18 @@ angle::Result ContextVk::drawElementsInstanced(const gl::Context *context, ...@@ -2104,21 +2149,18 @@ angle::Result ContextVk::drawElementsInstanced(const gl::Context *context,
const void *indices, const void *indices,
GLsizei instances) GLsizei instances)
{ {
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
uint32_t indexCount; uint32_t indexCount;
ANGLE_TRY( ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
count = indexCount; count = indexCount;
} }
else else
{ {
ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer)); ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
} }
commandBuffer->drawIndexedInstanced(count, instances); mRenderPassCommandBuffer->drawIndexedInstanced(count, instances);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -2130,21 +2172,18 @@ angle::Result ContextVk::drawElementsInstancedBaseVertex(const gl::Context *cont ...@@ -2130,21 +2172,18 @@ angle::Result ContextVk::drawElementsInstancedBaseVertex(const gl::Context *cont
GLsizei instances, GLsizei instances,
GLint baseVertex) GLint baseVertex)
{ {
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
uint32_t indexCount; uint32_t indexCount;
ANGLE_TRY( ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
count = indexCount; count = indexCount;
} }
else else
{ {
ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer)); ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
} }
commandBuffer->drawIndexedInstancedBaseVertex(count, instances, baseVertex); mRenderPassCommandBuffer->drawIndexedInstancedBaseVertex(count, instances, baseVertex);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -2157,21 +2196,18 @@ angle::Result ContextVk::drawElementsInstancedBaseVertexBaseInstance(const gl::C ...@@ -2157,21 +2196,18 @@ angle::Result ContextVk::drawElementsInstancedBaseVertexBaseInstance(const gl::C
GLint baseVertex, GLint baseVertex,
GLuint baseInstance) GLuint baseInstance)
{ {
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
uint32_t indexCount; uint32_t indexCount;
ANGLE_TRY( ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount)); mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(
commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(indexCount, instances, 0, indexCount, instances, 0, baseVertex, baseInstance);
baseVertex, baseInstance);
return angle::Result::Continue; return angle::Result::Continue;
} }
ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer)); ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(count, instances, 0, baseVertex, mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(count, instances, 0,
baseInstance); baseVertex, baseInstance);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -2232,8 +2268,6 @@ angle::Result ContextVk::drawArraysIndirect(const gl::Context *context, ...@@ -2232,8 +2268,6 @@ angle::Result ContextVk::drawArraysIndirect(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
ASSERT(indirectBuffer); ASSERT(indirectBuffer);
...@@ -2241,17 +2275,19 @@ angle::Result ContextVk::drawArraysIndirect(const gl::Context *context, ...@@ -2241,17 +2275,19 @@ angle::Result ContextVk::drawArraysIndirect(const gl::Context *context,
VkDeviceSize dstIndirectBufOffset = 0; VkDeviceSize dstIndirectBufOffset = 0;
ANGLE_TRY(setupLineLoopIndirectDraw(context, mode, currentIndirectBuf, ANGLE_TRY(setupLineLoopIndirectDraw(context, mode, currentIndirectBuf,
currentIndirectBufOffset, &commandBuffer, currentIndirectBufOffset, &dstIndirectBuf,
&dstIndirectBuf, &dstIndirectBufOffset)); &dstIndirectBufOffset));
commandBuffer->drawIndexedIndirect(dstIndirectBuf->getBuffer(), dstIndirectBufOffset, 1, 0); mRenderPassCommandBuffer->drawIndexedIndirect(dstIndirectBuf->getBuffer(),
dstIndirectBufOffset, 1, 0);
return angle::Result::Continue; return angle::Result::Continue;
} }
ANGLE_TRY(setupIndirectDraw(context, mode, mNonIndexedDirtyBitsMask, currentIndirectBuf, ANGLE_TRY(setupIndirectDraw(context, mode, mNonIndexedDirtyBitsMask, currentIndirectBuf,
currentIndirectBufOffset, &commandBuffer)); currentIndirectBufOffset));
commandBuffer->drawIndirect(currentIndirectBuf->getBuffer(), currentIndirectBufOffset, 1, 0); mRenderPassCommandBuffer->drawIndirect(currentIndirectBuf->getBuffer(),
currentIndirectBufOffset, 1, 0);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -2304,16 +2340,14 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context, ...@@ -2304,16 +2340,14 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
currentIndirectBufOffset = dstIndirectBufOffset; currentIndirectBufOffset = dstIndirectBufOffset;
} }
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
vk::BufferHelper *dstIndirectBuf; vk::BufferHelper *dstIndirectBuf;
VkDeviceSize dstIndirectBufOffset; VkDeviceSize dstIndirectBufOffset;
ANGLE_TRY(setupLineLoopIndexedIndirectDraw(context, mode, type, currentIndirectBuf, ANGLE_TRY(setupLineLoopIndexedIndirectDraw(context, mode, type, currentIndirectBuf,
currentIndirectBufOffset, &commandBuffer, currentIndirectBufOffset, &dstIndirectBuf,
&dstIndirectBuf, &dstIndirectBufOffset)); &dstIndirectBufOffset));
currentIndirectBuf = dstIndirectBuf; currentIndirectBuf = dstIndirectBuf;
currentIndirectBufOffset = dstIndirectBufOffset; currentIndirectBufOffset = dstIndirectBufOffset;
...@@ -2321,11 +2355,11 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context, ...@@ -2321,11 +2355,11 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
else else
{ {
ANGLE_TRY(setupIndexedIndirectDraw(context, mode, type, currentIndirectBuf, ANGLE_TRY(setupIndexedIndirectDraw(context, mode, type, currentIndirectBuf,
currentIndirectBufOffset, &commandBuffer)); currentIndirectBufOffset));
} }
commandBuffer->drawIndexedIndirect(currentIndirectBuf->getBuffer(), currentIndirectBufOffset, 1, mRenderPassCommandBuffer->drawIndexedIndirect(currentIndirectBuf->getBuffer(),
0); currentIndirectBufOffset, 1, 0);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -2759,10 +2793,10 @@ angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *co ...@@ -2759,10 +2793,10 @@ angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *co
} }
else else
{ {
invalidateCurrentGraphicsPipeline();
// No additional work is needed here. We will update the pipeline desc // No additional work is needed here. We will update the pipeline desc
// later. // later.
invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask()); invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
invalidateCurrentGraphicsPipeline();
invalidateVertexAndIndexBuffers(); invalidateVertexAndIndexBuffers();
bool useVertexBuffer = (executable->getMaxActiveAttribLocation() > 0); bool useVertexBuffer = (executable->getMaxActiveAttribLocation() > 0);
mNonIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer); mNonIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
...@@ -3005,6 +3039,7 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -3005,6 +3039,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
&mGraphicsPipelineTransition, depthStencilState, drawFramebuffer); &mGraphicsPipelineTransition, depthStencilState, drawFramebuffer);
mGraphicsPipelineDesc->updateStencilBackWriteMask( mGraphicsPipelineDesc->updateStencilBackWriteMask(
&mGraphicsPipelineTransition, depthStencilState, drawFramebuffer); &mGraphicsPipelineTransition, depthStencilState, drawFramebuffer);
mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
onDrawFramebufferRenderPassDescChange(mDrawFramebuffer); onDrawFramebufferRenderPassDescChange(mDrawFramebuffer);
break; break;
} }
...@@ -3508,11 +3543,11 @@ void ContextVk::onFramebufferChange(FramebufferVk *framebufferVk) ...@@ -3508,11 +3543,11 @@ void ContextVk::onFramebufferChange(FramebufferVk *framebufferVk)
updateScissor(mState); updateScissor(mState);
onDrawFramebufferRenderPassDescChange(framebufferVk); onDrawFramebufferRenderPassDescChange(framebufferVk);
invalidateCurrentGraphicsPipeline();
} }
void ContextVk::onDrawFramebufferRenderPassDescChange(FramebufferVk *framebufferVk) void ContextVk::onDrawFramebufferRenderPassDescChange(FramebufferVk *framebufferVk)
{ {
invalidateCurrentGraphicsPipeline();
mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition,
framebufferVk->getRenderPassDesc()); framebufferVk->getRenderPassDesc());
const gl::Box &dimensions = framebufferVk->getState().getDimensions(); const gl::Box &dimensions = framebufferVk->getState().getDimensions();
...@@ -3617,14 +3652,14 @@ angle::Result ContextVk::onPauseTransformFeedback() ...@@ -3617,14 +3652,14 @@ angle::Result ContextVk::onPauseTransformFeedback()
return angle::Result::Continue; return angle::Result::Continue;
} }
void ContextVk::invalidateGraphicsPipeline() void ContextVk::invalidateGraphicsPipelineBinding()
{ {
mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE); mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
} }
void ContextVk::invalidateComputePipeline() void ContextVk::invalidateComputePipelineBinding()
{ {
mComputeDirtyBits.set(DIRTY_BIT_PIPELINE); mComputeDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
} }
void ContextVk::invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet) void ContextVk::invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet)
...@@ -3652,25 +3687,23 @@ angle::Result ContextVk::dispatchCompute(const gl::Context *context, ...@@ -3652,25 +3687,23 @@ angle::Result ContextVk::dispatchCompute(const gl::Context *context,
GLuint numGroupsY, GLuint numGroupsY,
GLuint numGroupsZ) GLuint numGroupsZ)
{ {
vk::CommandBuffer *commandBuffer; ANGLE_TRY(setupDispatch(context));
ANGLE_TRY(setupDispatch(context, &commandBuffer));
commandBuffer->dispatch(numGroupsX, numGroupsY, numGroupsZ); mOutsideRenderPassCommands->getCommandBuffer().dispatch(numGroupsX, numGroupsY, numGroupsZ);
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) angle::Result ContextVk::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{ {
vk::CommandBuffer *commandBuffer; ANGLE_TRY(setupDispatch(context));
ANGLE_TRY(setupDispatch(context, &commandBuffer));
gl::Buffer *glBuffer = getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect); gl::Buffer *glBuffer = getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
vk::BufferHelper &buffer = vk::GetImpl(glBuffer)->getBuffer(); vk::BufferHelper &buffer = vk::GetImpl(glBuffer)->getBuffer();
mOutsideRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_INDIRECT_COMMAND_READ_BIT, mOutsideRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
vk::PipelineStage::DrawIndirect, &buffer); vk::PipelineStage::DrawIndirect, &buffer);
commandBuffer->dispatchIndirect(buffer.getBuffer(), indirect); mOutsideRenderPassCommands->getCommandBuffer().dispatchIndirect(buffer.getBuffer(), indirect);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -3826,8 +3859,7 @@ ANGLE_INLINE void ContextVk::pauseTransformFeedbackIfStarted(DirtyBits onResumeO ...@@ -3826,8 +3859,7 @@ ANGLE_INLINE void ContextVk::pauseTransformFeedbackIfStarted(DirtyBits onResumeO
} }
} }
angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator)
vk::CommandBuffer *commandBuffer)
{ {
// Allocate a new region in the dynamic buffer. // Allocate a new region in the dynamic buffer.
bool useGraphicsDriverUniformsExtended = getFeatures().forceDriverUniformOverSpecConst.enabled; bool useGraphicsDriverUniformsExtended = getFeatures().forceDriverUniformOverSpecConst.enabled;
...@@ -3951,8 +3983,7 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co ...@@ -3951,8 +3983,7 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co
&mDriverUniforms[PipelineType::Graphics]); &mDriverUniforms[PipelineType::Graphics]);
} }
angle::Result ContextVk::handleDirtyComputeDriverUniforms(const gl::Context *context, angle::Result ContextVk::handleDirtyComputeDriverUniforms()
vk::CommandBuffer *commandBuffer)
{ {
// Allocate a new region in the dynamic buffer. // Allocate a new region in the dynamic buffer.
uint8_t *ptr; uint8_t *ptr;
...@@ -3992,20 +4023,20 @@ void ContextVk::handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandB ...@@ -3992,20 +4023,20 @@ void ContextVk::handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandB
&driverUniforms->descriptorSet, 1, &driverUniforms->dynamicOffset); &driverUniforms->descriptorSet, 1, &driverUniforms->dynamicOffset);
} }
angle::Result ContextVk::handleDirtyGraphicsDriverUniformsBinding(const gl::Context *context, angle::Result ContextVk::handleDirtyGraphicsDriverUniformsBinding(
vk::CommandBuffer *commandBuffer) DirtyBits::Iterator *dirtyBitsIterator)
{ {
// Bind the driver descriptor set. // Bind the driver descriptor set.
handleDirtyDriverUniformsBindingImpl(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, handleDirtyDriverUniformsBindingImpl(mRenderPassCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
&mDriverUniforms[PipelineType::Graphics]); &mDriverUniforms[PipelineType::Graphics]);
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::handleDirtyComputeDriverUniformsBinding(const gl::Context *context, angle::Result ContextVk::handleDirtyComputeDriverUniformsBinding()
vk::CommandBuffer *commandBuffer)
{ {
// Bind the driver descriptor set. // Bind the driver descriptor set.
handleDirtyDriverUniformsBindingImpl(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, handleDirtyDriverUniformsBindingImpl(&mOutsideRenderPassCommands->getCommandBuffer(),
VK_PIPELINE_BIND_POINT_COMPUTE,
&mDriverUniforms[PipelineType::Compute]); &mDriverUniforms[PipelineType::Compute]);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -4230,8 +4261,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -4230,8 +4261,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::updateActiveImages(const gl::Context *context, angle::Result ContextVk::updateActiveImages(vk::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();
...@@ -4657,20 +4687,21 @@ angle::Result ContextVk::beginNewRenderPass( ...@@ -4657,20 +4687,21 @@ angle::Result ContextVk::beginNewRenderPass(
mRenderPassCommands->beginRenderPass(framebuffer, renderArea, renderPassDesc, mRenderPassCommands->beginRenderPass(framebuffer, renderArea, renderPassDesc,
renderPassAttachmentOps, depthStencilAttachmentIndex, renderPassAttachmentOps, depthStencilAttachmentIndex,
clearValues, commandBufferOut); clearValues, commandBufferOut);
// Restart at subpass 0.
mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
mPerfCounters.renderPasses++; mPerfCounters.renderPasses++;
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea, angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut)
{ {
mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits; ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, renderArea, &mRenderPassCommandBuffer,
renderPassDescChangedOut));
ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, renderArea, &mRenderPassCommandBuffer)); // Make sure the render pass is not restarted if it is started by UtilsVk (as opposed to
// setupDraw(), which clears this bit automatically).
mGraphicsDirtyBits.reset(DIRTY_BIT_RENDER_PASS);
ANGLE_TRY(resumeRenderPassQueriesIfActive()); ANGLE_TRY(resumeRenderPassQueriesIfActive());
...@@ -4795,6 +4826,11 @@ angle::Result ContextVk::flushCommandsAndEndRenderPass() ...@@ -4795,6 +4826,11 @@ angle::Result ContextVk::flushCommandsAndEndRenderPass()
ANGLE_TRY(flushImpl(nullptr)); ANGLE_TRY(flushImpl(nullptr));
} }
mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
// Restart at subpass 0.
mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -333,8 +333,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -333,8 +333,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
// When UtilsVk issues draw or dispatch calls, it binds a new pipeline and descriptor sets that // When UtilsVk issues draw or dispatch calls, it binds a new pipeline and descriptor sets that
// the context is not aware of. These functions are called to make sure the pipeline and // the context is not aware of. These functions are called to make sure the pipeline and
// affected descriptor set bindings are dirtied for the next application draw/dispatch call. // affected descriptor set bindings are dirtied for the next application draw/dispatch call.
void invalidateGraphicsPipeline(); void invalidateGraphicsPipelineBinding();
void invalidateComputePipeline(); void invalidateComputePipelineBinding();
void invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet); void invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet);
void invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet); void invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet);
...@@ -524,7 +524,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -524,7 +524,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
uint32_t getCurrentSubpassIndex() const; uint32_t getCurrentSubpassIndex() const;
egl::ContextPriority getContextPriority() const override { return mContextPriority; } egl::ContextPriority getContextPriority() const override { return mContextPriority; }
angle::Result startRenderPass(gl::Rectangle renderArea, vk::CommandBuffer **commandBufferOut); angle::Result startRenderPass(gl::Rectangle renderArea,
vk::CommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut);
void startNextSubpass(); void startNextSubpass();
angle::Result flushCommandsAndEndRenderPass(); angle::Result flushCommandsAndEndRenderPass();
...@@ -588,15 +590,29 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -588,15 +590,29 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
// Dirty bits. // Dirty bits.
enum DirtyBitType : size_t enum DirtyBitType : size_t
{ {
DIRTY_BIT_EVENT_LOG, // Dirty bits that must be processed before the render pass is started. The handlers for
// these dirty bits don't record any commands.
DIRTY_BIT_DEFAULT_ATTRIBS, DIRTY_BIT_DEFAULT_ATTRIBS,
DIRTY_BIT_PIPELINE, // The pipeline has changed and needs to be recreated. This dirty bit may close the render
// pass.
DIRTY_BIT_PIPELINE_DESC,
// Start the render pass.
DIRTY_BIT_RENDER_PASS,
// Dirty bits that must be processed after the render pass is started. Their handlers
// record commands.
DIRTY_BIT_EVENT_LOG,
// Pipeline needs to rebind because a new command buffer has been allocated, or UtilsVk has
// changed the binding. The pipeline itself doesn't need to be recreated.
DIRTY_BIT_PIPELINE_BINDING,
DIRTY_BIT_TEXTURES, DIRTY_BIT_TEXTURES,
DIRTY_BIT_VERTEX_BUFFERS, DIRTY_BIT_VERTEX_BUFFERS,
DIRTY_BIT_INDEX_BUFFER, DIRTY_BIT_INDEX_BUFFER,
DIRTY_BIT_DRIVER_UNIFORMS, DIRTY_BIT_DRIVER_UNIFORMS,
DIRTY_BIT_DRIVER_UNIFORMS_BINDING, DIRTY_BIT_DRIVER_UNIFORMS_BINDING,
DIRTY_BIT_SHADER_RESOURCES, // excluding textures, which are handled separately. // Shader resources excluding textures, which are handled separately.
DIRTY_BIT_SHADER_RESOURCES,
DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS, DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS,
DIRTY_BIT_TRANSFORM_FEEDBACK_STATE, DIRTY_BIT_TRANSFORM_FEEDBACK_STATE,
DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME, DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME,
...@@ -606,8 +622,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -606,8 +622,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
using DirtyBitHandler = angle::Result (ContextVk::*)(const gl::Context *, using GraphicsDirtyBitHandler =
vk::CommandBuffer *commandBuffer); angle::Result (ContextVk::*)(DirtyBits::Iterator *dirtyBitsIterator);
using ComputeDirtyBitHandler = angle::Result (ContextVk::*)();
struct DriverUniformsDescriptorSet struct DriverUniformsDescriptorSet
{ {
...@@ -684,42 +701,36 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -684,42 +701,36 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
GLsizei instanceCount, GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid, gl::DrawElementsType indexTypeOrInvalid,
const void *indices, const void *indices,
DirtyBits dirtyBitMask, DirtyBits dirtyBitMask);
vk::CommandBuffer **commandBufferOut);
angle::Result setupIndexedDraw(const gl::Context *context, angle::Result setupIndexedDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLsizei indexCount, GLsizei indexCount,
GLsizei instanceCount, GLsizei instanceCount,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
const void *indices, const void *indices);
vk::CommandBuffer **commandBufferOut);
angle::Result setupIndirectDraw(const gl::Context *context, angle::Result setupIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
DirtyBits dirtyBitMask, DirtyBits dirtyBitMask,
vk::BufferHelper *indirectBuffer, vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset, VkDeviceSize indirectBufferOffset);
vk::CommandBuffer **commandBufferOut);
angle::Result setupIndexedIndirectDraw(const gl::Context *context, angle::Result setupIndexedIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
vk::BufferHelper *indirectBuffer, vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset, VkDeviceSize indirectBufferOffset);
vk::CommandBuffer **commandBufferOut);
angle::Result setupLineLoopIndexedIndirectDraw(const gl::Context *context, angle::Result setupLineLoopIndexedIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
gl::DrawElementsType indexType, gl::DrawElementsType indexType,
vk::BufferHelper *srcIndirectBuf, vk::BufferHelper *srcIndirectBuf,
VkDeviceSize indirectBufferOffset, VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut,
vk::BufferHelper **indirectBufferOut, vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut); VkDeviceSize *indirectBufferOffsetOut);
angle::Result setupLineLoopIndirectDraw(const gl::Context *context, angle::Result setupLineLoopIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
vk::BufferHelper *indirectBuffer, vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset, VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut,
vk::BufferHelper **indirectBufferOut, vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut); VkDeviceSize *indirectBufferOffsetOut);
...@@ -729,9 +740,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -729,9 +740,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
GLsizei vertexOrIndexCount, GLsizei vertexOrIndexCount,
gl::DrawElementsType indexTypeOrInvalid, gl::DrawElementsType indexTypeOrInvalid,
const void *indices, const void *indices,
vk::CommandBuffer **commandBufferOut,
uint32_t *numIndicesOut); uint32_t *numIndicesOut);
angle::Result setupDispatch(const gl::Context *context, vk::CommandBuffer **commandBufferOut); angle::Result setupDispatch(const gl::Context *context);
gl::Rectangle getCorrectedViewport(const gl::Rectangle &viewport) const; gl::Rectangle getCorrectedViewport(const gl::Rectangle &viewport) const;
void updateViewport(FramebufferVk *framebufferVk, void updateViewport(FramebufferVk *framebufferVk,
...@@ -745,18 +755,19 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -745,18 +755,19 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
void updateSurfaceRotationReadFramebuffer(const gl::State &glState); void updateSurfaceRotationReadFramebuffer(const gl::State &glState);
angle::Result updateActiveTextures(const gl::Context *context); angle::Result updateActiveTextures(const gl::Context *context);
angle::Result updateActiveImages(const gl::Context *context, angle::Result updateActiveImages(vk::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()
{ {
mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE); // Note: DIRTY_BIT_PIPELINE_BIND will be automatically set if pipeline bind is necessary.
mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE_DESC);
} }
ANGLE_INLINE void invalidateCurrentComputePipeline() ANGLE_INLINE void invalidateCurrentComputePipeline()
{ {
mComputeDirtyBits.set(DIRTY_BIT_PIPELINE); mComputeDirtyBits.set(DIRTY_BIT_PIPELINE_DESC);
mComputeDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
mCurrentComputePipeline = nullptr; mCurrentComputePipeline = nullptr;
} }
...@@ -767,56 +778,44 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -767,56 +778,44 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
void invalidateDriverUniforms(); void invalidateDriverUniforms();
// Handlers for graphics pipeline dirty bits. // Handlers for graphics pipeline dirty bits.
angle::Result handleDirtyGraphicsEventLog(const gl::Context *context, angle::Result handleDirtyGraphicsEventLog(DirtyBits::Iterator *dirtyBitsIterator);
vk::CommandBuffer *commandBuffer); angle::Result handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsDefaultAttribs(const gl::Context *context, angle::Result handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator *dirtyBitsIterator);
vk::CommandBuffer *commandBuffer); angle::Result handleDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsPipeline(const gl::Context *context, angle::Result handleDirtyGraphicsPipelineBinding(DirtyBits::Iterator *dirtyBitsIterator);
vk::CommandBuffer *commandBuffer); angle::Result handleDirtyGraphicsTextures(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsTextures(const gl::Context *context, angle::Result handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *dirtyBitsIterator);
vk::CommandBuffer *commandBuffer); angle::Result handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsVertexBuffers(const gl::Context *context, angle::Result handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator);
vk::CommandBuffer *commandBuffer); angle::Result handleDirtyGraphicsDriverUniformsBinding(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsIndexBuffer(const gl::Context *context, angle::Result handleDirtyGraphicsShaderResources(DirtyBits::Iterator *dirtyBitsIterator);
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsDriverUniforms(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsDriverUniformsBinding(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsShaderResources(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsTransformFeedbackBuffersEmulation( angle::Result handleDirtyGraphicsTransformFeedbackBuffersEmulation(
const gl::Context *context, DirtyBits::Iterator *dirtyBitsIterator);
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsTransformFeedbackBuffersExtension( angle::Result handleDirtyGraphicsTransformFeedbackBuffersExtension(
const gl::Context *context, DirtyBits::Iterator *dirtyBitsIterator);
vk::CommandBuffer *commandBuffer); angle::Result handleDirtyGraphicsTransformFeedbackState(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsTransformFeedbackState(const gl::Context *context, angle::Result handleDirtyGraphicsTransformFeedbackResume(
vk::CommandBuffer *commandBuffer); DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsTransformFeedbackResume(const gl::Context *context, angle::Result handleDirtyGraphicsDescriptorSets(DirtyBits::Iterator *dirtyBitsIterator);
vk::CommandBuffer *commandBuffer);
// Handlers for compute pipeline dirty bits. // Handlers for compute pipeline dirty bits.
angle::Result handleDirtyComputePipeline(const gl::Context *context, angle::Result handleDirtyComputeEventLog();
vk::CommandBuffer *commandBuffer); angle::Result handleDirtyComputePipelineDesc();
angle::Result handleDirtyComputeTextures(const gl::Context *context, angle::Result handleDirtyComputePipelineBinding();
vk::CommandBuffer *commandBuffer); angle::Result handleDirtyComputeTextures();
angle::Result handleDirtyComputeDriverUniforms(const gl::Context *context, angle::Result handleDirtyComputeDriverUniforms();
vk::CommandBuffer *commandBuffer); angle::Result handleDirtyComputeDriverUniformsBinding();
angle::Result handleDirtyComputeDriverUniformsBinding(const gl::Context *context, angle::Result handleDirtyComputeShaderResources();
vk::CommandBuffer *commandBuffer); angle::Result handleDirtyComputeDescriptorSets();
angle::Result handleDirtyComputeShaderResources(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
// Common parts of the common dirty bit handlers. // Common parts of the common dirty bit handlers.
angle::Result handleDirtyEventLogImpl(vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyTexturesImpl(vk::CommandBufferHelper *commandBufferHelper); angle::Result handleDirtyTexturesImpl(vk::CommandBufferHelper *commandBufferHelper);
angle::Result handleDirtyShaderResourcesImpl(const gl::Context *context, angle::Result handleDirtyShaderResourcesImpl(vk::CommandBufferHelper *commandBufferHelper);
vk::CommandBufferHelper *commandBufferHelper);
void handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandBuffer, void handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandBuffer,
VkPipelineBindPoint bindPoint, VkPipelineBindPoint bindPoint,
DriverUniformsDescriptorSet *driverUniforms); DriverUniformsDescriptorSet *driverUniforms);
angle::Result handleDirtyDescriptorSets(const gl::Context *context, angle::Result handleDirtyDescriptorSetsImpl(vk::CommandBuffer *commandBuffer);
vk::CommandBuffer *commandBuffer);
angle::Result allocateDriverUniforms(size_t driverUniformsSize, angle::Result allocateDriverUniforms(size_t driverUniformsSize,
DriverUniformsDescriptorSet *driverUniforms, DriverUniformsDescriptorSet *driverUniforms,
uint8_t **ptrOut, uint8_t **ptrOut,
...@@ -876,8 +875,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -876,8 +875,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
SpecConstUsageBits getCurrentProgramSpecConstUsageBits() const; SpecConstUsageBits getCurrentProgramSpecConstUsageBits() const;
void updateGraphicsPipelineDescWithSpecConstUsageBits(SpecConstUsageBits usageBits); void updateGraphicsPipelineDescWithSpecConstUsageBits(SpecConstUsageBits usageBits);
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers; std::array<GraphicsDirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers;
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers; std::array<ComputeDirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers;
vk::CommandBuffer *mRenderPassCommandBuffer; vk::CommandBuffer *mRenderPassCommandBuffer;
......
...@@ -2318,7 +2318,8 @@ angle::Result FramebufferVk::getSamplePosition(const gl::Context *context, ...@@ -2318,7 +2318,8 @@ angle::Result FramebufferVk::getSamplePosition(const gl::Context *context,
angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
const gl::Rectangle &scissoredRenderArea, const gl::Rectangle &scissoredRenderArea,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut)
{ {
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass()); ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
...@@ -2536,13 +2537,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2536,13 +2537,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
// or the existence of resolve attachments in single subpass render passes. The modification // or the existence of resolve attachments in single subpass render passes. The modification
// here can add/remove a subpass, or modify its input attachments. // here can add/remove a subpass, or modify its input attachments.
gl::DrawBufferMask unresolveColorMask = mRenderPassDesc.getColorUnresolveAttachmentMask(); gl::DrawBufferMask unresolveColorMask = mRenderPassDesc.getColorUnresolveAttachmentMask();
bool unresolveDepth = mRenderPassDesc.hasDepthUnresolveAttachment(); const bool unresolveDepth = mRenderPassDesc.hasDepthUnresolveAttachment();
bool unresolveStencil = mRenderPassDesc.hasStencilUnresolveAttachment(); const bool unresolveStencil = mRenderPassDesc.hasStencilUnresolveAttachment();
if (previousUnresolveColorMask != unresolveColorMask || const bool unresolveChanged = previousUnresolveColorMask != unresolveColorMask ||
previousUnresolveDepth != unresolveDepth || previousUnresolveStencil != unresolveStencil) previousUnresolveDepth != unresolveDepth ||
previousUnresolveStencil != unresolveStencil;
if (unresolveChanged)
{ {
contextVk->onDrawFramebufferRenderPassDescChange(this);
// Make sure framebuffer is recreated. // Make sure framebuffer is recreated.
mFramebuffer = nullptr; mFramebuffer = nullptr;
...@@ -2580,7 +2581,8 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2580,7 +2581,8 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
mCurrentFramebufferDesc.getLayerCount()); mCurrentFramebufferDesc.getLayerCount());
} }
if (unresolveColorMask.any() || unresolveDepth || unresolveStencil) const bool anyUnresolve = unresolveColorMask.any() || unresolveDepth || unresolveStencil;
if (anyUnresolve)
{ {
// Unresolve attachments if any. // Unresolve attachments if any.
UtilsVk::UnresolveParameters params; UtilsVk::UnresolveParameters params;
...@@ -2594,6 +2596,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2594,6 +2596,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
contextVk->startNextSubpass(); contextVk->startNextSubpass();
} }
if (unresolveChanged || anyUnresolve)
{
contextVk->onDrawFramebufferRenderPassDescChange(this);
// Notify that the render pass desc has changed.
*renderPassDescChangedOut = true;
}
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -2701,7 +2710,7 @@ angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk) ...@@ -2701,7 +2710,7 @@ angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk)
return angle::Result::Continue; return angle::Result::Continue;
} }
return contextVk->startRenderPass(getRotatedCompleteRenderArea(contextVk), nullptr); return contextVk->startRenderPass(getRotatedCompleteRenderArea(contextVk), nullptr, nullptr);
} }
void FramebufferVk::updateRenderPassReadOnlyDepthMode(ContextVk *contextVk, void FramebufferVk::updateRenderPassReadOnlyDepthMode(ContextVk *contextVk,
......
...@@ -138,7 +138,8 @@ class FramebufferVk : public FramebufferImpl ...@@ -138,7 +138,8 @@ class FramebufferVk : public FramebufferImpl
angle::Result startNewRenderPass(ContextVk *contextVk, angle::Result startNewRenderPass(ContextVk *contextVk,
const gl::Rectangle &scissoredRenderArea, const gl::Rectangle &scissoredRenderArea,
vk::CommandBuffer **commandBufferOut); vk::CommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut);
RenderTargetVk *getFirstRenderTarget() const; RenderTargetVk *getFirstRenderTarget() const;
GLint getSamples() const; GLint getSamples() const;
......
...@@ -996,7 +996,7 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk, ...@@ -996,7 +996,7 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
pipelineAndSerial->updateSerial(serial); pipelineAndSerial->updateSerial(serial);
commandBuffer->bindComputePipeline(pipelineAndSerial->get()); commandBuffer->bindComputePipeline(pipelineAndSerial->get());
contextVk->invalidateComputePipeline(); contextVk->invalidateComputePipelineBinding();
} }
else else
{ {
...@@ -1017,7 +1017,7 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk, ...@@ -1017,7 +1017,7 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
helper->updateSerial(serial); helper->updateSerial(serial);
commandBuffer->bindGraphicsPipeline(helper->getPipeline()); commandBuffer->bindGraphicsPipeline(helper->getPipeline());
contextVk->invalidateGraphicsPipeline(); contextVk->invalidateGraphicsPipelineBinding();
} }
if (descriptorSet != VK_NULL_HANDLE) if (descriptorSet != VK_NULL_HANDLE)
...@@ -1492,7 +1492,9 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk, ...@@ -1492,7 +1492,9 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
} }
else else
{ {
ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer)); bool renderPassDescChanged = false;
ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer,
&renderPassDescChanged));
} }
if (params.clearStencil || params.clearDepth) if (params.clearStencil || params.clearDepth)
...@@ -1810,7 +1812,7 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, ...@@ -1810,7 +1812,7 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea)); pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer)); ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer, nullptr));
contextVk->onImageRenderPassRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly, contextVk->onImageRenderPassRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly,
src); src);
......
...@@ -943,6 +943,63 @@ TEST_P(StateChangeTest, VertexBufferUpdatedAfterDraw) ...@@ -943,6 +943,63 @@ TEST_P(StateChangeTest, VertexBufferUpdatedAfterDraw)
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
// Tests that drawing after flush without any state change works.
TEST_P(StateChangeTest, DrawAfterFlushWithNoStateChange)
{
// Draw (0.125, 0.25, 0.5, 0.5) once, using additive blend
ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
glUseProgram(drawColor);
GLint colorUniformLocation =
glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
ASSERT_NE(colorUniformLocation, -1);
GLint positionLocation = glGetAttribLocation(drawColor, essl1_shaders::PositionAttrib());
ASSERT_NE(-1, positionLocation);
// Setup VAO
const auto &quadVertices = GetQuadVertices();
GLBuffer vertexBuffer;
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
GLVertexArray vertexArray;
glBindVertexArray(vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(positionLocation);
ASSERT_GL_NO_ERROR();
// Clear and draw
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glUniform4f(colorUniformLocation, 0.125f, 0.25f, 0.5f, 0.5f);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
// Make sure the work is submitted.
glFinish();
// Draw again with no state change
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
// Make sure the pixels have the correct colors.
const int h = getWindowHeight() - 1;
const int w = getWindowWidth() - 1;
const GLColor kExpected(63, 127, 255, 255);
EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, kExpected, 1);
EXPECT_PIXEL_COLOR_NEAR(0, h - 1, kExpected, 1);
EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, kExpected, 1);
}
// Test that switching VAOs keeps the disabled "current value" attributes up-to-date. // Test that switching VAOs keeps the disabled "current value" attributes up-to-date.
TEST_P(StateChangeTestES3, VertexArrayObjectAndDisabledAttributes) TEST_P(StateChangeTestES3, VertexArrayObjectAndDisabledAttributes)
{ {
......
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