summaryrefslogtreecommitdiff
path: root/src/broadcom/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/broadcom/compiler')
-rw-r--r--src/broadcom/compiler/nir_to_vir.c48
-rw-r--r--src/broadcom/compiler/v3d_compiler.h6
2 files changed, 40 insertions, 14 deletions
diff --git a/src/broadcom/compiler/nir_to_vir.c b/src/broadcom/compiler/nir_to_vir.c
index 6ec5db58a2..77d460c1b6 100644
--- a/src/broadcom/compiler/nir_to_vir.c
+++ b/src/broadcom/compiler/nir_to_vir.c
@@ -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;
diff --git a/src/broadcom/compiler/v3d_compiler.h b/src/broadcom/compiler/v3d_compiler.h
index 1111102e6b..7cb2e59b8f 100644
--- a/src/broadcom/compiler/v3d_compiler.h
+++ b/src/broadcom/compiler/v3d_compiler.h
@@ -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,