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 35struct 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 ubwc_offset; 51 uint32_t offset; 52 bool buffer; 53}; 54 55static void translate_image(struct fd6_image *img, const struct pipe_image_view *pimg) 56{ 57 enum pipe_format format = pimg->format; 58 struct pipe_resource *prsc = pimg->resource; 59 struct fd_resource *rsc = fd_resource(prsc); 60 61 if (!prsc) { 62 memset(img, 0, sizeof(*img)); 63 return; 64 } 65 66 img->prsc = prsc; 67 img->pfmt = format; 68 img->fmt = fd6_pipe2tex(format); 69 img->fetchsize = fd6_pipe2fetchsize(format); 70 img->type = fd6_tex_type(prsc->target); 71 img->srgb = util_format_is_srgb(format); 72 img->cpp = rsc->cpp; 73 img->bo = rsc->bo; 74 75 /* Treat cube textures as 2d-array: */ 76 if (img->type == A6XX_TEX_CUBE) 77 img->type = A6XX_TEX_2D; 78 79 if (prsc->target == PIPE_BUFFER) { 80 img->buffer = true; 81 img->ubwc_offset = 0; /* not valid for buffers */ 82 img->offset = pimg->u.buf.offset; 83 img->pitch = 0; 84 img->array_pitch = 0; 85 86 /* size is encoded with low 15b in WIDTH and high bits in 87 * HEIGHT, in units of elements: 88 */ 89 unsigned sz = prsc->width0; 90 img->width = sz & MASK(15); 91 img->height = sz >> 15; 92 img->depth = 0; 93 } else { 94 img->buffer = false; 95 96 unsigned lvl = pimg->u.tex.level; 97 unsigned layers = pimg->u.tex.last_layer - pimg->u.tex.first_layer + 1; 98 99 img->ubwc_offset = fd_resource_ubwc_offset(rsc, lvl, pimg->u.tex.first_layer); 100 img->offset = fd_resource_offset(rsc, lvl, pimg->u.tex.first_layer); 101 img->pitch = rsc->slices[lvl].pitch * rsc->cpp; 102 103 switch (prsc->target) { 104 case PIPE_TEXTURE_RECT: 105 case PIPE_TEXTURE_1D: 106 case PIPE_TEXTURE_2D: 107 img->array_pitch = rsc->layer_size; 108 img->depth = 1; 109 break; 110 case PIPE_TEXTURE_1D_ARRAY: 111 case PIPE_TEXTURE_2D_ARRAY: 112 case PIPE_TEXTURE_CUBE: 113 case PIPE_TEXTURE_CUBE_ARRAY: 114 img->array_pitch = rsc->layer_size; 115 // TODO the CUBE/CUBE_ARRAY might need to be layers/6 for tex state, 116 // but empirically for ibo state it shouldn't be divided. 117 img->depth = layers; 118 break; 119 case PIPE_TEXTURE_3D: 120 img->array_pitch = rsc->slices[lvl].size0; 121 img->depth = u_minify(prsc->depth0, lvl); 122 break; 123 default: 124 break; 125 } 126 127 img->level = lvl; 128 img->width = u_minify(prsc->width0, lvl); 129 img->height = u_minify(prsc->height0, lvl); 130 } 131} 132 133static void translate_buf(struct fd6_image *img, const struct pipe_shader_buffer *pimg) 134{ 135 enum pipe_format format = PIPE_FORMAT_R32_UINT; 136 struct pipe_resource *prsc = pimg->buffer; 137 struct fd_resource *rsc = fd_resource(prsc); 138 139 if (!prsc) { 140 memset(img, 0, sizeof(*img)); 141 return; 142 } 143 144 img->prsc = prsc; 145 img->pfmt = format; 146 img->fmt = fd6_pipe2tex(format); 147 img->fetchsize = fd6_pipe2fetchsize(format); 148 img->type = fd6_tex_type(prsc->target); 149 img->srgb = util_format_is_srgb(format); 150 img->cpp = rsc->cpp; 151 img->bo = rsc->bo; 152 img->buffer = true; 153 154 img->ubwc_offset = 0; /* not valid for buffers */ 155 img->offset = pimg->buffer_offset; 156 img->pitch = 0; 157 img->array_pitch = 0; 158 159 /* size is encoded with low 15b in WIDTH and high bits in HEIGHT, 160 * in units of elements: 161 */ 162 unsigned sz = pimg->buffer_size / 4; 163 img->width = sz & MASK(15); 164 img->height = sz >> 15; 165 img->depth = 0; 166} 167 168static void emit_image_tex(struct fd_ringbuffer *ring, struct fd6_image *img) 169{ 170 struct fd_resource *rsc = fd_resource(img->prsc); 171 bool ubwc_enabled = fd_resource_ubwc_enabled(rsc, img->level); 172 173 OUT_RING(ring, fd6_tex_const_0(img->prsc, img->level, img->pfmt, 174 PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, 175 PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W)); 176 OUT_RING(ring, A6XX_TEX_CONST_1_WIDTH(img->width) | 177 A6XX_TEX_CONST_1_HEIGHT(img->height)); 178 OUT_RING(ring, A6XX_TEX_CONST_2_FETCHSIZE(img->fetchsize) | 179 COND(img->buffer, A6XX_TEX_CONST_2_UNK4 | A6XX_TEX_CONST_2_UNK31) | 180 A6XX_TEX_CONST_2_TYPE(img->type) | 181 A6XX_TEX_CONST_2_PITCH(img->pitch)); 182 OUT_RING(ring, A6XX_TEX_CONST_3_ARRAY_PITCH(img->array_pitch) | 183 COND(ubwc_enabled, A6XX_TEX_CONST_3_FLAG | A6XX_TEX_CONST_3_UNK27)); 184 if (img->bo) { 185 OUT_RELOC(ring, img->bo, img->offset, 186 (uint64_t)A6XX_TEX_CONST_5_DEPTH(img->depth) << 32, 0); 187 } else { 188 OUT_RING(ring, 0x00000000); 189 OUT_RING(ring, A6XX_TEX_CONST_5_DEPTH(img->depth)); 190 } 191 192 OUT_RING(ring, 0x00000000); /* texconst6 */ 193 194 if (ubwc_enabled) { 195 OUT_RELOC(ring, rsc->bo, img->ubwc_offset, 0, 0); 196 OUT_RING(ring, A6XX_TEX_CONST_9_FLAG_BUFFER_ARRAY_PITCH(rsc->ubwc_size)); 197 OUT_RING(ring, A6XX_TEX_CONST_10_FLAG_BUFFER_PITCH(rsc->ubwc_pitch)); 198 } else { 199 OUT_RING(ring, 0x00000000); /* texconst7 */ 200 OUT_RING(ring, 0x00000000); /* texconst8 */ 201 OUT_RING(ring, 0x00000000); /* texconst9 */ 202 OUT_RING(ring, 0x00000000); /* texconst10 */ 203 } 204 205 OUT_RING(ring, 0x00000000); /* texconst11 */ 206 OUT_RING(ring, 0x00000000); /* texconst12 */ 207 OUT_RING(ring, 0x00000000); /* texconst13 */ 208 OUT_RING(ring, 0x00000000); /* texconst14 */ 209 OUT_RING(ring, 0x00000000); /* texconst15 */ 210} 211 212void 213fd6_emit_image_tex(struct fd_ringbuffer *ring, const struct pipe_image_view *pimg) 214{ 215 struct fd6_image img; 216 translate_image(&img, pimg); 217 emit_image_tex(ring, &img); 218} 219 220void 221fd6_emit_ssbo_tex(struct fd_ringbuffer *ring, const struct pipe_shader_buffer *pbuf) 222{ 223 struct fd6_image img; 224 translate_buf(&img, pbuf); 225 emit_image_tex(ring, &img); 226} 227 228static void emit_image_ssbo(struct fd_ringbuffer *ring, struct fd6_image *img) 229{ 230 struct fd_resource *rsc = fd_resource(img->prsc); 231 enum a6xx_tile_mode tile_mode = TILE6_LINEAR; 232 bool ubwc_enabled = fd_resource_ubwc_enabled(rsc, img->level); 233 234 if (rsc->tile_mode && !fd_resource_level_linear(img->prsc, img->level)) { 235 tile_mode = rsc->tile_mode; 236 } 237 238 OUT_RING(ring, A6XX_IBO_0_FMT(img->fmt) | 239 A6XX_IBO_0_TILE_MODE(tile_mode)); 240 OUT_RING(ring, A6XX_IBO_1_WIDTH(img->width) | 241 A6XX_IBO_1_HEIGHT(img->height)); 242 OUT_RING(ring, A6XX_IBO_2_PITCH(img->pitch) | 243 COND(img->buffer, A6XX_IBO_2_UNK4 | A6XX_IBO_2_UNK31) | 244 A6XX_IBO_2_TYPE(img->type)); 245 OUT_RING(ring, A6XX_IBO_3_ARRAY_PITCH(img->array_pitch) | 246 COND(ubwc_enabled, A6XX_IBO_3_FLAG | A6XX_IBO_3_UNK27)); 247 if (img->bo) { 248 OUT_RELOCW(ring, img->bo, img->offset, 249 (uint64_t)A6XX_IBO_5_DEPTH(img->depth) << 32, 0); 250 } else { 251 OUT_RING(ring, 0x00000000); 252 OUT_RING(ring, A6XX_IBO_5_DEPTH(img->depth)); 253 } 254 OUT_RING(ring, 0x00000000); 255 256 if (ubwc_enabled) { 257 OUT_RELOCW(ring, rsc->bo, img->ubwc_offset, 0, 0); 258 OUT_RING(ring, A6XX_IBO_9_FLAG_BUFFER_ARRAY_PITCH(rsc->ubwc_size)); 259 OUT_RING(ring, A6XX_IBO_10_FLAG_BUFFER_PITCH(rsc->ubwc_pitch)); 260 } else { 261 OUT_RING(ring, 0x00000000); 262 OUT_RING(ring, 0x00000000); 263 OUT_RING(ring, 0x00000000); 264 OUT_RING(ring, 0x00000000); 265 } 266 267 OUT_RING(ring, 0x00000000); 268 OUT_RING(ring, 0x00000000); 269 OUT_RING(ring, 0x00000000); 270 OUT_RING(ring, 0x00000000); 271 OUT_RING(ring, 0x00000000); 272} 273 274/* Build combined image/SSBO "IBO" state, returns ownership of state reference */ 275struct fd_ringbuffer * 276fd6_build_ibo_state(struct fd_context *ctx, const struct ir3_shader_variant *v, 277 enum pipe_shader_type shader) 278{ 279 struct fd_shaderbuf_stateobj *bufso = &ctx->shaderbuf[shader]; 280 struct fd_shaderimg_stateobj *imgso = &ctx->shaderimg[shader]; 281 const struct ir3_ibo_mapping *mapping = &v->image_mapping; 282 283 struct fd_ringbuffer *state = 284 fd_submit_new_ringbuffer(ctx->batch->submit, 285 mapping->num_ibo * 16 * 4, FD_RINGBUFFER_STREAMING); 286 287 assert(shader == PIPE_SHADER_COMPUTE || shader == PIPE_SHADER_FRAGMENT); 288 289 for (unsigned i = 0; i < mapping->num_ibo; i++) { 290 struct fd6_image img; 291 unsigned idx = mapping->ibo_to_image[i]; 292 293 if (idx & IBO_SSBO) { 294 translate_buf(&img, &bufso->sb[idx & ~IBO_SSBO]); 295 } else { 296 translate_image(&img, &imgso->si[idx]); 297 } 298 299 emit_image_ssbo(state, &img); 300 } 301 302 return state; 303} 304