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