diff --git a/docs/features.txt b/docs/features.txt index f5297f37cb9..12c83971d16 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -114,7 +114,7 @@ GL 3.3, GLSL 3.30 --- all DONE: freedreno, nv50, nvc0, r600, radeonsi, llvmpipe, GL 4.0, GLSL 4.00 --- all DONE: freedreno/a6xx, nvc0, r600, radeonsi, llvmpipe, virgl, zink, d3d12, iris, crocus/gen7+, asahi GL_ARB_draw_buffers_blend DONE (freedreno, nv50, softpipe, panfrost, v3d, crocus/gen6+, etnaviv/HALTI5+) - GL_ARB_draw_indirect DONE (freedreno, softpipe, v3d) + GL_ARB_draw_indirect DONE (freedreno, softpipe, v3d, etnaviv/HALTI5+) GL_ARB_gpu_shader5 DONE (freedreno/a6xx) - 'precise' qualifier DONE (softpipe) - Dynamically uniform sampler array indices DONE (softpipe) diff --git a/docs/relnotes/new_features.txt b/docs/relnotes/new_features.txt index 64efbb722f6..443cb2f96e7 100644 --- a/docs/relnotes/new_features.txt +++ b/docs/relnotes/new_features.txt @@ -24,3 +24,4 @@ VK_KHR_shader_quad_control on nvk GL_EXT_draw_buffers2 on etnaviv/HALTI5+ GL_ARB_draw_buffers_blend on etnaviv/HALTI5+ VK_KHR_fragment_shading_rate on NVK +GL_ARB_draw_indirect on etnaviv/HALTI5+ diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c index e0e36fb6f54..bf049ff8946 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_context.c +++ b/src/gallium/drivers/etnaviv/etnaviv_context.c @@ -254,7 +254,7 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, return; int prims = u_decomposed_prims_for_vertices(info->mode, draws[0].count); - if (unlikely(prims <= 0)) { + if (!indirect && unlikely(prims <= 0)) { DBG("Invalid draw primitive mode=%i or no primitives to be drawn", info->mode); return; } @@ -375,6 +375,19 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, } } + if (indirect) { + /* + * When the indirect buffer is written by the GPU, e.g. by a compute shader, + * the shader L1 cache needs to be flushed for the data to become visible to + * the FE. Also there needs to be a PE/FE stall enforced between commands + * that generate the indirect buffer content and the indirect draw. + * + * This isn't implemented right now, so we don't support GPU written indirect buffers for now. + */ + assert(!(etna_resource_status(ctx, etna_resource(indirect->buffer)) & ETNA_PENDING_WRITE)); + resource_read(ctx, indirect->buffer); + } + ctx->stats.prims_generated += u_reduced_prims_for_vertices(info->mode, draws[0].count); ctx->stats.draw_calls++; @@ -401,15 +414,19 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, } } - if (screen->info->halti >= 2) { - /* On HALTI2+ (GC3000 and higher) only use instanced drawing commands, as the blob does */ - etna_draw_instanced(ctx->stream, info->index_size, draw_mode, info->instance_count, - draws[0].count, info->index_size ? draws->index_bias : draws[0].start); + if (indirect) { + etna_draw_indirect(ctx->stream, draw_mode, indirect->buffer, indirect->offset, info->index_size); } else { - if (info->index_size) - etna_draw_indexed_primitives(ctx->stream, draw_mode, 0, prims, draws->index_bias); - else - etna_draw_primitives(ctx->stream, draw_mode, draws[0].start, prims); + if (screen->info->halti >= 2) { + /* On HALTI2+ (GC3000 and higher) only use instanced drawing commands, as the blob does */ + etna_draw_instanced(ctx->stream, info->index_size, draw_mode, info->instance_count, + draws[0].count, info->index_size ? draws->index_bias : draws[0].start); + } else { + if (info->index_size) + etna_draw_indexed_primitives(ctx->stream, draw_mode, 0, prims, draws->index_bias); + else + etna_draw_primitives(ctx->stream, draw_mode, draws[0].start, prims); + } } if (DBG_ENABLED(ETNA_DBG_DRAW_STALL)) { diff --git a/src/gallium/drivers/etnaviv/etnaviv_emit.h b/src/gallium/drivers/etnaviv/etnaviv_emit.h index 6018af91dfd..e9aa04d39ad 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_emit.h +++ b/src/gallium/drivers/etnaviv/etnaviv_emit.h @@ -28,6 +28,7 @@ #define H_ETNA_EMIT #include "etnaviv_screen.h" +#include "etnaviv_resource.h" #include "etnaviv_util.h" #include "hw/cmdstream.xml.h" @@ -140,6 +141,25 @@ etna_draw_instanced(struct etna_cmd_stream *stream, etna_cmd_stream_emit(stream, 0); } +static inline void +etna_draw_indirect(struct etna_cmd_stream *stream, + uint32_t primitive_type, + struct pipe_resource *buffer, + unsigned offset, + bool indexed) +{ + etna_cmd_stream_reserve(stream, 2); + etna_cmd_stream_emit(stream, + VIV_FE_DRAW_INDIRECT_HEADER_OP_DRAW_INDIRECT | + VIV_FE_DRAW_INDIRECT_HEADER_TYPE(primitive_type) | + COND(indexed, VIV_FE_DRAW_INDIRECT_HEADER_INDEXED)); + etna_cmd_stream_reloc(stream, &(struct etna_reloc) { + .bo = etna_resource(buffer)->bo, + .flags = ETNA_RELOC_READ, + .offset = offset, + }); +} + static inline void etna_coalesce_start(struct etna_cmd_stream *stream, struct etna_coalesce *coalesce) diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c index 46e132f51f7..65f7c864418 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c @@ -198,6 +198,9 @@ etna_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_ALPHA_TEST: return !VIV_FEATURE(screen, ETNA_FEATURE_PE_NO_ALPHA_TEST); + case PIPE_CAP_DRAW_INDIRECT: + return VIV_FEATURE(screen, ETNA_FEATURE_HALTI5); + /* Unsupported features. */ case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_TEXRECT: