зеркало из https://github.com/AvaloniaUI/angle.git
Vulkan: Output the reason for RP closure in command buffer
To make it easier when viewing the command buffer in a graphics debugger, this change inserts a marker just before closing the render pass that specifies why the render pass was closed. Bug: angleproject:2472 Change-Id: I862e500cd58332d6e199c853315c560fe6a73dc2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3265609 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Tim Van Patten <timvp@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Родитель
a9f2e87ec9
Коммит
dbc0c646c4
|
@ -64,15 +64,6 @@ struct FeaturesVk : FeatureSetBase
|
|||
"The depth value is not clamped to [0,1] for floating point depth buffers.", &members,
|
||||
"http://anglebug.com/3970"};
|
||||
|
||||
// On some android devices, the memory barrier between the compute shader that converts vertex
|
||||
// attributes and the vertex shader that reads from it is ineffective. Only known workaround is
|
||||
// to perform a flush after the conversion. http://anglebug.com/3016
|
||||
Feature flushAfterVertexConversion = {
|
||||
"flushAfterVertexConversion", FeatureCategory::VulkanWorkarounds,
|
||||
"The memory barrier between the compute shader that converts vertex attributes and the "
|
||||
"vertex shader that reads from it is ineffective",
|
||||
&members, "http://anglebug.com/3016"};
|
||||
|
||||
Feature supportsRenderpass2 = {"supportsRenderpass2", FeatureCategory::VulkanFeatures,
|
||||
"VkDevice supports the VK_KHR_create_renderpass2 extension",
|
||||
&members};
|
||||
|
|
|
@ -577,8 +577,9 @@ angle::Result BufferVk::handleDeviceLocalBufferMap(ContextVk *contextVk,
|
|||
|
||||
VkBufferCopy copyRegion = {mBufferOffset + offset, mHostVisibleBufferOffset, size};
|
||||
ANGLE_TRY(hostVisibleBuffer->copyFromBuffer(contextVk, mBuffer, 1, ©Region));
|
||||
ANGLE_TRY(
|
||||
hostVisibleBuffer->waitForIdle(contextVk, "GPU stall due to mapping device local buffer"));
|
||||
ANGLE_TRY(hostVisibleBuffer->waitForIdle(contextVk,
|
||||
"GPU stall due to mapping device local buffer",
|
||||
RenderPassClosureReason::DeviceLocalBufferMap));
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
@ -699,7 +700,8 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk,
|
|||
// If there are pending commands for the resource, flush them.
|
||||
if (mBuffer->usedInRecordedCommands())
|
||||
{
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr));
|
||||
ANGLE_TRY(
|
||||
contextVk->flushImpl(nullptr, RenderPassClosureReason::BufferWriteThenMap));
|
||||
}
|
||||
ANGLE_TRY(mBuffer->finishGPUWriteCommands(contextVk));
|
||||
}
|
||||
|
@ -742,7 +744,8 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk,
|
|||
else if ((access & GL_MAP_UNSYNCHRONIZED_BIT) == 0)
|
||||
{
|
||||
ANGLE_TRY(mBuffer->waitForIdle(
|
||||
contextVk, "GPU stall due to mapping buffer in use by the GPU"));
|
||||
contextVk, "GPU stall due to mapping buffer in use by the GPU",
|
||||
RenderPassClosureReason::BufferInUseWhenSynchronizedMap));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -198,24 +198,18 @@ bool IsRenderPassStartedAndUsesImage(const vk::CommandBufferHelper &renderPassCo
|
|||
//
|
||||
// Note: these are mat2's that are appropriately padded (4 floats per row).
|
||||
using PreRotationMatrixValues = std::array<float, 8>;
|
||||
constexpr angle::PackedEnumMap<rx::SurfaceRotation,
|
||||
PreRotationMatrixValues,
|
||||
angle::EnumSize<rx::SurfaceRotation>()>
|
||||
kFragRotationMatrices = {
|
||||
{{rx::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
|
||||
{rx::SurfaceRotation::Rotated90Degrees,
|
||||
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
|
||||
{rx::SurfaceRotation::Rotated180Degrees,
|
||||
{{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
|
||||
{rx::SurfaceRotation::Rotated270Degrees,
|
||||
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
|
||||
{rx::SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
|
||||
{rx::SurfaceRotation::FlippedRotated90Degrees,
|
||||
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
|
||||
{rx::SurfaceRotation::FlippedRotated180Degrees,
|
||||
{{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
|
||||
{rx::SurfaceRotation::FlippedRotated270Degrees,
|
||||
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}}}};
|
||||
constexpr angle::PackedEnumMap<rx::SurfaceRotation, PreRotationMatrixValues> kFragRotationMatrices =
|
||||
{{{SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
|
||||
{SurfaceRotation::Rotated90Degrees, {{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
|
||||
{SurfaceRotation::Rotated180Degrees, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
|
||||
{SurfaceRotation::Rotated270Degrees, {{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
|
||||
{SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
|
||||
{SurfaceRotation::FlippedRotated90Degrees,
|
||||
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
|
||||
{SurfaceRotation::FlippedRotated180Degrees,
|
||||
{{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
|
||||
{SurfaceRotation::FlippedRotated270Degrees,
|
||||
{{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}}}};
|
||||
|
||||
bool IsRotatedAspectRatio(SurfaceRotation rotation)
|
||||
{
|
||||
|
@ -337,6 +331,102 @@ void AppendBufferVectorToDesc(vk::ShaderBuffersDescriptorDesc *desc,
|
|||
|
||||
desc->append32BitValue(std::numeric_limits<uint32_t>::max());
|
||||
}
|
||||
|
||||
constexpr angle::PackedEnumMap<RenderPassClosureReason, const char *> kRenderPassClosureReason = {{
|
||||
{RenderPassClosureReason::AlreadySpecifiedElsewhere, nullptr},
|
||||
{RenderPassClosureReason::ContextDestruction, "Render pass closed due to context destruction"},
|
||||
{RenderPassClosureReason::ContextChange, "Render pass closed due to context change"},
|
||||
{RenderPassClosureReason::GLFlush, "Render pass closed due to glFlush()"},
|
||||
{RenderPassClosureReason::GLFinish, "Render pass closed due to glFinish()"},
|
||||
{RenderPassClosureReason::EGLSwapBuffers, "Render pass closed due to eglSwapBuffers()"},
|
||||
{RenderPassClosureReason::EGLWaitClient, "Render pass closed due to eglWaitClient()"},
|
||||
{RenderPassClosureReason::FramebufferBindingChange,
|
||||
"Render pass closed due to framebuffer binding change"},
|
||||
{RenderPassClosureReason::FramebufferChange, "Render pass closed due to framebuffer change"},
|
||||
{RenderPassClosureReason::NewRenderPass,
|
||||
"Render pass closed due to starting a new render pass"},
|
||||
{RenderPassClosureReason::BufferUseThenXfbWrite,
|
||||
"Render pass closed due to buffer use as transform feedback output after prior use in render "
|
||||
"pass"},
|
||||
{RenderPassClosureReason::XfbWriteThenVertexIndexBuffer,
|
||||
"Render pass closed due to transform feedback buffer use as vertex/index input"},
|
||||
{RenderPassClosureReason::XfbWriteThenIndirectDrawBuffer,
|
||||
"Render pass closed due to indirect draw buffer previously used as transform feedback output "
|
||||
"in render pass"},
|
||||
{RenderPassClosureReason::XfbResumeAfterDrawBasedClear,
|
||||
"Render pass closed due to transform feedback resume after clear through draw"},
|
||||
{RenderPassClosureReason::DepthStencilUseInFeedbackLoop,
|
||||
"Render pass closed due to depth/stencil attachment use under feedback loop"},
|
||||
{RenderPassClosureReason::DepthStencilWriteAfterFeedbackLoop,
|
||||
"Render pass closed due to depth/stencil attachment write after feedback loop"},
|
||||
{RenderPassClosureReason::PipelineBindWhileXfbActive,
|
||||
"Render pass closed due to graphics pipeline change while transform feedback is active"},
|
||||
{RenderPassClosureReason::BufferWriteThenMap,
|
||||
"Render pass closed due to mapping buffer being written to by said render pass"},
|
||||
{RenderPassClosureReason::BufferUseThenOutOfRPRead,
|
||||
"Render pass closed due to non-render-pass read of buffer that was written to in render pass"},
|
||||
{RenderPassClosureReason::BufferUseThenOutOfRPWrite,
|
||||
"Render pass closed due to non-render-pass write of buffer that was used in render pass"},
|
||||
{RenderPassClosureReason::ImageUseThenOutOfRPRead,
|
||||
"Render pass closed due to non-render-pass read of image that was used in render pass"},
|
||||
{RenderPassClosureReason::ImageUseThenOutOfRPWrite,
|
||||
"Render pass closed due to non-render-pass write of image that was used in render pass"},
|
||||
{RenderPassClosureReason::XfbWriteThenComputeRead,
|
||||
"Render pass closed due to compute read of buffer previously used as transform feedback "
|
||||
"output in render pass"},
|
||||
{RenderPassClosureReason::XfbWriteThenIndirectDispatchBuffer,
|
||||
"Render pass closed due to indirect dispatch buffer previously used as transform feedback "
|
||||
"output in render pass"},
|
||||
{RenderPassClosureReason::ImageAttachmentThenComputeRead,
|
||||
"Render pass closed due to compute read of image previously used as framebuffer attachment in "
|
||||
"render pass"},
|
||||
{RenderPassClosureReason::GetQueryResult, "Render pass closed due to getting query result"},
|
||||
{RenderPassClosureReason::BeginNonRenderPassQuery,
|
||||
"Render pass closed due to non-render-pass query begin"},
|
||||
{RenderPassClosureReason::EndNonRenderPassQuery,
|
||||
"Render pass closed due to non-render-pass query end"},
|
||||
{RenderPassClosureReason::TimestampQuery, "Render pass closed due to timestamp query"},
|
||||
{RenderPassClosureReason::GLReadPixels, "Render pass closed due to glReadPixels()"},
|
||||
{RenderPassClosureReason::BufferUseThenReleaseToExternal,
|
||||
"Render pass closed due to buffer (used by render pass) release to external"},
|
||||
{RenderPassClosureReason::ImageUseThenReleaseToExternal,
|
||||
"Render pass closed due to image (used by render pass) release to external"},
|
||||
{RenderPassClosureReason::BufferInUseWhenSynchronizedMap,
|
||||
"Render pass closed due to mapping buffer in use by GPU without GL_MAP_UNSYNCHRONIZED_BIT"},
|
||||
{RenderPassClosureReason::ImageOrphan, "Render pass closed due to EGL image being orphaned"},
|
||||
{RenderPassClosureReason::GLMemoryBarrierThenStorageResource,
|
||||
"Render pass closed due to glMemoryBarrier before storage output in render pass"},
|
||||
{RenderPassClosureReason::StorageResourceUseThenGLMemoryBarrier,
|
||||
"Render pass closed due to glMemoryBarrier after storage output in render pass"},
|
||||
{RenderPassClosureReason::ExternalSemaphoreSignal,
|
||||
"Render pass closed due to external semaphore signal"},
|
||||
{RenderPassClosureReason::SyncObjectInit, "Render pass closed due to sync object insertion"},
|
||||
{RenderPassClosureReason::SyncObjectWithFdInit,
|
||||
"Render pass closed due to sync object with fd insertion"},
|
||||
{RenderPassClosureReason::SyncObjectClientWait,
|
||||
"Render pass closed due to sync object client wait"},
|
||||
{RenderPassClosureReason::SyncObjectServerWait,
|
||||
"Render pass closed due to sync object server wait"},
|
||||
{RenderPassClosureReason::XfbPause, "Render pass closed due to transform feedback pause"},
|
||||
{RenderPassClosureReason::FramebufferFetchEmulation,
|
||||
"Render pass closed due to framebuffer fetch emulation"},
|
||||
{RenderPassClosureReason::ColorBufferInvalidate,
|
||||
"Render pass closed due to glInvalidateFramebuffer() on a color buffer"},
|
||||
{RenderPassClosureReason::GenerateMipmapOnCPU,
|
||||
"Render pass closed due to fallback to CPU when generating mipmaps"},
|
||||
{RenderPassClosureReason::CopyTextureOnCPU,
|
||||
"Render pass closed due to fallback to CPU when copying texture"},
|
||||
{RenderPassClosureReason::TextureReformatToRenderable,
|
||||
"Render pass closed due to reformatting texture to a renderable fallback"},
|
||||
{RenderPassClosureReason::DeviceLocalBufferMap,
|
||||
"Render pass closed due to mapping device local buffer"},
|
||||
{RenderPassClosureReason::TemporaryForImageClear,
|
||||
"Temporary render pass used for image clear closed"},
|
||||
{RenderPassClosureReason::TemporaryForImageCopy,
|
||||
"Temporary render pass used for image copy closed"},
|
||||
{RenderPassClosureReason::OverlayFontCreation,
|
||||
"Render pass closed due to creating Overlay font"},
|
||||
}};
|
||||
} // anonymous namespace
|
||||
|
||||
// Not necessary once upgraded to C++17.
|
||||
|
@ -363,10 +453,21 @@ void ContextVk::flushDescriptorSetUpdates()
|
|||
mDescriptorImageInfos.clear();
|
||||
}
|
||||
|
||||
ANGLE_INLINE void ContextVk::onRenderPassFinished()
|
||||
ANGLE_INLINE void ContextVk::onRenderPassFinished(RenderPassClosureReason reason)
|
||||
{
|
||||
pauseRenderPassQueriesIfActive();
|
||||
|
||||
if (mRenderPassCommandBuffer != nullptr)
|
||||
{
|
||||
// If reason is specified, add it to the command buffer right before ending the render pass,
|
||||
// so it will show up in GPU debuggers.
|
||||
const char *reasonText = kRenderPassClosureReason[reason];
|
||||
if (reasonText)
|
||||
{
|
||||
insertEventMarkerImpl(reasonText);
|
||||
}
|
||||
}
|
||||
|
||||
mRenderPassCommandBuffer = nullptr;
|
||||
mGraphicsDirtyBits.set(DIRTY_BIT_RENDER_PASS);
|
||||
}
|
||||
|
@ -586,7 +687,7 @@ void ContextVk::onDestroy(const gl::Context *context)
|
|||
mIncompleteTextures.onDestroy(context);
|
||||
|
||||
// Flush and complete current outstanding work before destruction.
|
||||
(void)finishImpl();
|
||||
(void)finishImpl(RenderPassClosureReason::ContextDestruction);
|
||||
|
||||
VkDevice device = getDevice();
|
||||
|
||||
|
@ -810,12 +911,12 @@ angle::Result ContextVk::flush(const gl::Context *context)
|
|||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
return flushImpl(nullptr);
|
||||
return flushImpl(nullptr, RenderPassClosureReason::GLFlush);
|
||||
}
|
||||
|
||||
angle::Result ContextVk::finish(const gl::Context *context)
|
||||
{
|
||||
return finishImpl();
|
||||
return finishImpl(RenderPassClosureReason::GLFinish);
|
||||
}
|
||||
|
||||
angle::Result ContextVk::setupDraw(const gl::Context *context,
|
||||
|
@ -974,7 +1075,8 @@ angle::Result ContextVk::setupIndirectDraw(const gl::Context *context,
|
|||
// feedback.
|
||||
if (mCurrentTransformFeedbackBuffers.contains(indirectBuffer))
|
||||
{
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(
|
||||
flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbWriteThenIndirectDrawBuffer));
|
||||
}
|
||||
|
||||
ANGLE_TRY(setupDraw(context, mode, firstVertex, vertexCount, instanceCount,
|
||||
|
@ -1245,11 +1347,14 @@ angle::Result ContextVk::handleDirtyMemoryBarrierImpl(DirtyBits::Iterator *dirty
|
|||
// dirty bits directly (if called during handling of compute dirty bits).
|
||||
if (dirtyBitsIterator)
|
||||
{
|
||||
return flushDirtyGraphicsRenderPass(dirtyBitsIterator, dirtyBitMask);
|
||||
return flushDirtyGraphicsRenderPass(
|
||||
dirtyBitsIterator, dirtyBitMask,
|
||||
RenderPassClosureReason::GLMemoryBarrierThenStorageResource);
|
||||
}
|
||||
else
|
||||
{
|
||||
return flushCommandsAndEndRenderPass();
|
||||
return flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::GLMemoryBarrierThenStorageResource);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1414,7 +1519,8 @@ angle::Result ContextVk::handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator *di
|
|||
// feedback counter buffer.
|
||||
if (mRenderPassCommands->started() && mRenderPassCommands->isTransformFeedbackActiveUnpaused())
|
||||
{
|
||||
ANGLE_TRY(flushDirtyGraphicsRenderPass(dirtyBitsIterator, dirtyBitMask));
|
||||
ANGLE_TRY(flushDirtyGraphicsRenderPass(
|
||||
dirtyBitsIterator, dirtyBitMask, RenderPassClosureReason::PipelineBindWhileXfbActive));
|
||||
|
||||
dirtyBitsIterator->setLaterBit(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
|
||||
}
|
||||
|
@ -1433,7 +1539,8 @@ angle::Result ContextVk::handleDirtyGraphicsRenderPass(DirtyBits::Iterator *dirt
|
|||
if (mRenderPassCommands->started())
|
||||
{
|
||||
ANGLE_TRY(flushDirtyGraphicsRenderPass(dirtyBitsIterator,
|
||||
dirtyBitMask & ~DirtyBits{DIRTY_BIT_RENDER_PASS}));
|
||||
dirtyBitMask & ~DirtyBits{DIRTY_BIT_RENDER_PASS},
|
||||
RenderPassClosureReason::AlreadySpecifiedElsewhere));
|
||||
}
|
||||
|
||||
gl::Rectangle scissoredRenderArea = mDrawFramebuffer->getRotatedScissoredRenderArea(this);
|
||||
|
@ -2162,7 +2269,7 @@ angle::Result ContextVk::submitFrame(const vk::Semaphore *signalSemaphore, Seria
|
|||
getShareGroupVk()->releaseResourceUseLists(),
|
||||
std::move(mCurrentGarbage), &mCommandPool, submitSerialOut));
|
||||
|
||||
onRenderPassFinished();
|
||||
onRenderPassFinished(RenderPassClosureReason::AlreadySpecifiedElsewhere);
|
||||
mComputeDirtyBits |= mNewComputeCommandBufferDirtyBits;
|
||||
|
||||
if (mGpuEventsEnabled)
|
||||
|
@ -3468,7 +3575,8 @@ angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *co
|
|||
if (mLastProgramUsesFramebufferFetch != executable->usesFramebufferFetch())
|
||||
{
|
||||
mLastProgramUsesFramebufferFetch = executable->usesFramebufferFetch();
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(
|
||||
flushCommandsAndEndRenderPass(RenderPassClosureReason::FramebufferFetchEmulation));
|
||||
|
||||
ASSERT(mDrawFramebuffer);
|
||||
mDrawFramebuffer->onSwitchProgramFramebufferFetch(this,
|
||||
|
@ -3682,7 +3790,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
|
|||
// as some optimizations in non-draw commands require the render pass to remain
|
||||
// open, such as invalidate or blit. Note that we always start a new command buffer
|
||||
// because we currently can only support one open RenderPass at a time.
|
||||
onRenderPassFinished();
|
||||
onRenderPassFinished(RenderPassClosureReason::FramebufferBindingChange);
|
||||
if (mRenderer->getFeatures().preferSubmitAtFBOBoundary.enabled)
|
||||
{
|
||||
// This will behave as if user called glFlush, but the actual flush will be
|
||||
|
@ -3941,7 +4049,7 @@ angle::Result ContextVk::onMakeCurrent(const gl::Context *context)
|
|||
|
||||
angle::Result ContextVk::onUnMakeCurrent(const gl::Context *context)
|
||||
{
|
||||
ANGLE_TRY(flushImpl(nullptr));
|
||||
ANGLE_TRY(flushImpl(nullptr, RenderPassClosureReason::ContextChange));
|
||||
mCurrentWindowSurface = nullptr;
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
@ -4289,7 +4397,7 @@ angle::Result ContextVk::onFramebufferChange(FramebufferVk *framebufferVk, gl::C
|
|||
// Always consider the render pass finished. FramebufferVk::syncState (caller of this function)
|
||||
// normally closes the render pass, except for blit to allow an optimization. The following
|
||||
// code nevertheless must treat the render pass closed.
|
||||
onRenderPassFinished();
|
||||
onRenderPassFinished(RenderPassClosureReason::FramebufferChange);
|
||||
|
||||
// Ensure that the pipeline description is updated.
|
||||
if (mGraphicsPipelineDesc->getRasterizationSamples() !=
|
||||
|
@ -4398,7 +4506,7 @@ angle::Result ContextVk::onBeginTransformFeedback(
|
|||
|
||||
if (shouldEndRenderPass)
|
||||
{
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::BufferUseThenXfbWrite));
|
||||
}
|
||||
|
||||
populateTransformFeedbackBufferSet(bufferCount, buffers);
|
||||
|
@ -4444,7 +4552,7 @@ angle::Result ContextVk::onPauseTransformFeedback()
|
|||
// settings in the render pass.
|
||||
if (mRenderPassCommands->isTransformFeedbackActiveUnpaused())
|
||||
{
|
||||
return flushCommandsAndEndRenderPass();
|
||||
return flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbPause);
|
||||
}
|
||||
}
|
||||
else if (getFeatures().emulateTransformFeedback.enabled)
|
||||
|
@ -4512,7 +4620,8 @@ angle::Result ContextVk::dispatchComputeIndirect(const gl::Context *context, GLi
|
|||
// feedback.
|
||||
if (mCurrentTransformFeedbackBuffers.contains(&buffer))
|
||||
{
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::XfbWriteThenIndirectDispatchBuffer));
|
||||
}
|
||||
|
||||
ANGLE_TRY(setupDispatch(context));
|
||||
|
@ -4589,7 +4698,8 @@ angle::Result ContextVk::memoryBarrier(const gl::Context *context, GLbitfield ba
|
|||
if (mRenderPassCommands->hasShaderStorageOutput())
|
||||
{
|
||||
// Break the render pass if necessary as future non-draw commands can't know if they should.
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::StorageResourceUseThenGLMemoryBarrier));
|
||||
}
|
||||
else if (mOutsideRenderPassCommands->hasShaderStorageOutput())
|
||||
{
|
||||
|
@ -5078,7 +5188,8 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context, gl::Co
|
|||
{
|
||||
// To enter depth feedback loop, we must flush and start a new renderpass.
|
||||
// Otherwise it will stick with writable layout and cause validation error.
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::DepthStencilUseInFeedbackLoop));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5279,14 +5390,16 @@ bool ContextVk::hasRecordedCommands()
|
|||
return !mOutsideRenderPassCommands->empty() || mRenderPassCommands->started();
|
||||
}
|
||||
|
||||
angle::Result ContextVk::flushImpl(const vk::Semaphore *signalSemaphore)
|
||||
angle::Result ContextVk::flushImpl(const vk::Semaphore *signalSemaphore,
|
||||
RenderPassClosureReason renderPassClosureReason)
|
||||
{
|
||||
Serial unusedSerial;
|
||||
return flushAndGetSerial(signalSemaphore, &unusedSerial);
|
||||
return flushAndGetSerial(signalSemaphore, &unusedSerial, renderPassClosureReason);
|
||||
}
|
||||
|
||||
angle::Result ContextVk::flushAndGetSerial(const vk::Semaphore *signalSemaphore,
|
||||
Serial *submitSerialOut)
|
||||
Serial *submitSerialOut,
|
||||
RenderPassClosureReason renderPassClosureReason)
|
||||
{
|
||||
ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::flushImpl");
|
||||
|
||||
|
@ -5295,7 +5408,7 @@ angle::Result ContextVk::flushAndGetSerial(const vk::Semaphore *signalSemaphore,
|
|||
mHasDeferredFlush = false;
|
||||
|
||||
// Avoid calling vkQueueSubmit() twice, since submitFrame() below will do that.
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPassWithoutQueueSubmit());
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPassWithoutQueueSubmit(renderPassClosureReason));
|
||||
|
||||
if (mIsAnyHostVisibleBufferWritten)
|
||||
{
|
||||
|
@ -5366,11 +5479,11 @@ angle::Result ContextVk::flushAndGetSerial(const vk::Semaphore *signalSemaphore,
|
|||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
angle::Result ContextVk::finishImpl()
|
||||
angle::Result ContextVk::finishImpl(RenderPassClosureReason renderPassClosureReason)
|
||||
{
|
||||
ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::finishImpl");
|
||||
|
||||
ANGLE_TRY(flushImpl(nullptr));
|
||||
ANGLE_TRY(flushImpl(nullptr, renderPassClosureReason));
|
||||
ANGLE_TRY(mRenderer->finish(this, hasProtectedContent()));
|
||||
|
||||
clearAllGarbage();
|
||||
|
@ -5578,7 +5691,8 @@ angle::Result ContextVk::onBufferReleaseToExternal(const vk::BufferHelper &buffe
|
|||
{
|
||||
if (mRenderPassCommands->usesBuffer(buffer))
|
||||
{
|
||||
return flushCommandsAndEndRenderPass();
|
||||
return flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::BufferUseThenReleaseToExternal);
|
||||
}
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
@ -5587,7 +5701,8 @@ angle::Result ContextVk::onImageReleaseToExternal(const vk::ImageHelper &image)
|
|||
{
|
||||
if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, image))
|
||||
{
|
||||
return flushCommandsAndEndRenderPass();
|
||||
return flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::ImageUseThenReleaseToExternal);
|
||||
}
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
@ -5602,8 +5717,9 @@ angle::Result ContextVk::beginNewRenderPass(
|
|||
const vk::PackedClearValuesArray &clearValues,
|
||||
vk::CommandBuffer **commandBufferOut)
|
||||
{
|
||||
// Next end any currently outstanding renderPass
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass());
|
||||
// Next end any currently outstanding render pass. The render pass is normally closed before
|
||||
// reaching here for various reasons, except typically when UtilsVk needs to start one.
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass));
|
||||
|
||||
mPerfCounters.renderPasses++;
|
||||
return mRenderPassCommands->beginRenderPass(
|
||||
|
@ -5684,7 +5800,8 @@ uint32_t ContextVk::getCurrentViewCount() const
|
|||
return drawFBO->getRenderPassDesc().viewCount();
|
||||
}
|
||||
|
||||
angle::Result ContextVk::flushCommandsAndEndRenderPassImpl(QueueSubmitType queueSubmit)
|
||||
angle::Result ContextVk::flushCommandsAndEndRenderPassImpl(QueueSubmitType queueSubmit,
|
||||
RenderPassClosureReason reason)
|
||||
{
|
||||
// Ensure we flush the RenderPass *after* the prior commands.
|
||||
ANGLE_TRY(flushOutsideRenderPassCommands());
|
||||
|
@ -5692,7 +5809,7 @@ angle::Result ContextVk::flushCommandsAndEndRenderPassImpl(QueueSubmitType queue
|
|||
|
||||
if (!mRenderPassCommands->started())
|
||||
{
|
||||
onRenderPassFinished();
|
||||
onRenderPassFinished(RenderPassClosureReason::AlreadySpecifiedElsewhere);
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
|
@ -5716,7 +5833,7 @@ angle::Result ContextVk::flushCommandsAndEndRenderPassImpl(QueueSubmitType queue
|
|||
populateTransformFeedbackBufferSet(xfbBufferCount, transformFeedbackVk->getBufferHelpers());
|
||||
}
|
||||
|
||||
onRenderPassFinished();
|
||||
onRenderPassFinished(reason);
|
||||
|
||||
if (mGpuEventsEnabled)
|
||||
{
|
||||
|
@ -5756,28 +5873,30 @@ angle::Result ContextVk::flushCommandsAndEndRenderPassImpl(QueueSubmitType queue
|
|||
if (mHasDeferredFlush && queueSubmit == QueueSubmitType::PerformQueueSubmit)
|
||||
{
|
||||
// If we have deferred glFlush call in the middle of renderpass, flush them now.
|
||||
ANGLE_TRY(flushImpl(nullptr));
|
||||
ANGLE_TRY(flushImpl(nullptr, RenderPassClosureReason::AlreadySpecifiedElsewhere));
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
angle::Result ContextVk::flushCommandsAndEndRenderPass()
|
||||
angle::Result ContextVk::flushCommandsAndEndRenderPass(RenderPassClosureReason reason)
|
||||
{
|
||||
return flushCommandsAndEndRenderPassImpl(QueueSubmitType::PerformQueueSubmit);
|
||||
return flushCommandsAndEndRenderPassImpl(QueueSubmitType::PerformQueueSubmit, reason);
|
||||
}
|
||||
|
||||
angle::Result ContextVk::flushCommandsAndEndRenderPassWithoutQueueSubmit()
|
||||
angle::Result ContextVk::flushCommandsAndEndRenderPassWithoutQueueSubmit(
|
||||
RenderPassClosureReason reason)
|
||||
{
|
||||
return flushCommandsAndEndRenderPassImpl(QueueSubmitType::SkipQueueSubmit);
|
||||
return flushCommandsAndEndRenderPassImpl(QueueSubmitType::SkipQueueSubmit, reason);
|
||||
}
|
||||
|
||||
angle::Result ContextVk::flushDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator,
|
||||
DirtyBits dirtyBitMask)
|
||||
DirtyBits dirtyBitMask,
|
||||
RenderPassClosureReason reason)
|
||||
{
|
||||
ASSERT(mRenderPassCommands->started());
|
||||
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPassImpl(QueueSubmitType::PerformQueueSubmit));
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPassImpl(QueueSubmitType::PerformQueueSubmit, reason));
|
||||
|
||||
// Set dirty bits that need processing on new render pass on the dirty bits iterator that's
|
||||
// being processed right now.
|
||||
|
@ -6158,7 +6277,8 @@ angle::Result ContextVk::updateRenderPassDepthStencilAccess()
|
|||
// renderpass here. Otherwise, updating it to writeable layout will produce a writable
|
||||
// feedback loop that is illegal in vulkan and will trigger validation errors that depth
|
||||
// texture is using the writable layout.
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::DepthStencilWriteAfterFeedbackLoop));
|
||||
// Clear read-only depth feedback mode.
|
||||
mDrawFramebuffer->setReadOnlyDepthFeedbackLoopMode(false);
|
||||
}
|
||||
|
@ -6260,7 +6380,7 @@ angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferA
|
|||
// the render pass. http://anglebug.com/4984
|
||||
if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, *imageAccess.image))
|
||||
{
|
||||
return flushCommandsAndEndRenderPass();
|
||||
return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPRead);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6269,7 +6389,7 @@ angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferA
|
|||
{
|
||||
if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, *imageWrite.access.image))
|
||||
{
|
||||
return flushCommandsAndEndRenderPass();
|
||||
return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPWrite);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6280,7 +6400,7 @@ angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferA
|
|||
{
|
||||
if (mRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer))
|
||||
{
|
||||
return flushCommandsAndEndRenderPass();
|
||||
return flushCommandsAndEndRenderPass(RenderPassClosureReason::BufferUseThenOutOfRPRead);
|
||||
}
|
||||
else if (mOutsideRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer))
|
||||
{
|
||||
|
@ -6293,7 +6413,8 @@ angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferA
|
|||
{
|
||||
if (mRenderPassCommands->usesBuffer(*bufferAccess.buffer))
|
||||
{
|
||||
return flushCommandsAndEndRenderPass();
|
||||
return flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::BufferUseThenOutOfRPWrite);
|
||||
}
|
||||
else if (mOutsideRenderPassCommands->usesBuffer(*bufferAccess.buffer))
|
||||
{
|
||||
|
@ -6349,7 +6470,8 @@ angle::Result ContextVk::endRenderPassIfComputeReadAfterTransformFeedbackWrite()
|
|||
vk::GetImpl(bufferBinding.get())->getBufferAndOffset(&bufferOffset);
|
||||
if (mCurrentTransformFeedbackBuffers.contains(&buffer))
|
||||
{
|
||||
return flushCommandsAndEndRenderPass();
|
||||
return flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::XfbWriteThenComputeRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6385,7 +6507,8 @@ angle::Result ContextVk::endRenderPassIfComputeReadAfterAttachmentWrite()
|
|||
|
||||
if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, image))
|
||||
{
|
||||
return flushCommandsAndEndRenderPass();
|
||||
return flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::ImageAttachmentThenComputeRead);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ enum class GraphicsEventCmdBuf
|
|||
EnumCount = 3,
|
||||
};
|
||||
|
||||
enum QueueSubmitType
|
||||
enum class QueueSubmitType
|
||||
{
|
||||
PerformQueueSubmit,
|
||||
SkipQueueSubmit,
|
||||
|
@ -407,9 +407,12 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
|
|||
|
||||
angle::Result onIndexBufferChange(const vk::BufferHelper *currentIndexBuffer);
|
||||
|
||||
angle::Result flushImpl(const vk::Semaphore *semaphore);
|
||||
angle::Result flushAndGetSerial(const vk::Semaphore *semaphore, Serial *submitSerialOut);
|
||||
angle::Result finishImpl();
|
||||
angle::Result flushImpl(const vk::Semaphore *semaphore,
|
||||
RenderPassClosureReason renderPassClosureReason);
|
||||
angle::Result flushAndGetSerial(const vk::Semaphore *semaphore,
|
||||
Serial *submitSerialOut,
|
||||
RenderPassClosureReason renderPassClosureReason);
|
||||
angle::Result finishImpl(RenderPassClosureReason renderPassClosureReason);
|
||||
|
||||
void addWaitSemaphore(VkSemaphore semaphore, VkPipelineStageFlags stageMask);
|
||||
|
||||
|
@ -575,8 +578,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
|
|||
vk::CommandBuffer **commandBufferOut,
|
||||
bool *renderPassDescChangedOut);
|
||||
void startNextSubpass();
|
||||
angle::Result flushCommandsAndEndRenderPass();
|
||||
angle::Result flushCommandsAndEndRenderPassWithoutQueueSubmit();
|
||||
angle::Result flushCommandsAndEndRenderPass(RenderPassClosureReason reason);
|
||||
angle::Result flushCommandsAndEndRenderPassWithoutQueueSubmit(RenderPassClosureReason reason);
|
||||
|
||||
angle::Result syncExternalMemory();
|
||||
|
||||
|
@ -923,11 +926,13 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
|
|||
// flushCommandsAndEndRenderPass() and flushDirtyGraphicsRenderPass() will set the dirty bits
|
||||
// directly or through the iterator respectively. Outside those two functions, this shouldn't
|
||||
// be called directly.
|
||||
angle::Result flushCommandsAndEndRenderPassImpl(QueueSubmitType queueSubmit);
|
||||
angle::Result flushCommandsAndEndRenderPassImpl(QueueSubmitType queueSubmit,
|
||||
RenderPassClosureReason reason);
|
||||
angle::Result flushDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator,
|
||||
DirtyBits dirtyBitMask);
|
||||
DirtyBits dirtyBitMask,
|
||||
RenderPassClosureReason reason);
|
||||
|
||||
void onRenderPassFinished();
|
||||
void onRenderPassFinished(RenderPassClosureReason reason);
|
||||
|
||||
void initIndexTypeMap();
|
||||
|
||||
|
@ -1204,7 +1209,7 @@ ANGLE_INLINE angle::Result ContextVk::endRenderPassIfTransformFeedbackBuffer(
|
|||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
return flushCommandsAndEndRenderPass();
|
||||
return flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbWriteThenVertexIndexBuffer);
|
||||
}
|
||||
|
||||
ANGLE_INLINE angle::Result ContextVk::onIndexBufferChange(
|
||||
|
|
|
@ -111,7 +111,8 @@ egl::Error DisplayVk::waitClient(const gl::Context *context)
|
|||
{
|
||||
ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitClient");
|
||||
ContextVk *contextVk = vk::GetImpl(context);
|
||||
return angle::ToEGL(contextVk->finishImpl(), this, EGL_BAD_ACCESS);
|
||||
return angle::ToEGL(contextVk->finishImpl(RenderPassClosureReason::EGLWaitClient), this,
|
||||
EGL_BAD_ACCESS);
|
||||
}
|
||||
|
||||
egl::Error DisplayVk::waitNative(const gl::Context *context, EGLint engine)
|
||||
|
|
|
@ -1419,7 +1419,8 @@ angle::Result FramebufferVk::resolveColorWithSubpass(ContextVk *contextVk,
|
|||
|
||||
// End the render pass now since we don't (yet) support subpass dependencies.
|
||||
drawRenderTarget->onColorResolve(contextVk, mCurrentFramebufferDesc.getLayerCount());
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::AlreadySpecifiedElsewhere));
|
||||
|
||||
// Remove the resolve attachment from the source framebuffer.
|
||||
srcFramebufferVk->removeColorResolveAttachment(readColorIndexGL);
|
||||
|
@ -1608,7 +1609,8 @@ angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk,
|
|||
//
|
||||
// Since we are not aware of any application that invalidates a color buffer and
|
||||
// continues to draw to it, we leave that unoptimized.
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::ColorBufferInvalidate));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1933,7 +1935,8 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
|
|||
// multisampled-render-to-texture, then srcFramebuffer->getSamples(context) gives > 1, but
|
||||
// there's no resolve happening as the read buffer's single sampled image will be used as
|
||||
// blit src. FramebufferVk::blit() will handle those details for us.
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(
|
||||
contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::FramebufferChange));
|
||||
}
|
||||
|
||||
updateRenderPassDesc(contextVk);
|
||||
|
@ -2409,7 +2412,7 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
|
|||
vk::CommandBuffer **commandBufferOut,
|
||||
bool *renderPassDescChangedOut)
|
||||
{
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass));
|
||||
|
||||
// Initialize RenderPass info.
|
||||
vk::AttachmentOpsArray renderPassAttachmentOps;
|
||||
|
|
|
@ -160,9 +160,7 @@ angle::Result ImageVk::orphan(const gl::Context *context, egl::ImageSibling *sib
|
|||
ContextVk *contextVk = vk::GetImpl(context);
|
||||
|
||||
// Flush the context to make sure the fence has been submitted.
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr));
|
||||
|
||||
return angle::Result::Continue;
|
||||
return contextVk->flushImpl(nullptr, RenderPassClosureReason::ImageOrphan);
|
||||
}
|
||||
|
||||
} // namespace rx
|
||||
|
|
|
@ -69,7 +69,7 @@ angle::Result OverlayVk::init(const gl::Context *context, bool *successOut)
|
|||
|
||||
mRefreshCulledWidgets = true;
|
||||
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr));
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr, RenderPassClosureReason::OverlayFontCreation));
|
||||
*successOut = true;
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
|
|
@ -521,7 +521,7 @@ angle::Result QueryVk::getResult(const gl::Context *context, bool wait)
|
|||
|
||||
if (isUsedInRecordedCommands())
|
||||
{
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr));
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr, RenderPassClosureReason::GetQueryResult));
|
||||
|
||||
ASSERT(!mQueryHelperTimeElapsedBegin.usedInRecordedCommands());
|
||||
ASSERT(!mQueryHelper.get().usedInRecordedCommands());
|
||||
|
|
|
@ -2523,13 +2523,6 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
|
|||
ExtensionFound(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, deviceExtensionNames) &&
|
||||
(!IsLinux() || nvidiaVersion.major > 418u));
|
||||
|
||||
// Work around ineffective compute-graphics barriers on Nexus 5X.
|
||||
// TODO(syoussefi): Figure out which other vendors and driver versions are affected.
|
||||
// http://anglebug.com/3019
|
||||
ANGLE_FEATURE_CONDITION(&mFeatures, flushAfterVertexConversion,
|
||||
IsAndroid() && IsNexus5X(mPhysicalDeviceProperties.vendorID,
|
||||
mPhysicalDeviceProperties.deviceID));
|
||||
|
||||
ANGLE_FEATURE_CONDITION(
|
||||
&mFeatures, supportsRenderpass2,
|
||||
ExtensionFound(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, deviceExtensionNames));
|
||||
|
|
|
@ -23,12 +23,15 @@ angle::Result FinishRunningCommands(ContextVk *contextVk, Serial serial)
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
angle::Result WaitForIdle(ContextVk *contextVk, const char *debugMessage, T *resource)
|
||||
angle::Result WaitForIdle(ContextVk *contextVk,
|
||||
T *resource,
|
||||
const char *debugMessage,
|
||||
RenderPassClosureReason reason)
|
||||
{
|
||||
// If there are pending commands for the resource, flush them.
|
||||
if (resource->usedInRecordedCommands())
|
||||
{
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr));
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr, reason));
|
||||
}
|
||||
|
||||
// Make sure the driver is done with the resource.
|
||||
|
@ -68,9 +71,11 @@ angle::Result Resource::finishRunningCommands(ContextVk *contextVk)
|
|||
return FinishRunningCommands(contextVk, mUse.getSerial());
|
||||
}
|
||||
|
||||
angle::Result Resource::waitForIdle(ContextVk *contextVk, const char *debugMessage)
|
||||
angle::Result Resource::waitForIdle(ContextVk *contextVk,
|
||||
const char *debugMessage,
|
||||
RenderPassClosureReason reason)
|
||||
{
|
||||
return WaitForIdle(contextVk, debugMessage, this);
|
||||
return WaitForIdle(contextVk, this, debugMessage, reason);
|
||||
}
|
||||
|
||||
// Resource implementation.
|
||||
|
@ -104,9 +109,11 @@ angle::Result ReadWriteResource::finishGPUWriteCommands(ContextVk *contextVk)
|
|||
return FinishRunningCommands(contextVk, mReadWriteUse.getSerial());
|
||||
}
|
||||
|
||||
angle::Result ReadWriteResource::waitForIdle(ContextVk *contextVk, const char *debugMessage)
|
||||
angle::Result ReadWriteResource::waitForIdle(ContextVk *contextVk,
|
||||
const char *debugMessage,
|
||||
RenderPassClosureReason reason)
|
||||
{
|
||||
return WaitForIdle(contextVk, debugMessage, this);
|
||||
return WaitForIdle(contextVk, this, debugMessage, reason);
|
||||
}
|
||||
|
||||
// SharedGarbage implementation.
|
||||
|
|
|
@ -184,7 +184,9 @@ class Resource : angle::NonCopyable
|
|||
angle::Result finishRunningCommands(ContextVk *contextVk);
|
||||
|
||||
// Complete all recorded and in-flight commands involving this resource
|
||||
angle::Result waitForIdle(ContextVk *contextVk, const char *debugMessage);
|
||||
angle::Result waitForIdle(ContextVk *contextVk,
|
||||
const char *debugMessage,
|
||||
RenderPassClosureReason reason);
|
||||
|
||||
// Adds the resource to a resource use list.
|
||||
void retain(ResourceUseList *resourceUseList) const;
|
||||
|
@ -236,7 +238,9 @@ class ReadWriteResource : public angle::NonCopyable
|
|||
angle::Result finishGPUWriteCommands(ContextVk *contextVk);
|
||||
|
||||
// Complete all recorded and in-flight commands involving this resource
|
||||
angle::Result waitForIdle(ContextVk *contextVk, const char *debugMessage);
|
||||
angle::Result waitForIdle(ContextVk *contextVk,
|
||||
const char *debugMessage,
|
||||
RenderPassClosureReason reason);
|
||||
|
||||
// Adds the resource to a resource use list.
|
||||
void retainReadOnly(ResourceUseList *resourceUseList) const;
|
||||
|
|
|
@ -219,7 +219,7 @@ angle::Result SemaphoreVk::signal(gl::Context *context,
|
|||
ANGLE_TRY(contextVk->syncExternalMemory());
|
||||
}
|
||||
|
||||
ANGLE_TRY(contextVk->flushImpl(&mSemaphore));
|
||||
ANGLE_TRY(contextVk->flushImpl(&mSemaphore, RenderPassClosureReason::ExternalSemaphoreSignal));
|
||||
|
||||
// The external has asked for the semaphore to be signaled. It will wait on this semaphore and
|
||||
// so we must ensure that the above flush (resulting in vkQueueSubmit) has actually been
|
||||
|
|
|
@ -1560,7 +1560,8 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
|
|||
// present can be destroyed.
|
||||
presentHistory.oldSwapchains = std::move(mOldSwapchains);
|
||||
|
||||
ANGLE_TRY(contextVk->flushAndGetSerial(presentSemaphore, swapSerial));
|
||||
ANGLE_TRY(contextVk->flushAndGetSerial(presentSemaphore, swapSerial,
|
||||
RenderPassClosureReason::EGLSwapBuffers));
|
||||
|
||||
VkPresentInfoKHR presentInfo = {};
|
||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
|
|
|
@ -94,7 +94,7 @@ angle::Result SyncHelper::initialize(ContextVk *contextVk, bool isEglSyncObject)
|
|||
// (for example when a buffer is mapped).
|
||||
//
|
||||
retain(&contextVk->getResourceUseList());
|
||||
return contextVk->flushImpl(nullptr);
|
||||
return contextVk->flushImpl(nullptr, RenderPassClosureReason::SyncObjectInit);
|
||||
}
|
||||
|
||||
angle::Result SyncHelper::clientWait(Context *context,
|
||||
|
@ -224,7 +224,7 @@ angle::Result SyncHelperNativeFence::initializeWithFd(ContextVk *contextVk, int
|
|||
with the newly created sync object.
|
||||
*/
|
||||
// Flush first because the fence comes after current pending set of commands.
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr));
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr, RenderPassClosureReason::SyncObjectWithFdInit));
|
||||
|
||||
retain(&contextVk->getResourceUseList());
|
||||
|
||||
|
@ -274,7 +274,7 @@ angle::Result SyncHelperNativeFence::clientWait(Context *context,
|
|||
|
||||
if (flushCommands && contextVk)
|
||||
{
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr));
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr, RenderPassClosureReason::SyncObjectClientWait));
|
||||
}
|
||||
|
||||
VkResult status = VK_SUCCESS;
|
||||
|
@ -318,7 +318,7 @@ angle::Result SyncHelperNativeFence::serverWait(ContextVk *contextVk)
|
|||
ANGLE_VK_TRY(contextVk, waitSemaphore.get().importFd(device, importFdInfo));
|
||||
|
||||
// Flush current work, block after current pending commands.
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr));
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr, RenderPassClosureReason::SyncObjectServerWait));
|
||||
|
||||
// Add semaphore to next submit job.
|
||||
contextVk->addWaitSemaphore(waitSemaphore.get().getHandle(),
|
||||
|
|
|
@ -866,8 +866,9 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
|
|||
|
||||
// Read back the requested region of the source texture
|
||||
uint8_t *sourceData = nullptr;
|
||||
ANGLE_TRY(source->copyImageDataToBufferAndGetData(contextVk, sourceLevelGL, sourceBox.depth,
|
||||
sourceBox, &sourceData));
|
||||
ANGLE_TRY(source->copyImageDataToBufferAndGetData(
|
||||
contextVk, sourceLevelGL, sourceBox.depth, sourceBox,
|
||||
RenderPassClosureReason::CopyTextureOnCPU, &sourceData));
|
||||
|
||||
const angle::Format &srcTextureFormat = source->getImage().getActualFormat();
|
||||
const angle::Format &dstTextureFormat =
|
||||
|
@ -1673,6 +1674,7 @@ angle::Result TextureVk::copyImageDataToBufferAndGetData(ContextVk *contextVk,
|
|||
gl::LevelIndex sourceLevelGL,
|
||||
uint32_t layerCount,
|
||||
const gl::Box &sourceArea,
|
||||
RenderPassClosureReason reason,
|
||||
uint8_t **outDataPtr)
|
||||
{
|
||||
ANGLE_TRACE_EVENT0("gpu.angle", "TextureVk::copyImageDataToBufferAndGetData");
|
||||
|
@ -1701,7 +1703,7 @@ angle::Result TextureVk::copyImageDataToBufferAndGetData(ContextVk *contextVk,
|
|||
&sourceCopyOffsets, outDataPtr));
|
||||
|
||||
// Explicitly finish. If new use cases arise where we don't want to block we can change this.
|
||||
ANGLE_TRY(contextVk->finishImpl());
|
||||
ANGLE_TRY(contextVk->finishImpl(reason));
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
@ -1880,6 +1882,7 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
|
|||
baseLevelExtents.depth);
|
||||
|
||||
ANGLE_TRY(copyImageDataToBufferAndGetData(contextVk, baseLevelGL, imageLayerCount, imageArea,
|
||||
RenderPassClosureReason::GenerateMipmapOnCPU,
|
||||
&imageData));
|
||||
|
||||
const angle::Format &angleFormat = mImage->getActualFormat();
|
||||
|
@ -2097,10 +2100,7 @@ angle::Result TextureVk::reinitImageAsRenderable(ContextVk *contextVk,
|
|||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW,
|
||||
"Copying data due to texture format fallback");
|
||||
|
||||
// Make sure the source is initialized and it's staged updates are flushed.
|
||||
// Make sure the source is initialized and its staged updates are flushed.
|
||||
ANGLE_TRY(flushImageStagedUpdates(contextVk));
|
||||
|
||||
const angle::Format &srcFormat = mImage->getActualFormat();
|
||||
|
@ -2112,6 +2112,9 @@ angle::Result TextureVk::reinitImageAsRenderable(ContextVk *contextVk,
|
|||
// staged updates that we just staged inside the loop which is wrong.
|
||||
if (levelCount == 1 && layerCount == 1)
|
||||
{
|
||||
ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW,
|
||||
"Copying image data due to texture format fallback");
|
||||
|
||||
ASSERT(CanCopyWithDraw(renderer, mImage->getActualFormatID(), mImage->getTilingMode(),
|
||||
format.getActualImageFormatID(getRequiredImageAccess()),
|
||||
getTilingMode()));
|
||||
|
@ -2134,6 +2137,9 @@ angle::Result TextureVk::reinitImageAsRenderable(ContextVk *contextVk,
|
|||
continue;
|
||||
}
|
||||
|
||||
ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
|
||||
"GPU stall due to texture format fallback");
|
||||
|
||||
gl::Box sourceBox(gl::kOffsetZero, mImage->getLevelExtents(levelVk));
|
||||
// copy and stage entire layer
|
||||
const gl::ImageIndex index =
|
||||
|
@ -2150,7 +2156,7 @@ angle::Result TextureVk::reinitImageAsRenderable(ContextVk *contextVk,
|
|||
|
||||
// Explicitly finish. If new use cases arise where we don't want to block we can change
|
||||
// this.
|
||||
ANGLE_TRY(contextVk->finishImpl());
|
||||
ANGLE_TRY(contextVk->finishImpl(RenderPassClosureReason::TextureReformatToRenderable));
|
||||
|
||||
size_t dstBufferSize = sourceBox.width * sourceBox.height * sourceBox.depth *
|
||||
dstFormat.pixelBytes * layerCount;
|
||||
|
|
|
@ -351,6 +351,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
|
|||
gl::LevelIndex sourceLevelGL,
|
||||
uint32_t layerCount,
|
||||
const gl::Box &sourceArea,
|
||||
RenderPassClosureReason reason,
|
||||
uint8_t **outDataPtr);
|
||||
|
||||
angle::Result copyBufferDataToImage(ContextVk *contextVk,
|
||||
|
|
|
@ -2109,7 +2109,8 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
|
|||
// render pass.
|
||||
if (isTransformFeedbackActiveUnpaused)
|
||||
{
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::XfbResumeAfterDrawBasedClear));
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
|
@ -2207,7 +2208,8 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk,
|
|||
contextVk->addGarbage(&destViewObject);
|
||||
|
||||
// Close the render pass for this temporary framebuffer.
|
||||
return contextVk->flushCommandsAndEndRenderPass();
|
||||
return contextVk->flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::TemporaryForImageClear);
|
||||
}
|
||||
|
||||
angle::Result UtilsVk::colorBlitResolve(ContextVk *contextVk,
|
||||
|
@ -2877,7 +2879,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
|
|||
descriptorPoolBinding.reset();
|
||||
|
||||
// Close the render pass for this temporary framebuffer.
|
||||
return contextVk->flushCommandsAndEndRenderPass();
|
||||
return contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::TemporaryForImageCopy);
|
||||
}
|
||||
|
||||
angle::Result UtilsVk::copyImageBits(ContextVk *contextVk,
|
||||
|
|
|
@ -589,7 +589,6 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
|
|||
GLuint stride;
|
||||
// Init attribute offset to the front-end value
|
||||
mCurrentArrayBufferRelativeOffsets[attribIndex] = attrib.relativeOffset;
|
||||
bool anyVertexBufferConvertedOnGpu = false;
|
||||
gl::Buffer *bufferGL = binding.getBuffer().get();
|
||||
// Emulated and/or client-side attribs will be streamed
|
||||
bool isStreamingVertexAttrib =
|
||||
|
@ -643,7 +642,6 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
|
|||
ANGLE_TRY(convertVertexBufferGPU(contextVk, bufferVk, binding, attribIndex,
|
||||
vertexFormat, conversion,
|
||||
attrib.relativeOffset, compressed));
|
||||
anyVertexBufferConvertedOnGpu = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -729,12 +727,6 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
|
|||
mCurrentArrayBufferStrides[attribIndex] = stride;
|
||||
mCurrentArrayBufferCompressed[attribIndex] = compressed;
|
||||
}
|
||||
|
||||
if (anyVertexBufferConvertedOnGpu &&
|
||||
renderer->getFeatures().flushAfterVertexConversion.enabled)
|
||||
{
|
||||
ANGLE_TRY(contextVk->flushImpl(nullptr));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -139,7 +139,7 @@ egl::Error IOSurfaceSurfaceVkMac::unMakeCurrent(const gl::Context *context)
|
|||
ASSERT(context != nullptr);
|
||||
ContextVk *contextVk = vk::GetImpl(context);
|
||||
DisplayVk *displayVk = vk::GetImpl(context->getDisplay());
|
||||
angle::Result result = contextVk->flushImpl(nullptr);
|
||||
angle::Result result = contextVk->flushImpl(nullptr, RenderPassClosureReason::ContextChange);
|
||||
return angle::ToEGL(result, displayVk, EGL_BAD_SURFACE);
|
||||
}
|
||||
|
||||
|
|
|
@ -2982,7 +2982,8 @@ angle::Result QueryHelper::beginQuery(ContextVk *contextVk)
|
|||
{
|
||||
if (contextVk->hasStartedRenderPass())
|
||||
{
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::BeginNonRenderPassQuery));
|
||||
}
|
||||
|
||||
CommandBuffer *commandBuffer;
|
||||
|
@ -2999,7 +3000,8 @@ angle::Result QueryHelper::endQuery(ContextVk *contextVk)
|
|||
{
|
||||
if (contextVk->hasStartedRenderPass())
|
||||
{
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
|
||||
RenderPassClosureReason::EndNonRenderPassQuery));
|
||||
}
|
||||
|
||||
CommandBuffer *commandBuffer;
|
||||
|
@ -3037,7 +3039,8 @@ angle::Result QueryHelper::flushAndWriteTimestamp(ContextVk *contextVk)
|
|||
{
|
||||
if (contextVk->hasStartedRenderPass())
|
||||
{
|
||||
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
|
||||
ANGLE_TRY(
|
||||
contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::TimestampQuery));
|
||||
}
|
||||
|
||||
CommandBuffer *commandBuffer;
|
||||
|
@ -7349,7 +7352,7 @@ angle::Result ImageHelper::readPixels(ContextVk *contextVk,
|
|||
|
||||
// Triggers a full finish.
|
||||
// TODO(jmadill): Don't block on asynchronous readback.
|
||||
ANGLE_TRY(contextVk->finishImpl());
|
||||
ANGLE_TRY(contextVk->finishImpl(RenderPassClosureReason::GLReadPixels));
|
||||
|
||||
// The buffer we copied to needs to be invalidated before we read from it because its not been
|
||||
// created with the host coherent bit.
|
||||
|
|
|
@ -1082,6 +1082,82 @@ GLuint GetSampleCount(VkSampleCountFlags supportedCounts, GLuint requestedCount)
|
|||
gl::LevelIndex GetLevelIndex(vk::LevelIndex levelVk, gl::LevelIndex baseLevel);
|
||||
} // namespace vk_gl
|
||||
|
||||
enum class RenderPassClosureReason
|
||||
{
|
||||
// Don't specify the reason (it should already be specified elsewhere)
|
||||
AlreadySpecifiedElsewhere,
|
||||
|
||||
// Implicit closures due to flush/wait/etc.
|
||||
ContextDestruction,
|
||||
ContextChange,
|
||||
GLFlush,
|
||||
GLFinish,
|
||||
EGLSwapBuffers,
|
||||
EGLWaitClient,
|
||||
|
||||
// Closure due to switching rendering to another framebuffer.
|
||||
FramebufferBindingChange,
|
||||
FramebufferChange,
|
||||
NewRenderPass,
|
||||
|
||||
// Incompatible use of resource in the same render pass
|
||||
BufferUseThenXfbWrite,
|
||||
XfbWriteThenVertexIndexBuffer,
|
||||
XfbWriteThenIndirectDrawBuffer,
|
||||
XfbResumeAfterDrawBasedClear,
|
||||
DepthStencilUseInFeedbackLoop,
|
||||
DepthStencilWriteAfterFeedbackLoop,
|
||||
PipelineBindWhileXfbActive,
|
||||
|
||||
// Use of resource after render pass
|
||||
BufferWriteThenMap,
|
||||
BufferUseThenOutOfRPRead,
|
||||
BufferUseThenOutOfRPWrite,
|
||||
ImageUseThenOutOfRPRead,
|
||||
ImageUseThenOutOfRPWrite,
|
||||
XfbWriteThenComputeRead,
|
||||
XfbWriteThenIndirectDispatchBuffer,
|
||||
ImageAttachmentThenComputeRead,
|
||||
GetQueryResult,
|
||||
BeginNonRenderPassQuery,
|
||||
EndNonRenderPassQuery,
|
||||
TimestampQuery,
|
||||
GLReadPixels,
|
||||
|
||||
// Synchronization
|
||||
BufferUseThenReleaseToExternal,
|
||||
ImageUseThenReleaseToExternal,
|
||||
BufferInUseWhenSynchronizedMap,
|
||||
ImageOrphan,
|
||||
GLMemoryBarrierThenStorageResource,
|
||||
StorageResourceUseThenGLMemoryBarrier,
|
||||
ExternalSemaphoreSignal,
|
||||
SyncObjectInit,
|
||||
SyncObjectWithFdInit,
|
||||
SyncObjectClientWait,
|
||||
SyncObjectServerWait,
|
||||
|
||||
// Closures that ANGLE could have avoided, but doesn't for simplicity or optimization of more
|
||||
// common cases.
|
||||
XfbPause,
|
||||
FramebufferFetchEmulation,
|
||||
ColorBufferInvalidate,
|
||||
GenerateMipmapOnCPU,
|
||||
CopyTextureOnCPU,
|
||||
TextureReformatToRenderable,
|
||||
DeviceLocalBufferMap,
|
||||
|
||||
// UtilsVk
|
||||
TemporaryForImageClear,
|
||||
TemporaryForImageCopy,
|
||||
|
||||
// Misc
|
||||
OverlayFontCreation,
|
||||
|
||||
InvalidEnum,
|
||||
EnumCount = InvalidEnum,
|
||||
};
|
||||
|
||||
} // namespace rx
|
||||
|
||||
#define ANGLE_VK_TRY(context, command) \
|
||||
|
|
Загрузка…
Ссылка в новой задаче