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 ...@@ -653,6 +653,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
if (getFeatures().supportsTransformFeedbackExtension.enabled) if (getFeatures().supportsTransformFeedbackExtension.enabled)
{ {
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_STATE); mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_STATE);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
} }
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS); mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING); mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
...@@ -663,6 +664,12 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -663,6 +664,12 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS); mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING); 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] = mGraphicsDirtyBitHandlers[DIRTY_BIT_DEFAULT_ATTRIBS] =
&ContextVk::handleDirtyGraphicsDefaultAttribs; &ContextVk::handleDirtyGraphicsDefaultAttribs;
mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE] = &ContextVk::handleDirtyGraphicsPipeline; mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE] = &ContextVk::handleDirtyGraphicsPipeline;
...@@ -682,6 +689,8 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -682,6 +689,8 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
&ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension; &ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension;
mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_STATE] = mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_STATE] =
&ContextVk::handleDirtyGraphicsTransformFeedbackState; &ContextVk::handleDirtyGraphicsTransformFeedbackState;
mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME] =
&ContextVk::handleDirtyGraphicsTransformFeedbackResume;
} }
else if (getFeatures().emulateTransformFeedback.enabled) else if (getFeatures().emulateTransformFeedback.enabled)
{ {
...@@ -1221,6 +1230,7 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context, ...@@ -1221,6 +1230,7 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
mGraphicsPipelineTransition.reset(); mGraphicsPipelineTransition.reset();
} }
mRenderPassCommands.pauseTransformFeedbackIfStarted();
commandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline()); commandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline());
// Update the queue serial for the pipeline object. // Update the queue serial for the pipeline object.
ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid()); ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid());
...@@ -1507,6 +1517,14 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Con ...@@ -1507,6 +1517,14 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Con
return angle::Result::Continue; 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, angle::Result ContextVk::handleDirtyDescriptorSets(const gl::Context *context,
vk::CommandBuffer *commandBuffer) vk::CommandBuffer *commandBuffer)
{ {
...@@ -4212,6 +4230,8 @@ angle::Result ContextVk::endRenderPass() ...@@ -4212,6 +4230,8 @@ angle::Result ContextVk::endRenderPass()
ANGLE_TRY(traceGpuEvent(&mPrimaryCommands, TRACE_EVENT_PHASE_BEGIN, eventName)); ANGLE_TRY(traceGpuEvent(&mPrimaryCommands, TRACE_EVENT_PHASE_BEGIN, eventName));
} }
mRenderPassCommands.pauseTransformFeedbackIfStarted();
ANGLE_TRY(mRenderPassCommands.flushToPrimary(this, &mPrimaryCommands)); ANGLE_TRY(mRenderPassCommands.flushToPrimary(this, &mPrimaryCommands));
if (mGpuEventsEnabled) if (mGpuEventsEnabled)
...@@ -4598,15 +4618,7 @@ angle::Result RenderPassCommandBuffer::flushToPrimary(ContextVk *contextVk, ...@@ -4598,15 +4618,7 @@ angle::Result RenderPassCommandBuffer::flushToPrimary(ContextVk *contextVk,
} }
else else
{ {
uint32_t numCounterBuffers =
(mRebindTransformFeedbackBuffers) ? 0 : mValidTransformFeedbackBufferCount;
primary->beginTransformFeedbackEXT(0, numCounterBuffers,
mTransformFeedbackCounterBuffers.data(), nullptr);
mCommandBuffer.executeCommands(primary->getHandle()); mCommandBuffer.executeCommands(primary->getHandle());
primary->endTransformFeedbackEXT(0, mValidTransformFeedbackBufferCount,
mTransformFeedbackCounterBuffers.data(), nullptr);
primary->endRenderPass(); primary->endRenderPass();
// Would be better to accumulate this barrier using the command APIs. // Would be better to accumulate this barrier using the command APIs.
...@@ -4693,4 +4705,31 @@ void RenderPassCommandBuffer::reset() ...@@ -4693,4 +4705,31 @@ void RenderPassCommandBuffer::reset()
mRebindTransformFeedbackBuffers = false; 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 } // namespace rx
...@@ -226,6 +226,9 @@ class RenderPassCommandBuffer final : public CommandBufferHelper ...@@ -226,6 +226,9 @@ class RenderPassCommandBuffer final : public CommandBufferHelper
bool started() const { return mRenderPassStarted; } bool started() const { return mRenderPassStarted; }
void reset(); void reset();
void resumeTransformFeedbackIfStarted();
void pauseTransformFeedbackIfStarted();
uint32_t getAndResetCounter() uint32_t getAndResetCounter()
{ {
uint32_t count = mCounter; uint32_t count = mCounter;
...@@ -690,6 +693,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -690,6 +693,7 @@ class ContextVk : public ContextImpl, public vk::Context
DIRTY_BIT_SHADER_RESOURCES, // excluding textures, which are handled separately. DIRTY_BIT_SHADER_RESOURCES, // excluding textures, which are handled separately.
DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS, DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS,
DIRTY_BIT_TRANSFORM_FEEDBACK_STATE, DIRTY_BIT_TRANSFORM_FEEDBACK_STATE,
DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME,
DIRTY_BIT_DESCRIPTOR_SETS, DIRTY_BIT_DESCRIPTOR_SETS,
DIRTY_BIT_MAX, DIRTY_BIT_MAX,
}; };
...@@ -829,7 +833,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -829,7 +833,7 @@ class ContextVk : public ContextImpl, public vk::Context
ANGLE_INLINE void invalidateCurrentGraphicsPipeline() ANGLE_INLINE void invalidateCurrentGraphicsPipeline()
{ {
mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE); mGraphicsDirtyBits |= mNewGraphicsPipelineDirtyBits;
// The draw mode may have changed, toggling whether line rasterization is // The draw mode may have changed, toggling whether line rasterization is
// enabled or not, which means we need to recreate the graphics pipeline. // enabled or not, which means we need to recreate the graphics pipeline.
mCurrentGraphicsPipeline = nullptr; mCurrentGraphicsPipeline = nullptr;
...@@ -871,6 +875,8 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -871,6 +875,8 @@ class ContextVk : public ContextImpl, public vk::Context
vk::CommandBuffer *commandBuffer); vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsTransformFeedbackState(const gl::Context *context, angle::Result handleDirtyGraphicsTransformFeedbackState(const gl::Context *context,
vk::CommandBuffer *commandBuffer); vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyGraphicsTransformFeedbackResume(const gl::Context *context,
vk::CommandBuffer *commandBuffer);
// Handlers for compute pipeline dirty bits. // Handlers for compute pipeline dirty bits.
angle::Result handleDirtyComputePipeline(const gl::Context *context, angle::Result handleDirtyComputePipeline(const gl::Context *context,
...@@ -964,6 +970,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -964,6 +970,7 @@ class ContextVk : public ContextImpl, public vk::Context
DirtyBits mIndexedDirtyBitsMask; DirtyBits mIndexedDirtyBitsMask;
DirtyBits mNewGraphicsCommandBufferDirtyBits; DirtyBits mNewGraphicsCommandBufferDirtyBits;
DirtyBits mNewComputeCommandBufferDirtyBits; DirtyBits mNewComputeCommandBufferDirtyBits;
DirtyBits mNewGraphicsPipelineDirtyBits;
// Cached back-end objects. // Cached back-end objects.
VertexArrayVk *mVertexArray; VertexArrayVk *mVertexArray;
......
...@@ -107,6 +107,10 @@ const char *GetCommandString(CommandID id) ...@@ -107,6 +107,10 @@ const char *GetCommandString(CommandID id)
return "WaitEvents"; return "WaitEvents";
case CommandID::WriteTimestamp: case CommandID::WriteTimestamp:
return "WriteTimestamp"; return "WriteTimestamp";
case CommandID::BeginTransformFeedback:
return "BeginTransformFeedback";
case CommandID::EndTransformFeedback:
return "EndTransformFeedback";
default: default:
// Need this to work around MSVC warning 4715. // Need this to work around MSVC warning 4715.
UNREACHABLE(); UNREACHABLE();
...@@ -483,6 +487,26 @@ void SecondaryCommandBuffer::executeCommands(VkCommandBuffer cmdBuffer) ...@@ -483,6 +487,26 @@ void SecondaryCommandBuffer::executeCommands(VkCommandBuffer cmdBuffer)
params->query); params->query);
break; 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: default:
{ {
UNREACHABLE(); UNREACHABLE();
......
...@@ -70,6 +70,8 @@ enum class CommandID : uint16_t ...@@ -70,6 +70,8 @@ enum class CommandID : uint16_t
SetEvent, SetEvent,
WaitEvents, WaitEvents,
WriteTimestamp, WriteTimestamp,
BeginTransformFeedback,
EndTransformFeedback,
}; };
#define VERIFY_4_BYTE_ALIGNMENT(StructName) \ #define VERIFY_4_BYTE_ALIGNMENT(StructName) \
...@@ -401,6 +403,18 @@ struct WriteTimestampParams ...@@ -401,6 +403,18 @@ struct WriteTimestampParams
}; };
VERIFY_4_BYTE_ALIGNMENT(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 // Header for every cmd in custom cmd buffer
struct CommandHeader struct CommandHeader
{ {
...@@ -608,6 +622,11 @@ class SecondaryCommandBuffer final : angle::NonCopyable ...@@ -608,6 +622,11 @@ class SecondaryCommandBuffer final : angle::NonCopyable
void writeTimestamp(VkPipelineStageFlagBits pipelineStage, void writeTimestamp(VkPipelineStageFlagBits pipelineStage,
VkQueryPool queryPool, VkQueryPool queryPool,
uint32_t query); uint32_t query);
void beginTransformFeedback(uint32_t counterBufferCount, const VkBuffer *pCounterBuffers);
void endTransformFeedback(uint32_t counterBufferCount, const VkBuffer *pCounterBuffers);
// No-op for compatibility // No-op for compatibility
VkResult end() { return VK_SUCCESS; } VkResult end() { return VK_SUCCESS; }
...@@ -1280,6 +1299,28 @@ ANGLE_INLINE void SecondaryCommandBuffer::writeTimestamp(VkPipelineStageFlagBits ...@@ -1280,6 +1299,28 @@ ANGLE_INLINE void SecondaryCommandBuffer::writeTimestamp(VkPipelineStageFlagBits
paramStruct->queryPool = queryPool; paramStruct->queryPool = queryPool;
paramStruct->query = query; 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 priv
} // namespace vk } // namespace vk
} // namespace rx } // 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