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 by setting a bit to tell the VS whether the draw is indexed or not, so that gl_BaseVertex can be adjusted accordingly when used. Fixes a bug in KHR-GL45.shader_draw_parameters_tests.ShaderMultiDrawArraysParameters.* --- src/gallium/drivers/radeonsi/si_shader.c | 17 +++++++++++++++-- src/gallium/drivers/radeonsi/si_shader.h | 2 ++ src/gallium/drivers/radeonsi/si_state_draw.c | 8 ++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 02447dd..f1daebe 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -1394,23 +1394,36 @@ static void declare_system_value(struct si_shader_context *ctx, SI_PARAM_BASE_VERTEX), ""); break; case TGSI_SEMANTIC_VERTEXID_NOBASE: /* Unused. Clarify the meaning in indexed vs. non-indexed * draws if this is ever used again. */ assert(false); break; case TGSI_SEMANTIC_BASEVERTEX: - value = LLVMGetParam(ctx->main_fn, - SI_PARAM_BASE_VERTEX); + { + /* For non-indexed draws, the base vertex set by the driver + * (for direct draws) or the CP (for indirect draws) is the + * first vertex ID, but GLSL expects 0 to be returned. + */ + LLVMValueRef vs_state = LLVMGetParam(ctx->main_fn, SI_PARAM_VS_STATE_BITS); + LLVMValueRef indexed; + + indexed = LLVMBuildLShr(gallivm->builder, vs_state, ctx->i32_1, ""); + indexed = LLVMBuildTrunc(gallivm->builder, indexed, ctx->i1, ""); + + value = LLVMBuildSelect(gallivm->builder, indexed, + LLVMGetParam(ctx->main_fn, SI_PARAM_BASE_VERTEX), + ctx->i32_0, ""); break; + } case TGSI_SEMANTIC_BASEINSTANCE: value = LLVMGetParam(ctx->main_fn, SI_PARAM_START_INSTANCE); break; case TGSI_SEMANTIC_DRAWID: value = LLVMGetParam(ctx->main_fn, SI_PARAM_DRAWID); break; diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h index fdb0dd4..f145eab 100644 --- a/src/gallium/drivers/radeonsi/si_shader.h +++ b/src/gallium/drivers/radeonsi/si_shader.h @@ -213,20 +213,22 @@ enum { SI_PARAM_BLOCK_ID, SI_PARAM_THREAD_ID, SI_NUM_PARAMS = SI_PARAM_POS_FIXED_PT + 9, /* +8 for COLOR[0..1] */ }; /* Fields of driver-defined VS state SGPR. */ /* Clamp vertex color output (only used in VS as VS). */ #define S_VS_STATE_CLAMP_VERTEX_COLOR(x) (((unsigned)(x) & 0x1) << 0) #define C_VS_STATE_CLAMP_VERTEX_COLOR 0xFFFFFFFE +#define S_VS_STATE_INDEXED(x) (((unsigned)(x) & 0x1) << 1) +#define C_VS_STATE_INDEXED 0xFFFFFFFD #define S_VS_STATE_LS_OUT_PATCH_SIZE(x) (((unsigned)(x) & 0x1FFF) << 8) #define C_VS_STATE_LS_OUT_PATCH_SIZE 0xFFE000FF #define S_VS_STATE_LS_OUT_VERTEX_SIZE(x) (((unsigned)(x) & 0xFF) << 24) #define C_VS_STATE_LS_OUT_VERTEX_SIZE 0x00FFFFFF /* SI-specific system values. */ enum { TGSI_SEMANTIC_DEFAULT_TESSOUTER_SI = TGSI_SEMANTIC_COUNT, TGSI_SEMANTIC_DEFAULT_TESSINNER_SI, }; diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c index 0d70ea9..aa528ce 100644 --- a/src/gallium/drivers/radeonsi/si_state_draw.c +++ b/src/gallium/drivers/radeonsi/si_state_draw.c @@ -487,22 +487,26 @@ static void si_emit_rasterizer_prim_state(struct si_context *sctx) * reset the stipple pattern at each packet (line strips, line loops). */ radeon_set_context_reg(cs, R_028A0C_PA_SC_LINE_STIPPLE, rs->pa_sc_line_stipple | S_028A0C_AUTO_RESET_CNTL(rast_prim == PIPE_PRIM_LINES ? 1 : 2)); sctx->last_rast_prim = rast_prim; sctx->last_sc_line_stipple = rs->pa_sc_line_stipple; } -static void si_emit_vs_state(struct si_context *sctx) +static void si_emit_vs_state(struct si_context *sctx, + const struct pipe_draw_info *info) { + sctx->current_vs_state &= C_VS_STATE_INDEXED; + sctx->current_vs_state |= S_VS_STATE_INDEXED(!!info->indexed); + if (sctx->current_vs_state != sctx->last_vs_state) { struct radeon_winsys_cs *cs = sctx->b.gfx.cs; radeon_set_sh_reg(cs, sctx->shader_userdata.sh_base[PIPE_SHADER_VERTEX] + SI_SGPR_VS_STATE_BITS * 4, sctx->current_vs_state); sctx->last_vs_state = sctx->current_vs_state; } @@ -1298,21 +1302,21 @@ void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) continue; si_pm4_emit(sctx, state); sctx->emitted.array[i] = state; } sctx->dirty_states = 0; si_emit_rasterizer_prim_state(sctx); if (sctx->tes_shader.cso) si_emit_derived_tess_state(sctx, info, &num_patches); - si_emit_vs_state(sctx); + si_emit_vs_state(sctx, info); si_emit_draw_registers(sctx, info, num_patches); si_ce_pre_draw_synchronization(sctx); si_emit_draw_packets(sctx, info, ib); si_ce_post_draw_synchronization(sctx); if (sctx->trace_buf) si_trace_emit(sctx); /* Workaround for a VGT hang when streamout is enabled. -- 2.9.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev