Commit d5ba916d by Jian Li Committed by Commit Bot

Vulkan: Change to record transform feedback related APIs per spec

Fix not to record vkCmdBindPipeline and vkCmdBindTransformFeedbackBuffers during transform feedback is active. Initiated by Hyunchang Kim hckim.kim@samsung.com https://chromium-review.googlesource.com/c/angle/angle/+/1971953 Pause Transform feedback on binding graphics pipeline and end of render pass. Set a new dirty bit to indicate transform feedback may need resume when invalidate graphics pipeline. Test: dEQP-GLES3.functional.transform_feedback.* Test: angle_end2end_tests --gtest_filter=TransformFeedbackTest* Bug: angleproject:3206 Change-Id: I6c70ef461a31dcd618058b167835ac278a21d04a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2139474 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 2aa42d8b
......@@ -653,6 +653,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
if (getFeatures().supportsTransformFeedbackExtension.enabled)
{
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_STATE);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
}
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
......@@ -663,6 +664,12 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
mNewGraphicsPipelineDirtyBits.set(DIRTY_BIT_PIPELINE);
if (getFeatures().supportsTransformFeedbackExtension.enabled)
{
mNewGraphicsPipelineDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
}
mGraphicsDirtyBitHandlers[DIRTY_BIT_DEFAULT_ATTRIBS] =
&ContextVk::handleDirtyGraphicsDefaultAttribs;
mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE] = &ContextVk::handleDirtyGraphicsPipeline;
......@@ -682,6 +689,8 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
&ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension;
mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_STATE] =
&ContextVk::handleDirtyGraphicsTransformFeedbackState;
mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME] =
&ContextVk::handleDirtyGraphicsTransformFeedbackResume;
}
else if (getFeatures().emulateTransformFeedback.enabled)
{
......@@ -1221,6 +1230,7 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
mGraphicsPipelineTransition.reset();
}
mRenderPassCommands.pauseTransformFeedbackIfStarted();
commandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline());
// Update the queue serial for the pipeline object.
ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid());
......@@ -1507,6 +1517,14 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Con
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume(
const gl::Context *context,
vk::CommandBuffer *commandBuffer)
{
mRenderPassCommands.resumeTransformFeedbackIfStarted();
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyDescriptorSets(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
{
......@@ -4212,6 +4230,8 @@ angle::Result ContextVk::endRenderPass()
ANGLE_TRY(traceGpuEvent(&mPrimaryCommands, TRACE_EVENT_PHASE_BEGIN, eventName));
}
mRenderPassCommands.pauseTransformFeedbackIfStarted();
ANGLE_TRY(mRenderPassCommands.flushToPrimary(this, &mPrimaryCommands));
if (mGpuEventsEnabled)
......@@ -4598,15 +4618,7 @@ angle::Result RenderPassCommandBuffer::flushToPrimary(ContextVk *contextVk,
}
else
{
uint32_t numCounterBuffers =
(mRebindTransformFeedbackBuffers) ? 0 : mValidTransformFeedbackBufferCount;
primary->beginTransformFeedbackEXT(0, numCounterBuffers,
mTransformFeedbackCounterBuffers.data(), nullptr);
mCommandBuffer.executeCommands(primary->getHandle());
primary->endTransformFeedbackEXT(0, mValidTransformFeedbackBufferCount,
mTransformFeedbackCounterBuffers.data(), nullptr);
primary->endRenderPass();
// Would be better to accumulate this barrier using the command APIs.
......@@ -4693,4 +4705,31 @@ void RenderPassCommandBuffer::reset()
mRebindTransformFeedbackBuffers = false;
}
void RenderPassCommandBuffer::resumeTransformFeedbackIfStarted()
{
if (mValidTransformFeedbackBufferCount == 0)
{
return;
}
uint32_t numCounterBuffers =
mRebindTransformFeedbackBuffers ? 0 : mValidTransformFeedbackBufferCount;
mRebindTransformFeedbackBuffers = false;
mCommandBuffer.beginTransformFeedback(numCounterBuffers,
mTransformFeedbackCounterBuffers.data());
}
void RenderPassCommandBuffer::pauseTransformFeedbackIfStarted()
{
if (mValidTransformFeedbackBufferCount == 0)
{
return;
}
mCommandBuffer.endTransformFeedback(mValidTransformFeedbackBufferCount,
mTransformFeedbackCounterBuffers.data());
}
} // namespace rx
......@@ -226,6 +226,9 @@ class RenderPassCommandBuffer final : public CommandBufferHelper
bool started() const { return mRenderPassStarted; }
void reset();
void resumeTransformFeedbackIfStarted();
void pauseTransformFeedbackIfStarted();
uint32_t getAndResetCounter()
{
uint32_t count = mCounter;
......@@ -690,6 +693,7 @@ class ContextVk : public ContextImpl, public vk::Context
DIRTY_BIT_SHADER_RESOURCES, // excluding textures, which are handled separately.
DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS,
DIRTY_BIT_TRANSFORM_FEEDBACK_STATE,
DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME,
DIRTY_BIT_DESCRIPTOR_SETS,
DIRTY_BIT_MAX,
};
......@@ -829,7 +833,7 @@ class ContextVk : public ContextImpl, public vk::Context
ANGLE_INLINE void invalidateCurrentGraphicsPipeline()
{
mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE);
mGraphicsDirtyBits |= mNewGraphicsPipelineDirtyBits;
// The draw mode may have changed, toggling whether line rasterization is
// enabled or not, which means we need to recreate the graphics pipeline.
mCurrentGraphicsPipeline = nullptr;
......@@ -871,6 +875,8 @@ class ContextVk : public ContextImpl, public vk::Context
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsTransformFeedbackState(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsTransformFeedbackResume(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
// Handlers for compute pipeline dirty bits.
angle::Result handleDirtyComputePipeline(const gl::Context *context,
......@@ -964,6 +970,7 @@ class ContextVk : public ContextImpl, public vk::Context
DirtyBits mIndexedDirtyBitsMask;
DirtyBits mNewGraphicsCommandBufferDirtyBits;
DirtyBits mNewComputeCommandBufferDirtyBits;
DirtyBits mNewGraphicsPipelineDirtyBits;
// Cached back-end objects.
VertexArrayVk *mVertexArray;
......
......@@ -107,6 +107,10 @@ const char *GetCommandString(CommandID id)
return "WaitEvents";
case CommandID::WriteTimestamp:
return "WriteTimestamp";
case CommandID::BeginTransformFeedback:
return "BeginTransformFeedback";
case CommandID::EndTransformFeedback:
return "EndTransformFeedback";
default:
// Need this to work around MSVC warning 4715.
UNREACHABLE();
......@@ -483,6 +487,26 @@ void SecondaryCommandBuffer::executeCommands(VkCommandBuffer cmdBuffer)
params->query);
break;
}
case CommandID::BeginTransformFeedback:
{
const BeginTransformFeedbackParams *params =
getParamPtr<BeginTransformFeedbackParams>(currentCommand);
const VkBuffer *counterBuffers =
Offset<VkBuffer>(params, sizeof(BeginTransformFeedbackParams));
vkCmdBeginTransformFeedbackEXT(cmdBuffer, 0, params->bufferCount,
counterBuffers, nullptr);
break;
}
case CommandID::EndTransformFeedback:
{
const EndTransformFeedbackParams *params =
getParamPtr<EndTransformFeedbackParams>(currentCommand);
const VkBuffer *counterBuffers =
Offset<VkBuffer>(params, sizeof(EndTransformFeedbackParams));
vkCmdEndTransformFeedbackEXT(cmdBuffer, 0, params->bufferCount, counterBuffers,
nullptr);
break;
}
default:
{
UNREACHABLE();
......
......@@ -70,6 +70,8 @@ enum class CommandID : uint16_t
SetEvent,
WaitEvents,
WriteTimestamp,
BeginTransformFeedback,
EndTransformFeedback,
};
#define VERIFY_4_BYTE_ALIGNMENT(StructName) \
......@@ -401,6 +403,18 @@ struct WriteTimestampParams
};
VERIFY_4_BYTE_ALIGNMENT(WriteTimestampParams)
struct BeginTransformFeedbackParams
{
uint32_t bufferCount;
};
VERIFY_4_BYTE_ALIGNMENT(BeginTransformFeedbackParams)
struct EndTransformFeedbackParams
{
uint32_t bufferCount;
};
VERIFY_4_BYTE_ALIGNMENT(EndTransformFeedbackParams)
// Header for every cmd in custom cmd buffer
struct CommandHeader
{
......@@ -608,6 +622,11 @@ class SecondaryCommandBuffer final : angle::NonCopyable
void writeTimestamp(VkPipelineStageFlagBits pipelineStage,
VkQueryPool queryPool,
uint32_t query);
void beginTransformFeedback(uint32_t counterBufferCount, const VkBuffer *pCounterBuffers);
void endTransformFeedback(uint32_t counterBufferCount, const VkBuffer *pCounterBuffers);
// No-op for compatibility
VkResult end() { return VK_SUCCESS; }
......@@ -1280,6 +1299,28 @@ ANGLE_INLINE void SecondaryCommandBuffer::writeTimestamp(VkPipelineStageFlagBits
paramStruct->queryPool = queryPool;
paramStruct->query = query;
}
ANGLE_INLINE void SecondaryCommandBuffer::beginTransformFeedback(uint32_t bufferCount,
const VkBuffer *counterBuffers)
{
uint8_t *writePtr;
size_t bufferSize = bufferCount * sizeof(VkBuffer);
BeginTransformFeedbackParams *paramStruct = initCommand<BeginTransformFeedbackParams>(
CommandID::BeginTransformFeedback, bufferSize, &writePtr);
paramStruct->bufferCount = bufferCount;
storePointerParameter(writePtr, counterBuffers, bufferSize);
}
ANGLE_INLINE void SecondaryCommandBuffer::endTransformFeedback(uint32_t bufferCount,
const VkBuffer *counterBuffers)
{
uint8_t *writePtr;
size_t bufferSize = bufferCount * sizeof(VkBuffer);
EndTransformFeedbackParams *paramStruct = initCommand<EndTransformFeedbackParams>(
CommandID::EndTransformFeedback, bufferSize, &writePtr);
paramStruct->bufferCount = bufferCount;
storePointerParameter(writePtr, counterBuffers, bufferSize);
}
} // namespace priv
} // namespace vk
} // namespace rx
......
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