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 34static enum a4xx_state_block texsb[] = { 35 [PIPE_SHADER_COMPUTE] = SB4_CS_TEX, 36 [PIPE_SHADER_FRAGMENT] = SB4_FS_TEX, 37}; 38 39static enum a4xx_state_block imgsb[] = { 40 [PIPE_SHADER_COMPUTE] = SB4_CS_SSBO, 41 [PIPE_SHADER_FRAGMENT] = SB4_SSBO, 42}; 43 44struct 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 63static 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 154static 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 200static 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 */ 233void 234fd4_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