summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/freedreno')
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c85
1 files changed, 81 insertions, 4 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
index d044c1ac214..f6f44e02af1 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
@@ -99,6 +99,10 @@ struct ir3_compile {
*/
bool flat_bypass;
+ /* on a3xx, we need to add one to # of array levels:
+ */
+ bool levels_add_one;
+
/* for looking up which system value is which */
unsigned sysval_semantics[8];
@@ -216,9 +220,11 @@ compile_init(struct ir3_shader_variant *so,
} else if (ir3_shader_gpuid(so->shader) >= 400) {
/* need special handling for "flat" */
ctx->flat_bypass = true;
+ ctx->levels_add_one = false;
} else {
/* no special handling for "flat" */
ctx->flat_bypass = false;
+ ctx->levels_add_one = true;
}
switch (so->type) {
@@ -1375,6 +1381,63 @@ emit_tex(struct ir3_compile *ctx, nir_tex_instr *tex)
split_dest(b, dst, sam);
}
+static void
+emit_tex_query_levels(struct ir3_compile *ctx, nir_tex_instr *tex)
+{
+ struct ir3_block *b = ctx->block;
+ struct ir3_instruction **dst, *sam;
+
+ dst = get_dst(ctx, &tex->dest, 1);
+
+ sam = ir3_SAM(b, OPC_GETINFO, TYPE_U32, TGSI_WRITEMASK_Z, 0,
+ tex->sampler_index, tex->sampler_index, NULL, NULL);
+
+ /* even though there is only one component, since it ends
+ * up in .z rather than .x, we need a split_dest()
+ */
+ split_dest(b, dst, sam);
+
+ /* The # of levels comes from getinfo.z. We need to add 1 to it, since
+ * the value in TEX_CONST_0 is zero-based.
+ */
+ if (ctx->levels_add_one)
+ dst[0] = ir3_ADD_U(b, dst[0], 0, create_immed(b, 1), 0);
+}
+
+static void
+emit_tex_txs(struct ir3_compile *ctx, nir_tex_instr *tex)
+{
+ struct ir3_block *b = ctx->block;
+ struct ir3_instruction **dst, *sam, *lod;
+ unsigned flags, coords;
+
+ tex_info(tex, &flags, &coords);
+
+ dst = get_dst(ctx, &tex->dest, 4);
+
+ compile_assert(ctx, tex->num_srcs == 1);
+ compile_assert(ctx, tex->src[0].src_type == nir_tex_src_lod);
+
+ lod = get_src(ctx, &tex->src[0].src)[0];
+
+ sam = ir3_SAM(b, OPC_GETSIZE, TYPE_U32, TGSI_WRITEMASK_XYZW, flags,
+ tex->sampler_index, tex->sampler_index, lod, NULL);
+
+ split_dest(b, dst, sam);
+
+ /* Array size actually ends up in .w rather than .z. This doesn't
+ * matter for miplevel 0, but for higher mips the value in z is
+ * minified whereas w stays. Also, the value in TEX_CONST_3_DEPTH is
+ * returned, which means that we have to add 1 to it for arrays.
+ */
+ if (tex->is_array) {
+ if (ctx->levels_add_one) {
+ dst[coords] = ir3_ADD_U(b, dst[3], 0, create_immed(b, 1), 0);
+ } else {
+ dst[coords] = ir3_MOV(b, dst[3], TYPE_U32);
+ }
+ }
+}
static void
emit_instr(struct ir3_compile *ctx, nir_instr *instr)
@@ -1392,10 +1455,23 @@ emit_instr(struct ir3_compile *ctx, nir_instr *instr)
case nir_instr_type_ssa_undef:
emit_undef(ctx, nir_instr_as_ssa_undef(instr));
break;
- case nir_instr_type_tex:
- emit_tex(ctx, nir_instr_as_tex(instr));
+ case nir_instr_type_tex: {
+ nir_tex_instr *tex = nir_instr_as_tex(instr);
+ /* couple tex instructions get special-cased:
+ */
+ switch (tex->op) {
+ case nir_texop_txs:
+ emit_tex_txs(ctx, tex);
+ break;
+ case nir_texop_query_levels:
+ emit_tex_query_levels(ctx, tex);
+ break;
+ default:
+ emit_tex(ctx, tex);
+ break;
+ }
break;
-
+ }
case nir_instr_type_call:
case nir_instr_type_jump:
case nir_instr_type_phi:
@@ -1490,7 +1566,8 @@ setup_input(struct ir3_compile *ctx, nir_variable *in)
/* with NIR, we need to infer TGSI_INTERPOLATE_COLOR
* from the semantic name:
*/
- if (semantic_name == TGSI_SEMANTIC_COLOR)
+ if ((semantic_name == TGSI_SEMANTIC_COLOR) ||
+ (semantic_name == TGSI_SEMANTIC_BCOLOR))
so->inputs[n].interpolate = TGSI_INTERPOLATE_COLOR;
if (ctx->flat_bypass) {