Alyssa Rosenzweig | 5ddf7ad | 2020-02-18 12:07:47 -0500 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2008 VMware, Inc. |
| 3 | * Copyright (C) 2014 Broadcom |
| 4 | * Copyright (C) 2018-2019 Alyssa Rosenzweig |
| 5 | * Copyright (C) 2019-2020 Collabora, Ltd. |
| 6 | * |
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 8 | * copy of this software and associated documentation files (the "Software"), |
| 9 | * to deal in the Software without restriction, including without limitation |
| 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 11 | * and/or sell copies of the Software, and to permit persons to whom the |
| 12 | * Software is furnished to do so, subject to the following conditions: |
| 13 | * |
| 14 | * The above copyright notice and this permission notice (including the next |
| 15 | * paragraph) shall be included in all copies or substantial portions of the |
| 16 | * Software. |
| 17 | * |
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 24 | * SOFTWARE. |
| 25 | * |
| 26 | */ |
| 27 | |
| 28 | #include "util/macros.h" |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 29 | #include "util/u_math.h" |
Alyssa Rosenzweig | 5ddf7ad | 2020-02-18 12:07:47 -0500 | [diff] [blame] | 30 | #include "pan_texture.h" |
Boris Brezillon | fefb3e9 | 2020-09-23 11:08:02 +0200 | [diff] [blame] | 31 | #include "panfrost-quirks.h" |
Alyssa Rosenzweig | 5ddf7ad | 2020-02-18 12:07:47 -0500 | [diff] [blame] | 32 | |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 33 | /* Generates a texture descriptor. Ideally, descriptors are immutable after the |
| 34 | * texture is created, so we can keep these hanging around in GPU memory in a |
| 35 | * dedicated BO and not have to worry. In practice there are some minor gotchas |
| 36 | * with this (the driver sometimes will change the format of a texture on the |
| 37 | * fly for compression) but it's fast enough to just regenerate the descriptor |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 38 | * in those cases, rather than monkeypatching at drawtime. A texture descriptor |
| 39 | * consists of a 32-byte header followed by pointers. |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 40 | */ |
| 41 | |
Alyssa Rosenzweig | 348d374 | 2020-07-20 18:03:56 -0400 | [diff] [blame] | 42 | /* List of supported modifiers, in descending order of preference. AFBC is |
| 43 | * faster than u-interleaved tiling which is faster than linear. Within AFBC, |
| 44 | * enabling the YUV-like transform is typically a win where possible. */ |
| 45 | |
| 46 | uint64_t pan_best_modifiers[PAN_MODIFIER_COUNT] = { |
| 47 | DRM_FORMAT_MOD_ARM_AFBC( |
| 48 | AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | |
| 49 | AFBC_FORMAT_MOD_SPARSE | |
| 50 | AFBC_FORMAT_MOD_YTR), |
| 51 | |
| 52 | DRM_FORMAT_MOD_ARM_AFBC( |
| 53 | AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | |
| 54 | AFBC_FORMAT_MOD_SPARSE), |
| 55 | |
| 56 | DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, |
| 57 | DRM_FORMAT_MOD_LINEAR |
| 58 | }; |
| 59 | |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 60 | /* Map modifiers to mali_texture_layout for packing in a texture descriptor */ |
| 61 | |
| 62 | static enum mali_texture_layout |
| 63 | panfrost_modifier_to_layout(uint64_t modifier) |
| 64 | { |
| 65 | if (drm_is_afbc(modifier)) |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 66 | return MALI_TEXTURE_LAYOUT_AFBC; |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 67 | else if (modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 68 | return MALI_TEXTURE_LAYOUT_TILED; |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 69 | else if (modifier == DRM_FORMAT_MOD_LINEAR) |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 70 | return MALI_TEXTURE_LAYOUT_LINEAR; |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 71 | else |
| 72 | unreachable("Invalid modifer"); |
| 73 | } |
| 74 | |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 75 | /* Check if we need to set a custom stride by computing the "expected" |
| 76 | * stride and comparing it to what the user actually wants. Only applies |
| 77 | * to linear textures, since tiled/compressed textures have strict |
| 78 | * alignment requirements for their strides as it is */ |
| 79 | |
| 80 | static bool |
| 81 | panfrost_needs_explicit_stride( |
| 82 | struct panfrost_slice *slices, |
| 83 | uint16_t width, |
| 84 | unsigned first_level, unsigned last_level, |
| 85 | unsigned bytes_per_pixel) |
| 86 | { |
| 87 | for (unsigned l = first_level; l <= last_level; ++l) { |
| 88 | unsigned actual = slices[l].stride; |
| 89 | unsigned expected = u_minify(width, l) * bytes_per_pixel; |
| 90 | |
| 91 | if (actual != expected) |
| 92 | return true; |
| 93 | } |
| 94 | |
| 95 | return false; |
| 96 | } |
| 97 | |
| 98 | /* A Scalable Texture Compression (ASTC) corresponds to just a few texture type |
| 99 | * in the hardware, but in fact can be parametrized to have various widths and |
| 100 | * heights for the so-called "stretch factor". It turns out these parameters |
| 101 | * are stuffed in the bottom bits of the payload pointers. This functions |
| 102 | * computes these magic stuffing constants based on the ASTC format in use. The |
| 103 | * constant in a given dimension is 3-bits, and two are stored side-by-side for |
| 104 | * each active dimension. |
| 105 | */ |
| 106 | |
| 107 | static unsigned |
| 108 | panfrost_astc_stretch(unsigned dim) |
| 109 | { |
| 110 | assert(dim >= 4 && dim <= 12); |
| 111 | return MIN2(dim, 11) - 4; |
| 112 | } |
| 113 | |
Icecream95 | 99446c9 | 2020-06-02 14:14:12 +1200 | [diff] [blame] | 114 | /* Texture addresses are tagged with information about compressed formats. |
| 115 | * AFBC uses a bit for whether the colorspace transform is enabled (RGB and |
| 116 | * RGBA only). |
| 117 | * For ASTC, this is a "stretch factor" encoding the block size. */ |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 118 | |
| 119 | static unsigned |
| 120 | panfrost_compression_tag( |
| 121 | const struct util_format_description *desc, |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 122 | enum mali_format format, uint64_t modifier) |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 123 | { |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 124 | if (drm_is_afbc(modifier)) |
| 125 | return (modifier & AFBC_FORMAT_MOD_YTR) ? 1 : 0; |
Alyssa Rosenzweig | d5a9cd1 | 2020-07-10 10:17:44 -0400 | [diff] [blame] | 126 | else if (format == MALI_ASTC_2D_LDR || format == MALI_ASTC_2D_HDR) |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 127 | return (panfrost_astc_stretch(desc->block.height) << 3) | |
| 128 | panfrost_astc_stretch(desc->block.width); |
| 129 | else |
| 130 | return 0; |
| 131 | } |
| 132 | |
| 133 | |
| 134 | /* Cubemaps have 6 faces as "layers" in between each actual layer. We |
| 135 | * need to fix this up. TODO: logic wrong in the asserted out cases ... |
| 136 | * can they happen, perhaps from cubemap arrays? */ |
| 137 | |
| 138 | static void |
| 139 | panfrost_adjust_cube_dimensions( |
| 140 | unsigned *first_face, unsigned *last_face, |
| 141 | unsigned *first_layer, unsigned *last_layer) |
| 142 | { |
| 143 | *first_face = *first_layer % 6; |
| 144 | *last_face = *last_layer % 6; |
| 145 | *first_layer /= 6; |
| 146 | *last_layer /= 6; |
| 147 | |
| 148 | assert((*first_layer == *last_layer) || (*first_face == 0 && *last_face == 5)); |
| 149 | } |
| 150 | |
| 151 | /* Following the texture descriptor is a number of pointers. How many? */ |
| 152 | |
| 153 | static unsigned |
| 154 | panfrost_texture_num_elements( |
| 155 | unsigned first_level, unsigned last_level, |
| 156 | unsigned first_layer, unsigned last_layer, |
Alyssa Rosenzweig | 6088891 | 2020-07-15 11:39:08 -0400 | [diff] [blame] | 157 | unsigned nr_samples, |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 158 | bool is_cube, bool manual_stride) |
| 159 | { |
| 160 | unsigned first_face = 0, last_face = 0; |
| 161 | |
| 162 | if (is_cube) { |
| 163 | panfrost_adjust_cube_dimensions(&first_face, &last_face, |
| 164 | &first_layer, &last_layer); |
| 165 | } |
| 166 | |
| 167 | unsigned levels = 1 + last_level - first_level; |
| 168 | unsigned layers = 1 + last_layer - first_layer; |
| 169 | unsigned faces = 1 + last_face - first_face; |
Alyssa Rosenzweig | 6088891 | 2020-07-15 11:39:08 -0400 | [diff] [blame] | 170 | unsigned num_elements = levels * layers * faces * MAX2(nr_samples, 1); |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 171 | |
| 172 | if (manual_stride) |
| 173 | num_elements *= 2; |
| 174 | |
| 175 | return num_elements; |
| 176 | } |
| 177 | |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 178 | /* Conservative estimate of the size of the texture payload a priori. |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 179 | * Average case, size equal to the actual size. Worst case, off by 2x (if |
| 180 | * a manual stride is not needed on a linear texture). Returned value |
| 181 | * must be greater than or equal to the actual size, so it's safe to use |
| 182 | * as an allocation amount */ |
| 183 | |
| 184 | unsigned |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 185 | panfrost_estimate_texture_payload_size( |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 186 | unsigned first_level, unsigned last_level, |
| 187 | unsigned first_layer, unsigned last_layer, |
Alyssa Rosenzweig | 6088891 | 2020-07-15 11:39:08 -0400 | [diff] [blame] | 188 | unsigned nr_samples, |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 189 | enum mali_texture_dimension dim, uint64_t modifier) |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 190 | { |
| 191 | /* Assume worst case */ |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 192 | unsigned manual_stride = (modifier == DRM_FORMAT_MOD_LINEAR); |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 193 | |
| 194 | unsigned elements = panfrost_texture_num_elements( |
| 195 | first_level, last_level, |
| 196 | first_layer, last_layer, |
Alyssa Rosenzweig | 6088891 | 2020-07-15 11:39:08 -0400 | [diff] [blame] | 197 | nr_samples, |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 198 | dim == MALI_TEXTURE_DIMENSION_CUBE, manual_stride); |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 199 | |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 200 | return sizeof(mali_ptr) * elements; |
| 201 | } |
| 202 | |
Alyssa Rosenzweig | bde19c0 | 2020-04-30 18:48:53 -0400 | [diff] [blame] | 203 | /* Bifrost requires a tile stride for tiled textures. This stride is computed |
| 204 | * as (16 * bpp * width) assuming there is at least one tile (width >= 16). |
Alyssa Rosenzweig | 92553b6 | 2020-06-15 12:42:40 -0400 | [diff] [blame] | 205 | * Otherwise if height <= 16, the blob puts zero. Interactions with AFBC are |
Alyssa Rosenzweig | bde19c0 | 2020-04-30 18:48:53 -0400 | [diff] [blame] | 206 | * currently unknown. |
| 207 | */ |
| 208 | |
| 209 | static unsigned |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 210 | panfrost_nonlinear_stride(uint64_t modifier, |
Alyssa Rosenzweig | bde19c0 | 2020-04-30 18:48:53 -0400 | [diff] [blame] | 211 | unsigned bytes_per_pixel, |
Alyssa Rosenzweig | 92553b6 | 2020-06-15 12:42:40 -0400 | [diff] [blame] | 212 | unsigned width, |
| 213 | unsigned height) |
Alyssa Rosenzweig | bde19c0 | 2020-04-30 18:48:53 -0400 | [diff] [blame] | 214 | { |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 215 | if (modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) { |
Alyssa Rosenzweig | 92553b6 | 2020-06-15 12:42:40 -0400 | [diff] [blame] | 216 | return (height <= 16) ? 0 : (16 * bytes_per_pixel * ALIGN_POT(width, 16)); |
Alyssa Rosenzweig | bde19c0 | 2020-04-30 18:48:53 -0400 | [diff] [blame] | 217 | } else { |
| 218 | unreachable("TODO: AFBC on Bifrost"); |
| 219 | } |
| 220 | } |
| 221 | |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 222 | static void |
| 223 | panfrost_emit_texture_payload( |
| 224 | mali_ptr *payload, |
| 225 | const struct util_format_description *desc, |
| 226 | enum mali_format mali_format, |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 227 | enum mali_texture_dimension dim, |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 228 | uint64_t modifier, |
Alyssa Rosenzweig | 92553b6 | 2020-06-15 12:42:40 -0400 | [diff] [blame] | 229 | unsigned width, unsigned height, |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 230 | unsigned first_level, unsigned last_level, |
| 231 | unsigned first_layer, unsigned last_layer, |
Alyssa Rosenzweig | 41c06de | 2020-06-30 16:43:32 -0400 | [diff] [blame] | 232 | unsigned nr_samples, |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 233 | unsigned cube_stride, |
| 234 | bool manual_stride, |
| 235 | mali_ptr base, |
| 236 | struct panfrost_slice *slices) |
| 237 | { |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 238 | base |= panfrost_compression_tag(desc, mali_format, modifier); |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 239 | |
| 240 | /* Inject the addresses in, interleaving array indices, mip levels, |
| 241 | * cube faces, and strides in that order */ |
| 242 | |
| 243 | unsigned first_face = 0, last_face = 0, face_mult = 1; |
| 244 | |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 245 | if (dim == MALI_TEXTURE_DIMENSION_CUBE) { |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 246 | face_mult = 6; |
| 247 | panfrost_adjust_cube_dimensions(&first_face, &last_face, &first_layer, &last_layer); |
| 248 | } |
| 249 | |
Alyssa Rosenzweig | 937d368 | 2020-06-30 16:43:47 -0400 | [diff] [blame] | 250 | nr_samples = MAX2(nr_samples, 1); |
| 251 | |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 252 | unsigned idx = 0; |
| 253 | |
| 254 | for (unsigned w = first_layer; w <= last_layer; ++w) { |
| 255 | for (unsigned l = first_level; l <= last_level; ++l) { |
| 256 | for (unsigned f = first_face; f <= last_face; ++f) { |
Alyssa Rosenzweig | 937d368 | 2020-06-30 16:43:47 -0400 | [diff] [blame] | 257 | for (unsigned s = 0; s < nr_samples; ++s) { |
| 258 | payload[idx++] = base + panfrost_texture_offset( |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 259 | slices, dim == MALI_TEXTURE_DIMENSION_3D, |
Alyssa Rosenzweig | 937d368 | 2020-06-30 16:43:47 -0400 | [diff] [blame] | 260 | cube_stride, l, w * face_mult + f, s); |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 261 | |
Alyssa Rosenzweig | 937d368 | 2020-06-30 16:43:47 -0400 | [diff] [blame] | 262 | if (manual_stride) { |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 263 | payload[idx++] = (modifier == DRM_FORMAT_MOD_LINEAR) ? |
Alyssa Rosenzweig | 937d368 | 2020-06-30 16:43:47 -0400 | [diff] [blame] | 264 | slices[l].stride : |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 265 | panfrost_nonlinear_stride(modifier, |
Alyssa Rosenzweig | 937d368 | 2020-06-30 16:43:47 -0400 | [diff] [blame] | 266 | MAX2(desc->block.bits / 8, 1), |
| 267 | u_minify(width, l), |
| 268 | u_minify(height, l)); |
| 269 | } |
Alyssa Rosenzweig | bde19c0 | 2020-04-30 18:48:53 -0400 | [diff] [blame] | 270 | } |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 271 | } |
| 272 | } |
| 273 | } |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 274 | } |
| 275 | |
Alyssa Rosenzweig | 816af26 | 2020-07-08 16:37:00 -0400 | [diff] [blame] | 276 | #define MALI_SWIZZLE_R001 \ |
Alyssa Rosenzweig | cdc3276 | 2020-08-12 16:46:07 -0400 | [diff] [blame] | 277 | (MALI_CHANNEL_R << 0) | \ |
| 278 | (MALI_CHANNEL_0 << 3) | \ |
| 279 | (MALI_CHANNEL_0 << 6) | \ |
| 280 | (MALI_CHANNEL_1 << 9) |
Alyssa Rosenzweig | 816af26 | 2020-07-08 16:37:00 -0400 | [diff] [blame] | 281 | |
Alyssa Rosenzweig | 4c89148 | 2020-07-03 13:01:16 -0400 | [diff] [blame] | 282 | #define MALI_SWIZZLE_A001 \ |
Alyssa Rosenzweig | cdc3276 | 2020-08-12 16:46:07 -0400 | [diff] [blame] | 283 | (MALI_CHANNEL_A << 0) | \ |
| 284 | (MALI_CHANNEL_0 << 3) | \ |
| 285 | (MALI_CHANNEL_0 << 6) | \ |
| 286 | (MALI_CHANNEL_1 << 9) |
Alyssa Rosenzweig | 4c89148 | 2020-07-03 13:01:16 -0400 | [diff] [blame] | 287 | |
Alyssa Rosenzweig | 816af26 | 2020-07-08 16:37:00 -0400 | [diff] [blame] | 288 | |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 289 | void |
| 290 | panfrost_new_texture( |
| 291 | void *out, |
| 292 | uint16_t width, uint16_t height, |
| 293 | uint16_t depth, uint16_t array_size, |
| 294 | enum pipe_format format, |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 295 | enum mali_texture_dimension dim, |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 296 | uint64_t modifier, |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 297 | unsigned first_level, unsigned last_level, |
| 298 | unsigned first_layer, unsigned last_layer, |
Alyssa Rosenzweig | 41c06de | 2020-06-30 16:43:32 -0400 | [diff] [blame] | 299 | unsigned nr_samples, |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 300 | unsigned cube_stride, |
| 301 | unsigned swizzle, |
| 302 | mali_ptr base, |
| 303 | struct panfrost_slice *slices) |
| 304 | { |
| 305 | const struct util_format_description *desc = |
| 306 | util_format_description(format); |
| 307 | |
| 308 | unsigned bytes_per_pixel = util_format_get_blocksize(format); |
| 309 | |
Alyssa Rosenzweig | 861e7dc | 2020-05-15 18:43:41 -0400 | [diff] [blame] | 310 | enum mali_format mali_format = panfrost_pipe_format_table[desc->format].hw; |
| 311 | assert(mali_format); |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 312 | |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 313 | bool manual_stride = (modifier == DRM_FORMAT_MOD_LINEAR) |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 314 | && panfrost_needs_explicit_stride(slices, width, |
| 315 | first_level, last_level, bytes_per_pixel); |
| 316 | |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 317 | unsigned format_swizzle = (format == PIPE_FORMAT_X24S8_UINT) ? |
Alyssa Rosenzweig | 4c89148 | 2020-07-03 13:01:16 -0400 | [diff] [blame] | 318 | MALI_SWIZZLE_A001 : |
Alyssa Rosenzweig | 816af26 | 2020-07-08 16:37:00 -0400 | [diff] [blame] | 319 | (format == PIPE_FORMAT_S8_UINT) ? |
| 320 | MALI_SWIZZLE_R001 : |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 321 | panfrost_translate_swizzle_4(desc->swizzle); |
| 322 | |
| 323 | bool srgb = (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB); |
| 324 | |
| 325 | pan_pack(out, MIDGARD_TEXTURE, cfg) { |
| 326 | cfg.width = u_minify(width, first_level); |
| 327 | cfg.height = u_minify(height, first_level); |
| 328 | cfg.depth = u_minify(depth, first_level); |
| 329 | cfg.array_size = array_size; |
| 330 | cfg.format = format_swizzle | (mali_format << 12) | (srgb << 20); |
| 331 | cfg.dimension = dim; |
| 332 | cfg.texel_ordering = panfrost_modifier_to_layout(modifier); |
| 333 | cfg.manual_stride = manual_stride; |
| 334 | cfg.levels = last_level - first_level; |
| 335 | cfg.swizzle = swizzle; |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 336 | }; |
| 337 | |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 338 | panfrost_emit_texture_payload( |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 339 | (mali_ptr *) (out + MALI_MIDGARD_TEXTURE_LENGTH), |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 340 | desc, |
| 341 | mali_format, |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 342 | dim, |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 343 | modifier, |
Alyssa Rosenzweig | 92553b6 | 2020-06-15 12:42:40 -0400 | [diff] [blame] | 344 | width, height, |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 345 | first_level, last_level, |
| 346 | first_layer, last_layer, |
Alyssa Rosenzweig | 41c06de | 2020-06-30 16:43:32 -0400 | [diff] [blame] | 347 | nr_samples, |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 348 | cube_stride, |
| 349 | manual_stride, |
| 350 | base, |
| 351 | slices); |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 352 | } |
| 353 | |
Tomeu Vizoso | e41894b | 2020-04-17 14:23:49 +0200 | [diff] [blame] | 354 | void |
| 355 | panfrost_new_texture_bifrost( |
Boris Brezillon | fefb3e9 | 2020-09-23 11:08:02 +0200 | [diff] [blame] | 356 | const struct panfrost_device *dev, |
Alyssa Rosenzweig | ad0b32c | 2020-08-06 18:12:28 -0400 | [diff] [blame] | 357 | struct mali_bifrost_texture_packed *out, |
Tomeu Vizoso | e41894b | 2020-04-17 14:23:49 +0200 | [diff] [blame] | 358 | uint16_t width, uint16_t height, |
| 359 | uint16_t depth, uint16_t array_size, |
| 360 | enum pipe_format format, |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 361 | enum mali_texture_dimension dim, |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 362 | uint64_t modifier, |
Tomeu Vizoso | e41894b | 2020-04-17 14:23:49 +0200 | [diff] [blame] | 363 | unsigned first_level, unsigned last_level, |
| 364 | unsigned first_layer, unsigned last_layer, |
Alyssa Rosenzweig | 41c06de | 2020-06-30 16:43:32 -0400 | [diff] [blame] | 365 | unsigned nr_samples, |
Tomeu Vizoso | e41894b | 2020-04-17 14:23:49 +0200 | [diff] [blame] | 366 | unsigned cube_stride, |
| 367 | unsigned swizzle, |
| 368 | mali_ptr base, |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 369 | struct panfrost_slice *slices, |
| 370 | struct panfrost_bo *payload) |
Tomeu Vizoso | e41894b | 2020-04-17 14:23:49 +0200 | [diff] [blame] | 371 | { |
| 372 | const struct util_format_description *desc = |
| 373 | util_format_description(format); |
| 374 | |
Alyssa Rosenzweig | 861e7dc | 2020-05-15 18:43:41 -0400 | [diff] [blame] | 375 | enum mali_format mali_format = panfrost_pipe_format_table[desc->format].hw; |
| 376 | assert(mali_format); |
Tomeu Vizoso | e41894b | 2020-04-17 14:23:49 +0200 | [diff] [blame] | 377 | |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 378 | panfrost_emit_texture_payload( |
| 379 | (mali_ptr *) payload->cpu, |
| 380 | desc, |
| 381 | mali_format, |
Alyssa Rosenzweig | f008a63 | 2020-08-11 17:27:36 -0400 | [diff] [blame] | 382 | dim, |
Alyssa Rosenzweig | 965537df | 2020-07-22 10:23:50 -0400 | [diff] [blame] | 383 | modifier, |
Alyssa Rosenzweig | 92553b6 | 2020-06-15 12:42:40 -0400 | [diff] [blame] | 384 | width, height, |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 385 | first_level, last_level, |
| 386 | first_layer, last_layer, |
Alyssa Rosenzweig | 41c06de | 2020-06-30 16:43:32 -0400 | [diff] [blame] | 387 | nr_samples, |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 388 | cube_stride, |
Alyssa Rosenzweig | bde19c0 | 2020-04-30 18:48:53 -0400 | [diff] [blame] | 389 | true, /* Stride explicit on Bifrost */ |
Alyssa Rosenzweig | a3d2936 | 2020-04-21 16:08:07 -0400 | [diff] [blame] | 390 | base, |
| 391 | slices); |
| 392 | |
Alyssa Rosenzweig | ad0b32c | 2020-08-06 18:12:28 -0400 | [diff] [blame] | 393 | bool srgb = (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB); |
| 394 | |
| 395 | pan_pack(out, BIFROST_TEXTURE, cfg) { |
| 396 | cfg.dimension = dim; |
| 397 | cfg.format = (mali_format << 12) | (srgb << 20); |
Boris Brezillon | fefb3e9 | 2020-09-23 11:08:02 +0200 | [diff] [blame] | 398 | if (dev->quirks & HAS_SWIZZLES) |
| 399 | cfg.format |= panfrost_get_default_swizzle(desc->nr_channels); |
| 400 | |
Alyssa Rosenzweig | ad0b32c | 2020-08-06 18:12:28 -0400 | [diff] [blame] | 401 | cfg.width = u_minify(width, first_level); |
| 402 | cfg.height = u_minify(height, first_level); |
| 403 | cfg.swizzle = swizzle; |
| 404 | cfg.texel_ordering = panfrost_modifier_to_layout(modifier); |
| 405 | cfg.levels = last_level - first_level; |
| 406 | cfg.surfaces = payload->gpu; |
| 407 | |
Alyssa Rosenzweig | 239e4e8 | 2020-10-06 21:46:56 -0400 | [diff] [blame^] | 408 | /* We specify API-level LOD clamps in the sampler descriptor |
| 409 | * and use these clamps simply for bounds checking */ |
| 410 | cfg.minimum_lod = FIXED_16(0, false); |
| 411 | cfg.maximum_lod = FIXED_16(cfg.levels, false); |
Alyssa Rosenzweig | ad0b32c | 2020-08-06 18:12:28 -0400 | [diff] [blame] | 412 | } |
Tomeu Vizoso | e41894b | 2020-04-17 14:23:49 +0200 | [diff] [blame] | 413 | } |
| 414 | |
Alyssa Rosenzweig | 5ddf7ad | 2020-02-18 12:07:47 -0500 | [diff] [blame] | 415 | /* Computes sizes for checksumming, which is 8 bytes per 16x16 tile. |
| 416 | * Checksumming is believed to be a CRC variant (CRC64 based on the size?). |
| 417 | * This feature is also known as "transaction elimination". */ |
| 418 | |
| 419 | #define CHECKSUM_TILE_WIDTH 16 |
| 420 | #define CHECKSUM_TILE_HEIGHT 16 |
| 421 | #define CHECKSUM_BYTES_PER_TILE 8 |
| 422 | |
| 423 | unsigned |
| 424 | panfrost_compute_checksum_size( |
| 425 | struct panfrost_slice *slice, |
| 426 | unsigned width, |
| 427 | unsigned height) |
| 428 | { |
| 429 | unsigned aligned_width = ALIGN_POT(width, CHECKSUM_TILE_WIDTH); |
| 430 | unsigned aligned_height = ALIGN_POT(height, CHECKSUM_TILE_HEIGHT); |
| 431 | |
| 432 | unsigned tile_count_x = aligned_width / CHECKSUM_TILE_WIDTH; |
| 433 | unsigned tile_count_y = aligned_height / CHECKSUM_TILE_HEIGHT; |
| 434 | |
| 435 | slice->checksum_stride = tile_count_x * CHECKSUM_BYTES_PER_TILE; |
| 436 | |
| 437 | return slice->checksum_stride * tile_count_y; |
| 438 | } |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 439 | |
| 440 | unsigned |
| 441 | panfrost_get_layer_stride(struct panfrost_slice *slices, bool is_3d, unsigned cube_stride, unsigned level) |
| 442 | { |
| 443 | return is_3d ? slices[level].size0 : cube_stride; |
| 444 | } |
| 445 | |
| 446 | /* Computes the offset into a texture at a particular level/face. Add to |
| 447 | * the base address of a texture to get the address to that level/face */ |
| 448 | |
| 449 | unsigned |
Alyssa Rosenzweig | 41c06de | 2020-06-30 16:43:32 -0400 | [diff] [blame] | 450 | panfrost_texture_offset(struct panfrost_slice *slices, bool is_3d, unsigned cube_stride, unsigned level, unsigned face, unsigned sample) |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 451 | { |
| 452 | unsigned layer_stride = panfrost_get_layer_stride(slices, is_3d, cube_stride, level); |
Alyssa Rosenzweig | 41c06de | 2020-06-30 16:43:32 -0400 | [diff] [blame] | 453 | return slices[level].offset + (face * layer_stride) + (sample * slices[level].size0); |
Alyssa Rosenzweig | b929565 | 2020-02-18 14:20:16 -0500 | [diff] [blame] | 454 | } |