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()
pauseRenderPassQueriesIfActive();
mRenderPassCommandBuffer = nullptr;
mGraphicsDirtyBits.set(DIRTY_BIT_RENDER_PASS);
}
// ContextVk::ScopedDescriptorSetUpdates implementation.
......@@ -366,7 +367,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mDrawFramebuffer(nullptr),
mProgram(nullptr),
mExecutable(nullptr),
mLastIndexBufferOffset(0),
mLastIndexBufferOffset(nullptr),
mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum),
mXfbBaseVertex(0),
mXfbVertexCountPerInstance(0),
......@@ -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
// 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.
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_VERTEX_BUFFERS);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
......@@ -419,7 +421,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
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_SHADER_RESOURCES);
mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
......@@ -428,7 +430,11 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mGraphicsDirtyBitHandlers[DIRTY_BIT_EVENT_LOG] = &ContextVk::handleDirtyGraphicsEventLog;
mGraphicsDirtyBitHandlers[DIRTY_BIT_DEFAULT_ATTRIBS] =
&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_VERTEX_BUFFERS] =
&ContextVk::handleDirtyGraphicsVertexBuffers;
......@@ -454,18 +460,22 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
&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_PIPELINE] = &ContextVk::handleDirtyComputePipeline;
mComputeDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyComputeTextures;
mComputeDirtyBitHandlers[DIRTY_BIT_EVENT_LOG] = &ContextVk::handleDirtyComputeEventLog;
mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE_DESC] = &ContextVk::handleDirtyComputePipelineDesc;
mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE_BINDING] =
&ContextVk::handleDirtyComputePipelineBinding;
mComputeDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyComputeTextures;
mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] =
&ContextVk::handleDirtyComputeDriverUniforms;
mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS_BINDING] =
&ContextVk::handleDirtyComputeDriverUniformsBinding;
mComputeDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] =
&ContextVk::handleDirtyComputeShaderResources;
mComputeDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] = &ContextVk::handleDirtyDescriptorSets;
mComputeDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] =
&ContextVk::handleDirtyComputeDescriptorSets;
mGraphicsDirtyBits = mNewGraphicsCommandBufferDirtyBits;
mComputeDirtyBits = mNewComputeCommandBufferDirtyBits;
......@@ -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,
// - CLEAR_* only affect following clear calls,
// - PACK/UNPACK_STATE only affect texture data upload/download,
// - *_BINDING only affect descriptor sets,
// - CURRENT_VALUES only affects (default) vertex attributes.
// - *_BINDING only affect descriptor sets.
//
mPipelineDirtyBitsMask.set();
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
......@@ -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_BUFFER_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_DISPATCH_INDIRECT_BUFFER_BINDING);
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_SAMPLER_BINDINGS);
......@@ -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_SHADER_STORAGE_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
mDescriptorBufferInfos.reserve(kDescriptorBufferInfosInitialSize);
......@@ -766,8 +773,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid,
const void *indices,
DirtyBits dirtyBitMask,
vk::CommandBuffer **commandBufferOut)
DirtyBits dirtyBitMask)
{
// Set any dirty bits that depend on draw call parameters or other objects.
if (mode != mCurrentDrawMode)
......@@ -788,23 +794,6 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
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
// function
ScopedDescriptorSetUpdates descriptorSetUpdates(this);
......@@ -836,18 +825,30 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
if (dirtyBits.none())
{
ASSERT(mRenderPassCommandBuffer);
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.
for (size_t dirtyBit : dirtyBits)
for (DirtyBits::Iterator dirtyBitIter = dirtyBits.begin(); dirtyBitIter != dirtyBits.end();
++dirtyBitIter)
{
ASSERT(mGraphicsDirtyBitHandlers[dirtyBit]);
ANGLE_TRY((this->*mGraphicsDirtyBitHandlers[dirtyBit])(context, *commandBufferOut));
ASSERT(mGraphicsDirtyBitHandlers[*dirtyBitIter]);
ANGLE_TRY((this->*mGraphicsDirtyBitHandlers[*dirtyBitIter])(&dirtyBitIter));
}
mGraphicsDirtyBits &= ~dirtyBitMask;
// Render pass must be always available at this point.
ASSERT(mRenderPassCommandBuffer);
return angle::Result::Continue;
}
......@@ -856,8 +857,7 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
GLsizei indexCount,
GLsizei instanceCount,
gl::DrawElementsType indexType,
const void *indices,
vk::CommandBuffer **commandBufferOut)
const void *indices)
{
ASSERT(mode != gl::PrimitiveMode::LineLoop);
......@@ -909,15 +909,14 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
}
return setupDraw(context, mode, 0, indexCount, instanceCount, indexType, indices,
mIndexedDirtyBitsMask, commandBufferOut);
mIndexedDirtyBitsMask);
}
angle::Result ContextVk::setupIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode,
DirtyBits dirtyBitMask,
vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut)
VkDeviceSize indirectBufferOffset)
{
GLint firstVertex = -1;
GLsizei vertexCount = 0;
......@@ -933,8 +932,7 @@ angle::Result ContextVk::setupIndirectDraw(const gl::Context *context,
vk::PipelineStage::DrawIndirect, indirectBuffer);
ANGLE_TRY(setupDraw(context, mode, firstVertex, vertexCount, instanceCount,
gl::DrawElementsType::InvalidEnum, nullptr, dirtyBitMask,
commandBufferOut));
gl::DrawElementsType::InvalidEnum, nullptr, dirtyBitMask));
return angle::Result::Continue;
}
......@@ -943,8 +941,7 @@ angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode,
gl::DrawElementsType indexType,
vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut)
VkDeviceSize indirectBufferOffset)
{
ASSERT(mode != gl::PrimitiveMode::LineLoop);
......@@ -955,7 +952,7 @@ angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context,
}
return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBuffer,
indirectBufferOffset, commandBufferOut);
indirectBufferOffset);
}
angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *context,
......@@ -963,7 +960,6 @@ angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *con
gl::DrawElementsType indexType,
vk::BufferHelper *srcIndirectBuf,
VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut,
vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut)
{
......@@ -986,14 +982,13 @@ angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *con
}
return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, dstIndirectBuf,
dstIndirectBufOffset, commandBufferOut);
dstIndirectBufOffset);
}
angle::Result ContextVk::setupLineLoopIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode,
vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut,
vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut)
{
......@@ -1014,7 +1009,7 @@ angle::Result ContextVk::setupLineLoopIndirectDraw(const gl::Context *context,
}
return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBufferHelperOut,
*indirectBufferOffsetOut, commandBufferOut);
*indirectBufferOffsetOut);
}
angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
......@@ -1023,7 +1018,6 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
GLsizei vertexOrIndexCount,
gl::DrawElementsType indexTypeOrInvalid,
const void *indices,
vk::CommandBuffer **commandBufferOut,
uint32_t *numIndicesOut)
{
ANGLE_TRY(mVertexArray->handleLineLoop(this, firstVertex, vertexOrIndexCount,
......@@ -1033,17 +1027,15 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
? indexTypeOrInvalid
: gl::DrawElementsType::UnsignedInt;
return setupDraw(context, mode, firstVertex, vertexOrIndexCount, 1, indexTypeOrInvalid, indices,
mIndexedDirtyBitsMask, commandBufferOut);
mIndexedDirtyBitsMask);
}
angle::Result ContextVk::setupDispatch(const gl::Context *context,
vk::CommandBuffer **commandBufferOut)
angle::Result ContextVk::setupDispatch(const gl::Context *context)
{
// |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.
// The following ensures prior commands are flushed before we start processing dirty bits.
ANGLE_TRY(flushCommandsAndEndRenderPass());
*commandBufferOut = &mOutsideRenderPassCommands->getCommandBuffer();
// Create a local object to ensure we flush the descriptor updates to device when we leave this
// function
......@@ -1066,7 +1058,7 @@ angle::Result ContextVk::setupDispatch(const gl::Context *context,
for (size_t dirtyBit : dirtyBits)
{
ASSERT(mComputeDirtyBitHandlers[dirtyBit]);
ANGLE_TRY((this->*mComputeDirtyBitHandlers[dirtyBit])(context, *commandBufferOut));
ANGLE_TRY((this->*mComputeDirtyBitHandlers[dirtyBit])());
}
mComputeDirtyBits.reset();
......@@ -1074,8 +1066,17 @@ angle::Result ContextVk::setupDispatch(const gl::Context *context,
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyGraphicsEventLog(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsEventLog(DirtyBits::Iterator *dirtyBitsIterator)
{
return handleDirtyEventLogImpl(mRenderPassCommandBuffer);
}
angle::Result ContextVk::handleDirtyComputeEventLog()
{
return handleDirtyEventLogImpl(&mOutsideRenderPassCommands->getCommandBuffer());
}
angle::Result ContextVk::handleDirtyEventLogImpl(vk::CommandBuffer *commandBuffer)
{
if (mEventLog.empty())
{
......@@ -1125,8 +1126,7 @@ angle::Result ContextVk::handleDirtyGraphicsEventLog(const gl::Context *context,
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator *dirtyBitsIterator)
{
ASSERT(mDirtyDefaultAttribsMask.any());
......@@ -1139,9 +1139,12 @@ angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(const gl::Context *co
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator *dirtyBitsIterator)
{
const VkPipeline previousPipeline = mCurrentGraphicsPipeline
? mCurrentGraphicsPipeline->getPipeline().getHandle()
: VK_NULL_HANDLE;
ASSERT(mExecutable);
if (!mCurrentGraphicsPipeline)
......@@ -1156,8 +1159,8 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
// Draw call shader patching, shader compilation, and pipeline cache query.
ANGLE_TRY(mExecutable->getGraphicsPipeline(
this, mCurrentDrawMode, *mGraphicsPipelineDesc,
context->getState().getProgramExecutable()->getNonBuiltinAttribLocationsMask(),
&descPtr, &mCurrentGraphicsPipeline));
mState.getProgramExecutable()->getNonBuiltinAttribLocationsMask(), &descPtr,
&mCurrentGraphicsPipeline));
mGraphicsPipelineTransition.reset();
}
else if (mGraphicsPipelineTransition.any())
......@@ -1170,8 +1173,8 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
ANGLE_TRY(mExecutable->getGraphicsPipeline(
this, mCurrentDrawMode, *mGraphicsPipelineDesc,
context->getState().getProgramExecutable()->getNonBuiltinAttribLocationsMask(),
&descPtr, &mCurrentGraphicsPipeline));
mState.getProgramExecutable()->getNonBuiltinAttribLocationsMask(), &descPtr,
&mCurrentGraphicsPipeline));
oldPipeline->addTransition(mGraphicsPipelineTransition, descPtr,
mCurrentGraphicsPipeline);
......@@ -1179,20 +1182,63 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
mGraphicsPipelineTransition.reset();
}
pauseTransformFeedbackIfStarted({});
commandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline());
// Update the queue serial for the pipeline object.
ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid());
// TODO: https://issuetracker.google.com/issues/169788986: Need to change this so that we get
// the actual serial used when this work is submitted.
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;
}
angle::Result ContextVk::handleDirtyComputePipeline(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator)
{
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)
{
......@@ -1200,7 +1246,17 @@ angle::Result ContextVk::handleDirtyComputePipeline(const gl::Context *context,
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
// the actual serial used when this work is submitted.
mCurrentComputePipeline->updateSerial(getCurrentQueueSerial());
......@@ -1306,33 +1362,31 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyGraphicsTextures(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsTextures(DirtyBits::Iterator *dirtyBitsIterator)
{
return handleDirtyTexturesImpl(mRenderPassCommands);
}
angle::Result ContextVk::handleDirtyComputeTextures(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyComputeTextures()
{
return handleDirtyTexturesImpl(mOutsideRenderPassCommands);
}
angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *dirtyBitsIterator)
{
uint32_t maxAttrib = context->getState().getProgramExecutable()->getMaxActiveAttribLocation();
uint32_t maxAttrib = mState.getProgramExecutable()->getMaxActiveAttribLocation();
const gl::AttribArray<VkBuffer> &bufferHandles = mVertexArray->getCurrentArrayBufferHandles();
const gl::AttribArray<VkDeviceSize> &bufferOffsets =
mVertexArray->getCurrentArrayBufferOffsets();
commandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(), bufferOffsets.data());
mRenderPassCommandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(),
bufferOffsets.data());
const gl::AttribArray<vk::BufferHelper *> &arrayBufferResources =
mVertexArray->getCurrentArrayBuffers();
// 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();
for (size_t attribIndex : attribsMask)
{
......@@ -1347,15 +1401,14 @@ angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(const gl::Context *con
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator *dirtyBitsIterator)
{
vk::BufferHelper *elementArrayBuffer = mVertexArray->getCurrentElementArrayBuffer();
ASSERT(elementArrayBuffer != nullptr);
commandBuffer->bindIndexBuffer(elementArrayBuffer->getBuffer(),
mVertexArray->getCurrentElementArrayBufferOffset(),
getVkIndexType(mCurrentDrawElementsType));
mRenderPassCommandBuffer->bindIndexBuffer(elementArrayBuffer->getBuffer(),
mVertexArray->getCurrentElementArrayBufferOffset(),
getVkIndexType(mCurrentDrawElementsType));
mRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_INDEX_READ_BIT,
vk::PipelineStage::VertexInput, elementArrayBuffer);
......@@ -1364,7 +1417,6 @@ angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(const gl::Context *conte
}
ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
const gl::Context *context,
vk::CommandBufferHelper *commandBufferHelper)
{
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
......@@ -1372,7 +1424,7 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
if (executable->hasImages())
{
ANGLE_TRY(updateActiveImages(context, commandBufferHelper));
ANGLE_TRY(updateActiveImages(commandBufferHelper));
}
if (executable->hasUniformBuffers() || executable->hasStorageBuffers() ||
......@@ -1384,21 +1436,18 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyGraphicsShaderResources(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsShaderResources(DirtyBits::Iterator *dirtyBitsIterator)
{
return handleDirtyShaderResourcesImpl(context, mRenderPassCommands);
return handleDirtyShaderResourcesImpl(mRenderPassCommands);
}
angle::Result ContextVk::handleDirtyComputeShaderResources(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyComputeShaderResources()
{
return handleDirtyShaderResourcesImpl(context, mOutsideRenderPassCommands);
return handleDirtyShaderResourcesImpl(mOutsideRenderPassCommands);
}
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
const gl::Context *context,
vk::CommandBuffer *commandBuffer)
DirtyBits::Iterator *dirtyBitsIterator)
{
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
......@@ -1438,8 +1487,7 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
}
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
const gl::Context *context,
vk::CommandBuffer *commandBuffer)
DirtyBits::Iterator *dirtyBitsIterator)
{
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
......@@ -1471,15 +1519,15 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferSizes =
transformFeedbackVk->getBufferSizes();
commandBuffer->bindTransformFeedbackBuffers(static_cast<uint32_t>(bufferCount),
bufferHandles.data(), bufferOffsets.data(),
bufferSizes.data());
mRenderPassCommandBuffer->bindTransformFeedbackBuffers(
static_cast<uint32_t>(bufferCount), bufferHandles.data(), bufferOffsets.data(),
bufferSizes.data());
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(
DirtyBits::Iterator *dirtyBitsIterator)
{
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
......@@ -1505,8 +1553,7 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Con
}
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume(
const gl::Context *context,
vk::CommandBuffer *commandBuffer)
DirtyBits::Iterator *dirtyBitsIterator)
{
if (mRenderPassCommands->isTransformFeedbackStarted())
{
......@@ -1515,11 +1562,19 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume(
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyDescriptorSets(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsDescriptorSets(DirtyBits::Iterator *dirtyBitsIterator)
{
ANGLE_TRY(mExecutable->updateDescriptorSets(this, commandBuffer));
return angle::Result::Continue;
return handleDirtyDescriptorSetsImpl(mRenderPassCommandBuffer);
}
angle::Result ContextVk::handleDirtyComputeDescriptorSets()
{
return handleDirtyDescriptorSetsImpl(&mOutsideRenderPassCommands->getCommandBuffer());
}
angle::Result ContextVk::handleDirtyDescriptorSetsImpl(vk::CommandBuffer *commandBuffer)
{
return mExecutable->updateDescriptorSets(this, commandBuffer);
}
void ContextVk::updateOverlayOnPresent()
......@@ -1977,21 +2032,20 @@ angle::Result ContextVk::drawArrays(const gl::Context *context,
GLint first,
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)
{
uint32_t numIndices;
ANGLE_TRY(setupLineLoopDraw(context, mode, first, count, gl::DrawElementsType::InvalidEnum,
nullptr, &commandBuffer, &numIndices));
vk::LineLoopHelper::Draw(numIndices, 0, commandBuffer);
nullptr, &numIndices));
vk::LineLoopHelper::Draw(numIndices, 0, mRenderPassCommandBuffer);
}
else
{
ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->draw(clampedVertexCount, first);
nullptr, mNonIndexedDirtyBitsMask));
mRenderPassCommandBuffer->draw(clampedVertexCount, first);
}
return angle::Result::Continue;
......@@ -2003,22 +2057,20 @@ angle::Result ContextVk::drawArraysInstanced(const gl::Context *context,
GLsizei count,
GLsizei instances)
{
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop)
{
uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
uint32_t numIndices;
ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
gl::DrawElementsType::InvalidEnum, nullptr, &commandBuffer,
&numIndices));
commandBuffer->drawIndexedInstanced(numIndices, instances);
gl::DrawElementsType::InvalidEnum, nullptr, &numIndices));
mRenderPassCommandBuffer->drawIndexedInstanced(numIndices, instances);
return angle::Result::Continue;
}
ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->drawInstanced(gl::GetClampedVertexCount<uint32_t>(count), instances, first);
nullptr, mNonIndexedDirtyBitsMask));
mRenderPassCommandBuffer->drawInstanced(gl::GetClampedVertexCount<uint32_t>(count), instances,
first);
return angle::Result::Continue;
}
......@@ -2029,24 +2081,21 @@ angle::Result ContextVk::drawArraysInstancedBaseInstance(const gl::Context *cont
GLsizei instances,
GLuint baseInstance)
{
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop)
{
uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
uint32_t numIndices;
ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
gl::DrawElementsType::InvalidEnum, nullptr, &commandBuffer,
&numIndices));
commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(numIndices, instances, 0, 0,
baseInstance);
gl::DrawElementsType::InvalidEnum, nullptr, &numIndices));
mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(numIndices, instances,
0, 0, baseInstance);
return angle::Result::Continue;
}
ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->drawInstancedBaseInstance(gl::GetClampedVertexCount<uint32_t>(count), instances,
first, baseInstance);
nullptr, mNonIndexedDirtyBitsMask));
mRenderPassCommandBuffer->drawInstancedBaseInstance(gl::GetClampedVertexCount<uint32_t>(count),
instances, first, baseInstance);
return angle::Result::Continue;
}
......@@ -2056,18 +2105,16 @@ angle::Result ContextVk::drawElements(const gl::Context *context,
gl::DrawElementsType type,
const void *indices)
{
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop)
{
uint32_t indexCount;
ANGLE_TRY(
setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
vk::LineLoopHelper::Draw(indexCount, 0, commandBuffer);
ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
vk::LineLoopHelper::Draw(indexCount, 0, mRenderPassCommandBuffer);
}
else
{
ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer));
commandBuffer->drawIndexed(count);
ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
mRenderPassCommandBuffer->drawIndexed(count);
}
return angle::Result::Continue;
......@@ -2080,18 +2127,16 @@ angle::Result ContextVk::drawElementsBaseVertex(const gl::Context *context,
const void *indices,
GLint baseVertex)
{
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop)
{
uint32_t indexCount;
ANGLE_TRY(
setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
vk::LineLoopHelper::Draw(indexCount, baseVertex, commandBuffer);
ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
vk::LineLoopHelper::Draw(indexCount, baseVertex, mRenderPassCommandBuffer);
}
else
{
ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer));
commandBuffer->drawIndexedBaseVertex(count, baseVertex);
ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
mRenderPassCommandBuffer->drawIndexedBaseVertex(count, baseVertex);
}
return angle::Result::Continue;
......@@ -2104,21 +2149,18 @@ angle::Result ContextVk::drawElementsInstanced(const gl::Context *context,
const void *indices,
GLsizei instances)
{
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop)
{
uint32_t indexCount;
ANGLE_TRY(
setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
count = indexCount;
}
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;
}
......@@ -2130,21 +2172,18 @@ angle::Result ContextVk::drawElementsInstancedBaseVertex(const gl::Context *cont
GLsizei instances,
GLint baseVertex)
{
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop)
{
uint32_t indexCount;
ANGLE_TRY(
setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
count = indexCount;
}
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;
}
......@@ -2157,21 +2196,18 @@ angle::Result ContextVk::drawElementsInstancedBaseVertexBaseInstance(const gl::C
GLint baseVertex,
GLuint baseInstance)
{
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop)
{
uint32_t indexCount;
ANGLE_TRY(
setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(indexCount, instances, 0,
baseVertex, baseInstance);
ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(
indexCount, instances, 0, baseVertex, baseInstance);
return angle::Result::Continue;
}
ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer));
commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(count, instances, 0, baseVertex,
baseInstance);
ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(count, instances, 0,
baseVertex, baseInstance);
return angle::Result::Continue;
}
......@@ -2232,8 +2268,6 @@ angle::Result ContextVk::drawArraysIndirect(const gl::Context *context,
return angle::Result::Continue;
}
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop)
{
ASSERT(indirectBuffer);
......@@ -2241,17 +2275,19 @@ angle::Result ContextVk::drawArraysIndirect(const gl::Context *context,
VkDeviceSize dstIndirectBufOffset = 0;
ANGLE_TRY(setupLineLoopIndirectDraw(context, mode, currentIndirectBuf,
currentIndirectBufOffset, &commandBuffer,
&dstIndirectBuf, &dstIndirectBufOffset));
currentIndirectBufOffset, &dstIndirectBuf,
&dstIndirectBufOffset));
commandBuffer->drawIndexedIndirect(dstIndirectBuf->getBuffer(), dstIndirectBufOffset, 1, 0);
mRenderPassCommandBuffer->drawIndexedIndirect(dstIndirectBuf->getBuffer(),
dstIndirectBufOffset, 1, 0);
return angle::Result::Continue;
}
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;
}
......@@ -2304,16 +2340,14 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
currentIndirectBufOffset = dstIndirectBufOffset;
}
vk::CommandBuffer *commandBuffer = nullptr;
if (mode == gl::PrimitiveMode::LineLoop)
{
vk::BufferHelper *dstIndirectBuf;
VkDeviceSize dstIndirectBufOffset;
ANGLE_TRY(setupLineLoopIndexedIndirectDraw(context, mode, type, currentIndirectBuf,
currentIndirectBufOffset, &commandBuffer,
&dstIndirectBuf, &dstIndirectBufOffset));
currentIndirectBufOffset, &dstIndirectBuf,
&dstIndirectBufOffset));
currentIndirectBuf = dstIndirectBuf;
currentIndirectBufOffset = dstIndirectBufOffset;
......@@ -2321,11 +2355,11 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
else
{
ANGLE_TRY(setupIndexedIndirectDraw(context, mode, type, currentIndirectBuf,
currentIndirectBufOffset, &commandBuffer));
currentIndirectBufOffset));
}
commandBuffer->drawIndexedIndirect(currentIndirectBuf->getBuffer(), currentIndirectBufOffset, 1,
0);
mRenderPassCommandBuffer->drawIndexedIndirect(currentIndirectBuf->getBuffer(),
currentIndirectBufOffset, 1, 0);
return angle::Result::Continue;
}
......@@ -2759,10 +2793,10 @@ angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *co
}
else
{
invalidateCurrentGraphicsPipeline();
// No additional work is needed here. We will update the pipeline desc
// later.
invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
invalidateCurrentGraphicsPipeline();
invalidateVertexAndIndexBuffers();
bool useVertexBuffer = (executable->getMaxActiveAttribLocation() > 0);
mNonIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
......@@ -3005,6 +3039,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
&mGraphicsPipelineTransition, depthStencilState, drawFramebuffer);
mGraphicsPipelineDesc->updateStencilBackWriteMask(
&mGraphicsPipelineTransition, depthStencilState, drawFramebuffer);
mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
onDrawFramebufferRenderPassDescChange(mDrawFramebuffer);
break;
}
......@@ -3508,11 +3543,11 @@ void ContextVk::onFramebufferChange(FramebufferVk *framebufferVk)
updateScissor(mState);
onDrawFramebufferRenderPassDescChange(framebufferVk);
invalidateCurrentGraphicsPipeline();
}
void ContextVk::onDrawFramebufferRenderPassDescChange(FramebufferVk *framebufferVk)
{
invalidateCurrentGraphicsPipeline();
mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition,
framebufferVk->getRenderPassDesc());
const gl::Box &dimensions = framebufferVk->getState().getDimensions();
......@@ -3617,14 +3652,14 @@ angle::Result ContextVk::onPauseTransformFeedback()
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)
......@@ -3652,25 +3687,23 @@ angle::Result ContextVk::dispatchCompute(const gl::Context *context,
GLuint numGroupsY,
GLuint numGroupsZ)
{
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(setupDispatch(context, &commandBuffer));
ANGLE_TRY(setupDispatch(context));
commandBuffer->dispatch(numGroupsX, numGroupsY, numGroupsZ);
mOutsideRenderPassCommands->getCommandBuffer().dispatch(numGroupsX, numGroupsY, numGroupsZ);
return angle::Result::Continue;
}
angle::Result ContextVk::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(setupDispatch(context, &commandBuffer));
ANGLE_TRY(setupDispatch(context));
gl::Buffer *glBuffer = getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
vk::BufferHelper &buffer = vk::GetImpl(glBuffer)->getBuffer();
mOutsideRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
vk::PipelineStage::DrawIndirect, &buffer);
commandBuffer->dispatchIndirect(buffer.getBuffer(), indirect);
mOutsideRenderPassCommands->getCommandBuffer().dispatchIndirect(buffer.getBuffer(), indirect);
return angle::Result::Continue;
}
......@@ -3826,8 +3859,7 @@ ANGLE_INLINE void ContextVk::pauseTransformFeedbackIfStarted(DirtyBits onResumeO
}
}
angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator)
{
// Allocate a new region in the dynamic buffer.
bool useGraphicsDriverUniformsExtended = getFeatures().forceDriverUniformOverSpecConst.enabled;
......@@ -3951,8 +3983,7 @@ angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *co
&mDriverUniforms[PipelineType::Graphics]);
}
angle::Result ContextVk::handleDirtyComputeDriverUniforms(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyComputeDriverUniforms()
{
// Allocate a new region in the dynamic buffer.
uint8_t *ptr;
......@@ -3992,20 +4023,20 @@ void ContextVk::handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandB
&driverUniforms->descriptorSet, 1, &driverUniforms->dynamicOffset);
}
angle::Result ContextVk::handleDirtyGraphicsDriverUniformsBinding(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyGraphicsDriverUniformsBinding(
DirtyBits::Iterator *dirtyBitsIterator)
{
// Bind the driver descriptor set.
handleDirtyDriverUniformsBindingImpl(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
handleDirtyDriverUniformsBindingImpl(mRenderPassCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
&mDriverUniforms[PipelineType::Graphics]);
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyComputeDriverUniformsBinding(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
angle::Result ContextVk::handleDirtyComputeDriverUniformsBinding()
{
// Bind the driver descriptor set.
handleDirtyDriverUniformsBindingImpl(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE,
handleDirtyDriverUniformsBindingImpl(&mOutsideRenderPassCommands->getCommandBuffer(),
VK_PIPELINE_BIND_POINT_COMPUTE,
&mDriverUniforms[PipelineType::Compute]);
return angle::Result::Continue;
}
......@@ -4230,8 +4261,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
return angle::Result::Continue;
}
angle::Result ContextVk::updateActiveImages(const gl::Context *context,
vk::CommandBufferHelper *commandBufferHelper)
angle::Result ContextVk::updateActiveImages(vk::CommandBufferHelper *commandBufferHelper)
{
const gl::State &glState = mState;
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
......@@ -4657,20 +4687,21 @@ angle::Result ContextVk::beginNewRenderPass(
mRenderPassCommands->beginRenderPass(framebuffer, renderArea, renderPassDesc,
renderPassAttachmentOps, depthStencilAttachmentIndex,
clearValues, commandBufferOut);
// Restart at subpass 0.
mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
mPerfCounters.renderPasses++;
return angle::Result::Continue;
}
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());
......@@ -4795,6 +4826,11 @@ angle::Result ContextVk::flushCommandsAndEndRenderPass()
ANGLE_TRY(flushImpl(nullptr));
}
mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
// Restart at subpass 0.
mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
return angle::Result::Continue;
}
......
......@@ -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
// 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.
void invalidateGraphicsPipeline();
void invalidateComputePipeline();
void invalidateGraphicsPipelineBinding();
void invalidateComputePipelineBinding();
void invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet);
void invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet);
......@@ -524,7 +524,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
uint32_t getCurrentSubpassIndex() const;
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();
angle::Result flushCommandsAndEndRenderPass();
......@@ -588,15 +590,29 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
// Dirty bits.
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_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_VERTEX_BUFFERS,
DIRTY_BIT_INDEX_BUFFER,
DIRTY_BIT_DRIVER_UNIFORMS,
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_STATE,
DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME,
......@@ -606,8 +622,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
using DirtyBitHandler = angle::Result (ContextVk::*)(const gl::Context *,
vk::CommandBuffer *commandBuffer);
using GraphicsDirtyBitHandler =
angle::Result (ContextVk::*)(DirtyBits::Iterator *dirtyBitsIterator);
using ComputeDirtyBitHandler = angle::Result (ContextVk::*)();
struct DriverUniformsDescriptorSet
{
......@@ -684,42 +701,36 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid,
const void *indices,
DirtyBits dirtyBitMask,
vk::CommandBuffer **commandBufferOut);
DirtyBits dirtyBitMask);
angle::Result setupIndexedDraw(const gl::Context *context,
gl::PrimitiveMode mode,
GLsizei indexCount,
GLsizei instanceCount,
gl::DrawElementsType indexType,
const void *indices,
vk::CommandBuffer **commandBufferOut);
const void *indices);
angle::Result setupIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode,
DirtyBits dirtyBitMask,
vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut);
VkDeviceSize indirectBufferOffset);
angle::Result setupIndexedIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode,
gl::DrawElementsType indexType,
vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut);
VkDeviceSize indirectBufferOffset);
angle::Result setupLineLoopIndexedIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode,
gl::DrawElementsType indexType,
vk::BufferHelper *srcIndirectBuf,
VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut,
vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut);
angle::Result setupLineLoopIndirectDraw(const gl::Context *context,
gl::PrimitiveMode mode,
vk::BufferHelper *indirectBuffer,
VkDeviceSize indirectBufferOffset,
vk::CommandBuffer **commandBufferOut,
vk::BufferHelper **indirectBufferOut,
VkDeviceSize *indirectBufferOffsetOut);
......@@ -729,9 +740,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
GLsizei vertexOrIndexCount,
gl::DrawElementsType indexTypeOrInvalid,
const void *indices,
vk::CommandBuffer **commandBufferOut,
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;
void updateViewport(FramebufferVk *framebufferVk,
......@@ -745,18 +755,19 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
void updateSurfaceRotationReadFramebuffer(const gl::State &glState);
angle::Result updateActiveTextures(const gl::Context *context);
angle::Result updateActiveImages(const gl::Context *context,
vk::CommandBufferHelper *commandBufferHelper);
angle::Result updateActiveImages(vk::CommandBufferHelper *commandBufferHelper);
angle::Result updateDefaultAttribute(size_t attribIndex);
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()
{
mComputeDirtyBits.set(DIRTY_BIT_PIPELINE);
mComputeDirtyBits.set(DIRTY_BIT_PIPELINE_DESC);
mComputeDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
mCurrentComputePipeline = nullptr;
}
......@@ -767,56 +778,44 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
void invalidateDriverUniforms();
// Handlers for graphics pipeline dirty bits.
angle::Result handleDirtyGraphicsEventLog(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsDefaultAttribs(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsPipeline(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsTextures(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsVertexBuffers(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsIndexBuffer(const gl::Context *context,
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 handleDirtyGraphicsEventLog(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsPipelineBinding(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsTextures(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsDriverUniformsBinding(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsShaderResources(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsTransformFeedbackBuffersEmulation(
const gl::Context *context,
vk::CommandBuffer *commandBuffer);
DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsTransformFeedbackBuffersExtension(
const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsTransformFeedbackState(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsTransformFeedbackResume(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsTransformFeedbackState(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsTransformFeedbackResume(
DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyGraphicsDescriptorSets(DirtyBits::Iterator *dirtyBitsIterator);
// Handlers for compute pipeline dirty bits.
angle::Result handleDirtyComputePipeline(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyComputeTextures(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyComputeDriverUniforms(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyComputeDriverUniformsBinding(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyComputeShaderResources(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyComputeEventLog();
angle::Result handleDirtyComputePipelineDesc();
angle::Result handleDirtyComputePipelineBinding();
angle::Result handleDirtyComputeTextures();
angle::Result handleDirtyComputeDriverUniforms();
angle::Result handleDirtyComputeDriverUniformsBinding();
angle::Result handleDirtyComputeShaderResources();
angle::Result handleDirtyComputeDescriptorSets();
// Common parts of the common dirty bit handlers.
angle::Result handleDirtyEventLogImpl(vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyTexturesImpl(vk::CommandBufferHelper *commandBufferHelper);
angle::Result handleDirtyShaderResourcesImpl(const gl::Context *context,
vk::CommandBufferHelper *commandBufferHelper);
angle::Result handleDirtyShaderResourcesImpl(vk::CommandBufferHelper *commandBufferHelper);
void handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandBuffer,
VkPipelineBindPoint bindPoint,
DriverUniformsDescriptorSet *driverUniforms);
angle::Result handleDirtyDescriptorSets(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyDescriptorSetsImpl(vk::CommandBuffer *commandBuffer);
angle::Result allocateDriverUniforms(size_t driverUniformsSize,
DriverUniformsDescriptorSet *driverUniforms,
uint8_t **ptrOut,
......@@ -876,8 +875,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
SpecConstUsageBits getCurrentProgramSpecConstUsageBits() const;
void updateGraphicsPipelineDescWithSpecConstUsageBits(SpecConstUsageBits usageBits);
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers;
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers;
std::array<GraphicsDirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers;
std::array<ComputeDirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers;
vk::CommandBuffer *mRenderPassCommandBuffer;
......
......@@ -2318,7 +2318,8 @@ angle::Result FramebufferVk::getSamplePosition(const gl::Context *context,
angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
const gl::Rectangle &scissoredRenderArea,
vk::CommandBuffer **commandBufferOut)
vk::CommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut)
{
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
......@@ -2536,13 +2537,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
// or the existence of resolve attachments in single subpass render passes. The modification
// here can add/remove a subpass, or modify its input attachments.
gl::DrawBufferMask unresolveColorMask = mRenderPassDesc.getColorUnresolveAttachmentMask();
bool unresolveDepth = mRenderPassDesc.hasDepthUnresolveAttachment();
bool unresolveStencil = mRenderPassDesc.hasStencilUnresolveAttachment();
if (previousUnresolveColorMask != unresolveColorMask ||
previousUnresolveDepth != unresolveDepth || previousUnresolveStencil != unresolveStencil)
const bool unresolveDepth = mRenderPassDesc.hasDepthUnresolveAttachment();
const bool unresolveStencil = mRenderPassDesc.hasStencilUnresolveAttachment();
const bool unresolveChanged = previousUnresolveColorMask != unresolveColorMask ||
previousUnresolveDepth != unresolveDepth ||
previousUnresolveStencil != unresolveStencil;
if (unresolveChanged)
{
contextVk->onDrawFramebufferRenderPassDescChange(this);
// Make sure framebuffer is recreated.
mFramebuffer = nullptr;
......@@ -2580,7 +2581,8 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
mCurrentFramebufferDesc.getLayerCount());
}
if (unresolveColorMask.any() || unresolveDepth || unresolveStencil)
const bool anyUnresolve = unresolveColorMask.any() || unresolveDepth || unresolveStencil;
if (anyUnresolve)
{
// Unresolve attachments if any.
UtilsVk::UnresolveParameters params;
......@@ -2594,6 +2596,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
contextVk->startNextSubpass();
}
if (unresolveChanged || anyUnresolve)
{
contextVk->onDrawFramebufferRenderPassDescChange(this);
// Notify that the render pass desc has changed.
*renderPassDescChangedOut = true;
}
return angle::Result::Continue;
}
......@@ -2701,7 +2710,7 @@ angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk)
return angle::Result::Continue;
}
return contextVk->startRenderPass(getRotatedCompleteRenderArea(contextVk), nullptr);
return contextVk->startRenderPass(getRotatedCompleteRenderArea(contextVk), nullptr, nullptr);
}
void FramebufferVk::updateRenderPassReadOnlyDepthMode(ContextVk *contextVk,
......
......@@ -138,7 +138,8 @@ class FramebufferVk : public FramebufferImpl
angle::Result startNewRenderPass(ContextVk *contextVk,
const gl::Rectangle &scissoredRenderArea,
vk::CommandBuffer **commandBufferOut);
vk::CommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut);
RenderTargetVk *getFirstRenderTarget() const;
GLint getSamples() const;
......
......@@ -996,7 +996,7 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
pipelineAndSerial->updateSerial(serial);
commandBuffer->bindComputePipeline(pipelineAndSerial->get());
contextVk->invalidateComputePipeline();
contextVk->invalidateComputePipelineBinding();
}
else
{
......@@ -1017,7 +1017,7 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
helper->updateSerial(serial);
commandBuffer->bindGraphicsPipeline(helper->getPipeline());
contextVk->invalidateGraphicsPipeline();
contextVk->invalidateGraphicsPipelineBinding();
}
if (descriptorSet != VK_NULL_HANDLE)
......@@ -1492,7 +1492,9 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
}
else
{
ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer));
bool renderPassDescChanged = false;
ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer,
&renderPassDescChanged));
}
if (params.clearStencil || params.clearDepth)
......@@ -1810,7 +1812,7 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
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,
src);
......
......@@ -943,6 +943,63 @@ TEST_P(StateChangeTest, VertexBufferUpdatedAfterDraw)
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_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