Skip to content
Snippets Groups Projects
Commit 9d1c7ae0 authored by Danylo Piliaiev's avatar Danylo Piliaiev :flag_ua:
Browse files

anv: Add support for VK_KHR_draw_indirect_count


This implementation depends on the requirement for caller
to provide maxDrawCount which allows to issue maxDrawCount 3DPRIMITIVE
commands and have each of them predicate on
 draw_id < draw_count_from_buffer

'predicate_enable' flag will also be useful for VK_EXT_conditional_render

Signed-off-by: default avatarDanylo Piliaiev <danylo.piliaiev@globallogic.com>
parent 90819abb
No related branches found
No related tags found
No related merge requests found
......@@ -78,6 +78,7 @@ EXTENSIONS = [
Extension('VK_KHR_descriptor_update_template', 1, True),
Extension('VK_KHR_device_group', 1, True),
Extension('VK_KHR_device_group_creation', 1, True),
Extension('VK_KHR_draw_indirect_count', 1, True),
Extension('VK_KHR_external_fence', 1,
'device->has_syncobj_wait'),
Extension('VK_KHR_external_fence_capabilities', 1, True),
......
......@@ -2011,6 +2011,8 @@ struct anv_cmd_state {
*/
bool hiz_enabled;
bool predicate_enable;
/**
* Array length is anv_cmd_state::pass::attachment_count. Array content is
* valid only when recording a render pass instance.
......
......@@ -2972,6 +2972,156 @@ void genX(CmdDrawIndexedIndirect)(
}
}
static void
emit_draw_count_predicate(struct anv_cmd_buffer *cmd_buffer,
struct anv_buffer *count_buffer,
uint64_t count_buffer_offset,
uint32_t draw_index)
{
struct anv_address count_addr =
anv_address_add(count_buffer->address, count_buffer_offset);
/* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
* command when loading the values into the predicate source registers.
*/
anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pipe);
/* Upload the current draw count from the draw parameters buffer to
* MI_PREDICATE_SRC0.
*/
emit_lrm(&cmd_buffer->batch, MI_PREDICATE_SRC0, count_addr);
/* Zero the top 32-bits of MI_PREDICATE_SRC0 */
emit_lri(&cmd_buffer->batch, MI_PREDICATE_SRC0 + 4, 0);
/* Upload the id of the current primitive to MI_PREDICATE_SRC1. */
emit_lri(&cmd_buffer->batch, MI_PREDICATE_SRC1, draw_index);
emit_lri(&cmd_buffer->batch, MI_PREDICATE_SRC1 + 4, 0);
if (!cmd_buffer->state.predicate_enable) {
/* If there is no previous predicate we should only set
* current predicate's result.
*/
anv_batch_emit(&cmd_buffer->batch, GENX(MI_PREDICATE), mip) {
mip.LoadOperation = LOAD_LOADINV;
mip.CombineOperation = COMBINE_SET;
mip.CompareOperation = COMPARE_SRCS_EQUAL;
}
} else {
/* 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;
}
}
cmd_buffer->state.predicate_enable = true;
}
void genX(CmdDrawIndirectCountKHR)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
VkBuffer _countBuffer,
VkDeviceSize countBufferOffset,
uint32_t maxDrawCount,
uint32_t stride)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
ANV_FROM_HANDLE(anv_buffer, count_buffer, _countBuffer);
struct anv_cmd_state *cmd_state = &cmd_buffer->state;
struct anv_pipeline *pipeline = cmd_state->gfx.base.pipeline;
const struct brw_vs_prog_data *vs_prog_data = get_vs_prog_data(pipeline);
if (anv_batch_has_error(&cmd_buffer->batch))
return;
genX(cmd_buffer_flush_state)(cmd_buffer);
const bool prev_predicate_enable = cmd_state->predicate_enable;
for (uint32_t i = 0; i < maxDrawCount; i++) {
struct anv_address draw = anv_address_add(buffer->address, offset);
emit_draw_count_predicate(cmd_buffer, count_buffer, countBufferOffset, i);
if (vs_prog_data->uses_firstvertex ||
vs_prog_data->uses_baseinstance)
emit_base_vertex_instance_bo(cmd_buffer, anv_address_add(draw, 8));
if (vs_prog_data->uses_drawid)
emit_draw_index(cmd_buffer, i);
load_indirect_parameters(cmd_buffer, draw, false);
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) {
prim.IndirectParameterEnable = true;
prim.PredicateEnable = cmd_state->predicate_enable;
prim.VertexAccessType = SEQUENTIAL;
prim.PrimitiveTopologyType = pipeline->topology;
}
offset += stride;
}
cmd_state->predicate_enable = prev_predicate_enable;
}
void genX(CmdDrawIndexedIndirectCountKHR)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
VkBuffer _countBuffer,
VkDeviceSize countBufferOffset,
uint32_t maxDrawCount,
uint32_t stride)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
ANV_FROM_HANDLE(anv_buffer, count_buffer, _countBuffer);
struct anv_cmd_state *cmd_state = &cmd_buffer->state;
struct anv_pipeline *pipeline = cmd_state->gfx.base.pipeline;
const struct brw_vs_prog_data *vs_prog_data = get_vs_prog_data(pipeline);
if (anv_batch_has_error(&cmd_buffer->batch))
return;
genX(cmd_buffer_flush_state)(cmd_buffer);
const bool prev_predicate_enable = cmd_state->predicate_enable;
for (uint32_t i = 0; i < maxDrawCount; i++) {
struct anv_address draw = anv_address_add(buffer->address, offset);
emit_draw_count_predicate(cmd_buffer, count_buffer, countBufferOffset, i);
/* TODO: We need to stomp base vertex to 0 somehow */
if (vs_prog_data->uses_firstvertex ||
vs_prog_data->uses_baseinstance)
emit_base_vertex_instance_bo(cmd_buffer, anv_address_add(draw, 12));
if (vs_prog_data->uses_drawid)
emit_draw_index(cmd_buffer, i);
load_indirect_parameters(cmd_buffer, draw, true);
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) {
prim.IndirectParameterEnable = true;
prim.PredicateEnable = cmd_state->predicate_enable;
prim.VertexAccessType = RANDOM;
prim.PrimitiveTopologyType = pipeline->topology;
}
offset += stride;
}
cmd_state->predicate_enable = prev_predicate_enable;
}
static VkResult
flush_compute_descriptor_set(struct anv_cmd_buffer *cmd_buffer)
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment