freedreno/ir3: Use RESINFO for a6xx image size queries.
authorEric Anholt <eric@anholt.net>
Tue, 21 Jan 2020 22:36:32 +0000 (14:36 -0800)
committerMarge Bot <eric+marge@anholt.net>
Tue, 26 May 2020 18:17:46 +0000 (18:17 +0000)
The closed GL driver uses resinfo on images with the writeonly flag (using
the texture-path's getsize only for readonly images).  The closed vulkan
driver seems to use resinfo regardless.  Using resinfo doesn't need any
fixups after the instruction.  It also avoids one of the needs for the
TEX_CONST state for the image, which is awkward to set up in the GL
driver.

The new handler goes into ir3_a6xx to be next to the other current image
code, but the a4xx version is left in place because it wants a bunch of
sampler helpers.

Fixes assertion failure in dEQP-VK.image.image_size.buffer.readonly_32.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3501>

src/freedreno/ir3/ir3.c
src/freedreno/ir3/ir3_a4xx.c
src/freedreno/ir3/ir3_a6xx.c
src/freedreno/ir3/ir3_compiler_nir.c
src/freedreno/ir3/ir3_context.h
src/freedreno/ir3/ir3_cp.c

index d41022b7b29b1435daf862002fadb17b63658b30..5f4b86d610d2bea990db4c63d57cd5da1b80d7e5 100644 (file)
@@ -606,6 +606,7 @@ static int emit_cat6_a6xx(struct ir3_instruction *instr, void *ptr,
                cat6->pad5 = 0x2;
                break;
        case OPC_LDIB:
+       case OPC_RESINFO:
                cat6->pad1 = 0x1;
                cat6->pad3 = 0xc;
                cat6->pad5 = 0x2;
@@ -653,6 +654,7 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr,
                case OPC_STIB:
                case OPC_LDIB:
                case OPC_LDC:
+               case OPC_RESINFO:
                        return emit_cat6_a6xx(instr, ptr, info);
                default:
                        break;
index 04dec6c027f5cc38899819227856196820cb280f..8dbc61c484603c0b7fd4e118d17d7f79e84e08bd 100644 (file)
@@ -356,4 +356,5 @@ const struct ir3_context_funcs ir3_a4xx_funcs = {
                .emit_intrinsic_atomic_ssbo = emit_intrinsic_atomic_ssbo,
                .emit_intrinsic_store_image = emit_intrinsic_store_image,
                .emit_intrinsic_atomic_image = emit_intrinsic_atomic_image,
+               .emit_intrinsic_image_size = emit_intrinsic_image_size_tex,
 };
index 9b8f154bb6451681b6bf12b3e4af942de16d17fc..39549d44b1d38f205edf22be37988c3ea1ffd94c 100644 (file)
@@ -340,6 +340,23 @@ emit_intrinsic_atomic_image(struct ir3_context *ctx, nir_intrinsic_instr *intr)
        return atomic;
 }
 
+static void
+emit_intrinsic_image_size(struct ir3_context *ctx, nir_intrinsic_instr *intr,
+               struct ir3_instruction **dst)
+{
+       struct ir3_block *b = ctx->block;
+       struct ir3_instruction *ibo = ir3_image_to_ibo(ctx, intr->src[0]);
+       struct ir3_instruction *resinfo = ir3_RESINFO(b, ibo, 0);
+       resinfo->cat6.iim_val = 1;
+       resinfo->cat6.d = intr->num_components;
+       resinfo->cat6.type = TYPE_U32;
+       resinfo->cat6.typed = false;
+       resinfo->regs[0]->wrmask = MASK(intr->num_components);
+       ir3_handle_bindless_cat6(resinfo, intr->src[0]);
+
+       ir3_split_dest(b, dst, resinfo, 0, intr->num_components);
+}
+
 const struct ir3_context_funcs ir3_a6xx_funcs = {
                .emit_intrinsic_load_ssbo = emit_intrinsic_load_ssbo,
                .emit_intrinsic_store_ssbo = emit_intrinsic_store_ssbo,
@@ -347,6 +364,7 @@ const struct ir3_context_funcs ir3_a6xx_funcs = {
                .emit_intrinsic_load_image = emit_intrinsic_load_image,
                .emit_intrinsic_store_image = emit_intrinsic_store_image,
                .emit_intrinsic_atomic_image = emit_intrinsic_atomic_image,
+               .emit_intrinsic_image_size = emit_intrinsic_image_size,
 };
 
 /*
index e12a814abd8b584faa9c81672ebd52b9523aa309..054c679aedf86c2d023097c5006cebff6b3240be 100644 (file)
@@ -1175,8 +1175,9 @@ emit_intrinsic_load_image(struct ir3_context *ctx, nir_intrinsic_instr *intr,
        ir3_split_dest(b, dst, sam, 0, 4);
 }
 
-static void
-emit_intrinsic_image_size(struct ir3_context *ctx, nir_intrinsic_instr *intr,
+/* A4xx version of image_size, see ir3_a6xx.c for newer resinfo version. */
+void
+emit_intrinsic_image_size_tex(struct ir3_context *ctx, nir_intrinsic_instr *intr,
                struct ir3_instruction **dst)
 {
        struct ir3_block *b = ctx->block;
@@ -1726,7 +1727,7 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
                break;
        case nir_intrinsic_image_size:
        case nir_intrinsic_bindless_image_size:
-               emit_intrinsic_image_size(ctx, intr, dst);
+               ctx->funcs->emit_intrinsic_image_size(ctx, intr, dst);
                break;
        case nir_intrinsic_image_atomic_add:
        case nir_intrinsic_bindless_image_atomic_add:
index c977dc15285abe34b1215815ee2355073b0e72fc..9cd147d9a6d89653618f8838987db3923281082b 100644 (file)
@@ -163,6 +163,8 @@ struct ir3_context_funcs {
                        struct ir3_instruction **dst);
        void (*emit_intrinsic_store_image)(struct ir3_context *ctx, nir_intrinsic_instr *intr);
        struct ir3_instruction * (*emit_intrinsic_atomic_image)(struct ir3_context *ctx, nir_intrinsic_instr *intr);
+       void (*emit_intrinsic_image_size)(struct ir3_context *ctx, nir_intrinsic_instr *intr,
+                       struct ir3_instruction **dst);
 };
 
 extern const struct ir3_context_funcs ir3_a4xx_funcs;
@@ -181,6 +183,8 @@ struct ir3_instruction * ir3_create_collect(struct ir3_context *ctx,
 void ir3_split_dest(struct ir3_block *block, struct ir3_instruction **dst,
                struct ir3_instruction *src, unsigned base, unsigned n);
 void ir3_handle_bindless_cat6(struct ir3_instruction *instr, nir_src rsrc);
+void emit_intrinsic_image_size_tex(struct ir3_context *ctx, nir_intrinsic_instr *intr,
+               struct ir3_instruction **dst);
 
 NORETURN void ir3_context_error(struct ir3_context *ctx, const char *format, ...);
 
index fd1373018741ffe77969e38f42a27f4ebe0baab2..fb5ea8dc8cb8c5266ffbe97428c6691460326a4f 100644 (file)
@@ -233,8 +233,8 @@ static bool valid_flags(struct ir3_instruction *instr, unsigned n,
                        if (instr->opc == OPC_LDLW && n == 0)
                                return false;
 
-                       /* disallow CP into anything but the SSBO slot argument for
-                        * atomics:
+                       /* disallow immediates in anything but the SSBO slot argument for
+                        * cat6 instructions:
                         */
                        if (is_atomic(instr->opc) && (n != 0))
                                return false;
@@ -245,11 +245,19 @@ static bool valid_flags(struct ir3_instruction *instr, unsigned n,
                        if (instr->opc == OPC_STG && (instr->flags & IR3_INSTR_G) && (n != 2))
                                return false;
 
-                       /* as with atomics, ldib and ldc on a6xx can only have immediate
-                        * for SSBO slot argument
+                       /* as with atomics, these cat6 instrs can only have an immediate
+                        * for SSBO/IBO slot argument
                         */
-                       if ((instr->opc == OPC_LDIB || instr->opc == OPC_LDC) && (n != 0))
-                               return false;
+                       switch (instr->opc) {
+                       case OPC_LDIB:
+                       case OPC_LDC:
+                       case OPC_RESINFO:
+                               if (n != 0)
+                                       return false;
+                               break;
+                       default:
+                               break;
+                       }
                }
 
                break;