[Mesa-dev] Implementation of VK_KHR_draw_indirect_count extension for anv

Danylo Piliaiev danylo.piliaiev at gmail.com
Tue Sep 18 10:56:53 UTC 2018

On 9/18/18 1:46 PM, Danylo Piliaiev wrote:
> 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 <mailto: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 <mailto: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
>>>>         <mailto: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 _secondary_ command buffers should be constructed with 
> dependency on predicate. Just to be sure: is the dependency on 
> predicate cheap?
Sorry, forgot *secondary*.

And the last question: could conditional rendering be enabled  when 
secondary buffer is constructed and another one is enable when this 
secondary buffer is executes making it depend on two conditions?
>> The second issue is in communicating the predicate value.  If we 
>> don't have secondaries, we can just hang on to the condition buffer 
>> and re-read it whenever needed. If we're going to use secondaries, we 
>> won't have it available in the secondary.  One obvious option would 
>> be to simply reserve one of the CS_GPR registers, say CS_GPR15, for 
>> storing the predicate value.  On Ivy Bridge, the CS_GPRs don't exist 
>> and we'd have to pick some other RW register.  Digging through the 
>> docs, I found the MI_PREDICATE_DATA which seems to exist for just 
>> this sort of thing. :-)  Exactly what register we use will have to 
>> depend on how we want to compute predicate values; I could see 
>> CS_GPR15 being more convenient if we use MI_MATH, for instance.
> Thanks for suggestion!
>> --Jason

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20180918/094d2311/attachment.html>

More information about the mesa-dev mailing list