[Mesa-dev] Implementation of VK_KHR_draw_indirect_count extension for anv

Jason Ekstrand jason at jlekstrand.net
Tue Sep 18 12:29:45 UTC 2018

On Tue, Sep 18, 2018 at 5:47 AM Danylo Piliaiev <danylo.piliaiev at gmail.com>

> On 9/18/18 1:08 PM, Jason Ekstrand wrote:
> On Tue, Sep 18, 2018 at 4:08 AM Danylo Piliaiev <danylo.piliaiev at gmail.com>
> wrote:
>> On 9/17/18 7:03 PM, Jason Ekstrand wrote:
>> On Mon, Sep 17, 2018 at 10:08 AM Danylo Piliaiev <
>> danylo.piliaiev at gmail.com> wrote:
>>> On 9/17/18 5:34 PM, Jason Ekstrand wrote:
>>> On Mon, Sep 17, 2018 at 8:34 AM Danylo Piliaiev <
>>> danylo.piliaiev at gmail.com> wrote:
>>>> Hi Jason,
>>>> I have implemented the extension and it works, however before sending
>>>> the patch I decided to see how it can interact with other extension -
>>>> VK_EXT_conditional_render
>>>> and got confused:
>>>> From the spec it is not disallowed to call functions of
>>>> VK_KHR_draw_indirect_count in conditional rendering block. So let's say
>>>> that predicate of conditional rendering
>>>> will result in FALSE, we call vkCmdDrawIndirectCountKHR which sees
>>>> that there is already a predicate emitted and it should be taken into
>>>> account, since it will be FALSE
>>>> all next predicates should result in FALSE. The issue is that I don't
>>>> see an easy way to do this.
>>>> My current implementation uses the next predicate (it is same as in GL
>>>> implementation):
>>>>        /* While draw_index < maxDrawCount the predicate's result will be
>>>>         *  (draw_index == maxDrawCount) ^ TRUE = TRUE
>>>>         * When draw_index == maxDrawCount the result is
>>>>         *  (TRUE) ^ TRUE = FALSE
>>>>         * After this all results will be:
>>>>         *  (FALSE) ^ FALSE = FALSE
>>>>         */
>>>>        anv_batch_emit(&cmd_buffer->batch, GENX(MI_PREDICATE), mip) {
>>>>           mip.LoadOperation    = LOAD_LOAD;
>>>>           mip.CombineOperation = COMBINE_XOR;
>>>>           mip.CompareOperation = COMPARE_SRCS_EQUAL;
>>>>        }
>>>> But if the initial predicate state is FALSE then when draw_index equals
>>>> maxDrawCount the result will be
>>>>   (FALSE) ^ TRUE = TRUE
>>>> Which isn't something we want. But without "not equal" operation or
>>>> without MI_MATH I don't see how to fix this.
>>> First off, thanks for looking into the combination of these two
>>> features.  Getting them to work together nicely is half of the difficulty
>>> of these two extensions.
>>> On platforms which support MI_MATH, I think we're probably better off
>>> just using it.  For Ivy Bridge, the only thing I could think to do when
>>> both are in use would be to do two MI_PREDICATEs for every draw call.  The
>>> first would be what you describe above and the second would be the
>>> MI_PREDICATE for the conditional render with COMBINE_AND.  When the
>>> condition is true, the AND would have no effect and you would get the
>>> behavior above.  If the condition is false, the above logic for
>>> implementing draw_indirect_count wouldn't matter because it would get ANDed
>>> with false.  On Haswell and later, it's likely more efficient to just use
>>> MI_MATH and avoid re-loading the draw count and condition on every draw
>>> call.  (We could just leave the draw count in CS_GPR0, for instance.)  Does
>>> that work?
>>> Looks like a plan. I'll try to go this path.
>>> Also there is another interaction which wasn't thought of before:
>>> Several vkCmdDrawIndirectCountKHR in conditional render block but using
>>> MI_MATH should solve it.
>> In that case, we'll have to basically re-do the conditional bit for every
>> draw call.  There may be some interesting interactions here with secondary
>> command buffers as well.  I don't remember what we decided about inheriting
>> conditions in secondaries.  Again, if we decide we need MI_MATH, then we'll
>> just drop support for one or both extensions on Ivy Bridge.
>> About the secondary command buffers:
>> If inherited conditional rendering
>> <https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#features-features-inheritedConditionalRendering>
>> is supported it means that secondary buffers can be executed inside
>> conditional rendering block and commands which can be affected by
>> conditional rendering are affected by it in secondary buffer and also in
>> primary, is it right?
>> However at this point the secondary buffer is already composed without
>> commands for conditions and since our implementation depends on commands
>> emitted to the buffer making its commands to depend on condition either
>> highly tricky to do (secondary buffer needs to have certain points where to
>> inject conditions?) or just impossible.
>> And this secondary buffer may have been formed inside conditional render
>> block so they could be affected by two conditions if I understand correctly.
>> Is is doable to implement?
> I think it is.  The obvious way to implement it would be to have a boolean
> in the command buffer somewhere that tells you whether or not conditional
> rendering is enabled and use that to set the PredicateEnable bit on
> 3DPRIMITIVE commands.  For secondary command buffers, however, we would
> have to assume that predication is enabled and set the predicate to true in
> vkCmdExecuteCommands if conditional rendering is disabled.
> For primary buffers I'm already doing it this way.
> So if we want to support inherited conditional rendering all relevant
> commands in command buffers should be constructed with dependency on
> predicate. Just to be sure: is the dependency on predicate cheap?

I think it's relatively cheap.  We've been using predication for pipeline
barriers for a while and haven't noticed any performance problems related
to them.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20180918/d68099fa/attachment-0001.html>

More information about the mesa-dev mailing list