freedreno/a6xx: image/ssbo state emit
[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 width;
44 uint32_t height;
45 uint32_t depth;
46 uint32_t pitch;
47 uint32_t array_pitch;
48 struct fd_bo *bo;
49 uint32_t offset;
50 bool buffer;
51 };
52
53 static void translate_image(struct fd6_image *img, const struct pipe_image_view *pimg)
54 {
55 enum pipe_format format = pimg->format;
56 struct pipe_resource *prsc = pimg->resource;
57 struct fd_resource *rsc = fd_resource(prsc);
58
59 if (!prsc) {
60 memset(img, 0, sizeof(*img));
61 return;
62 }
63
64 img->prsc = prsc;
65 img->pfmt = format;
66 img->fmt = fd6_pipe2tex(format);
67 img->fetchsize = fd6_pipe2fetchsize(format);
68 img->type = fd6_tex_type(prsc->target);
69 img->srgb = util_format_is_srgb(format);
70 img->cpp = rsc->cpp;
71 img->bo = rsc->bo;
72
73 if (prsc->target == PIPE_BUFFER) {
74 img->buffer = true;
75 img->offset = pimg->u.buf.offset;
76 img->pitch = 0;
77 img->array_pitch = 0;
78
79 /* size is encoded with low 15b in WIDTH and high bits in
80 * HEIGHT, in units of elements:
81 */
82 unsigned sz = prsc->width0;
83 img->width = sz & MASK(15);
84 img->height = sz >> 15;
85 img->depth = 0;
86 } else {
87 img->buffer = false;
88 unsigned lvl = pimg->u.tex.level;
89 img->offset = rsc->slices[lvl].offset;
90 img->pitch = rsc->slices[lvl].pitch * rsc->cpp;
91 img->array_pitch = rsc->layer_size;
92
93 img->width = u_minify(prsc->width0, lvl);
94 img->height = u_minify(prsc->height0, lvl);
95 img->depth = u_minify(prsc->depth0, lvl);
96 }
97 }
98
99 static void translate_buf(struct fd6_image *img, const struct pipe_shader_buffer *pimg)
100 {
101 enum pipe_format format = PIPE_FORMAT_R32_UINT;
102 struct pipe_resource *prsc = pimg->buffer;
103 struct fd_resource *rsc = fd_resource(prsc);
104
105 if (!prsc) {
106 memset(img, 0, sizeof(*img));
107 return;
108 }
109
110 img->prsc = prsc;
111 img->pfmt = format;
112 img->fmt = fd6_pipe2tex(format);
113 img->fetchsize = fd6_pipe2fetchsize(format);
114 img->type = fd6_tex_type(prsc->target);
115 img->srgb = util_format_is_srgb(format);
116 img->cpp = rsc->cpp;
117 img->bo = rsc->bo;
118 img->buffer = true;
119
120 img->offset = pimg->buffer_offset;
121 img->pitch = 0;
122 img->array_pitch = 0;
123
124 /* size is encoded with low 15b in WIDTH and high bits in HEIGHT,
125 * in units of elements:
126 */
127 unsigned sz = pimg->buffer_size / 4;
128 img->width = sz & MASK(15);
129 img->height = sz >> 15;
130 img->depth = 0;
131 }
132
133 static void emit_image_tex(struct fd_ringbuffer *ring, struct fd6_image *img)
134 {
135 OUT_RING(ring, A6XX_TEX_CONST_0_FMT(img->fmt) |
136 A6XX_TEX_CONST_0_TILE_MODE(fd_resource(img->prsc)->tile_mode) |
137 fd6_tex_swiz(img->prsc, img->fmt, PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
138 PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W) |
139 COND(img->srgb, A6XX_TEX_CONST_0_SRGB));
140 OUT_RING(ring, A6XX_TEX_CONST_1_WIDTH(img->width) |
141 A6XX_TEX_CONST_1_HEIGHT(img->height));
142 OUT_RING(ring, A6XX_TEX_CONST_2_FETCHSIZE(img->fetchsize) |
143 COND(img->buffer, A6XX_TEX_CONST_2_UNK4 | A6XX_TEX_CONST_2_UNK31) |
144 A6XX_TEX_CONST_2_TYPE(img->type) |
145 A6XX_TEX_CONST_2_PITCH(img->pitch));
146 OUT_RING(ring, A6XX_TEX_CONST_3_ARRAY_PITCH(img->array_pitch));
147 if (img->bo) {
148 OUT_RELOC(ring, img->bo, img->offset,
149 (uint64_t)A6XX_TEX_CONST_5_DEPTH(img->depth) << 32, 0);
150 } else {
151 OUT_RING(ring, 0x00000000);
152 OUT_RING(ring, A6XX_TEX_CONST_5_DEPTH(img->depth));
153 }
154 OUT_RING(ring, 0x00000000);
155 OUT_RING(ring, 0x00000000);
156 OUT_RING(ring, 0x00000000);
157 OUT_RING(ring, 0x00000000);
158 OUT_RING(ring, 0x00000000);
159 OUT_RING(ring, 0x00000000);
160 OUT_RING(ring, 0x00000000);
161 OUT_RING(ring, 0x00000000);
162 OUT_RING(ring, 0x00000000);
163 OUT_RING(ring, 0x00000000);
164 }
165
166 void
167 fd6_emit_image_tex(struct fd_ringbuffer *ring, const struct pipe_image_view *pimg)
168 {
169 struct fd6_image img;
170 translate_image(&img, pimg);
171 emit_image_tex(ring, &img);
172 }
173
174 void
175 fd6_emit_ssbo_tex(struct fd_ringbuffer *ring, const struct pipe_shader_buffer *pbuf)
176 {
177 struct fd6_image img;
178 translate_buf(&img, pbuf);
179 emit_image_tex(ring, &img);
180 }
181
182 static void emit_image_ssbo(struct fd_ringbuffer *ring, struct fd6_image *img)
183 {
184 debug_assert(fd_resource(img->prsc)->tile_mode == 0);
185
186 OUT_RING(ring, A6XX_IBO_0_FMT(img->fmt));
187 OUT_RING(ring, A6XX_IBO_1_WIDTH(img->width) |
188 A6XX_IBO_1_HEIGHT(img->height));
189 OUT_RING(ring, A6XX_IBO_2_PITCH(img->pitch) |
190 COND(img->buffer, A6XX_IBO_2_UNK4 | A6XX_IBO_2_UNK31) |
191 A6XX_IBO_2_TYPE(img->type));
192 OUT_RING(ring, A6XX_IBO_3_ARRAY_PITCH(img->array_pitch));
193 if (img->bo) {
194 OUT_RELOCW(ring, img->bo, img->offset,
195 (uint64_t)A6XX_IBO_5_DEPTH(img->depth) << 32, 0);
196 } else {
197 OUT_RING(ring, 0x00000000);
198 OUT_RING(ring, A6XX_IBO_5_DEPTH(img->depth));
199 }
200 OUT_RING(ring, 0x00000000);
201 OUT_RING(ring, 0x00000000);
202 OUT_RING(ring, 0x00000000);
203 OUT_RING(ring, 0x00000000);
204 OUT_RING(ring, 0x00000000);
205 OUT_RING(ring, 0x00000000);
206 OUT_RING(ring, 0x00000000);
207 OUT_RING(ring, 0x00000000);
208 OUT_RING(ring, 0x00000000);
209 OUT_RING(ring, 0x00000000);
210 }
211
212 /* Build combined image/SSBO "IBO" state, returns ownership of state reference */
213 struct fd_ringbuffer *
214 fd6_build_ibo_state(struct fd_context *ctx, const struct ir3_shader_variant *v,
215 enum pipe_shader_type shader)
216 {
217 struct fd_shaderbuf_stateobj *bufso = &ctx->shaderbuf[shader];
218 struct fd_shaderimg_stateobj *imgso = &ctx->shaderimg[shader];
219 const struct ir3_ibo_mapping *mapping = &v->image_mapping;
220
221 struct fd_ringbuffer *state =
222 fd_submit_new_ringbuffer(ctx->batch->submit,
223 mapping->num_ibo * 16 * 4, FD_RINGBUFFER_STREAMING);
224
225 assert(shader == PIPE_SHADER_COMPUTE || shader == PIPE_SHADER_FRAGMENT);
226
227 for (unsigned i = 0; i < mapping->num_ibo; i++) {
228 struct fd6_image img;
229 unsigned idx = mapping->ibo_to_image[i];
230
231 if (idx & IBO_SSBO) {
232 translate_buf(&img, &bufso->sb[idx & ~IBO_SSBO]);
233 } else {
234 translate_image(&img, &imgso->si[idx]);
235 }
236
237 emit_image_ssbo(state, &img);
238 }
239
240 return state;
241 }