summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2013-08-20 13:51:35 -0400
committerRob Clark <[email protected]>2013-08-24 13:23:32 -0400
commitaee1ed708ac5fa4a5db47dc84be4aae00af9d0f0 (patch)
tree2c51d1c1a3f44679cbd90a34ada1a81225da30ab /src/gallium/drivers/freedreno
parent8b250bb8aa31b781681491b1d2a8baa15a024c1c (diff)
freedreno/a3xx/compiler: handle saturate on dst
Sometimes things other than color dst need saturating, like if there is a 'clamp(foo, 0.0, 1.0)'. So for saturated dst add the extra instructions to fix up dst. Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno')
-rw-r--r--src/gallium/drivers/freedreno/a3xx/fd3_compiler.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c b/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c
index 07bede4a4c8..e2c78531d1e 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c
@@ -131,6 +131,11 @@ struct fd3_compile_context {
struct tgsi_src_register tmp_src;
};
+
+static void vectorize(struct fd3_compile_context *ctx,
+ struct ir3_instruction *instr, struct tgsi_dst_register *dst,
+ int nsrcs, ...);
+
static unsigned
compile_init(struct fd3_compile_context *ctx, struct fd3_shader_stateobj *so,
const struct tgsi_token *tokens)
@@ -234,6 +239,10 @@ add_src_reg(struct fd3_compile_context *ctx, struct ir3_instruction *instr,
flags |= IR3_REG_CONST;
num = src->Index + ctx->base_reg[src->File];
break;
+ case TGSI_FILE_OUTPUT:
+ /* NOTE: we should only end up w/ OUTPUT file for things like
+ * clamp()'ing saturated dst instructions
+ */
case TGSI_FILE_INPUT:
case TGSI_FILE_TEMPORARY:
num = src->Index + ctx->base_reg[src->File];
@@ -407,6 +416,35 @@ create_mov(struct fd3_compile_context *ctx, struct tgsi_dst_register *dst,
}
+static void
+create_clamp(struct fd3_compile_context *ctx, struct tgsi_dst_register *dst,
+ struct tgsi_src_register *minval, struct tgsi_src_register *maxval)
+{
+ struct ir3_instruction *instr;
+ struct tgsi_src_register src;
+
+ src_from_dst(&src, dst);
+
+ instr = ir3_instr_create(ctx->ir, 2, OPC_MAX_F);
+ vectorize(ctx, instr, dst, 2, &src, 0, minval, 0);
+
+ instr = ir3_instr_create(ctx->ir, 2, OPC_MIN_F);
+ vectorize(ctx, instr, dst, 2, &src, 0, maxval, 0);
+}
+
+static void
+create_clamp_imm(struct fd3_compile_context *ctx,
+ struct tgsi_dst_register *dst,
+ uint32_t minval, uint32_t maxval)
+{
+ struct tgsi_src_register minconst, maxconst;
+
+ get_immediate(ctx, &minconst, minval);
+ get_immediate(ctx, &maxconst, maxval);
+
+ create_clamp(ctx, dst, &minconst, &maxconst);
+}
+
static struct tgsi_dst_register *
get_dst(struct fd3_compile_context *ctx, struct tgsi_full_instruction *inst)
{
@@ -1229,6 +1267,17 @@ compile_instructions(struct fd3_compile_context *ctx)
assert(0);
}
+ switch (inst->Instruction.Saturate) {
+ case TGSI_SAT_ZERO_ONE:
+ create_clamp_imm(ctx, &inst->Dst[0].Register,
+ fui(0.0), fui(1.0));
+ break;
+ case TGSI_SAT_MINUS_PLUS_ONE:
+ create_clamp_imm(ctx, &inst->Dst[0].Register,
+ fui(-1.0), fui(1.0));
+ break;
+ }
+
break;
}
default: