From e7a52a5cb810de49a8282cb9f9caea5d554c3348 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Mon, 10 Aug 2015 01:50:11 +0200 Subject: [PATCH] radeonsi: add support for gl_PrimitiveID in the fragment shader MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit It must be obtained from the VS. The GS scenario A must be enabled for PrimID to be generated for the VS. + 4 piglits Reviewed-by: Michel Dänzer --- src/gallium/drivers/radeonsi/si_shader.c | 22 +++++++++++++++--- src/gallium/drivers/radeonsi/si_shader.h | 12 ++++++++++ src/gallium/drivers/radeonsi/si_state.c | 1 - .../drivers/radeonsi/si_state_shaders.c | 23 +++++++++++++++---- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 61d36430bcf..ac1c1be7a79 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -73,6 +73,7 @@ struct si_shader_context int param_streamout_offset[4]; int param_vertex_id; int param_rel_auto_id; + int param_vs_prim_id; int param_instance_id; int param_tes_u; int param_tes_v; @@ -486,6 +487,9 @@ static LLVMValueRef get_primitive_id(struct lp_build_tgsi_context *bld_base, return bld_base->uint_bld.zero; switch (si_shader_ctx->type) { + case TGSI_PROCESSOR_VERTEX: + return LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, + si_shader_ctx->param_vs_prim_id); case TGSI_PROCESSOR_TESS_CTRL: return LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_PATCH_ID); @@ -2027,7 +2031,7 @@ static void si_llvm_emit_vs_epilogue(struct lp_build_tgsi_context * bld_base) struct si_shader_output_values *outputs = NULL; int i,j; - outputs = MALLOC(info->num_outputs * sizeof(outputs[0])); + outputs = MALLOC((info->num_outputs + 1) * sizeof(outputs[0])); for (i = 0; i < info->num_outputs; i++) { outputs[i].name = info->output_semantic_name[i]; @@ -2040,7 +2044,19 @@ static void si_llvm_emit_vs_epilogue(struct lp_build_tgsi_context * bld_base) ""); } - si_llvm_export_vs(bld_base, outputs, info->num_outputs); + /* Export PrimitiveID when PS needs it. */ + if (si_vs_exports_prim_id(si_shader_ctx->shader)) { + outputs[i].name = TGSI_SEMANTIC_PRIMID; + outputs[i].sid = 0; + outputs[i].values[0] = bitcast(bld_base, TGSI_TYPE_FLOAT, + get_primitive_id(bld_base, 0)); + outputs[i].values[1] = bld_base->base.undef; + outputs[i].values[2] = bld_base->base.undef; + outputs[i].values[3] = bld_base->base.undef; + i++; + } + + si_llvm_export_vs(bld_base, outputs, i); FREE(outputs); } @@ -3415,7 +3431,7 @@ static void create_function(struct si_shader_context *si_shader_ctx) /* VGPRs */ params[si_shader_ctx->param_vertex_id = num_params++] = i32; params[si_shader_ctx->param_rel_auto_id = num_params++] = i32; - params[num_params++] = i32; /* unused */ + params[si_shader_ctx->param_vs_prim_id = num_params++] = i32; params[si_shader_ctx->param_instance_id = num_params++] = i32; break; diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h index 82e9c915965..cd845c12e64 100644 --- a/src/gallium/drivers/radeonsi/si_shader.h +++ b/src/gallium/drivers/radeonsi/si_shader.h @@ -221,6 +221,7 @@ union si_shader_key { uint64_t es_enabled_outputs; unsigned as_es:1; /* export shader */ unsigned as_ls:1; /* local shader */ + unsigned export_prim_id; /* when PS needs it and GS is disabled */ } vs; struct { unsigned prim_mode:3; @@ -231,6 +232,7 @@ union si_shader_key { * This describes how outputs are laid out in memory. */ uint64_t es_enabled_outputs; unsigned as_es:1; /* export shader */ + unsigned export_prim_id; /* when PS needs it and GS is disabled */ } tes; /* tessellation evaluation shader */ }; @@ -289,6 +291,16 @@ static inline struct si_shader* si_get_vs_state(struct si_context *sctx) return sctx->vs_shader->current; } +static inline bool si_vs_exports_prim_id(struct si_shader *shader) +{ + if (shader->selector->type == PIPE_SHADER_VERTEX) + return shader->key.vs.export_prim_id; + else if (shader->selector->type == PIPE_SHADER_TESS_EVAL) + return shader->key.tes.export_prim_id; + else + return false; +} + /* radeonsi_shader.c */ int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm, struct si_shader *shader); diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 1cac8041d61..701671b8d99 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -3136,7 +3136,6 @@ static void si_init_config(struct si_context *sctx) si_pm4_set_reg(pm4, R_028A58_VGT_ES_PER_GS, 0x40); si_pm4_set_reg(pm4, R_028A5C_VGT_GS_PER_VS, 0x2); - si_pm4_set_reg(pm4, R_028A84_VGT_PRIMITIVEID_EN, 0x0); si_pm4_set_reg(pm4, R_028A8C_VGT_PRIMITIVEID_RESET, 0x0); si_pm4_set_reg(pm4, R_028AB8_VGT_VTX_CNT_EN, 0); si_pm4_set_reg(pm4, R_028B28_VGT_STRMOUT_DRAW_OPAQUE_OFFSET, 0); diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c index a6480b330cd..044acd8fcea 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.c +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c @@ -308,6 +308,7 @@ static void si_shader_vs(struct si_shader *shader) uint64_t va; unsigned window_space = shader->selector->info.properties[TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION]; + bool enable_prim_id = si_vs_exports_prim_id(shader); pm4 = shader->pm4 = CALLOC_STRUCT(si_pm4_state); @@ -317,8 +318,12 @@ static void si_shader_vs(struct si_shader *shader) /* If this is the GS copy shader, the GS state writes this register. * Otherwise, the VS state writes it. */ - if (!shader->is_gs_copy_shader) - si_pm4_set_reg(pm4, R_028A40_VGT_GS_MODE, 0); + if (!shader->is_gs_copy_shader) { + si_pm4_set_reg(pm4, R_028A40_VGT_GS_MODE, + S_028A40_MODE(enable_prim_id ? V_028A40_GS_SCENARIO_A : 0)); + si_pm4_set_reg(pm4, R_028A84_VGT_PRIMITIVEID_EN, enable_prim_id); + } else + si_pm4_set_reg(pm4, R_028A84_VGT_PRIMITIVEID_EN, 0); va = shader->bo->gpu_address; si_pm4_add_bo(pm4, shader->bo, RADEON_USAGE_READ, RADEON_PRIO_SHADER_DATA); @@ -327,7 +332,7 @@ static void si_shader_vs(struct si_shader *shader) vgpr_comp_cnt = 0; /* only VertexID is needed for GS-COPY. */ num_user_sgprs = SI_GSCOPY_NUM_USER_SGPR; } else if (shader->selector->type == PIPE_SHADER_VERTEX) { - vgpr_comp_cnt = shader->uses_instanceid ? 3 : 0; + vgpr_comp_cnt = shader->uses_instanceid ? 3 : (enable_prim_id ? 2 : 0); num_user_sgprs = SI_VS_NUM_USER_SGPR; } else if (shader->selector->type == PIPE_SHADER_TESS_EVAL) { vgpr_comp_cnt = 3; /* all components are needed for TES */ @@ -534,6 +539,10 @@ static inline void si_shader_selector_key(struct pipe_context *ctx, key->vs.as_es = 1; key->vs.es_enabled_outputs = sctx->gs_shader->inputs_read; } + + if (!sctx->gs_shader && sctx->ps_shader && + sctx->ps_shader->info.uses_primid) + key->vs.export_prim_id = 1; break; case PIPE_SHADER_TESS_CTRL: key->tcs.prim_mode = @@ -543,7 +552,8 @@ static inline void si_shader_selector_key(struct pipe_context *ctx, if (sctx->gs_shader) { key->tes.as_es = 1; key->tes.es_enabled_outputs = sctx->gs_shader->inputs_read; - } + } else if (sctx->ps_shader && sctx->ps_shader->info.uses_primid) + key->tes.export_prim_id = 1; break; case PIPE_SHADER_GEOMETRY: break; @@ -977,7 +987,10 @@ bcolor: } } - if (j == vsinfo->num_outputs && !G_028644_PT_SPRITE_TEX(tmp)) { + if (name == TGSI_SEMANTIC_PRIMID) + /* PrimID is written after the last output. */ + tmp |= S_028644_OFFSET(vs->vs_output_param_offset[vsinfo->num_outputs]); + else if (j == vsinfo->num_outputs && !G_028644_PT_SPRITE_TEX(tmp)) { /* No corresponding output found, load defaults into input. * Don't set any other bits. * (FLAT_SHADE=1 completely changes behavior) */ -- 2.30.2