[Mesa-dev] [PATCH] radeonsi: fix gl_BaseVertex value in non-indexed draws
Nicolai Hähnle
nhaehnle at gmail.com
Fri Apr 7 22:41:12 UTC 2017
From: Nicolai Hähnle <nicolai.haehnle at 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
More information about the mesa-dev
mailing list