shader->info.nr_param_exports = param_count;
}
+/**
+ * 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.
+ */
+static void si_vertex_color_clamping(struct si_shader_context *ctx,
+ struct si_shader_output_values *outputs,
+ unsigned noutput)
+{
+ LLVMValueRef addr[SI_MAX_VS_OUTPUTS][4];
+ bool has_colors = false;
+
+ /* Store original colors to alloca variables. */
+ for (unsigned i = 0; i < noutput; i++) {
+ if (outputs[i].semantic_name != TGSI_SEMANTIC_COLOR &&
+ outputs[i].semantic_name != TGSI_SEMANTIC_BCOLOR)
+ continue;
+
+ for (unsigned j = 0; j < 4; j++) {
+ addr[i][j] = ac_build_alloca_undef(&ctx->ac, ctx->f32, "");
+ LLVMBuildStore(ctx->ac.builder, outputs[i].values[j], addr[i][j]);
+ }
+ has_colors = true;
+ }
+
+ if (!has_colors)
+ return;
+
+ /* The state is in the first bit of the user SGPR. */
+ LLVMValueRef cond = LLVMGetParam(ctx->main_fn, ctx->param_vs_state_bits);
+ cond = LLVMBuildTrunc(ctx->ac.builder, cond, ctx->i1, "");
+
+ struct lp_build_if_state if_ctx;
+ lp_build_if(&if_ctx, &ctx->gallivm, cond);
+
+ /* Store clamped colors to alloca variables within the conditional block. */
+ for (unsigned i = 0; i < noutput; i++) {
+ if (outputs[i].semantic_name != TGSI_SEMANTIC_COLOR &&
+ outputs[i].semantic_name != TGSI_SEMANTIC_BCOLOR)
+ continue;
+
+ for (unsigned j = 0; j < 4; j++) {
+ LLVMBuildStore(ctx->ac.builder,
+ ac_build_clamp(&ctx->ac, outputs[i].values[j]),
+ addr[i][j]);
+ }
+ }
+ lp_build_endif(&if_ctx);
+
+ /* Load clamped colors */
+ for (unsigned i = 0; i < noutput; i++) {
+ if (outputs[i].semantic_name != TGSI_SEMANTIC_COLOR &&
+ outputs[i].semantic_name != TGSI_SEMANTIC_BCOLOR)
+ continue;
+
+ for (unsigned j = 0; j < 4; j++) {
+ outputs[i].values[j] =
+ LLVMBuildLoad(ctx->ac.builder, addr[i][j], "");
+ }
+ }
+}
+
/* Generate export instructions for hardware VS shader stage */
static void si_llvm_export_vs(struct si_shader_context *ctx,
struct si_shader_output_values *outputs,
unsigned pos_idx;
int i;
+ si_vertex_color_clamping(ctx, outputs, noutput);
+
/* Build position exports. */
for (i = 0; i < noutput; i++) {
switch (outputs[i].semantic_name) {
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.
- */
- 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;
-
- /* 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 (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];
stream);
}
- 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);
-
+ if (stream == 0)
si_llvm_export_vs(&ctx, outputs, gsinfo->num_outputs);
- }
LLVMBuildBr(builder, end_bb);
}