if (si_shader_ctx->type == TGSI_PROCESSOR_FRAGMENT) {
int cbuf = target - V_008DFC_SQ_EXP_MRT;
- if (cbuf >= 0 && cbuf < 8) {
+ if (cbuf >= 0 && cbuf < 8)
compressed = (si_shader_ctx->shader->key.ps.export_16bpc >> cbuf) & 0x1;
-
- if (compressed)
- si_shader_ctx->shader->spi_shader_col_format |=
- V_028714_SPI_SHADER_FP16_ABGR << (4 * cbuf);
- else
- si_shader_ctx->shader->spi_shader_col_format |=
- V_028714_SPI_SHADER_32_ABGR << (4 * cbuf);
-
- si_shader_ctx->shader->cb_shader_mask |= 0xf << (4 * cbuf);
- }
}
/* Set COMPR flag */
LLVMInt32TypeInContext(base->gallivm->context),
pack_args, 2,
LLVMReadNoneAttribute | LLVMNoUnwindAttribute);
- args[chan + 7] = args[chan + 5] =
+ args[chan + 5] =
LLVMBuildBitCast(base->gallivm->builder,
packed,
LLVMFloatTypeInContext(base->gallivm->context),
"");
+ args[chan + 7] = base->undef;
}
} else
memcpy(&args[5], values, sizeof(values[0]) * 4);
}
-/* Load from output pointers and initialize arguments for the shader export intrinsic */
-static void si_llvm_init_export_args_load(struct lp_build_tgsi_context *bld_base,
- LLVMValueRef *out_ptr,
- unsigned target,
- LLVMValueRef *args)
-{
- struct gallivm_state *gallivm = bld_base->base.gallivm;
- LLVMValueRef values[4];
- int i;
-
- for (i = 0; i < 4; i++)
- values[i] = LLVMBuildLoad(gallivm->builder, out_ptr[i], "");
-
- si_llvm_init_export_args(bld_base, values, target, args);
-}
-
static void si_alpha_test(struct lp_build_tgsi_context *bld_base,
- LLVMValueRef alpha_ptr)
+ LLVMValueRef alpha)
{
struct si_shader_context *si_shader_ctx = si_shader_context(bld_base);
struct gallivm_state *gallivm = bld_base->base.gallivm;
LLVMValueRef alpha_pass =
lp_build_cmp(&bld_base->base,
si_shader_ctx->shader->key.ps.alpha_func,
- LLVMBuildLoad(gallivm->builder, alpha_ptr, ""),
- alpha_ref);
+ alpha, alpha_ref);
LLVMValueRef arg =
lp_build_select(&bld_base->base,
alpha_pass,
}
}
-static void si_scale_alpha_by_sample_mask(struct lp_build_tgsi_context *bld_base,
- LLVMValueRef alpha_ptr)
+static LLVMValueRef si_scale_alpha_by_sample_mask(struct lp_build_tgsi_context *bld_base,
+ LLVMValueRef alpha)
{
struct si_shader_context *si_shader_ctx = si_shader_context(bld_base);
struct gallivm_state *gallivm = bld_base->base.gallivm;
- LLVMValueRef coverage, alpha;
+ LLVMValueRef coverage;
/* alpha = alpha * popcount(coverage) / SI_NUM_SMOOTH_AA_SAMPLES */
coverage = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn,
lp_build_const_float(gallivm,
1.0 / SI_NUM_SMOOTH_AA_SAMPLES), "");
- alpha = LLVMBuildLoad(gallivm->builder, alpha_ptr, "");
- alpha = LLVMBuildFMul(gallivm->builder, alpha, coverage, "");
- LLVMBuildStore(gallivm->builder, alpha, alpha_ptr);
+ return LLVMBuildFMul(gallivm->builder, alpha, coverage, "");
}
static void si_llvm_emit_clipvertex(struct lp_build_tgsi_context * bld_base,
FREE(outputs);
}
+static void si_export_mrt_z(struct lp_build_tgsi_context *bld_base,
+ LLVMValueRef depth, LLVMValueRef stencil,
+ LLVMValueRef samplemask)
+{
+ struct si_screen *sscreen = si_shader_context(bld_base)->screen;
+ struct lp_build_context *base = &bld_base->base;
+ struct lp_build_context *uint = &bld_base->uint_bld;
+ LLVMValueRef args[9];
+ unsigned mask = 0;
+
+ assert(depth || stencil || samplemask);
+
+ args[1] = uint->one; /* whether the EXEC mask is valid */
+ args[2] = uint->one; /* DONE bit */
+
+ /* Specify the target we are exporting */
+ args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_MRTZ);
+
+ args[4] = uint->zero; /* COMP flag */
+ args[5] = base->undef; /* R, depth */
+ args[6] = base->undef; /* G, stencil test value[0:7], stencil op value[8:15] */
+ args[7] = base->undef; /* B, sample mask */
+ args[8] = base->undef; /* A, alpha to mask */
+
+ if (depth) {
+ args[5] = depth;
+ mask |= 0x1;
+ }
+
+ if (stencil) {
+ args[6] = stencil;
+ mask |= 0x2;
+ }
+
+ if (samplemask) {
+ args[7] = samplemask;
+ mask |= 0x4;
+ }
+
+ /* SI (except OLAND) has a bug that it only looks
+ * at the X writemask component. */
+ if (sscreen->b.chip_class == SI &&
+ sscreen->b.family != CHIP_OLAND)
+ mask |= 0x1;
+
+ /* Specify which components to enable */
+ args[0] = lp_build_const_int32(base->gallivm, mask);
+
+ lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
+ LLVMVoidTypeInContext(base->gallivm->context),
+ args, 9, 0);
+}
+
+static void si_export_mrt_color(struct lp_build_tgsi_context *bld_base,
+ LLVMValueRef *color, unsigned index,
+ bool is_last)
+{
+ struct si_shader_context *si_shader_ctx = si_shader_context(bld_base);
+ struct lp_build_context *base = &bld_base->base;
+ LLVMValueRef args[9];
+ int i;
+
+ /* Clamp color */
+ if (si_shader_ctx->shader->key.ps.clamp_color)
+ for (i = 0; i < 4; i++)
+ color[i] = radeon_llvm_saturate(bld_base, color[i]);
+
+ /* Alpha to one */
+ if (si_shader_ctx->shader->key.ps.alpha_to_one)
+ color[3] = base->one;
+
+ /* Alpha test */
+ if (index == 0 &&
+ si_shader_ctx->shader->key.ps.alpha_func != PIPE_FUNC_ALWAYS)
+ si_alpha_test(bld_base, color[3]);
+
+ /* Line & polygon smoothing */
+ if (si_shader_ctx->shader->key.ps.poly_line_smoothing)
+ color[3] = si_scale_alpha_by_sample_mask(bld_base, color[3]);
+
+ /* If last_cbuf > 0, FS_COLOR0_WRITES_ALL_CBUFS is true. */
+ if (index == 0 &&
+ si_shader_ctx->shader->key.ps.last_cbuf > 0) {
+ for (int c = 1; c <= si_shader_ctx->shader->key.ps.last_cbuf; c++) {
+ si_llvm_init_export_args(bld_base, color,
+ V_008DFC_SQ_EXP_MRT + c, args);
+ lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
+ LLVMVoidTypeInContext(base->gallivm->context),
+ args, 9, 0);
+ }
+ }
+
+ /* Export */
+ si_llvm_init_export_args(bld_base, color, V_008DFC_SQ_EXP_MRT + index,
+ args);
+ if (is_last) {
+ args[1] = bld_base->uint_bld.one; /* whether the EXEC mask is valid */
+ args[2] = bld_base->uint_bld.one; /* DONE bit */
+ }
+ lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
+ LLVMVoidTypeInContext(base->gallivm->context),
+ args, 9, 0);
+}
+
static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base)
{
struct si_shader_context * si_shader_ctx = si_shader_context(bld_base);
struct tgsi_shader_info *info = &shader->selector->info;
LLVMBuilderRef builder = base->gallivm->builder;
LLVMValueRef args[9];
- LLVMValueRef last_args[9] = { 0 };
- int depth_index = -1, stencil_index = -1, samplemask_index = -1;
+ LLVMValueRef depth = NULL, stencil = NULL, samplemask = NULL;
+ int last_color_export = -1;
int i;
+ /* If there are no outputs, add a dummy export. */
+ if (!info->num_outputs) {
+ args[0] = lp_build_const_int32(base->gallivm, 0x0); /* enabled channels */
+ args[1] = uint->one; /* whether the EXEC mask is valid */
+ args[2] = uint->one; /* DONE bit */
+ args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_NULL);
+ args[4] = uint->zero; /* COMPR flag (0 = 32-bit export) */
+ args[5] = uint->undef; /* R */
+ args[6] = uint->undef; /* G */
+ args[7] = uint->undef; /* B */
+ args[8] = uint->undef; /* A */
+
+ lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
+ LLVMVoidTypeInContext(base->gallivm->context),
+ args, 9, 0);
+ return;
+ }
+
+ /* Determine the last export. If MRTZ is present, it's always last.
+ * Otherwise, find the last color export.
+ */
+ if (!info->writes_z && !info->writes_stencil && !info->writes_samplemask)
+ for (i = 0; i < info->num_outputs; i++)
+ if (info->output_semantic_name[i] == TGSI_SEMANTIC_COLOR)
+ last_color_export = i;
+
for (i = 0; i < info->num_outputs; i++) {
unsigned semantic_name = info->output_semantic_name[i];
unsigned semantic_index = info->output_semantic_index[i];
- unsigned target;
- LLVMValueRef alpha_ptr;
+ unsigned j;
+ LLVMValueRef color[4] = {};
/* Select the correct target */
switch (semantic_name) {
case TGSI_SEMANTIC_POSITION:
- depth_index = i;
- continue;
+ depth = LLVMBuildLoad(builder,
+ si_shader_ctx->radeon_bld.soa.outputs[i][2], "");
+ break;
case TGSI_SEMANTIC_STENCIL:
- stencil_index = i;
- continue;
+ stencil = LLVMBuildLoad(builder,
+ si_shader_ctx->radeon_bld.soa.outputs[i][1], "");
+ break;
case TGSI_SEMANTIC_SAMPLEMASK:
- samplemask_index = i;
- continue;
+ samplemask = LLVMBuildLoad(builder,
+ si_shader_ctx->radeon_bld.soa.outputs[i][0], "");
+ break;
case TGSI_SEMANTIC_COLOR:
- target = V_008DFC_SQ_EXP_MRT + semantic_index;
- alpha_ptr = si_shader_ctx->radeon_bld.soa.outputs[i][3];
-
- if (si_shader_ctx->shader->key.ps.clamp_color) {
- for (int j = 0; j < 4; j++) {
- LLVMValueRef ptr = si_shader_ctx->radeon_bld.soa.outputs[i][j];
- LLVMValueRef result = LLVMBuildLoad(builder, ptr, "");
-
- result = radeon_llvm_saturate(bld_base, result);
- LLVMBuildStore(builder, result, ptr);
- }
- }
-
- if (si_shader_ctx->shader->key.ps.alpha_to_one)
- LLVMBuildStore(base->gallivm->builder,
- base->one, alpha_ptr);
-
- if (semantic_index == 0 &&
- si_shader_ctx->shader->key.ps.alpha_func != PIPE_FUNC_ALWAYS)
- si_alpha_test(bld_base, alpha_ptr);
-
- if (si_shader_ctx->shader->key.ps.poly_line_smoothing)
- si_scale_alpha_by_sample_mask(bld_base, alpha_ptr);
+ for (j = 0; j < 4; j++)
+ color[j] = LLVMBuildLoad(builder,
+ si_shader_ctx->radeon_bld.soa.outputs[i][j], "");
+ si_export_mrt_color(bld_base, color, semantic_index,
+ last_color_export == i);
break;
default:
- target = 0;
fprintf(stderr,
"Warning: SI unhandled fs output type:%d\n",
semantic_name);
}
-
- si_llvm_init_export_args_load(bld_base,
- si_shader_ctx->radeon_bld.soa.outputs[i],
- target, args);
-
- if (semantic_name == TGSI_SEMANTIC_COLOR) {
- /* If there is an export instruction waiting to be emitted, do so now. */
- if (last_args[0]) {
- lp_build_intrinsic(base->gallivm->builder,
- "llvm.SI.export",
- LLVMVoidTypeInContext(base->gallivm->context),
- last_args, 9, 0);
- }
-
- /* This instruction will be emitted at the end of the shader. */
- memcpy(last_args, args, sizeof(args));
-
- /* Handle FS_COLOR0_WRITES_ALL_CBUFS. */
- if (shader->selector->info.properties[TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS] &&
- semantic_index == 0 &&
- si_shader_ctx->shader->key.ps.last_cbuf > 0) {
- for (int c = 1; c <= si_shader_ctx->shader->key.ps.last_cbuf; c++) {
- si_llvm_init_export_args_load(bld_base,
- si_shader_ctx->radeon_bld.soa.outputs[i],
- V_008DFC_SQ_EXP_MRT + c, args);
- lp_build_intrinsic(base->gallivm->builder,
- "llvm.SI.export",
- LLVMVoidTypeInContext(base->gallivm->context),
- args, 9, 0);
- }
- }
- } else {
- lp_build_intrinsic(base->gallivm->builder,
- "llvm.SI.export",
- LLVMVoidTypeInContext(base->gallivm->context),
- args, 9, 0);
- }
- }
-
- if (depth_index >= 0 || stencil_index >= 0 || samplemask_index >= 0) {
- LLVMValueRef out_ptr;
- unsigned mask = 0;
-
- /* Specify the target we are exporting */
- args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_MRTZ);
-
- args[5] = base->zero; /* R, depth */
- args[6] = base->zero; /* G, stencil test value[0:7], stencil op value[8:15] */
- args[7] = base->zero; /* B, sample mask */
- args[8] = base->zero; /* A, alpha to mask */
-
- if (depth_index >= 0) {
- out_ptr = si_shader_ctx->radeon_bld.soa.outputs[depth_index][2];
- args[5] = LLVMBuildLoad(base->gallivm->builder, out_ptr, "");
- mask |= 0x1;
- }
-
- if (stencil_index >= 0) {
- out_ptr = si_shader_ctx->radeon_bld.soa.outputs[stencil_index][1];
- args[6] = LLVMBuildLoad(base->gallivm->builder, out_ptr, "");
- mask |= 0x2;
- }
-
- if (samplemask_index >= 0) {
- out_ptr = si_shader_ctx->radeon_bld.soa.outputs[samplemask_index][0];
- args[7] = LLVMBuildLoad(base->gallivm->builder, out_ptr, "");
- mask |= 0x4;
- }
-
- /* SI (except OLAND) has a bug that it only looks
- * at the X writemask component. */
- if (si_shader_ctx->screen->b.chip_class == SI &&
- si_shader_ctx->screen->b.family != CHIP_OLAND)
- mask |= 0x1;
-
- if (samplemask_index >= 0)
- si_shader_ctx->shader->spi_shader_z_format = V_028710_SPI_SHADER_32_ABGR;
- else if (stencil_index >= 0)
- si_shader_ctx->shader->spi_shader_z_format = V_028710_SPI_SHADER_32_GR;
- else
- si_shader_ctx->shader->spi_shader_z_format = V_028710_SPI_SHADER_32_R;
-
- /* Specify which components to enable */
- args[0] = lp_build_const_int32(base->gallivm, mask);
-
- args[1] =
- args[2] =
- args[4] = uint->zero;
-
- if (last_args[0])
- lp_build_intrinsic(base->gallivm->builder,
- "llvm.SI.export",
- LLVMVoidTypeInContext(base->gallivm->context),
- args, 9, 0);
- else
- memcpy(last_args, args, sizeof(args));
- }
-
- if (!last_args[0]) {
- /* Specify which components to enable */
- last_args[0] = lp_build_const_int32(base->gallivm, 0x0);
-
- /* Specify the target we are exporting */
- last_args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_MRT);
-
- /* Set COMPR flag to zero to export data as 32-bit */
- last_args[4] = uint->zero;
-
- /* dummy bits */
- last_args[5]= uint->zero;
- last_args[6]= uint->zero;
- last_args[7]= uint->zero;
- last_args[8]= uint->zero;
}
- /* Specify whether the EXEC mask represents the valid mask */
- last_args[1] = uint->one;
-
- /* Specify that this is the last export */
- last_args[2] = lp_build_const_int32(base->gallivm, 1);
-
- lp_build_intrinsic(base->gallivm->builder,
- "llvm.SI.export",
- LLVMVoidTypeInContext(base->gallivm->context),
- last_args, 9, 0);
+ if (depth || stencil || samplemask)
+ si_export_mrt_z(bld_base, depth, stencil, samplemask);
}
static void build_tex_intrinsic(const struct lp_build_tgsi_action * action,