struct gallivm_state *gallivm = base->gallivm;
struct si_shader_context *ctx =
si_shader_context(&radeon_bld->soa.bld_base);
- unsigned divisor = ctx->shader->key.vs.instance_divisors[input_index];
+ unsigned divisor =
+ ctx->shader->key.vs.prolog.instance_divisors[input_index];
unsigned chan;
static unsigned select_interp_param(struct si_shader_context *ctx,
unsigned param)
{
- if (!ctx->shader->key.ps.force_persample_interp)
+ if (!ctx->shader->key.ps.prolog.force_persample_interp)
return param;
/* If the shader doesn't use center/centroid, just return the parameter.
intr_name = interp_param ? "llvm.SI.fs.interp" : "llvm.SI.fs.constant";
if (semantic_name == TGSI_SEMANTIC_COLOR &&
- ctx->shader->key.ps.color_two_side) {
+ ctx->shader->key.ps.prolog.color_two_side) {
LLVMValueRef args[4];
LLVMValueRef is_face_positive;
LLVMValueRef back_attr_number;
if (ctx->type == TGSI_PROCESSOR_FRAGMENT) {
const union si_shader_key *key = &ctx->shader->key;
- unsigned col_formats = key->ps.spi_shader_col_format;
+ unsigned col_formats = key->ps.epilog.spi_shader_col_format;
int cbuf = target - V_008DFC_SQ_EXP_MRT;
assert(cbuf >= 0 && cbuf < 8);
spi_shader_col_format = (col_formats >> (cbuf * 4)) & 0xf;
- is_int8 = (key->ps.color_is_int8 >> cbuf) & 0x1;
+ is_int8 = (key->ps.epilog.color_is_int8 >> cbuf) & 0x1;
}
args[4] = uint->zero; /* COMPR flag */
struct si_shader_context *ctx = si_shader_context(bld_base);
struct gallivm_state *gallivm = bld_base->base.gallivm;
- if (ctx->shader->key.ps.alpha_func != PIPE_FUNC_NEVER) {
+ if (ctx->shader->key.ps.epilog.alpha_func != PIPE_FUNC_NEVER) {
LLVMValueRef alpha_ref = LLVMGetParam(ctx->radeon_bld.main_fn,
SI_PARAM_ALPHA_REF);
LLVMValueRef alpha_pass =
lp_build_cmp(&bld_base->base,
- ctx->shader->key.ps.alpha_func,
+ ctx->shader->key.ps.epilog.alpha_func,
alpha, alpha_ref);
LLVMValueRef arg =
lp_build_select(&bld_base->base,
invocation_id, bld_base->uint_bld.zero, ""));
/* Determine the layout of one tess factor element in the buffer. */
- switch (shader->key.tcs.prim_mode) {
+ switch (shader->key.tcs.epilog.prim_mode) {
case PIPE_PRIM_LINES:
stride = 2; /* 2 dwords, 1 vec2 store */
outer_comps = 2;
int i;
/* Clamp color */
- if (ctx->shader->key.ps.clamp_color)
+ if (ctx->shader->key.ps.epilog.clamp_color)
for (i = 0; i < 4; i++)
color[i] = radeon_llvm_saturate(bld_base, color[i]);
/* Alpha to one */
- if (ctx->shader->key.ps.alpha_to_one)
+ if (ctx->shader->key.ps.epilog.alpha_to_one)
color[3] = base->one;
/* Alpha test */
if (index == 0 &&
- ctx->shader->key.ps.alpha_func != PIPE_FUNC_ALWAYS)
+ ctx->shader->key.ps.epilog.alpha_func != PIPE_FUNC_ALWAYS)
si_alpha_test(bld_base, color[3]);
/* Line & polygon smoothing */
- if (ctx->shader->key.ps.poly_line_smoothing)
+ if (ctx->shader->key.ps.epilog.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 (ctx->shader->key.ps.last_cbuf > 0) {
+ if (ctx->shader->key.ps.epilog.last_cbuf > 0) {
LLVMValueRef args[8][9];
int c, last = -1;
/* Get the export arguments, also find out what the last one is. */
- for (c = 0; c <= ctx->shader->key.ps.last_cbuf; c++) {
+ for (c = 0; c <= ctx->shader->key.ps.epilog.last_cbuf; c++) {
si_llvm_init_export_args(bld_base, color,
V_008DFC_SQ_EXP_MRT + c, args[c]);
if (args[c][0] != bld_base->uint_bld.zero)
}
/* Emit all exports. */
- for (c = 0; c <= ctx->shader->key.ps.last_cbuf; c++) {
+ for (c = 0; c <= ctx->shader->key.ps.epilog.last_cbuf; c++) {
if (is_last && last == c) {
args[c][1] = bld_base->uint_bld.one; /* whether the EXEC mask is valid */
args[c][2] = bld_base->uint_bld.one; /* DONE bit */
* Otherwise, find the last color export.
*/
if (!info->writes_z && !info->writes_stencil && !info->writes_samplemask) {
- unsigned spi_format = shader->key.ps.spi_shader_col_format;
+ unsigned spi_format = shader->key.ps.epilog.spi_shader_col_format;
/* Don't export NULL and return if alpha-test is enabled. */
- if (shader->key.ps.alpha_func != PIPE_FUNC_ALWAYS &&
- shader->key.ps.alpha_func != PIPE_FUNC_NEVER &&
+ if (shader->key.ps.epilog.alpha_func != PIPE_FUNC_ALWAYS &&
+ shader->key.ps.epilog.alpha_func != PIPE_FUNC_NEVER &&
(spi_format & 0xf) == 0)
spi_format |= V_028714_SPI_SHADER_32_AR;
continue;
/* If last_cbuf > 0, FS_COLOR0_WRITES_ALL_CBUFS is true. */
- if (shader->key.ps.last_cbuf > 0) {
+ if (shader->key.ps.epilog.last_cbuf > 0) {
/* Just set this if any of the colorbuffers are enabled. */
if (spi_format &
- ((1llu << (4 * (shader->key.ps.last_cbuf + 1))) - 1))
+ ((1llu << (4 * (shader->key.ps.epilog.last_cbuf + 1))) - 1))
last_color_export = i;
continue;
}
switch (shader) {
case PIPE_SHADER_VERTEX:
fprintf(f, " instance_divisors = {");
- for (i = 0; i < Elements(key->vs.instance_divisors); i++)
+ for (i = 0; i < Elements(key->vs.prolog.instance_divisors); i++)
fprintf(f, !i ? "%u" : ", %u",
- key->vs.instance_divisors[i]);
+ key->vs.prolog.instance_divisors[i]);
fprintf(f, "}\n");
fprintf(f, " as_es = %u\n", key->vs.as_es);
fprintf(f, " as_ls = %u\n", key->vs.as_ls);
- fprintf(f, " export_prim_id = %u\n", key->vs.export_prim_id);
+ fprintf(f, " export_prim_id = %u\n", key->vs.epilog.export_prim_id);
break;
case PIPE_SHADER_TESS_CTRL:
- fprintf(f, " prim_mode = %u\n", key->tcs.prim_mode);
+ fprintf(f, " prim_mode = %u\n", key->tcs.epilog.prim_mode);
break;
case PIPE_SHADER_TESS_EVAL:
fprintf(f, " as_es = %u\n", key->tes.as_es);
- fprintf(f, " export_prim_id = %u\n", key->tes.export_prim_id);
+ fprintf(f, " export_prim_id = %u\n", key->tes.epilog.export_prim_id);
break;
case PIPE_SHADER_GEOMETRY:
break;
case PIPE_SHADER_FRAGMENT:
- fprintf(f, " spi_shader_col_format = 0x%x\n", key->ps.spi_shader_col_format);
- fprintf(f, " last_cbuf = %u\n", key->ps.last_cbuf);
- fprintf(f, " color_two_side = %u\n", key->ps.color_two_side);
- fprintf(f, " alpha_func = %u\n", key->ps.alpha_func);
- fprintf(f, " alpha_to_one = %u\n", key->ps.alpha_to_one);
- fprintf(f, " poly_stipple = %u\n", key->ps.poly_stipple);
- fprintf(f, " clamp_color = %u\n", key->ps.clamp_color);
+ fprintf(f, " prolog.color_two_side = %u\n", key->ps.prolog.color_two_side);
+ fprintf(f, " prolog.poly_stipple = %u\n", key->ps.prolog.poly_stipple);
+ fprintf(f, " prolog.force_persample_interp = %u\n", key->ps.prolog.force_persample_interp);
+ fprintf(f, " epilog.spi_shader_col_format = 0x%x\n", key->ps.epilog.spi_shader_col_format);
+ fprintf(f, " epilog.color_is_int8 = 0x%X\n", key->ps.epilog.color_is_int8);
+ fprintf(f, " epilog.last_cbuf = %u\n", key->ps.epilog.last_cbuf);
+ fprintf(f, " epilog.alpha_func = %u\n", key->ps.epilog.alpha_func);
+ fprintf(f, " epilog.alpha_to_one = %u\n", key->ps.epilog.alpha_to_one);
+ fprintf(f, " epilog.poly_line_smoothing = %u\n", key->ps.epilog.poly_line_smoothing);
+ fprintf(f, " epilog.clamp_color = %u\n", key->ps.epilog.clamp_color);
break;
default:
LLVMModuleRef mod;
int r = 0;
bool poly_stipple = sel->type == PIPE_SHADER_FRAGMENT &&
- shader->key.ps.poly_stipple;
+ shader->key.ps.prolog.poly_stipple;
if (poly_stipple) {
tokens = util_pstipple_create_fragment_shader(tokens, NULL,
* With both: LS | HS | ES | GS | VS | PS
*/
+/* Common VS bits between the shader key and the prolog key. */
+struct si_vs_prolog_bits {
+ unsigned instance_divisors[SI_NUM_VERTEX_BUFFERS];
+};
+
+/* Common VS bits between the shader key and the epilog key. */
+struct si_vs_epilog_bits {
+ unsigned export_prim_id:1; /* when PS needs it and GS is disabled */
+ /* TODO:
+ * - skip clipdist, culldist (including clipvertex code) exports based
+ * on which clip_plane_enable bits are set
+ * - skip layer, viewport, clipdist, and culldist parameter exports
+ * if PS doesn't read them
+ */
+};
+
+/* Common TCS bits between the shader key and the epilog key. */
+struct si_tcs_epilog_bits {
+ unsigned prim_mode:3;
+};
+
+/* Common PS bits between the shader key and the prolog key. */
+struct si_ps_prolog_bits {
+ unsigned color_two_side:1;
+ /* TODO: add a flatshade bit that skips interpolation for colors */
+ unsigned poly_stipple:1;
+ unsigned force_persample_interp:1;
+ /* TODO:
+ * - add force_center_interp if MSAA is disabled and centroid or
+ * sample are present
+ * - add force_center_interp_bc_optimize to force center interpolation
+ * based on the bc_optimize SGPR bit if MSAA is enabled, centroid is
+ * present and sample isn't present.
+ */
+};
+
+/* Common PS bits between the shader key and the epilog key. */
+struct si_ps_epilog_bits {
+ unsigned spi_shader_col_format;
+ unsigned color_is_int8:8;
+ unsigned last_cbuf:3;
+ unsigned alpha_func:3;
+ unsigned alpha_to_one:1;
+ unsigned poly_line_smoothing:1;
+ unsigned clamp_color:1;
+};
+
union si_shader_key {
struct {
- unsigned spi_shader_col_format;
- unsigned color_is_int8:8;
- unsigned last_cbuf:3;
- unsigned color_two_side:1;
- unsigned alpha_func:3;
- unsigned alpha_to_one:1;
- unsigned poly_stipple:1;
- unsigned poly_line_smoothing:1;
- unsigned clamp_color:1;
- unsigned force_persample_interp:1;
+ struct si_ps_prolog_bits prolog;
+ struct si_ps_epilog_bits epilog;
} ps;
struct {
- unsigned instance_divisors[SI_NUM_VERTEX_BUFFERS];
- /* Mask of "get_unique_index" bits - which outputs are read
- * by the next stage (needed by ES).
- * This describes how outputs are laid out in memory. */
+ struct si_vs_prolog_bits prolog;
+ struct si_vs_epilog_bits epilog;
unsigned as_es:1; /* export shader */
unsigned as_ls:1; /* local shader */
- unsigned export_prim_id:1; /* when PS needs it and GS is disabled */
} vs;
struct {
- unsigned prim_mode:3;
+ struct si_tcs_epilog_bits epilog;
} tcs; /* tessellation control shader */
struct {
- /* Mask of "get_unique_index" bits - which outputs are read
- * by the next stage (needed by ES).
- * This describes how outputs are laid out in memory. */
+ struct si_vs_epilog_bits epilog; /* same as VS */
unsigned as_es:1; /* export shader */
- unsigned export_prim_id:1; /* when PS needs it and GS is disabled */
} tes; /* tessellation evaluation shader */
};
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;
+ return shader->key.vs.epilog.export_prim_id;
else if (shader->selector->type == PIPE_SHADER_TESS_EVAL)
- return shader->key.tes.export_prim_id;
+ return shader->key.tes.epilog.export_prim_id;
else
return false;
}
if (sctx->b.family == CHIP_STONEY) {
unsigned spi_shader_col_format =
sctx->ps_shader.cso ?
- sctx->ps_shader.current->key.ps.spi_shader_col_format : 0;
+ sctx->ps_shader.current->key.ps.epilog.spi_shader_col_format : 0;
unsigned sx_ps_downconvert = 0;
unsigned sx_blend_opt_epsilon = 0;
unsigned sx_blend_opt_control = 0;
unsigned num_colors = !!(info->colors_read & 0x0f) +
!!(info->colors_read & 0xf0);
unsigned num_interp = ps->selector->info.num_inputs +
- (ps->key.ps.color_two_side ? num_colors : 0);
+ (ps->key.ps.prolog.color_two_side ? num_colors : 0);
assert(num_interp <= 32);
return MIN2(num_interp, 32);
static unsigned si_get_spi_shader_col_format(struct si_shader *shader)
{
- unsigned value = shader->key.ps.spi_shader_col_format;
+ unsigned value = shader->key.ps.epilog.spi_shader_col_format;
unsigned i, num_targets = (util_last_bit(value) + 3) / 4;
/* If the i-th target format is set, all previous target formats must
if (!spi_shader_col_format &&
!info->writes_z && !info->writes_stencil && !info->writes_samplemask &&
(shader->selector->info.uses_kill ||
- shader->key.ps.alpha_func != PIPE_FUNC_ALWAYS))
+ shader->key.ps.epilog.alpha_func != PIPE_FUNC_ALWAYS))
spi_shader_col_format = V_028714_SPI_SHADER_32_R;
si_pm4_set_reg(pm4, R_0286CC_SPI_PS_INPUT_ENA, input_ena);
switch (sel->type) {
case PIPE_SHADER_VERTEX:
- if (sctx->vertex_elements)
- for (i = 0; i < sctx->vertex_elements->count; ++i)
- key->vs.instance_divisors[i] =
+ if (sctx->vertex_elements) {
+ unsigned count = MIN2(sel->info.num_inputs,
+ sctx->vertex_elements->count);
+ for (i = 0; i < count; ++i)
+ key->vs.prolog.instance_divisors[i] =
sctx->vertex_elements->elements[i].instance_divisor;
-
+ }
if (sctx->tes_shader.cso)
key->vs.as_ls = 1;
else if (sctx->gs_shader.cso)
if (!sctx->gs_shader.cso && sctx->ps_shader.cso &&
sctx->ps_shader.cso->info.uses_primid)
- key->vs.export_prim_id = 1;
+ key->vs.epilog.export_prim_id = 1;
break;
case PIPE_SHADER_TESS_CTRL:
- key->tcs.prim_mode =
+ key->tcs.epilog.prim_mode =
sctx->tes_shader.cso->info.properties[TGSI_PROPERTY_TES_PRIM_MODE];
break;
case PIPE_SHADER_TESS_EVAL:
if (sctx->gs_shader.cso)
key->tes.as_es = 1;
else if (sctx->ps_shader.cso && sctx->ps_shader.cso->info.uses_primid)
- key->tes.export_prim_id = 1;
+ key->tes.epilog.export_prim_id = 1;
break;
case PIPE_SHADER_GEOMETRY:
break;
if (sel->info.properties[TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS] &&
sel->info.colors_written == 0x1)
- key->ps.last_cbuf = MAX2(sctx->framebuffer.state.nr_cbufs, 1) - 1;
+ key->ps.epilog.last_cbuf = MAX2(sctx->framebuffer.state.nr_cbufs, 1) - 1;
if (blend) {
/* Select the shader color format based on whether
* blending or alpha are needed.
*/
- key->ps.spi_shader_col_format =
+ key->ps.epilog.spi_shader_col_format =
(blend->blend_enable_4bit & blend->need_src_alpha_4bit &
sctx->framebuffer.spi_shader_col_format_blend_alpha) |
(blend->blend_enable_4bit & ~blend->need_src_alpha_4bit &
(~blend->blend_enable_4bit & ~blend->need_src_alpha_4bit &
sctx->framebuffer.spi_shader_col_format);
} else
- key->ps.spi_shader_col_format = sctx->framebuffer.spi_shader_col_format;
+ key->ps.epilog.spi_shader_col_format = sctx->framebuffer.spi_shader_col_format;
/* If alpha-to-coverage is enabled, we have to export alpha
* even if there is no color buffer.
*/
- if (!(key->ps.spi_shader_col_format & 0xf) &&
+ if (!(key->ps.epilog.spi_shader_col_format & 0xf) &&
blend && blend->alpha_to_coverage)
- key->ps.spi_shader_col_format |= V_028710_SPI_SHADER_32_AR;
+ key->ps.epilog.spi_shader_col_format |= V_028710_SPI_SHADER_32_AR;
/* On SI and CIK except Hawaii, the CB doesn't clamp outputs
* to the range supported by the type if a channel has less
* than 16 bits and the export format is 16_ABGR.
*/
if (sctx->b.chip_class <= CIK && sctx->b.family != CHIP_HAWAII)
- key->ps.color_is_int8 = sctx->framebuffer.color_is_int8;
+ key->ps.epilog.color_is_int8 = sctx->framebuffer.color_is_int8;
/* Disable unwritten outputs (if WRITE_ALL_CBUFS isn't enabled). */
- if (!key->ps.last_cbuf) {
- key->ps.spi_shader_col_format &= sel->colors_written_4bit;
- key->ps.color_is_int8 &= sel->info.colors_written;
+ if (!key->ps.epilog.last_cbuf) {
+ key->ps.epilog.spi_shader_col_format &= sel->colors_written_4bit;
+ key->ps.epilog.color_is_int8 &= sel->info.colors_written;
}
if (rs) {
sctx->current_rast_prim >= PIPE_PRIM_TRIANGLES_ADJACENCY;
bool is_line = !is_poly && sctx->current_rast_prim != PIPE_PRIM_POINTS;
- key->ps.color_two_side = rs->two_side && sel->info.colors_read;
+ key->ps.prolog.color_two_side = rs->two_side && sel->info.colors_read;
if (sctx->queued.named.blend) {
- key->ps.alpha_to_one = sctx->queued.named.blend->alpha_to_one &&
- rs->multisample_enable &&
- !sctx->framebuffer.cb0_is_integer;
+ key->ps.epilog.alpha_to_one = sctx->queued.named.blend->alpha_to_one &&
+ rs->multisample_enable &&
+ !sctx->framebuffer.cb0_is_integer;
}
- key->ps.poly_stipple = rs->poly_stipple_enable && is_poly;
- key->ps.poly_line_smoothing = ((is_poly && rs->poly_smooth) ||
- (is_line && rs->line_smooth)) &&
- sctx->framebuffer.nr_samples <= 1;
- key->ps.clamp_color = rs->clamp_fragment_color;
-
- key->ps.force_persample_interp = rs->force_persample_interp &&
- rs->multisample_enable &&
- sctx->framebuffer.nr_samples > 1 &&
- sctx->ps_iter_samples > 1 &&
- (sel->info.uses_persp_center ||
- sel->info.uses_persp_centroid ||
- sel->info.uses_linear_center ||
- sel->info.uses_linear_centroid);
+ key->ps.prolog.poly_stipple = rs->poly_stipple_enable && is_poly;
+ key->ps.epilog.poly_line_smoothing = ((is_poly && rs->poly_smooth) ||
+ (is_line && rs->line_smooth)) &&
+ sctx->framebuffer.nr_samples <= 1;
+ key->ps.epilog.clamp_color = rs->clamp_fragment_color;
+
+ key->ps.prolog.force_persample_interp =
+ rs->force_persample_interp &&
+ rs->multisample_enable &&
+ sctx->framebuffer.nr_samples > 1 &&
+ sctx->ps_iter_samples > 1 &&
+ (sel->info.uses_persp_center ||
+ sel->info.uses_persp_centroid ||
+ sel->info.uses_linear_center ||
+ sel->info.uses_linear_centroid);
}
- key->ps.alpha_func = si_get_alpha_test_func(sctx);
+ key->ps.epilog.alpha_func = si_get_alpha_test_func(sctx);
break;
}
default:
*/
switch (sel->type) {
case PIPE_SHADER_TESS_CTRL:
- key.tcs.prim_mode = PIPE_PRIM_TRIANGLES;
+ key.tcs.epilog.prim_mode = PIPE_PRIM_TRIANGLES;
break;
case PIPE_SHADER_FRAGMENT:
- key.ps.alpha_func = PIPE_FUNC_ALWAYS;
+ key.ps.epilog.alpha_func = PIPE_FUNC_ALWAYS;
for (i = 0; i < 8; i++)
if (sel->info.colors_written & (1 << i))
- key.ps.spi_shader_col_format |=
+ key.ps.epilog.spi_shader_col_format |=
V_028710_SPI_SHADER_FP16_ABGR << (i * 4);
break;
}
}
}
- if (ps->key.ps.color_two_side) {
+ if (ps->key.ps.prolog.color_two_side) {
unsigned bcol = TGSI_SEMANTIC_BCOLOR;
for (i = 0; i < 2; i++) {
si_mark_atom_dirty(sctx, &sctx->db_render_state);
}
- if (sctx->smoothing_enabled != sctx->ps_shader.current->key.ps.poly_line_smoothing) {
- sctx->smoothing_enabled = sctx->ps_shader.current->key.ps.poly_line_smoothing;
+ if (sctx->smoothing_enabled != sctx->ps_shader.current->key.ps.epilog.poly_line_smoothing) {
+ sctx->smoothing_enabled = sctx->ps_shader.current->key.ps.epilog.poly_line_smoothing;
si_mark_atom_dirty(sctx, &sctx->msaa_config);
if (sctx->b.chip_class == SI)