| # Transform Feedback via extension |
| |
| ## Outline |
| |
| ANGLE emulates transform feedback using the vertexPipelineStoresAndAtomics features in Vulkan. |
| But some GPU vendors do not support these atomics. Also the emulation becomes more difficult in |
| GLES 3.2. Therefore ANGLE must support using the VK_EXT_transform_feedback extension. |
| |
| We also expect a performance gain when we use this extension. |
| |
| ## Implementation of Pause/Resume using CounterBuffer |
| |
| The Vulkan extension does not provide separate APIs for `glPauseTransformFeedback` / |
| `glEndTransformFeedback`. |
| |
| Instead, Vulkan introduced Counter buffers in `vkCmdBeginTransformFeedbackEXT` / |
| `vkCmdEndTransformFeedbackEXT` as API parameters. |
| |
| To pause, we call `vkCmdEndTransformFeedbackEXT` and provide valid buffer handles in the |
| `pCounterBuffers` array and valid offsets in the `pCounterBufferOffsets` array for the |
| implementation to save the resume points. |
| |
| Then to resume, we call `vkCmdBeginTransformFeedbackEXT` with the previous `pCounterBuffers` |
| and `pCounterBufferOffsets` values. |
| |
| Between the pause and resume there needs to be a memory barrier for the counter buffers with a |
| source access of `VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT` at pipeline stage |
| `VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT` to a destination access of |
| `VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT` at pipeline stage |
| `VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT`. |
| |
| ## Implementation of glTransformFeedbackVaryings |
| |
| There is no equivalent function for glTransformFeedbackVaryings in Vulkan. The Vulkan specification |
| states that the last vertex processing stage shader must be declared with the XFB execution mode. |
| |
| The SPIR-V transformer takes care of adding this execution mode, as well as decorating the variables |
| that need to be captured. |
| |
| ANGLE modifies gl_position.z in vertex shader for the Vulkan coordinate system. So, if we capture |
| the value of 'gl_position' in the XFB buffer, the captured values will be incorrect. To resolve |
| this, we declare an internal position varying and copy the value from 'gl_position'. We capture the |
| internal position varying during transform feedback operation. For simplicity, we do this for every |
| captured varying, even though we could decorate the `gl_PerVertex` struct members in SPIR-V |
| directly. |