[Freedreno] [PATCH] ir3_compiler/nir: fix imageSize() for buffer-backed images
Eduardo Lima Mitev
elima at igalia.com
Tue Oct 23 10:11:28 UTC 2018
GL_EXT_texture_buffer introduced texture buffers, which can be used
in shaders through a new type imageBuffer.
Because how image access is implemented in freedreno, calling
imageSize on an imageBuffer returns the size in bytes instead of texels,
which is incorrect.
This patch adds a division of imageSize result by the bytes-per-pixel
of the image format, when image is buffer-backed.
Fixes all tests under
dEQP-GLES31.functional.image_load_store.buffer.image_size.*
---
.../drivers/freedreno/ir3/ir3_compiler_nir.c | 34 +++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
index 197196383b0..80ca2aa0161 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
@@ -2035,6 +2035,40 @@ emit_intrinsic_image_size(struct ir3_context *ctx, nir_intrinsic_instr *intr,
split_dest(b, tmp, sam, 0, 4);
+ /* get_size instruction returns size in bytes instead of texels
+ * for imageBuffer, so we need to divide it by the pixel size
+ * of the image format.
+ *
+ * TODO: This is at least true on a5xx. Check other gens.
+ */
+ enum glsl_sampler_dim dim =
+ glsl_get_sampler_dim(glsl_without_array(var->type));
+ if (dim == GLSL_SAMPLER_DIM_BUF) {
+ /* The image format's bytes-per-pixel should have been
+ * emitted as part of shader constants. It is
+ * the constant at offset 0 of image_dims. See
+ * ir3_shader::emit_image_dims().
+ */
+ unsigned cb = regid(ctx->so->constbase.image_dims, 0) +
+ ctx->so->const_layout.image_dims.off[var->data.driver_location];
+ struct ir3_instruction *aux = create_uniform(ctx, cb + 0);
+
+ /* Since all the possible values the divisor can take are [4, 8, 16],
+ * all power-of-two, we implement the division as a shift-right
+ * instruction. We just need the log2 of the divisor first.
+ *
+ * However, log2 instruction seems to operate only on a float
+ * type reg, so we need to convert the reg to float,
+ * perform the log2, and then convert the result back again
+ * to integer for shift-right.
+ */
+ aux = ir3_COV(b, aux, TYPE_S32, TYPE_F32);
+ aux = ir3_LOG2(b, aux, 0);
+ aux = ir3_COV(b, aux, TYPE_F32, TYPE_S32);
+
+ tmp[0] = ir3_SHR_B(b, tmp[0], 0, aux, 0);
+ }
+
for (unsigned i = 0; i < ncoords; i++)
dst[i] = tmp[i];
--
2.19.1
More information about the Freedreno
mailing list