From: Marek Olšák <marek.ol...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev