broadcom/vc5: Move texture return channel setup into the compiler.
authorEric Anholt <eric@anholt.net>
Tue, 2 Jan 2018 19:26:58 +0000 (11:26 -0800)
committerEric Anholt <eric@anholt.net>
Wed, 3 Jan 2018 22:25:23 +0000 (14:25 -0800)
The compiler decides how many LDTMUs we're going to emit, and that must
match the P1 flags.  This brings the return channel counting to a single
place (so all that's passed into the compiler is "how many return channels
you may request from this texture's format), and was a necessary step for
shadow samplers once we stop using OVRTMUOUT=0.

src/broadcom/cle/v3d_packet_v33.xml
src/broadcom/compiler/nir_to_vir.c
src/broadcom/compiler/v3d_compiler.h
src/gallium/drivers/vc5/vc5_state.c
src/gallium/drivers/vc5/vc5_uniforms.c

index 8d1ff2cf3b32831515714d346f60d3bf7a36b4f4..f18954d64c8dfd273e81d9e3f6caaf537c0d1dc6 100644 (file)
 
   <struct name="Texture Uniform Parameter 1 CFG_MODE=1">
     <field name="Texture state record base address" size="28" start="4" type="address"/>
-    <field name="Return word 3 of texture data" size="1" start="3" type="bool"/>
-    <field name="Return word 2 of texture data" size="1" start="2" type="bool"/>
-    <field name="Return word 1 of texture data" size="1" start="1" type="bool"/>
-    <field name="Return word 0 of texture data" size="1" start="0" type="bool"/>
+    <field name="Return words of texture data" size="4" start="0" type="uint"/>
   </struct>
 
   <struct name="Texture Shader State">
index 6ec5db58a261cff2319315256213014ada99364d..77d460c1b6283d5e49b5253454439fe2202fe251 100644 (file)
@@ -337,6 +337,9 @@ ntq_emit_tex(struct v3d_compile *c, nir_tex_instr *instr)
                 .fetch_sample_mode = instr->op == nir_texop_txf,
         };
 
+        struct V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1 p1_unpacked = {
+        };
+
         switch (instr->sampler_dim) {
         case GLSL_SAMPLER_DIM_1D:
                 if (instr->is_array)
@@ -419,11 +422,35 @@ ntq_emit_tex(struct v3d_compile *c, nir_tex_instr *instr)
                 }
         }
 
+        bool return_16 = (c->key->tex[unit].return_size == 16 ||
+                          p0_unpacked.shadow);
+
+        /* Limit the number of channels returned to both how many the NIR
+         * instruction writes and how many the instruction could produce.
+         */
+        uint32_t instr_return_channels = nir_tex_instr_dest_size(instr);
+        if (return_16)
+                instr_return_channels = (instr_return_channels + 1) / 2;
+
+        p1_unpacked.return_words_of_texture_data =
+                (1 << MIN2(instr_return_channels,
+                           c->key->tex[unit].return_channels)) - 1;
+
         uint32_t p0_packed;
         V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1_pack(NULL,
                                                          (uint8_t *)&p0_packed,
                                                          &p0_unpacked);
 
+        uint32_t p1_packed;
+        V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1_pack(NULL,
+                                                         (uint8_t *)&p1_packed,
+                                                         &p1_unpacked);
+        /* Load unit number into the address field, which will be be used by
+         * the driver to decide which texture to put in the actual address
+         * field.
+         */
+        p1_packed |= unit << 5;
+
         /* There is no native support for GL texture rectangle coordinates, so
          * we have to rescale from ([0, width], [0, height]) to ([0, 1], [0,
          * 1]).
@@ -439,7 +466,7 @@ ntq_emit_tex(struct v3d_compile *c, nir_tex_instr *instr)
 
         struct qreg texture_u[] = {
                 vir_uniform(c, QUNIFORM_TEXTURE_CONFIG_P0_0 + unit, p0_packed),
-                vir_uniform(c, QUNIFORM_TEXTURE_CONFIG_P1, unit),
+                vir_uniform(c, QUNIFORM_TEXTURE_CONFIG_P1, p1_packed),
         };
         uint32_t next_texture_u = 0;
 
@@ -460,17 +487,16 @@ ntq_emit_tex(struct v3d_compile *c, nir_tex_instr *instr)
                 }
         }
 
-        bool return_16 = (c->key->tex[unit].return_size == 16 ||
-                          p0_unpacked.shadow);
-
         struct qreg return_values[4];
-        for (int i = 0; i < c->key->tex[unit].return_channels; i++)
-                return_values[i] = vir_LDTMU(c);
-        /* Swizzling .zw of an RG texture should give undefined results, not
-         * crash the compiler.
-         */
-        for (int i = c->key->tex[unit].return_channels; i < 4; i++)
-                return_values[i] = c->undef;
+        for (int i = 0; i < 4; i++) {
+                /* Swizzling .zw of an RG texture should give undefined
+                 * results, not crash the compiler.
+                 */
+                if (p1_unpacked.return_words_of_texture_data & (1 << i))
+                        return_values[i] = vir_LDTMU(c);
+                else
+                        return_values[i] = c->undef;
+        }
 
         for (int i = 0; i < nir_tex_instr_dest_size(instr); i++) {
                 struct qreg chan;
index 1111102e6b13688a14ffdd9f3240500aa83e6051..7cb2e59b8f7246d07998eac2baf821591471d978 100644 (file)
@@ -215,9 +215,9 @@ enum quniform_contents {
          * A reference to a texture config parameter 1 uniform.
          *
          * This is a uniform implicitly loaded with a QPU_W_TMU* write, which
-         * defines texture width, height, filters, and wrap modes.  It will be
-         * found as a parameter to the second QOP_TEX_[STRB] instruction in a
-         * sequence.
+         * has the pointer to the indirect texture state.  Our data[] field
+         * will have a packed p1 value, but the address field will be just
+         * which texture unit's texture should be referenced.
          */
         QUNIFORM_TEXTURE_CONFIG_P1,
 
index d022aa84e42836f0bbf990f9a278016189e317f6..04ce3075a8f46c497df44d954c05a699b8b370e1 100644 (file)
@@ -588,19 +588,6 @@ vc5_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
 
         pipe_reference(NULL, &prsc->reference);
 
-        v3dx_pack(&so->p1, TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1, p1) {
-                p1.return_word_0_of_texture_data = true;
-                if (vc5_get_tex_return_size(cso->format) == 16) {
-                        p1.return_word_1_of_texture_data = true;
-                } else {
-                        int chans = vc5_get_tex_return_channels(cso->format);
-
-                        p1.return_word_1_of_texture_data = chans > 1;
-                        p1.return_word_2_of_texture_data = chans > 2;
-                        p1.return_word_3_of_texture_data = chans > 3;
-                }
-        }
-
         /* Compute the sampler view's swizzle up front. This will be plugged
          * into either the sampler (for 16-bit returns) or the shader's
          * texture key (for 32)
index 5e181344e731783c259e10b6b12a7b90bc4b6782..676ab1a32c96bb45a801d7cf2d99e2de6aeba260 100644 (file)
@@ -193,8 +193,14 @@ static void
 write_texture_p1(struct vc5_job *job,
                  struct vc5_cl_out **uniforms,
                  struct vc5_texture_stateobj *texstate,
-                 uint32_t unit)
+                 uint32_t data)
 {
+        /* Extract the texture unit from the top bits, and the compiler's
+         * packed p1 from the bottom.
+         */
+        uint32_t unit = data >> 5;
+        uint32_t p1 = data & 0x1f;
+
         struct pipe_sampler_view *psview = texstate->textures[unit];
         struct vc5_sampler_view *sview = vc5_sampler_view(psview);
 
@@ -207,7 +213,7 @@ write_texture_p1(struct vc5_job *job,
                                                          (uint8_t *)&packed,
                                                          &unpacked);
 
-        cl_aligned_u32(uniforms, packed | sview->p1);
+        cl_aligned_u32(uniforms, p1 | packed | sview->p1);
 }
 
 struct vc5_cl_reloc