9c1182777c02d59408401483de073426f8868beb
[mesa.git] / src / gallium / drivers / freedreno / a6xx / fd6_image.c
1 /*
2 * Copyright (C) 2017 Rob Clark <robclark@freedesktop.org>
3 * Copyright © 2018 Google, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Authors:
25 * Rob Clark <robclark@freedesktop.org>
26 */
27
28 #include "pipe/p_state.h"
29
30 #include "freedreno_resource.h"
31 #include "fd6_image.h"
32 #include "fd6_format.h"
33 #include "fd6_texture.h"
34
35 struct fd6_image {
36 struct pipe_resource *prsc;
37 enum pipe_format pfmt;
38 enum a6xx_tex_fmt fmt;
39 enum a6xx_tex_fetchsize fetchsize;
40 enum a6xx_tex_type type;
41 bool srgb;
42 uint32_t cpp;
43 uint32_t level;
44 uint32_t width;
45 uint32_t height;
46 uint32_t depth;
47 uint32_t pitch;
48 uint32_t array_pitch;
49 struct fd_bo *bo;
50 uint32_t offset;
51 bool buffer;
52 };
53
54 static void translate_image(struct fd6_image *img, const struct pipe_image_view *pimg)
55 {
56 enum pipe_format format = pimg->format;
57 struct pipe_resource *prsc = pimg->resource;
58 struct fd_resource *rsc = fd_resource(prsc);
59
60 if (!prsc) {
61 memset(img, 0, sizeof(*img));
62 return;
63 }
64
65 img->prsc = prsc;
66 img->pfmt = format;
67 img->fmt = fd6_pipe2tex(format);
68 img->fetchsize = fd6_pipe2fetchsize(format);
69 img->type = fd6_tex_type(prsc->target);
70 img->srgb = util_format_is_srgb(format);
71 img->cpp = rsc->cpp;
72 img->bo = rsc->bo;
73
74 /* Treat cube textures as 2d-array: */
75 if (img->type == A6XX_TEX_CUBE)
76 img->type = A6XX_TEX_2D;
77
78 if (prsc->target == PIPE_BUFFER) {
79 img->buffer = true;
80 img->offset = pimg->u.buf.offset;
81 img->pitch = 0;
82 img->array_pitch = 0;
83
84 /* size is encoded with low 15b in WIDTH and high bits in
85 * HEIGHT, in units of elements:
86 */
87 unsigned sz = prsc->width0;
88 img->width = sz & MASK(15);
89 img->height = sz >> 15;
90 img->depth = 0;
91 } else {
92 img->buffer = false;
93
94 unsigned lvl = pimg->u.tex.level;
95 unsigned layers = pimg->u.tex.last_layer - pimg->u.tex.first_layer + 1;
96
97 img->offset = fd_resource_offset(rsc, lvl, pimg->u.tex.first_layer);
98 img->pitch = rsc->slices[lvl].pitch * rsc->cpp;
99
100 switch (prsc->target) {
101 case PIPE_TEXTURE_RECT:
102 case PIPE_TEXTURE_1D:
103 case PIPE_TEXTURE_2D:
104 img->array_pitch = rsc->layer_size;
105 img->depth = 1;
106 break;
107 case PIPE_TEXTURE_1D_ARRAY:
108 case PIPE_TEXTURE_2D_ARRAY:
109 case PIPE_TEXTURE_CUBE:
110 case PIPE_TEXTURE_CUBE_ARRAY:
111 img->array_pitch = rsc->layer_size;
112 // TODO the CUBE/CUBE_ARRAY might need to be layers/6 for tex state,
113 // but empirically for ibo state it shouldn't be divided.
114 img->depth = layers;
115 break;
116 case PIPE_TEXTURE_3D:
117 img->array_pitch = rsc->slices[lvl].size0;
118 img->depth = u_minify(prsc->depth0, lvl);
119 break;
120 default:
121 break;
122 }
123
124 img->level = lvl;
125 img->width = u_minify(prsc->width0, lvl);
126 img->height = u_minify(prsc->height0, lvl);
127 }
128 }
129
130 static void translate_buf(struct fd6_image *img, const struct pipe_shader_buffer *pimg)
131 {
132 enum pipe_format format = PIPE_FORMAT_R32_UINT;
133 struct pipe_resource *prsc = pimg->buffer;
134 struct fd_resource *rsc = fd_resource(prsc);
135
136 if (!prsc) {
137 memset(img, 0, sizeof(*img));
138 return;
139 }
140
141 img->prsc = prsc;
142 img->pfmt = format;
143 img->fmt = fd6_pipe2tex(format);
144 img->fetchsize = fd6_pipe2fetchsize(format);
145 img->type = fd6_tex_type(prsc->target);
146 img->srgb = util_format_is_srgb(format);
147 img->cpp = rsc->cpp;
148 img->bo = rsc->bo;
149 img->buffer = true;
150
151 img->offset = pimg->buffer_offset;
152 img->pitch = 0;
153 img->array_pitch = 0;
154
155 /* size is encoded with low 15b in WIDTH and high bits in HEIGHT,
156 * in units of elements:
157 */
158 unsigned sz = pimg->buffer_size / 4;
159 img->width = sz & MASK(15);
160 img->height = sz >> 15;
161 img->depth = 0;
162 }
163
164 static void emit_image_tex(struct fd_ringbuffer *ring, struct fd6_image *img)
165 {
166 OUT_RING(ring, fd6_tex_const_0(img->prsc, img->level, img->pfmt,
167 PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
168 PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W));
169 OUT_RING(ring, A6XX_TEX_CONST_1_WIDTH(img->width) |
170 A6XX_TEX_CONST_1_HEIGHT(img->height));
171 OUT_RING(ring, A6XX_TEX_CONST_2_FETCHSIZE(img->fetchsize) |
172 COND(img->buffer, A6XX_TEX_CONST_2_UNK4 | A6XX_TEX_CONST_2_UNK31) |
173 A6XX_TEX_CONST_2_TYPE(img->type) |
174 A6XX_TEX_CONST_2_PITCH(img->pitch));
175 OUT_RING(ring, A6XX_TEX_CONST_3_ARRAY_PITCH(img->array_pitch));
176 if (img->bo) {
177 OUT_RELOC(ring, img->bo, img->offset,
178 (uint64_t)A6XX_TEX_CONST_5_DEPTH(img->depth) << 32, 0);
179 } else {
180 OUT_RING(ring, 0x00000000);
181 OUT_RING(ring, A6XX_TEX_CONST_5_DEPTH(img->depth));
182 }
183 OUT_RING(ring, 0x00000000);
184 OUT_RING(ring, 0x00000000);
185 OUT_RING(ring, 0x00000000);
186 OUT_RING(ring, 0x00000000);
187 OUT_RING(ring, 0x00000000);
188 OUT_RING(ring, 0x00000000);
189 OUT_RING(ring, 0x00000000);
190 OUT_RING(ring, 0x00000000);
191 OUT_RING(ring, 0x00000000);
192 OUT_RING(ring, 0x00000000);
193 }
194
195 void
196 fd6_emit_image_tex(struct fd_ringbuffer *ring, const struct pipe_image_view *pimg)
197 {
198 struct fd6_image img;
199 translate_image(&img, pimg);
200 emit_image_tex(ring, &img);
201 }
202
203 void
204 fd6_emit_ssbo_tex(struct fd_ringbuffer *ring, const struct pipe_shader_buffer *pbuf)
205 {
206 struct fd6_image img;
207 translate_buf(&img, pbuf);
208 emit_image_tex(ring, &img);
209 }
210
211 static void emit_image_ssbo(struct fd_ringbuffer *ring, struct fd6_image *img)
212 {
213 struct fd_resource *rsc = fd_resource(img->prsc);
214 enum a6xx_tile_mode tile_mode = TILE6_LINEAR;
215
216 if (rsc->tile_mode && !fd_resource_level_linear(img->prsc, img->level)) {
217 tile_mode = rsc->tile_mode;
218 }
219
220 OUT_RING(ring, A6XX_IBO_0_FMT(img->fmt) |
221 A6XX_IBO_0_TILE_MODE(tile_mode));
222 OUT_RING(ring, A6XX_IBO_1_WIDTH(img->width) |
223 A6XX_IBO_1_HEIGHT(img->height));
224 OUT_RING(ring, A6XX_IBO_2_PITCH(img->pitch) |
225 COND(img->buffer, A6XX_IBO_2_UNK4 | A6XX_IBO_2_UNK31) |
226 A6XX_IBO_2_TYPE(img->type));
227 OUT_RING(ring, A6XX_IBO_3_ARRAY_PITCH(img->array_pitch));
228 if (img->bo) {
229 OUT_RELOCW(ring, img->bo, img->offset,
230 (uint64_t)A6XX_IBO_5_DEPTH(img->depth) << 32, 0);
231 } else {
232 OUT_RING(ring, 0x00000000);
233 OUT_RING(ring, A6XX_IBO_5_DEPTH(img->depth));
234 }
235 OUT_RING(ring, 0x00000000);
236 OUT_RING(ring, 0x00000000);
237 OUT_RING(ring, 0x00000000);
238 OUT_RING(ring, 0x00000000);
239 OUT_RING(ring, 0x00000000);
240 OUT_RING(ring, 0x00000000);
241 OUT_RING(ring, 0x00000000);
242 OUT_RING(ring, 0x00000000);
243 OUT_RING(ring, 0x00000000);
244 OUT_RING(ring, 0x00000000);
245 }
246
247 /* Build combined image/SSBO "IBO" state, returns ownership of state reference */
248 struct fd_ringbuffer *
249 fd6_build_ibo_state(struct fd_context *ctx, const struct ir3_shader_variant *v,
250 enum pipe_shader_type shader)
251 {
252 struct fd_shaderbuf_stateobj *bufso = &ctx->shaderbuf[shader];
253 struct fd_shaderimg_stateobj *imgso = &ctx->shaderimg[shader];
254 const struct ir3_ibo_mapping *mapping = &v->image_mapping;
255
256 struct fd_ringbuffer *state =
257 fd_submit_new_ringbuffer(ctx->batch->submit,
258 mapping->num_ibo * 16 * 4, FD_RINGBUFFER_STREAMING);
259
260 assert(shader == PIPE_SHADER_COMPUTE || shader == PIPE_SHADER_FRAGMENT);
261
262 for (unsigned i = 0; i < mapping->num_ibo; i++) {
263 struct fd6_image img;
264 unsigned idx = mapping->ibo_to_image[i];
265
266 if (idx & IBO_SSBO) {
267 translate_buf(&img, &bufso->sb[idx & ~IBO_SSBO]);
268 } else {
269 translate_image(&img, &imgso->si[idx]);
270 }
271
272 emit_image_ssbo(state, &img);
273 }
274
275 return state;
276 }