vc4: Add #defines for the texture uniform fields.
[mesa.git] / src / gallium / drivers / vc4 / vc4_program.c
index 52de8a88ae78f386f05d174861c75d18455ee389..3995eccf54a22985f43b0932f35e9f328e325dfd 100644 (file)
@@ -43,7 +43,7 @@
 #endif
 
 struct vc4_key {
-        struct pipe_shader_state *shader_state;
+        struct vc4_uncompiled_shader *shader_state;
         struct {
                 enum pipe_format format;
                 unsigned compare_mode:1;
@@ -65,6 +65,7 @@ struct vc4_fs_key {
         bool is_lines;
         bool alpha_test;
         bool point_coord_upper_left;
+        bool light_twoside;
         uint8_t alpha_test_func;
         uint32_t point_sprite_mask;
 
@@ -273,6 +274,18 @@ tgsi_to_qir_alu(struct vc4_compile *c,
         return dst;
 }
 
+static struct qreg
+tgsi_to_qir_scalar(struct vc4_compile *c,
+                   struct tgsi_full_instruction *tgsi_inst,
+                   enum qop op, struct qreg *src, int i)
+{
+        struct qreg dst = qir_get_temp(c);
+        qir_emit(c, qir_inst(op, dst,
+                             src[0 * 4 + 0],
+                             c->undef));
+        return dst;
+}
+
 static struct qreg
 qir_srgb_decode(struct vc4_compile *c, struct qreg srgb)
 {
@@ -477,40 +490,6 @@ tgsi_to_qir_mad(struct vc4_compile *c,
                         src[2 * 4 + i]);
 }
 
-static struct qreg
-tgsi_to_qir_lit(struct vc4_compile *c,
-                 struct tgsi_full_instruction *tgsi_inst,
-                 enum qop op, struct qreg *src, int i)
-{
-        struct qreg x = src[0 * 4 + 0];
-        struct qreg y = src[0 * 4 + 1];
-        struct qreg w = src[0 * 4 + 3];
-
-        switch (i) {
-        case 0:
-        case 3:
-                return qir_uniform_f(c, 1.0);
-        case 1:
-                return qir_FMAX(c, src[0 * 4 + 0], qir_uniform_f(c, 0.0));
-        case 2: {
-                struct qreg zero = qir_uniform_f(c, 0.0);
-
-                qir_SF(c, x);
-                /* XXX: Clamp w to -128..128 */
-                return qir_SEL_X_0_NC(c,
-                                      qir_EXP2(c, qir_FMUL(c,
-                                                           w,
-                                                           qir_LOG2(c,
-                                                                    qir_FMAX(c,
-                                                                             y,
-                                                                             zero)))));
-        }
-        default:
-                assert(!"not reached");
-                return c->undef;
-        }
-}
-
 static struct qreg
 tgsi_to_qir_lrp(struct vc4_compile *c,
                  struct tgsi_full_instruction *tgsi_inst,
@@ -695,16 +674,6 @@ tgsi_to_qir_tex(struct vc4_compile *c,
         }
 }
 
-static struct qreg
-tgsi_to_qir_pow(struct vc4_compile *c,
-                struct tgsi_full_instruction *tgsi_inst,
-                enum qop op, struct qreg *src, int i)
-{
-        /* Note that this instruction replicates its result from the x channel
-         */
-        return qir_POW(c, src[0 * 4 + 0], src[1 * 4 + 0]);
-}
-
 static struct qreg
 tgsi_to_qir_trunc(struct vc4_compile *c,
                 struct tgsi_full_instruction *tgsi_inst,
@@ -751,44 +720,6 @@ tgsi_to_qir_flr(struct vc4_compile *c,
                               trunc);
 }
 
-static struct qreg
-tgsi_to_qir_dp(struct vc4_compile *c,
-               struct tgsi_full_instruction *tgsi_inst,
-               int num, struct qreg *src, int i)
-{
-        struct qreg sum = qir_FMUL(c, src[0 * 4 + 0], src[1 * 4 + 0]);
-        for (int j = 1; j < num; j++) {
-                sum = qir_FADD(c, sum, qir_FMUL(c,
-                                                src[0 * 4 + j],
-                                                src[1 * 4 + j]));
-        }
-        return sum;
-}
-
-static struct qreg
-tgsi_to_qir_dp2(struct vc4_compile *c,
-                 struct tgsi_full_instruction *tgsi_inst,
-                 enum qop op, struct qreg *src, int i)
-{
-        return tgsi_to_qir_dp(c, tgsi_inst, 2, src, i);
-}
-
-static struct qreg
-tgsi_to_qir_dp3(struct vc4_compile *c,
-                 struct tgsi_full_instruction *tgsi_inst,
-                 enum qop op, struct qreg *src, int i)
-{
-        return tgsi_to_qir_dp(c, tgsi_inst, 3, src, i);
-}
-
-static struct qreg
-tgsi_to_qir_dp4(struct vc4_compile *c,
-                 struct tgsi_full_instruction *tgsi_inst,
-                 enum qop op, struct qreg *src, int i)
-{
-        return tgsi_to_qir_dp(c, tgsi_inst, 4, src, i);
-}
-
 static struct qreg
 tgsi_to_qir_abs(struct vc4_compile *c,
                 struct tgsi_full_instruction *tgsi_inst,
@@ -1026,10 +957,15 @@ emit_tgsi_declaration(struct vc4_compile *c,
                       struct tgsi_full_declaration *decl)
 {
         switch (decl->Declaration.File) {
-        case TGSI_FILE_TEMPORARY:
+        case TGSI_FILE_TEMPORARY: {
+                uint32_t old_size = c->temps_array_size;
                 resize_qreg_array(c, &c->temps, &c->temps_array_size,
                                   (decl->Range.Last + 1) * 4);
+
+                for (int i = old_size; i < c->temps_array_size; i++)
+                        c->temps[i] = qir_uniform_ui(c, 0);
                 break;
+        }
 
         case TGSI_FILE_INPUT:
                 resize_qreg_array(c, &c->inputs, &c->inputs_array_size,
@@ -1128,16 +1064,11 @@ emit_tgsi_instruction(struct vc4_compile *c,
 
                 [TGSI_OPCODE_CMP] = { 0, tgsi_to_qir_cmp },
                 [TGSI_OPCODE_MAD] = { 0, tgsi_to_qir_mad },
-                [TGSI_OPCODE_DP2] = { 0, tgsi_to_qir_dp2 },
-                [TGSI_OPCODE_DP3] = { 0, tgsi_to_qir_dp3 },
-                [TGSI_OPCODE_DP4] = { 0, tgsi_to_qir_dp4 },
-                [TGSI_OPCODE_RCP] = { QOP_RCP, tgsi_to_qir_alu },
-                [TGSI_OPCODE_RSQ] = { QOP_RSQ, tgsi_to_qir_alu },
-                [TGSI_OPCODE_EX2] = { QOP_EXP2, tgsi_to_qir_alu },
-                [TGSI_OPCODE_LG2] = { QOP_LOG2, tgsi_to_qir_alu },
-                [TGSI_OPCODE_LIT] = { 0, tgsi_to_qir_lit },
+                [TGSI_OPCODE_RCP] = { QOP_RCP, tgsi_to_qir_scalar },
+                [TGSI_OPCODE_RSQ] = { QOP_RSQ, tgsi_to_qir_scalar },
+                [TGSI_OPCODE_EX2] = { QOP_EXP2, tgsi_to_qir_scalar },
+                [TGSI_OPCODE_LG2] = { QOP_LOG2, tgsi_to_qir_scalar },
                 [TGSI_OPCODE_LRP] = { 0, tgsi_to_qir_lrp },
-                [TGSI_OPCODE_POW] = { 0, tgsi_to_qir_pow },
                 [TGSI_OPCODE_TRUNC] = { 0, tgsi_to_qir_trunc },
                 [TGSI_OPCODE_FRC] = { 0, tgsi_to_qir_frc },
                 [TGSI_OPCODE_FLR] = { 0, tgsi_to_qir_flr },
@@ -1640,15 +1571,7 @@ vc4_shader_tgsi_to_qir(struct vc4_context *vc4,
         int ret;
 
         c->stage = stage;
-
-        c->shader_state = key->shader_state;
-        ret = tgsi_parse_init(&c->parser, c->shader_state->tokens);
-        assert(ret == TGSI_PARSE_OK);
-
-        if (vc4_debug & VC4_DEBUG_TGSI) {
-                fprintf(stderr, "TGSI:\n");
-                tgsi_dump(c->shader_state->tokens, 0);
-        }
+        c->shader_state = &key->shader_state->base;
 
         c->key = key;
         switch (stage) {
@@ -1669,6 +1592,37 @@ vc4_shader_tgsi_to_qir(struct vc4_context *vc4,
                 break;
         }
 
+        const struct tgsi_token *tokens = key->shader_state->base.tokens;
+        if (c->fs_key && c->fs_key->light_twoside) {
+                if (!key->shader_state->twoside_tokens) {
+                        const struct tgsi_lowering_config lowering_config = {
+                                .color_two_side = true,
+                        };
+                        struct tgsi_shader_info info;
+                        key->shader_state->twoside_tokens =
+                                tgsi_transform_lowering(&lowering_config,
+                                                        key->shader_state->base.tokens,
+                                                        &info);
+
+                        /* If no transformation occurred, then NULL is
+                         * returned and we just use our original tokens.
+                         */
+                        if (!key->shader_state->twoside_tokens) {
+                                key->shader_state->twoside_tokens =
+                                        key->shader_state->base.tokens;
+                        }
+                }
+                tokens = key->shader_state->twoside_tokens;
+        }
+
+        ret = tgsi_parse_init(&c->parser, tokens);
+        assert(ret == TGSI_PARSE_OK);
+
+        if (vc4_debug & VC4_DEBUG_TGSI) {
+                fprintf(stderr, "TGSI:\n");
+                tgsi_dump(tokens, 0);
+        }
+
         while (!tgsi_parse_end_of_tokens(&c->parser)) {
                 tgsi_parse_token(&c->parser);
 
@@ -1727,7 +1681,7 @@ static void *
 vc4_shader_state_create(struct pipe_context *pctx,
                         const struct pipe_shader_state *cso)
 {
-        struct pipe_shader_state *so = CALLOC_STRUCT(pipe_shader_state);
+        struct vc4_uncompiled_shader *so = CALLOC_STRUCT(vc4_uncompiled_shader);
         if (!so)
                 return NULL;
 
@@ -1735,16 +1689,21 @@ vc4_shader_state_create(struct pipe_context *pctx,
                 .lower_DST = true,
                 .lower_XPD = true,
                 .lower_SCS = true,
+                .lower_POW = true,
+                .lower_LIT = true,
                 .lower_EXP = true,
                 .lower_LOG = true,
+                .lower_DP4 = true,
+                .lower_DP3 = true,
                 .lower_DPH = true,
+                .lower_DP2 = true,
                 .lower_DP2A = true,
         };
 
         struct tgsi_shader_info info;
-        so->tokens = tgsi_transform_lowering(&lowering_config, cso->tokens, &info);
-        if (!so->tokens)
-                so->tokens = tgsi_dup_tokens(cso->tokens);
+        so->base.tokens = tgsi_transform_lowering(&lowering_config, cso->tokens, &info);
+        if (!so->base.tokens)
+                so->base.tokens = tgsi_dup_tokens(cso->tokens);
 
         return so;
 }
@@ -1871,6 +1830,8 @@ vc4_update_compiled_fs(struct vc4_context *vc4, uint8_t prim_mode)
                          PIPE_SPRITE_COORD_UPPER_LEFT);
         }
 
+        key->light_twoside = vc4->rasterizer->base.light_twoside;
+
         vc4->prog.fs = util_hash_table_get(vc4->fs_cache, key);
         if (vc4->prog.fs)
                 return;
@@ -1955,7 +1916,7 @@ vs_cache_compare(void *key1, void *key2)
 
 struct delete_state {
         struct vc4_context *vc4;
-        struct pipe_shader_state *shader_state;
+        struct vc4_uncompiled_shader *shader_state;
 };
 
 static enum pipe_error
@@ -1994,7 +1955,7 @@ static void
 vc4_shader_state_delete(struct pipe_context *pctx, void *hwcso)
 {
         struct vc4_context *vc4 = vc4_context(pctx);
-        struct pipe_shader_state *so = hwcso;
+        struct vc4_uncompiled_shader *so = hwcso;
         struct delete_state del;
 
         del.vc4 = vc4;
@@ -2002,7 +1963,9 @@ vc4_shader_state_delete(struct pipe_context *pctx, void *hwcso)
         util_hash_table_foreach(vc4->fs_cache, fs_delete_from_cache, &del);
         util_hash_table_foreach(vc4->vs_cache, vs_delete_from_cache, &del);
 
-        free((void *)so->tokens);
+        if (so->twoside_tokens != so->base.tokens)
+                free((void *)so->twoside_tokens);
+        free((void *)so->base.tokens);
         free(so);
 }
 
@@ -2034,12 +1997,12 @@ write_texture_p0(struct vc4_context *vc4,
         struct pipe_sampler_view *texture = texstate->textures[unit];
         struct vc4_resource *rsc = vc4_resource(texture->texture);
 
-        bool is_cube = texture->target == PIPE_TEXTURE_CUBE;
-
         cl_reloc(vc4, &vc4->uniforms, rsc->bo,
-                 rsc->slices[0].offset | texture->u.tex.last_level |
-                 is_cube << 9 |
-                 ((rsc->vc4_format & 7) << 4));
+                 VC4_SET_FIELD(rsc->slices[0].offset >> 12, VC4_TEX_P0_OFFSET) |
+                 VC4_SET_FIELD(texture->u.tex.last_level, VC4_TEX_P0_MIPLVLS) |
+                 VC4_SET_FIELD(texture->target == PIPE_TEXTURE_CUBE,
+                               VC4_TEX_P0_CMMODE) |
+                 VC4_SET_FIELD(rsc->vc4_format & 7, VC4_TEX_P0_TYPE));
 }
 
 static void
@@ -2051,13 +2014,16 @@ write_texture_p1(struct vc4_context *vc4,
         struct vc4_resource *rsc = vc4_resource(texture->texture);
         struct pipe_sampler_state *sampler = texstate->samplers[unit];
         static const uint8_t minfilter_map[6] = {
-                2, 4, /* mipfilter nearest */
-                3, 5, /* mipfilter linear */
-                1, 0, /* mipfilter none */
+                VC4_TEX_P1_MINFILT_NEAR_MIP_NEAR,
+                VC4_TEX_P1_MINFILT_LIN_MIP_NEAR,
+                VC4_TEX_P1_MINFILT_NEAR_MIP_LIN,
+                VC4_TEX_P1_MINFILT_LIN_MIP_LIN,
+                VC4_TEX_P1_MINFILT_NEAREST,
+                VC4_TEX_P1_MINFILT_LINEAR,
         };
         static const uint32_t magfilter_map[] = {
-                [PIPE_TEX_FILTER_NEAREST] = 1,
-                [PIPE_TEX_FILTER_LINEAR] = 0,
+                [PIPE_TEX_FILTER_NEAREST] = VC4_TEX_P1_MAGFILT_NEAREST,
+                [PIPE_TEX_FILTER_LINEAR] = VC4_TEX_P1_MAGFILT_LINEAR,
         };
 
         bool either_nearest =
@@ -2065,14 +2031,20 @@ write_texture_p1(struct vc4_context *vc4,
                  sampler->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST);
 
         cl_u32(&vc4->uniforms,
-               ((rsc->vc4_format >> 4) << 31) |
-               (texture->texture->height0 << 20) |
-               (texture->texture->width0 << 8) |
-               (magfilter_map[sampler->mag_img_filter] << 7) |
-               (minfilter_map[sampler->min_mip_filter * 2 +
-                              sampler->min_img_filter] << 4) |
-               (translate_wrap(sampler->wrap_t, either_nearest) << 2) |
-               (translate_wrap(sampler->wrap_s, either_nearest) << 0));
+               VC4_SET_FIELD(rsc->vc4_format >> 4, VC4_TEX_P1_TYPE4) |
+               VC4_SET_FIELD(texture->texture->height0 & 2047,
+                             VC4_TEX_P1_HEIGHT) |
+               VC4_SET_FIELD(texture->texture->width0 & 2047,
+                             VC4_TEX_P1_WIDTH) |
+               VC4_SET_FIELD(magfilter_map[sampler->mag_img_filter],
+                             VC4_TEX_P1_MAGFILT) |
+               VC4_SET_FIELD(minfilter_map[sampler->min_mip_filter * 2 +
+                                           sampler->min_img_filter],
+                             VC4_TEX_P1_MINFILT) |
+               VC4_SET_FIELD(translate_wrap(sampler->wrap_s, either_nearest),
+                             VC4_TEX_P1_WRAP_S) |
+               VC4_SET_FIELD(translate_wrap(sampler->wrap_t, either_nearest),
+                             VC4_TEX_P1_WRAP_T));
 }
 
 static void
@@ -2083,7 +2055,10 @@ write_texture_p2(struct vc4_context *vc4,
         struct pipe_sampler_view *texture = texstate->textures[unit];
         struct vc4_resource *rsc = vc4_resource(texture->texture);
 
-        cl_u32(&vc4->uniforms, (1 << 30) | rsc->cube_map_stride);
+        cl_u32(&vc4->uniforms,
+               VC4_SET_FIELD(VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE,
+                             VC4_TEX_P2_PTYPE) |
+               VC4_SET_FIELD(rsc->cube_map_stride >> 12, VC4_TEX_P2_CMST));
 }