[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