etnaviv: Implement ARB_draw_indirect

Passes all relevant piglits with forced GLSL 330 and GL 3.1.

Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31535>
This commit is contained in:
Christian Gmeiner 2023-12-07 17:12:54 +01:00
parent 13d99979d2
commit babeba264b
5 changed files with 51 additions and 10 deletions

View file

@ -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)

View file

@ -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+

View file

@ -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)) {

View file

@ -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)

View file

@ -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: