xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/freedreno/a5xx/fd5_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 "fd5_format.h"
12 #include "fd5_image.h"
13 #include "fd5_texture.h"
14 #include "freedreno_resource.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 fd5_image {
27    enum pipe_format pfmt;
28    enum a5xx_tex_fmt fmt;
29    enum a5xx_tex_type type;
30    bool srgb;
31    uint32_t cpp;
32    uint32_t width;
33    uint32_t height;
34    uint32_t depth;
35    uint32_t pitch;
36    uint32_t array_pitch;
37    struct fd_bo *bo;
38    uint32_t offset;
39    bool buffer;
40 };
41 
42 static void
translate_image(struct fd5_image * img,struct pipe_image_view * pimg)43 translate_image(struct fd5_image *img, struct pipe_image_view *pimg)
44 {
45    enum pipe_format format = pimg->format;
46    struct pipe_resource *prsc = pimg->resource;
47    struct fd_resource *rsc = fd_resource(prsc);
48 
49    if (!pimg->resource) {
50       memset(img, 0, sizeof(*img));
51       return;
52    }
53 
54    img->pfmt = format;
55    img->fmt = fd5_pipe2tex(format);
56    img->type = fd5_tex_type(prsc->target);
57    img->srgb = util_format_is_srgb(format);
58    img->cpp = rsc->layout.cpp;
59    img->bo = rsc->bo;
60 
61    /* Treat cube textures as 2d-array: */
62    if (img->type == A5XX_TEX_CUBE)
63       img->type = A5XX_TEX_2D;
64 
65    if (prsc->target == PIPE_BUFFER) {
66       img->buffer = true;
67       img->offset = pimg->u.buf.offset;
68       img->pitch = 0;
69       img->array_pitch = 0;
70 
71       /* size is encoded with low 15b in WIDTH and high bits in
72        * HEIGHT, in units of elements:
73        */
74       unsigned sz = pimg->u.buf.size / util_format_get_blocksize(format);
75       img->width = sz & MASK(15);
76       img->height = sz >> 15;
77       img->depth = 0;
78    } else {
79       img->buffer = false;
80 
81       unsigned lvl = pimg->u.tex.level;
82       img->offset = fd_resource_offset(rsc, lvl, pimg->u.tex.first_layer);
83       img->pitch = fd_resource_pitch(rsc, lvl);
84 
85       img->width = u_minify(prsc->width0, lvl);
86       img->height = u_minify(prsc->height0, lvl);
87 
88       unsigned layers = pimg->u.tex.last_layer - pimg->u.tex.first_layer + 1;
89 
90       switch (prsc->target) {
91       case PIPE_TEXTURE_RECT:
92       case PIPE_TEXTURE_1D:
93       case PIPE_TEXTURE_2D:
94          img->array_pitch = rsc->layout.layer_size;
95          img->depth = 1;
96          break;
97       case PIPE_TEXTURE_1D_ARRAY:
98       case PIPE_TEXTURE_2D_ARRAY:
99          img->array_pitch = rsc->layout.layer_size;
100          img->depth = layers;
101          break;
102       case PIPE_TEXTURE_CUBE:
103       case PIPE_TEXTURE_CUBE_ARRAY:
104          img->array_pitch = rsc->layout.layer_size;
105          img->depth = layers;
106          break;
107       case PIPE_TEXTURE_3D:
108          img->array_pitch = fd_resource_slice(rsc, lvl)->size0;
109          img->depth = u_minify(prsc->depth0, lvl);
110          break;
111       default:
112          img->array_pitch = 0;
113          img->depth = 0;
114          break;
115       }
116    }
117 }
118 
119 static void
emit_image_tex(struct fd_ringbuffer * ring,unsigned slot,struct fd5_image * img,enum pipe_shader_type shader)120 emit_image_tex(struct fd_ringbuffer *ring, unsigned slot, struct fd5_image *img,
121                enum pipe_shader_type shader)
122 {
123    OUT_PKT7(ring, CP_LOAD_STATE4, 3 + 12);
124    OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(slot) |
125                      CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
126                      CP_LOAD_STATE4_0_STATE_BLOCK(texsb[shader]) |
127                      CP_LOAD_STATE4_0_NUM_UNIT(1));
128    OUT_RING(ring, CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS) |
129                      CP_LOAD_STATE4_1_EXT_SRC_ADDR(0));
130    OUT_RING(ring, CP_LOAD_STATE4_2_EXT_SRC_ADDR_HI(0));
131 
132    OUT_RING(ring, A5XX_TEX_CONST_0_FMT(img->fmt) |
133                      fd5_tex_swiz(img->pfmt, PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
134                                   PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W) |
135                      COND(img->srgb, A5XX_TEX_CONST_0_SRGB));
136    OUT_RING(ring, A5XX_TEX_CONST_1_WIDTH(img->width) |
137                      A5XX_TEX_CONST_1_HEIGHT(img->height));
138    OUT_RING(ring,
139             COND(img->buffer, A5XX_TEX_CONST_2_BUFFER) |
140                A5XX_TEX_CONST_2_TYPE(img->type) |
141                A5XX_TEX_CONST_2_PITCH(img->pitch));
142    OUT_RING(ring, A5XX_TEX_CONST_3_ARRAY_PITCH(img->array_pitch));
143    if (img->bo) {
144       OUT_RELOC(ring, img->bo, img->offset,
145                 (uint64_t)A5XX_TEX_CONST_5_DEPTH(img->depth) << 32, 0);
146    } else {
147       OUT_RING(ring, 0x00000000);
148       OUT_RING(ring, A5XX_TEX_CONST_5_DEPTH(img->depth));
149    }
150    OUT_RING(ring, 0x00000000);
151    OUT_RING(ring, 0x00000000);
152    OUT_RING(ring, 0x00000000);
153    OUT_RING(ring, 0x00000000);
154    OUT_RING(ring, 0x00000000);
155    OUT_RING(ring, 0x00000000);
156 }
157 
158 static void
emit_image_ssbo(struct fd_ringbuffer * ring,unsigned slot,struct fd5_image * img,enum pipe_shader_type shader)159 emit_image_ssbo(struct fd_ringbuffer *ring, unsigned slot,
160                 struct fd5_image *img, enum pipe_shader_type shader)
161 {
162    OUT_PKT7(ring, CP_LOAD_STATE4, 3 + 2);
163    OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(slot) |
164                      CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
165                      CP_LOAD_STATE4_0_STATE_BLOCK(imgsb[shader]) |
166                      CP_LOAD_STATE4_0_NUM_UNIT(1));
167    OUT_RING(ring, CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS) |
168                      CP_LOAD_STATE4_1_EXT_SRC_ADDR(0));
169    OUT_RING(ring, CP_LOAD_STATE4_2_EXT_SRC_ADDR_HI(0));
170    OUT_RING(ring,
171             A5XX_SSBO_1_0_FMT(img->fmt) | A5XX_SSBO_1_0_WIDTH(img->width));
172    OUT_RING(ring, A5XX_SSBO_1_1_HEIGHT(img->height) |
173                      A5XX_SSBO_1_1_DEPTH(img->depth));
174 
175    OUT_PKT7(ring, CP_LOAD_STATE4, 3 + 2);
176    OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(slot) |
177                      CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
178                      CP_LOAD_STATE4_0_STATE_BLOCK(imgsb[shader]) |
179                      CP_LOAD_STATE4_0_NUM_UNIT(1));
180    OUT_RING(ring, CP_LOAD_STATE4_1_STATE_TYPE(ST4_UBO) |
181                      CP_LOAD_STATE4_1_EXT_SRC_ADDR(0));
182    OUT_RING(ring, CP_LOAD_STATE4_2_EXT_SRC_ADDR_HI(0));
183    if (img->bo) {
184       OUT_RELOC(ring, img->bo, img->offset, 0, 0);
185    } else {
186       OUT_RING(ring, 0x00000000);
187       OUT_RING(ring, 0x00000000);
188    }
189 }
190 
191 /* Emit required "SSBO" and sampler state.  The sampler state is used by the
192  * hw for imageLoad(), and "SSBO" state for imageStore().  Returns max sampler
193  * used.
194  */
195 void
fd5_emit_images(struct fd_context * ctx,struct fd_ringbuffer * ring,enum pipe_shader_type shader,const struct ir3_shader_variant * v)196 fd5_emit_images(struct fd_context *ctx, struct fd_ringbuffer *ring,
197                 enum pipe_shader_type shader,
198                 const struct ir3_shader_variant *v)
199 {
200    struct fd_shaderimg_stateobj *so = &ctx->shaderimg[shader];
201    unsigned enabled_mask = so->enabled_mask;
202    const struct ir3_ibo_mapping *m = &v->image_mapping;
203 
204    while (enabled_mask) {
205       unsigned index = u_bit_scan(&enabled_mask);
206       struct fd5_image img;
207 
208       translate_image(&img, &so->si[index]);
209 
210       if (m->image_to_tex[index] != IBO_INVALID)
211          emit_image_tex(ring, m->image_to_tex[index] + m->tex_base, &img, shader);
212       emit_image_ssbo(ring, v->num_ssbos + index, &img,
213                       shader);
214    }
215 }
216