xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/freedreno/a4xx/fd4_image.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2017 Rob Clark <[email protected]>
3  * SPDX-License-Identifier: MIT
4  *
5  * Authors:
6  *    Rob Clark <[email protected]>
7  */
8 
9 #include "pipe/p_state.h"
10 
11 #include "freedreno_resource.h"
12 #include "fd4_image.h"
13 #include "fd4_format.h"
14 #include "fd4_texture.h"
15 
16 static enum a4xx_state_block texsb[] = {
17    [PIPE_SHADER_COMPUTE] = SB4_CS_TEX,
18    [PIPE_SHADER_FRAGMENT] = SB4_FS_TEX,
19 };
20 
21 static enum a4xx_state_block imgsb[] = {
22    [PIPE_SHADER_COMPUTE] = SB4_CS_SSBO,
23    [PIPE_SHADER_FRAGMENT] = SB4_SSBO,
24 };
25 
26 struct fd4_image {
27    enum pipe_format pfmt;
28    enum a4xx_color_fmt fmt;
29    enum a4xx_tex_fmt texfmt;
30    enum a4xx_tex_type type;
31    bool srgb;
32    uint32_t cpp;
33    uint32_t width;
34    uint32_t height;
35    uint32_t depth;
36    uint32_t pitch;
37    uint32_t array_pitch;
38    uint32_t pitchalign;
39    struct fd_bo *bo;
40    uint32_t offset;
41    bool buffer;
42    uint32_t texconst4;
43 };
44 
translate_image(struct fd4_image * img,struct pipe_image_view * pimg)45 static void translate_image(struct fd4_image *img, struct pipe_image_view *pimg)
46 {
47    enum pipe_format format = pimg->format;
48    struct pipe_resource *prsc = pimg->resource;
49    struct fd_resource *rsc = fd_resource(prsc);
50 
51    if (!pimg->resource) {
52       memset(img, 0, sizeof(*img));
53       return;
54    }
55 
56    img->pfmt      = format;
57    img->fmt       = fd4_pipe2color(format);
58    img->texfmt    = fd4_pipe2tex(format);
59    img->type      = fd4_tex_type(prsc->target);
60    img->srgb      = util_format_is_srgb(format);
61    img->bo        = rsc->bo;
62    img->texconst4 = 0;
63 
64    /* Treat cube textures as 2d-array: */
65    if (img->type == A4XX_TEX_CUBE)
66       img->type = A4XX_TEX_2D;
67 
68    if (prsc->target == PIPE_BUFFER) {
69       img->buffer = true;
70       img->offset = pimg->u.buf.offset;
71       img->cpp = util_format_get_blocksize(format);
72       img->array_pitch = 0;
73       img->pitch = 0;
74       img->pitchalign = 0;
75 
76       /* size is encoded with low 16b in WIDTH and high bits in
77        * HEIGHT, in units of elements:
78        */
79       unsigned sz = pimg->u.buf.size / img->cpp;
80       img->width = sz & MASK(16);
81       img->height = sz >> 16;
82       img->depth = 0;
83 
84       /* Note that the blob sets the PITCH to the CPP in the SSBO descriptor,
85        * but that messes up the sampler we create, so skip that.
86        */
87    } else {
88       img->buffer = false;
89       img->cpp = rsc->layout.cpp;
90 
91       unsigned lvl = pimg->u.tex.level;
92       img->offset = fd_resource_offset(rsc, lvl, pimg->u.tex.first_layer);
93       img->pitch = fd_resource_pitch(rsc, lvl);
94       img->pitchalign = rsc->layout.pitchalign - 5;
95 
96       img->width = u_minify(prsc->width0, lvl);
97       img->height = u_minify(prsc->height0, lvl);
98 
99       unsigned layers = pimg->u.tex.last_layer - pimg->u.tex.first_layer + 1;
100 
101       switch (prsc->target) {
102       case PIPE_TEXTURE_RECT:
103       case PIPE_TEXTURE_1D:
104       case PIPE_TEXTURE_2D:
105          img->array_pitch = rsc->layout.layer_size;
106          img->depth = 1;
107          break;
108       case PIPE_TEXTURE_1D_ARRAY:
109       case PIPE_TEXTURE_2D_ARRAY:
110          img->array_pitch = rsc->layout.layer_size;
111          img->depth = layers;
112          break;
113       case PIPE_TEXTURE_CUBE:
114       case PIPE_TEXTURE_CUBE_ARRAY:
115          img->array_pitch = rsc->layout.layer_size;
116          img->depth = layers;
117          break;
118       case PIPE_TEXTURE_3D:
119          img->array_pitch = fd_resource_slice(rsc, lvl)->size0;
120          img->depth = u_minify(prsc->depth0, lvl);
121          if (layers == 1 && img->depth > 1) {
122             img->type = A4XX_TEX_2D;
123             img->depth = 1;
124          } else {
125             img->texconst4 = A4XX_TEX_CONST_4_LAYERSZ(img->array_pitch);
126          }
127          break;
128       default:
129          img->array_pitch = 0;
130          img->depth = 0;
131          break;
132       }
133    }
134 }
135 
emit_image_tex(struct fd_ringbuffer * ring,unsigned slot,struct fd4_image * img,enum pipe_shader_type shader)136 static void emit_image_tex(struct fd_ringbuffer *ring, unsigned slot,
137       struct fd4_image *img, enum pipe_shader_type shader)
138 {
139    OUT_PKT3(ring, CP_LOAD_STATE4, 2 + 8);
140    OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(slot) |
141       CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
142       CP_LOAD_STATE4_0_STATE_BLOCK(texsb[shader]) |
143       CP_LOAD_STATE4_0_NUM_UNIT(1));
144    OUT_RING(ring, CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS) |
145       CP_LOAD_STATE4_1_EXT_SRC_ADDR(0));
146 
147    OUT_RING(ring, A4XX_TEX_CONST_0_FMT(img->texfmt) |
148           A4XX_TEX_CONST_0_TYPE(img->type) |
149           fd4_tex_swiz(img->pfmt, PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
150                     PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W) |
151           COND(img->srgb, A4XX_TEX_CONST_0_SRGB));
152    OUT_RING(ring, A4XX_TEX_CONST_1_WIDTH(img->width) |
153       A4XX_TEX_CONST_1_HEIGHT(img->height));
154    OUT_RING(ring, A4XX_TEX_CONST_2_PITCHALIGN(img->pitchalign) |
155       A4XX_TEX_CONST_2_PITCH(img->pitch) |
156       COND(img->buffer, A4XX_TEX_CONST_2_BUFFER));
157    OUT_RING(ring, A4XX_TEX_CONST_3_DEPTH(img->depth) |
158           A4XX_TEX_CONST_3_LAYERSZ(img->array_pitch));
159    if (img->bo) {
160       OUT_RELOC(ring, img->bo, img->offset, img->texconst4, 0);
161    } else {
162       OUT_RING(ring, 0x00000000);
163    }
164    OUT_RING(ring, 0x00000000);
165    OUT_RING(ring, 0x00000000);
166    OUT_RING(ring, 0x00000000);
167 
168    /* Per fd4_emit.c, some of the hw likes samplers in pairs */
169    OUT_PKT3(ring, CP_LOAD_STATE4, 2 + 4);
170    OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(slot) |
171       CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
172       CP_LOAD_STATE4_0_STATE_BLOCK(texsb[shader]) |
173       CP_LOAD_STATE4_0_NUM_UNIT(2));
174    OUT_RING(ring, CP_LOAD_STATE4_1_STATE_TYPE(ST4_SHADER) |
175       CP_LOAD_STATE4_1_EXT_SRC_ADDR(0));
176    OUT_RING(ring, 0x00000000);
177    OUT_RING(ring, 0x00000000);
178    OUT_RING(ring, 0x00000000);
179    OUT_RING(ring, 0x00000000);
180 }
181 
emit_image_ssbo(struct fd_ringbuffer * ring,unsigned slot,struct fd4_image * img,enum pipe_shader_type shader)182 static void emit_image_ssbo(struct fd_ringbuffer *ring, unsigned slot,
183       struct fd4_image *img, enum pipe_shader_type shader)
184 {
185    OUT_PKT3(ring, CP_LOAD_STATE4, 2 + 4);
186    OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(slot) |
187       CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
188       CP_LOAD_STATE4_0_STATE_BLOCK(imgsb[shader]) |
189       CP_LOAD_STATE4_0_NUM_UNIT(1));
190    OUT_RING(ring, CP_LOAD_STATE4_1_STATE_TYPE(0) |
191       CP_LOAD_STATE4_1_EXT_SRC_ADDR(0));
192    OUT_RELOC(ring, img->bo, img->offset, 0, 0);
193    OUT_RING(ring, A4XX_SSBO_0_1_PITCH(img->pitch));
194    OUT_RING(ring, A4XX_SSBO_0_2_ARRAY_PITCH(img->array_pitch));
195    OUT_RING(ring, A4XX_SSBO_0_3_CPP(img->cpp));
196 
197    OUT_PKT3(ring, CP_LOAD_STATE4, 2 + 2);
198    OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(slot) |
199       CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
200       CP_LOAD_STATE4_0_STATE_BLOCK(imgsb[shader]) |
201       CP_LOAD_STATE4_0_NUM_UNIT(1));
202    OUT_RING(ring, CP_LOAD_STATE4_1_STATE_TYPE(1) |
203       CP_LOAD_STATE4_1_EXT_SRC_ADDR(0));
204    OUT_RING(ring, A4XX_SSBO_1_0_CPP(img->cpp) |
205       A4XX_SSBO_1_0_FMT(img->fmt) |
206       A4XX_SSBO_1_0_WIDTH(img->width));
207    OUT_RING(ring, A4XX_SSBO_1_1_HEIGHT(img->height) |
208       A4XX_SSBO_1_1_DEPTH(img->depth));
209 }
210 
211 /* Emit required "SSBO" and sampler state.  The sampler state is used by the
212  * hw for imageLoad(), and "SSBO" state for imageStore().  Returns max sampler
213  * used.
214  */
215 void
fd4_emit_images(struct fd_context * ctx,struct fd_ringbuffer * ring,enum pipe_shader_type shader,const struct ir3_shader_variant * v)216 fd4_emit_images(struct fd_context *ctx, struct fd_ringbuffer *ring,
217       enum pipe_shader_type shader,
218       const struct ir3_shader_variant *v)
219 {
220    struct fd_shaderimg_stateobj *so = &ctx->shaderimg[shader];
221    unsigned enabled_mask = so->enabled_mask;
222    const struct ir3_ibo_mapping *m = &v->image_mapping;
223 
224    while (enabled_mask) {
225       unsigned index = u_bit_scan(&enabled_mask);
226       struct fd4_image img;
227 
228       translate_image(&img, &so->si[index]);
229 
230       if (m->image_to_tex[index] != IBO_INVALID)
231          emit_image_tex(ring, m->image_to_tex[index] + m->tex_base, &img, shader);
232       emit_image_ssbo(ring, v->num_ssbos + index, &img, shader);
233    }
234 }
235