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