From: Nicolai Hähnle <nicolai.haeh...@amd.com> gl_BaseVertex is supposed to be 0 in non-indexed draws. Unfortunately, the way they're implemented, the VGT always generates indices starting at 0, and the VS prolog adds the start index.
There's a VGT_INDX_OFFSET register which causes the VGT to start at a driver-defined index. However, this register cannot be written from indirect draws. So fix this unlikely case in the VS prolog. Fixes a bug in KHR-GL45.shader_draw_parameters_tests.ShaderMultiDrawArraysParameters.* --- src/gallium/drivers/radeonsi/si_pipe.h | 1 + src/gallium/drivers/radeonsi/si_shader.c | 17 +++++++++++++++++ src/gallium/drivers/radeonsi/si_shader.h | 1 + src/gallium/drivers/radeonsi/si_state_draw.c | 5 +++++ src/gallium/drivers/radeonsi/si_state_shaders.c | 2 ++ 5 files changed, 26 insertions(+) diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h index daf2932..ecf0f41 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -343,20 +343,21 @@ struct si_context { int last_sh_base_reg; int last_primitive_restart_en; int last_restart_index; int last_gs_out_prim; int last_prim; int last_multi_vgt_param; int last_rast_prim; unsigned last_sc_line_stipple; enum pipe_prim_type current_rast_prim; /* primitive type after TES, GS */ bool gs_tri_strip_adj_fix; + bool current_indexed; /* Scratch buffer */ struct r600_atom scratch_state; struct r600_resource *scratch_buffer; unsigned scratch_waves; unsigned spi_tmpring_size; struct r600_resource *compute_scratch_buffer; /* Emitted derived tessellation state. */ diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index f5f86f9..e76ee05 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -7871,20 +7871,37 @@ static void si_build_vs_prolog_function(struct si_shader_context *ctx, index = LLVMBuildAdd(gallivm->builder, LLVMGetParam(func, ctx->param_vertex_id), LLVMGetParam(func, SI_SGPR_BASE_VERTEX), ""); } index = LLVMBuildBitCast(gallivm->builder, index, ctx->f32, ""); ret = LLVMBuildInsertValue(gallivm->builder, ret, index, num_params++, ""); } + /* For DrawArrays(Indirect) and variants, the basevertex loaded into + * the SGPR is the 'first' parameter of the draw call. However, the + * value returned as gl_BaseVertex to the VS should be 0. + */ + if (key->vs_prolog.states.clear_basevertex) { + LLVMValueRef index; + + index = LLVMBuildAdd(gallivm->builder, + LLVMGetParam(func, ctx->param_vertex_id), + LLVMGetParam(func, SI_SGPR_BASE_VERTEX), ""); + index = LLVMBuildBitCast(gallivm->builder, index, ctx->f32, ""); + ret = LLVMBuildInsertValue(gallivm->builder, ret, index, + ctx->param_vertex_id, ""); + ret = LLVMBuildInsertValue(gallivm->builder, ret, ctx->i32_0, + SI_SGPR_BASE_VERTEX, ""); + } + si_llvm_build_ret(ctx, ret); } /** * Build the vertex shader epilog function. This is also used by the tessellation * evaluation shader compiled as VS. * * The input is PrimitiveID. * * If PrimitiveID is required by the pixel shader, export it. diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h index 17ffc5d..a3fcb42 100644 --- a/src/gallium/drivers/radeonsi/si_shader.h +++ b/src/gallium/drivers/radeonsi/si_shader.h @@ -334,20 +334,21 @@ struct si_shader_selector { * | | | | | * Only VS & PS: VS | -- | -- | -- | -- | PS * With GS: ES | -- | -- | GS | VS | PS * With Tessel.: LS | HS | VS | -- | -- | PS * With both: LS | HS | ES | GS | VS | PS */ /* Common VS bits between the shader key and the prolog key. */ struct si_vs_prolog_bits { unsigned instance_divisors[SI_MAX_ATTRIBS]; + unsigned clear_basevertex:1; }; /* Common VS bits between the shader key and the epilog key. */ struct si_vs_epilog_bits { unsigned export_prim_id:1; /* when PS needs it and GS is disabled */ }; /* Common TCS bits between the shader key and the epilog key. */ struct si_tcs_epilog_bits { unsigned prim_mode:3; diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c index 2c4e371..4549dd2 100644 --- a/src/gallium/drivers/radeonsi/si_state_draw.c +++ b/src/gallium/drivers/radeonsi/si_state_draw.c @@ -1145,20 +1145,25 @@ void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) else if (sctx->tes_shader.cso) rast_prim = sctx->tes_shader.cso->info.properties[TGSI_PROPERTY_TES_PRIM_MODE]; else rast_prim = info->mode; if (rast_prim != sctx->current_rast_prim) { sctx->current_rast_prim = rast_prim; sctx->do_update_shaders = true; } + if (info->indexed != sctx->current_indexed) { + sctx->current_indexed = info->indexed; + sctx->do_update_shaders = true; + } + if (sctx->gs_shader.cso) { /* Determine whether the GS triangle strip adjacency fix should * be applied. Rotate every other triangle if * - triangle strips with adjacency are fed to the GS and * - primitive restart is disabled (the rotation doesn't help * when the restart occurs after an odd number of triangles). */ bool gs_tri_strip_adj_fix = !sctx->tes_shader.cso && info->mode == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY && diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c index ff4ff01..f821c9d 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.c +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c @@ -1043,20 +1043,22 @@ static inline void si_shader_selector_key(struct pipe_context *ctx, if (sctx->tes_shader.cso) key->as_ls = 1; else if (sctx->gs_shader.cso) key->as_es = 1; else { si_shader_selector_key_hw_vs(sctx, sel, key); if (sctx->ps_shader.cso && sctx->ps_shader.cso->info.uses_primid) key->part.vs.epilog.export_prim_id = 1; } + if (!sctx->current_indexed && sel->info.uses_basevertex) + key->part.vs.prolog.clear_basevertex = 1; break; case PIPE_SHADER_TESS_CTRL: key->part.tcs.epilog.prim_mode = sctx->tes_shader.cso->info.properties[TGSI_PROPERTY_TES_PRIM_MODE]; key->part.tcs.epilog.tes_reads_tess_factors = sctx->tes_shader.cso->info.reads_tess_factors; if (sel == sctx->fixed_func_tcs_shader.cso) key->mono.tcs.inputs_to_copy = sctx->vs_shader.cso->outputs_written; break; -- 2.9.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev