[Mesa-dev] [PATCH 2/3] radeonsi: enable vertex color clamping for tess and GS
Marek Olšák
maraeo at gmail.com
Wed Jun 27 20:10:24 UTC 2018
From: Marek Olšák <marek.olsak at amd.com>
---
src/gallium/drivers/radeonsi/si_descriptors.c | 10 +-
src/gallium/drivers/radeonsi/si_shader.c | 97 +++++++++++++------
src/gallium/drivers/radeonsi/si_shader.h | 2 +-
src/gallium/drivers/radeonsi/si_state_draw.c | 11 +++
4 files changed, 87 insertions(+), 33 deletions(-)
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index e8c028061d1..323cdbbf7af 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -1995,26 +1995,28 @@ static void si_shader_pointers_begin_new_cs(struct si_context *sctx)
* This assigns a mapping from PIPE_SHADER_* to SPI_SHADER_USER_DATA_*.
*/
static void si_set_user_data_base(struct si_context *sctx,
unsigned shader, uint32_t new_base)
{
uint32_t *base = &sctx->shader_pointers.sh_base[shader];
if (*base != new_base) {
*base = new_base;
- if (new_base) {
+ if (new_base)
si_mark_shader_pointers_dirty(sctx, shader);
- if (shader == PIPE_SHADER_VERTEX)
- sctx->last_vs_state = ~0;
- }
+ /* Any change in enabled shader stages requires re-emitting
+ * the VS state SGPR, because it contains the clamp_vertex_color
+ * state, which can be done VS, TES, and GS.
+ */
+ sctx->last_vs_state = ~0;
}
}
/* This must be called when these shaders are changed from non-NULL to NULL
* and vice versa:
* - geometry shader
* - tessellation control shader
* - tessellation evaluation shader
*/
void si_shader_change_notify(struct si_context *sctx)
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index 9bee8440027..32db089ed2c 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -3669,52 +3669,50 @@ static void si_llvm_emit_vs_epilogue(struct ac_shader_abi *abi,
assert(info->num_outputs <= max_outputs);
outputs = MALLOC((info->num_outputs + 1) * sizeof(outputs[0]));
/* Vertex color clamping.
*
* This uses a state constant loaded in a user data SGPR and
* an IF statement is added that clamps all colors if the constant
* is true.
*/
- if (ctx->type == PIPE_SHADER_VERTEX) {
- struct lp_build_if_state if_ctx;
- LLVMValueRef cond = NULL;
- LLVMValueRef addr, val;
-
- for (i = 0; i < info->num_outputs; i++) {
- if (info->output_semantic_name[i] != TGSI_SEMANTIC_COLOR &&
- info->output_semantic_name[i] != TGSI_SEMANTIC_BCOLOR)
- continue;
+ struct lp_build_if_state if_ctx;
+ LLVMValueRef cond = NULL;
+ LLVMValueRef addr, val;
- /* We've found a color. */
- if (!cond) {
- /* The state is in the first bit of the user SGPR. */
- cond = LLVMGetParam(ctx->main_fn,
- ctx->param_vs_state_bits);
- cond = LLVMBuildTrunc(ctx->ac.builder, cond,
- ctx->i1, "");
- lp_build_if(&if_ctx, &ctx->gallivm, cond);
- }
+ for (i = 0; i < info->num_outputs; i++) {
+ if (info->output_semantic_name[i] != TGSI_SEMANTIC_COLOR &&
+ info->output_semantic_name[i] != TGSI_SEMANTIC_BCOLOR)
+ continue;
- for (j = 0; j < 4; j++) {
- addr = addrs[4 * i + j];
- val = LLVMBuildLoad(ctx->ac.builder, addr, "");
- val = ac_build_clamp(&ctx->ac, val);
- LLVMBuildStore(ctx->ac.builder, val, addr);
- }
+ /* We've found a color. */
+ if (!cond) {
+ /* The state is in the first bit of the user SGPR. */
+ cond = LLVMGetParam(ctx->main_fn,
+ ctx->param_vs_state_bits);
+ cond = LLVMBuildTrunc(ctx->ac.builder, cond,
+ ctx->i1, "");
+ lp_build_if(&if_ctx, &ctx->gallivm, cond);
}
- if (cond)
- lp_build_endif(&if_ctx);
+ for (j = 0; j < 4; j++) {
+ addr = addrs[4 * i + j];
+ val = LLVMBuildLoad(ctx->ac.builder, addr, "");
+ val = ac_build_clamp(&ctx->ac, val);
+ LLVMBuildStore(ctx->ac.builder, val, addr);
+ }
}
+ if (cond)
+ lp_build_endif(&if_ctx);
+
for (i = 0; i < info->num_outputs; i++) {
outputs[i].semantic_name = info->output_semantic_name[i];
outputs[i].semantic_index = info->output_semantic_index[i];
for (j = 0; j < 4; j++) {
outputs[i].values[j] =
LLVMBuildLoad(ctx->ac.builder,
addrs[4 * i + j],
"");
outputs[i].vertex_stream[j] =
@@ -4738,21 +4736,21 @@ static void create_function(struct si_shader_context *ctx)
declare_vs_specific_input_sgprs(ctx, &fninfo);
ctx->param_vertex_buffers = add_arg(&fninfo, ARG_SGPR,
ac_array_in_const32_addr_space(ctx->v4i32));
if (shader->key.as_es) {
ctx->param_es2gs_offset = add_arg(&fninfo, ARG_SGPR, ctx->i32);
} else if (shader->key.as_ls) {
/* no extra parameters */
} else {
if (shader->is_gs_copy_shader) {
- fninfo.num_params = ctx->param_rw_buffers + 1;
+ fninfo.num_params = ctx->param_vs_state_bits + 1;
fninfo.num_sgpr_params = fninfo.num_params;
}
/* The locations of the other parameters are assigned dynamically. */
declare_streamout_params(ctx, &shader->selector->so,
&fninfo);
}
/* VGPRs */
declare_vs_input_vgprs(ctx, &fninfo, &num_prolog_vgprs);
@@ -5819,22 +5817,65 @@ si_generate_gs_copy_shader(struct si_screen *sscreen,
}
}
/* Streamout and exports. */
if (gs_selector->so.num_outputs) {
si_llvm_emit_streamout(&ctx, outputs,
gsinfo->num_outputs,
stream);
}
- if (stream == 0)
+ if (stream == 0) {
+ /* Vertex color clamping.
+ *
+ * This uses a state constant loaded in a user data SGPR and
+ * an IF statement is added that clamps all colors if the constant
+ * is true.
+ */
+ struct lp_build_if_state if_ctx;
+ LLVMValueRef v[2], cond = NULL;
+ LLVMBasicBlockRef blocks[2];
+
+ for (unsigned i = 0; i < gsinfo->num_outputs; i++) {
+ if (gsinfo->output_semantic_name[i] != TGSI_SEMANTIC_COLOR &&
+ gsinfo->output_semantic_name[i] != TGSI_SEMANTIC_BCOLOR)
+ continue;
+
+ /* We've found a color. */
+ if (!cond) {
+ /* The state is in the first bit of the user SGPR. */
+ cond = LLVMGetParam(ctx.main_fn,
+ ctx.param_vs_state_bits);
+ cond = LLVMBuildTrunc(ctx.ac.builder, cond,
+ ctx.i1, "");
+ lp_build_if(&if_ctx, &ctx.gallivm, cond);
+ /* Remember blocks for Phi. */
+ blocks[0] = if_ctx.true_block;
+ blocks[1] = if_ctx.entry_block;
+ }
+
+ for (unsigned j = 0; j < 4; j++) {
+ /* Insert clamp into the true block. */
+ v[0] = ac_build_clamp(&ctx.ac, outputs[i].values[j]);
+ v[1] = outputs[i].values[j];
+
+ /* Insert Phi into the endif block. */
+ LLVMPositionBuilderAtEnd(ctx.ac.builder, if_ctx.merge_block);
+ outputs[i].values[j] = ac_build_phi(&ctx.ac, ctx.f32, 2, v, blocks);
+ LLVMPositionBuilderAtEnd(ctx.ac.builder, if_ctx.true_block);
+ }
+ }
+ if (cond)
+ lp_build_endif(&if_ctx);
+
si_llvm_export_vs(&ctx, outputs, gsinfo->num_outputs);
+ }
LLVMBuildBr(builder, end_bb);
}
LLVMPositionBuilderAtEnd(builder, end_bb);
LLVMBuildRetVoid(ctx.ac.builder);
ctx.type = PIPE_SHADER_GEOMETRY; /* override for shader dumping */
si_llvm_optimize_module(&ctx);
diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h
index bba4d4f9018..0dc27f29afd 100644
--- a/src/gallium/drivers/radeonsi/si_shader.h
+++ b/src/gallium/drivers/radeonsi/si_shader.h
@@ -221,21 +221,21 @@ enum {
/* GS limits */
GFX6_GS_NUM_USER_SGPR = SI_NUM_RESOURCE_SGPRS,
#if HAVE_32BIT_POINTERS
GFX9_VSGS_NUM_USER_SGPR = SI_VS_NUM_USER_SGPR,
GFX9_TESGS_NUM_USER_SGPR = SI_TES_NUM_USER_SGPR,
#else
GFX9_VSGS_NUM_USER_SGPR = GFX9_MERGED_NUM_USER_SGPR,
GFX9_TESGS_NUM_USER_SGPR = GFX9_MERGED_NUM_USER_SGPR,
#endif
- SI_GSCOPY_NUM_USER_SGPR = SI_SGPR_RW_BUFFERS + (HAVE_32BIT_POINTERS ? 1 : 2),
+ SI_GSCOPY_NUM_USER_SGPR = SI_NUM_VS_STATE_RESOURCE_SGPRS,
/* PS only */
SI_SGPR_ALPHA_REF = SI_NUM_RESOURCE_SGPRS,
SI_PS_NUM_USER_SGPR,
};
/* LLVM function parameter indices */
enum {
SI_NUM_RESOURCE_PARAMS = 4,
diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c
index 2291b4a00ad..f35f73a37ce 100644
--- a/src/gallium/drivers/radeonsi/si_state_draw.c
+++ b/src/gallium/drivers/radeonsi/si_state_draw.c
@@ -564,25 +564,36 @@ static void si_emit_vs_state(struct si_context *sctx,
if (sctx->num_vs_blit_sgprs) {
/* Re-emit the state after we leave u_blitter. */
sctx->last_vs_state = ~0;
return;
}
if (sctx->current_vs_state != sctx->last_vs_state) {
struct radeon_cmdbuf *cs = sctx->gfx_cs;
+ /* For the API vertex shader (VS_STATE_INDEXED). */
radeon_set_sh_reg(cs,
sctx->shader_pointers.sh_base[PIPE_SHADER_VERTEX] +
SI_SGPR_VS_STATE_BITS * 4,
sctx->current_vs_state);
+ /* For vertex color clamping, which is done in the last stage
+ * before the rasterizer. */
+ if (sctx->gs_shader.cso || sctx->tes_shader.cso) {
+ /* GS copy shader or TES if GS is missing. */
+ radeon_set_sh_reg(cs,
+ R_00B130_SPI_SHADER_USER_DATA_VS_0 +
+ SI_SGPR_VS_STATE_BITS * 4,
+ sctx->current_vs_state);
+ }
+
sctx->last_vs_state = sctx->current_vs_state;
}
}
static inline bool si_prim_restart_index_changed(struct si_context *sctx,
const struct pipe_draw_info *info)
{
return info->primitive_restart &&
(info->restart_index != sctx->last_restart_index ||
sctx->last_restart_index == SI_RESTART_INDEX_UNKNOWN);
--
2.17.1
More information about the mesa-dev
mailing list