aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRoland Scheidegger <[email protected]>2018-02-04 23:54:26 +0100
committerRoland Scheidegger <[email protected]>2018-02-08 04:07:52 +0100
commitb936f4d1ca0d2ab1e828ff6a6e617f12469687fa (patch)
treed10124e13dbb3fe6cd6d0f48848f6629aaa01bfc /src
parent07d724326aba79451133337e5ee3711df7f73dfb (diff)
r600: partly fix sampleMaskIn value
The hw gives us coverage for pixel, not for individual fragment shader invocations, in case execution isn't per pixel (eg, unlike cm, actually cannot do "real" minSampleShading, it's either per-pixel or per-fragment, but it doesn't really make a difference here). Also, with msaa disabled, the hw still gives us a mask corresponding to the number of samples, where GL requires this to be 1. Fix this up by masking the sampleMaskIn bits with the bit corresponding to the sampleID, if we know this shader is always executed at per-sample granularity. (In case of a per-sample frequency shader and msaa disabled, the sampleID will always be 0, so this works just fine there.) Fixing this for the minSampleShading case will need a shader key (radeonsi uses the prolog part for) (for eg, could get away with a single bit, cm would need more bits depending on sample/invocation ratio, or read the bits from a uniform), unless we'd want to always use a sample mask uniform (which is probably not a good idea, as it would make the ordinary common msaa case slower for no good reason). This fixes some parts of piglit arb_sample_shading-samplemask (with fixed test), in particular those which use a sampleID, still failing others as expected. Reviewed-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/r600/r600_shader.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index 8b9bb47a2ed..26f9ddb9401 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -1138,6 +1138,11 @@ static int allocate_system_value_inputs(struct r600_shader_ctx *ctx, int gpr_off
tgsi_parse_free(&parse);
+ if (ctx->info.reads_samplemask &&
+ (ctx->info.uses_linear_sample || ctx->info.uses_linear_sample)) {
+ inputs[1].enabled = true;
+ }
+
if (ctx->bc->chip_class >= EVERGREEN) {
int num_baryc = 0;
/* assign gpr to each interpolator according to priority */
@@ -3503,8 +3508,57 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
r = eg_load_helper_invocation(&ctx);
if (r)
return r;
+ }
+
+ /*
+ * XXX this relies on fixed_pt_position_gpr only being present when
+ * this shader should be executed per sample. Should be the case for now...
+ */
+ if (ctx.fixed_pt_position_gpr != -1 && ctx.info.reads_samplemask) {
+ /*
+ * Fix up sample mask. The hw always gives us coverage mask for
+ * the pixel. However, for per-sample shading, we need the
+ * coverage for the shader invocation only.
+ * Also, with disabled msaa, only the first bit should be set
+ * (luckily the same fixup works for both problems).
+ * For now, we can only do it if we know this shader is always
+ * executed per sample (due to usage of bits in the shader
+ * forcing per-sample execution).
+ * If the fb is not multisampled, we'd do unnecessary work but
+ * it should still be correct.
+ * It will however do nothing for sample shading according
+ * to MinSampleShading.
+ */
+ struct r600_bytecode_alu alu;
+ int tmp = r600_get_temp(&ctx);
+ assert(ctx.face_gpr != -1);
+ memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+
+ alu.op = ALU_OP2_LSHL_INT;
+ alu.src[0].sel = V_SQ_ALU_SRC_LITERAL;
+ alu.src[0].value = 0x1;
+ alu.src[1].sel = ctx.fixed_pt_position_gpr;
+ alu.src[1].chan = 3;
+ alu.dst.sel = tmp;
+ alu.dst.chan = 0;
+ alu.dst.write = 1;
+ alu.last = 1;
+ if ((r = r600_bytecode_add_alu(ctx.bc, &alu)))
+ return r;
+ memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+ alu.op = ALU_OP2_AND_INT;
+ alu.src[0].sel = tmp;
+ alu.src[1].sel = ctx.face_gpr;
+ alu.src[1].chan = 2;
+ alu.dst.sel = ctx.face_gpr;
+ alu.dst.chan = 2;
+ alu.dst.write = 1;
+ alu.last = 1;
+ if ((r = r600_bytecode_add_alu(ctx.bc, &alu)))
+ return r;
}
+
if (ctx.fragcoord_input >= 0) {
if (ctx.bc->chip_class == CAYMAN) {
for (j = 0 ; j < 4; j++) {