• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 Rob Clark <robclark@freedesktop.org>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Rob Clark <robclark@freedesktop.org>
25  */
26 
27 #include "pipe/p_state.h"
28 
29 #include "freedreno_resource.h"
30 #include "fd4_image.h"
31 #include "fd4_format.h"
32 #include "fd4_texture.h"
33 
34 static enum a4xx_state_block texsb[] = {
35    [PIPE_SHADER_COMPUTE] = SB4_CS_TEX,
36    [PIPE_SHADER_FRAGMENT] = SB4_FS_TEX,
37 };
38 
39 static enum a4xx_state_block imgsb[] = {
40    [PIPE_SHADER_COMPUTE] = SB4_CS_SSBO,
41    [PIPE_SHADER_FRAGMENT] = SB4_SSBO,
42 };
43 
44 struct fd4_image {
45    enum pipe_format pfmt;
46    enum a4xx_color_fmt fmt;
47    enum a4xx_tex_fmt texfmt;
48    enum a4xx_tex_type type;
49    bool srgb;
50    uint32_t cpp;
51    uint32_t width;
52    uint32_t height;
53    uint32_t depth;
54    uint32_t pitch;
55    uint32_t array_pitch;
56    uint32_t pitchalign;
57    struct fd_bo *bo;
58    uint32_t offset;
59    bool buffer;
60    uint32_t texconst4;
61 };
62 
translate_image(struct fd4_image * img,struct pipe_image_view * pimg)63 static void translate_image(struct fd4_image *img, struct pipe_image_view *pimg)
64 {
65    enum pipe_format format = pimg->format;
66    struct pipe_resource *prsc = pimg->resource;
67    struct fd_resource *rsc = fd_resource(prsc);
68 
69    if (!pimg->resource) {
70       memset(img, 0, sizeof(*img));
71       return;
72    }
73 
74    img->pfmt      = format;
75    img->fmt       = fd4_pipe2color(format);
76    img->texfmt    = fd4_pipe2tex(format);
77    img->type      = fd4_tex_type(prsc->target);
78    img->srgb      = util_format_is_srgb(format);
79    img->bo        = rsc->bo;
80    img->texconst4 = 0;
81 
82    /* Treat cube textures as 2d-array: */
83    if (img->type == A4XX_TEX_CUBE)
84       img->type = A4XX_TEX_2D;
85 
86    if (prsc->target == PIPE_BUFFER) {
87       img->buffer = true;
88       img->offset = pimg->u.buf.offset;
89       img->cpp = util_format_get_blocksize(format);
90       img->array_pitch = 0;
91       img->pitch = 0;
92       img->pitchalign = 0;
93 
94       /* size is encoded with low 16b in WIDTH and high bits in
95        * HEIGHT, in units of elements:
96        */
97       unsigned sz = pimg->u.buf.size / img->cpp;
98       img->width = sz & MASK(16);
99       img->height = sz >> 16;
100       img->depth = 0;
101 
102       /* Note that the blob sets the PITCH to the CPP in the SSBO descriptor,
103        * but that messes up the sampler we create, so skip that.
104        */
105    } else {
106       img->buffer = false;
107       img->cpp = rsc->layout.cpp;
108 
109       unsigned lvl = pimg->u.tex.level;
110       img->offset = fd_resource_offset(rsc, lvl, pimg->u.tex.first_layer);
111       img->pitch = fd_resource_pitch(rsc, lvl);
112       img->pitchalign = rsc->layout.pitchalign - 5;
113 
114       img->width = u_minify(prsc->width0, lvl);
115       img->height = u_minify(prsc->height0, lvl);
116 
117       unsigned layers = pimg->u.tex.last_layer - pimg->u.tex.first_layer + 1;
118 
119       switch (prsc->target) {
120       case PIPE_TEXTURE_RECT:
121       case PIPE_TEXTURE_1D:
122       case PIPE_TEXTURE_2D:
123          img->array_pitch = rsc->layout.layer_size;
124          img->depth = 1;
125          break;
126       case PIPE_TEXTURE_1D_ARRAY:
127       case PIPE_TEXTURE_2D_ARRAY:
128          img->array_pitch = rsc->layout.layer_size;
129          img->depth = layers;
130          break;
131       case PIPE_TEXTURE_CUBE:
132       case PIPE_TEXTURE_CUBE_ARRAY:
133          img->array_pitch = rsc->layout.layer_size;
134          img->depth = layers;
135          break;
136       case PIPE_TEXTURE_3D:
137          img->array_pitch = fd_resource_slice(rsc, lvl)->size0;
138          img->depth = u_minify(prsc->depth0, lvl);
139          if (layers == 1 && img->depth > 1) {
140             img->type = A4XX_TEX_2D;
141             img->depth = 1;
142          } else {
143             img->texconst4 = A4XX_TEX_CONST_4_LAYERSZ(img->array_pitch);
144          }
145          break;
146       default:
147          img->array_pitch = 0;
148          img->depth = 0;
149          break;
150       }
151    }
152 }
153 
emit_image_tex(struct fd_ringbuffer * ring,unsigned slot,struct fd4_image * img,enum pipe_shader_type shader)154 static void emit_image_tex(struct fd_ringbuffer *ring, unsigned slot,
155       struct fd4_image *img, enum pipe_shader_type shader)
156 {
157    OUT_PKT3(ring, CP_LOAD_STATE4, 2 + 8);
158    OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(slot) |
159       CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
160       CP_LOAD_STATE4_0_STATE_BLOCK(texsb[shader]) |
161       CP_LOAD_STATE4_0_NUM_UNIT(1));
162    OUT_RING(ring, CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS) |
163       CP_LOAD_STATE4_1_EXT_SRC_ADDR(0));
164 
165    OUT_RING(ring, A4XX_TEX_CONST_0_FMT(img->texfmt) |
166           A4XX_TEX_CONST_0_TYPE(img->type) |
167           fd4_tex_swiz(img->pfmt, PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
168                     PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W) |
169           COND(img->srgb, A4XX_TEX_CONST_0_SRGB));
170    OUT_RING(ring, A4XX_TEX_CONST_1_WIDTH(img->width) |
171       A4XX_TEX_CONST_1_HEIGHT(img->height));
172    OUT_RING(ring, A4XX_TEX_CONST_2_PITCHALIGN(img->pitchalign) |
173       A4XX_TEX_CONST_2_PITCH(img->pitch) |
174       COND(img->buffer, A4XX_TEX_CONST_2_BUFFER));
175    OUT_RING(ring, A4XX_TEX_CONST_3_DEPTH(img->depth) |
176           A4XX_TEX_CONST_3_LAYERSZ(img->array_pitch));
177    if (img->bo) {
178       OUT_RELOC(ring, img->bo, img->offset, img->texconst4, 0);
179    } else {
180       OUT_RING(ring, 0x00000000);
181    }
182    OUT_RING(ring, 0x00000000);
183    OUT_RING(ring, 0x00000000);
184    OUT_RING(ring, 0x00000000);
185 
186    /* Per fd4_emit.c, some of the hw likes samplers in pairs */
187    OUT_PKT3(ring, CP_LOAD_STATE4, 2 + 4);
188    OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(slot) |
189       CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
190       CP_LOAD_STATE4_0_STATE_BLOCK(texsb[shader]) |
191       CP_LOAD_STATE4_0_NUM_UNIT(2));
192    OUT_RING(ring, CP_LOAD_STATE4_1_STATE_TYPE(ST4_SHADER) |
193       CP_LOAD_STATE4_1_EXT_SRC_ADDR(0));
194    OUT_RING(ring, 0x00000000);
195    OUT_RING(ring, 0x00000000);
196    OUT_RING(ring, 0x00000000);
197    OUT_RING(ring, 0x00000000);
198 }
199 
emit_image_ssbo(struct fd_ringbuffer * ring,unsigned slot,struct fd4_image * img,enum pipe_shader_type shader)200 static void emit_image_ssbo(struct fd_ringbuffer *ring, unsigned slot,
201       struct fd4_image *img, enum pipe_shader_type shader)
202 {
203    OUT_PKT3(ring, CP_LOAD_STATE4, 2 + 4);
204    OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(slot) |
205       CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
206       CP_LOAD_STATE4_0_STATE_BLOCK(imgsb[shader]) |
207       CP_LOAD_STATE4_0_NUM_UNIT(1));
208    OUT_RING(ring, CP_LOAD_STATE4_1_STATE_TYPE(0) |
209       CP_LOAD_STATE4_1_EXT_SRC_ADDR(0));
210    OUT_RELOC(ring, img->bo, img->offset, 0, 0);
211    OUT_RING(ring, A4XX_SSBO_0_1_PITCH(img->pitch));
212    OUT_RING(ring, A4XX_SSBO_0_2_ARRAY_PITCH(img->array_pitch));
213    OUT_RING(ring, A4XX_SSBO_0_3_CPP(img->cpp));
214 
215    OUT_PKT3(ring, CP_LOAD_STATE4, 2 + 2);
216    OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(slot) |
217       CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
218       CP_LOAD_STATE4_0_STATE_BLOCK(imgsb[shader]) |
219       CP_LOAD_STATE4_0_NUM_UNIT(1));
220    OUT_RING(ring, CP_LOAD_STATE4_1_STATE_TYPE(1) |
221       CP_LOAD_STATE4_1_EXT_SRC_ADDR(0));
222    OUT_RING(ring, A4XX_SSBO_1_0_CPP(img->cpp) |
223       A4XX_SSBO_1_0_FMT(img->fmt) |
224       A4XX_SSBO_1_0_WIDTH(img->width));
225    OUT_RING(ring, A4XX_SSBO_1_1_HEIGHT(img->height) |
226       A4XX_SSBO_1_1_DEPTH(img->depth));
227 }
228 
229 /* Emit required "SSBO" and sampler state.  The sampler state is used by the
230  * hw for imageLoad(), and "SSBO" state for imageStore().  Returns max sampler
231  * used.
232  */
233 void
fd4_emit_images(struct fd_context * ctx,struct fd_ringbuffer * ring,enum pipe_shader_type shader,const struct ir3_shader_variant * v)234 fd4_emit_images(struct fd_context *ctx, struct fd_ringbuffer *ring,
235       enum pipe_shader_type shader,
236       const struct ir3_shader_variant *v)
237 {
238    struct fd_shaderimg_stateobj *so = &ctx->shaderimg[shader];
239    unsigned enabled_mask = so->enabled_mask;
240    const struct ir3_ibo_mapping *m = &v->image_mapping;
241 
242    while (enabled_mask) {
243       unsigned index = u_bit_scan(&enabled_mask);
244       struct fd4_image img;
245 
246       translate_image(&img, &so->si[index]);
247 
248       if (m->image_to_tex[index] != IBO_INVALID)
249          emit_image_tex(ring, m->image_to_tex[index] + m->tex_base, &img, shader);
250       emit_image_ssbo(ring, v->num_ssbos + index, &img, shader);
251    }
252 }
253