1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2018 Rob Clark <robclark@freedesktop.org> 3bf215546Sopenharmony_ci * Copyright © 2018 Google, Inc. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci * Authors: 25bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 26bf215546Sopenharmony_ci */ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "drm-uapi/drm_fourcc.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "fd6_resource.h" 31bf215546Sopenharmony_ci#include "fdl/fd6_format_table.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "a6xx.xml.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci/* A subset of the valid tiled formats can be compressed. We do 36bf215546Sopenharmony_ci * already require tiled in order to be compressed, but just because 37bf215546Sopenharmony_ci * it can be tiled doesn't mean it can be compressed. 38bf215546Sopenharmony_ci */ 39bf215546Sopenharmony_cistatic bool 40bf215546Sopenharmony_ciok_ubwc_format(struct pipe_screen *pscreen, enum pipe_format pfmt) 41bf215546Sopenharmony_ci{ 42bf215546Sopenharmony_ci const struct fd_dev_info *info = fd_screen(pscreen)->info; 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci switch (pfmt) { 45bf215546Sopenharmony_ci case PIPE_FORMAT_X24S8_UINT: 46bf215546Sopenharmony_ci case PIPE_FORMAT_Z24_UNORM_S8_UINT: 47bf215546Sopenharmony_ci /* We can't sample stencil with UBWC on a630, and we may need to be able 48bf215546Sopenharmony_ci * to sample stencil at some point. We can't just use 49bf215546Sopenharmony_ci * fd_resource_uncompress() at the point of stencil sampling because 50bf215546Sopenharmony_ci * that itself uses stencil sampling in the fd_blitter_blit path. 51bf215546Sopenharmony_ci */ 52bf215546Sopenharmony_ci return info->a6xx.has_z24uint_s8uint; 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci case PIPE_FORMAT_R8_G8B8_420_UNORM: 55bf215546Sopenharmony_ci return true; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci default: 58bf215546Sopenharmony_ci break; 59bf215546Sopenharmony_ci } 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci switch (fd6_color_format(pfmt, TILE6_LINEAR)) { 62bf215546Sopenharmony_ci case FMT6_10_10_10_2_UINT: 63bf215546Sopenharmony_ci case FMT6_10_10_10_2_UNORM_DEST: 64bf215546Sopenharmony_ci case FMT6_11_11_10_FLOAT: 65bf215546Sopenharmony_ci case FMT6_16_FLOAT: 66bf215546Sopenharmony_ci case FMT6_16_16_16_16_FLOAT: 67bf215546Sopenharmony_ci case FMT6_16_16_16_16_SINT: 68bf215546Sopenharmony_ci case FMT6_16_16_16_16_UINT: 69bf215546Sopenharmony_ci case FMT6_16_16_FLOAT: 70bf215546Sopenharmony_ci case FMT6_16_16_SINT: 71bf215546Sopenharmony_ci case FMT6_16_16_UINT: 72bf215546Sopenharmony_ci case FMT6_16_SINT: 73bf215546Sopenharmony_ci case FMT6_16_UINT: 74bf215546Sopenharmony_ci case FMT6_32_32_32_32_SINT: 75bf215546Sopenharmony_ci case FMT6_32_32_32_32_UINT: 76bf215546Sopenharmony_ci case FMT6_32_32_SINT: 77bf215546Sopenharmony_ci case FMT6_32_32_UINT: 78bf215546Sopenharmony_ci case FMT6_5_6_5_UNORM: 79bf215546Sopenharmony_ci case FMT6_5_5_5_1_UNORM: 80bf215546Sopenharmony_ci case FMT6_8_8_8_8_SINT: 81bf215546Sopenharmony_ci case FMT6_8_8_8_8_UINT: 82bf215546Sopenharmony_ci case FMT6_8_8_8_8_UNORM: 83bf215546Sopenharmony_ci case FMT6_8_8_8_X8_UNORM: 84bf215546Sopenharmony_ci case FMT6_8_8_SINT: 85bf215546Sopenharmony_ci case FMT6_8_8_UINT: 86bf215546Sopenharmony_ci case FMT6_8_8_UNORM: 87bf215546Sopenharmony_ci case FMT6_Z24_UNORM_S8_UINT: 88bf215546Sopenharmony_ci case FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8: 89bf215546Sopenharmony_ci return true; 90bf215546Sopenharmony_ci case FMT6_8_UNORM: 91bf215546Sopenharmony_ci return info->a6xx.has_8bpp_ubwc; 92bf215546Sopenharmony_ci default: 93bf215546Sopenharmony_ci return false; 94bf215546Sopenharmony_ci } 95bf215546Sopenharmony_ci} 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_cistatic bool 98bf215546Sopenharmony_cican_do_ubwc(struct pipe_resource *prsc) 99bf215546Sopenharmony_ci{ 100bf215546Sopenharmony_ci /* limit things to simple single level 2d for now: */ 101bf215546Sopenharmony_ci if ((prsc->depth0 != 1) || (prsc->array_size != 1) || 102bf215546Sopenharmony_ci (prsc->last_level != 0)) 103bf215546Sopenharmony_ci return false; 104bf215546Sopenharmony_ci if (prsc->target != PIPE_TEXTURE_2D) 105bf215546Sopenharmony_ci return false; 106bf215546Sopenharmony_ci if (!ok_ubwc_format(prsc->screen, prsc->format)) 107bf215546Sopenharmony_ci return false; 108bf215546Sopenharmony_ci return true; 109bf215546Sopenharmony_ci} 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_cistatic bool 112bf215546Sopenharmony_ciis_norm(enum pipe_format format) 113bf215546Sopenharmony_ci{ 114bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(format); 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci return desc->is_snorm || desc->is_unorm; 117bf215546Sopenharmony_ci} 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_cistatic bool 120bf215546Sopenharmony_civalid_format_cast(struct fd_resource *rsc, enum pipe_format format) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci /* Special case "casting" format in hw: */ 123bf215546Sopenharmony_ci if (format == PIPE_FORMAT_Z24_UNORM_S8_UINT_AS_R8G8B8A8) 124bf215546Sopenharmony_ci return true; 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci /* For some color values (just "solid white") compression metadata maps to 127bf215546Sopenharmony_ci * different pixel values for uint/sint vs unorm/snorm, so we can't reliably 128bf215546Sopenharmony_ci * "cast" u/snorm to u/sint and visa versa: 129bf215546Sopenharmony_ci */ 130bf215546Sopenharmony_ci if (is_norm(format) != is_norm(rsc->b.b.format)) 131bf215546Sopenharmony_ci return false; 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci /* The UBWC formats can be re-interpreted so long as the components 134bf215546Sopenharmony_ci * have the same # of bits 135bf215546Sopenharmony_ci */ 136bf215546Sopenharmony_ci for (unsigned i = 0; i < 4; i++) { 137bf215546Sopenharmony_ci unsigned sb, db; 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci sb = util_format_get_component_bits(rsc->b.b.format, UTIL_FORMAT_COLORSPACE_RGB, i); 140bf215546Sopenharmony_ci db = util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, i); 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci if (sb != db) 143bf215546Sopenharmony_ci return false; 144bf215546Sopenharmony_ci } 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci return true; 147bf215546Sopenharmony_ci} 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci/** 150bf215546Sopenharmony_ci * R8G8 have a different block width/height and height alignment from other 151bf215546Sopenharmony_ci * formats that would normally be compatible (like R16), and so if we are 152bf215546Sopenharmony_ci * trying to, for example, sample R16 as R8G8 we need to demote to linear. 153bf215546Sopenharmony_ci */ 154bf215546Sopenharmony_cistatic bool 155bf215546Sopenharmony_ciis_r8g8(enum pipe_format format) 156bf215546Sopenharmony_ci{ 157bf215546Sopenharmony_ci return (util_format_get_blocksize(format) == 2) && 158bf215546Sopenharmony_ci (util_format_get_nr_components(format) == 2); 159bf215546Sopenharmony_ci} 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci/** 162bf215546Sopenharmony_ci * Ensure the rsc is in an ok state to be used with the specified format. 163bf215546Sopenharmony_ci * This handles the case of UBWC buffers used with non-UBWC compatible 164bf215546Sopenharmony_ci * formats, by triggering an uncompress. 165bf215546Sopenharmony_ci */ 166bf215546Sopenharmony_civoid 167bf215546Sopenharmony_cifd6_validate_format(struct fd_context *ctx, struct fd_resource *rsc, 168bf215546Sopenharmony_ci enum pipe_format format) 169bf215546Sopenharmony_ci{ 170bf215546Sopenharmony_ci enum pipe_format orig_format = rsc->b.b.format; 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci tc_assert_driver_thread(ctx->tc); 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci if (orig_format == format) 175bf215546Sopenharmony_ci return; 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci if (rsc->layout.tile_mode && (is_r8g8(orig_format) != is_r8g8(format))) { 178bf215546Sopenharmony_ci perf_debug_ctx(ctx, 179bf215546Sopenharmony_ci "%" PRSC_FMT ": demoted to linear+uncompressed due to use as %s", 180bf215546Sopenharmony_ci PRSC_ARGS(&rsc->b.b), util_format_short_name(format)); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci fd_resource_uncompress(ctx, rsc, true); 183bf215546Sopenharmony_ci return; 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci if (!rsc->layout.ubwc) 187bf215546Sopenharmony_ci return; 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci if (ok_ubwc_format(rsc->b.b.screen, format) && valid_format_cast(rsc, format)) 190bf215546Sopenharmony_ci return; 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci perf_debug_ctx(ctx, 193bf215546Sopenharmony_ci "%" PRSC_FMT ": demoted to uncompressed due to use as %s", 194bf215546Sopenharmony_ci PRSC_ARGS(&rsc->b.b), util_format_short_name(format)); 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci fd_resource_uncompress(ctx, rsc, false); 197bf215546Sopenharmony_ci} 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_cistatic void 200bf215546Sopenharmony_cisetup_lrz(struct fd_resource *rsc) 201bf215546Sopenharmony_ci{ 202bf215546Sopenharmony_ci struct fd_screen *screen = fd_screen(rsc->b.b.screen); 203bf215546Sopenharmony_ci unsigned width0 = rsc->b.b.width0; 204bf215546Sopenharmony_ci unsigned height0 = rsc->b.b.height0; 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci /* LRZ buffer is super-sampled: */ 207bf215546Sopenharmony_ci switch (rsc->b.b.nr_samples) { 208bf215546Sopenharmony_ci case 4: 209bf215546Sopenharmony_ci width0 *= 2; 210bf215546Sopenharmony_ci FALLTHROUGH; 211bf215546Sopenharmony_ci case 2: 212bf215546Sopenharmony_ci height0 *= 2; 213bf215546Sopenharmony_ci } 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci unsigned lrz_pitch = align(DIV_ROUND_UP(width0, 8), 32); 216bf215546Sopenharmony_ci unsigned lrz_height = align(DIV_ROUND_UP(height0, 8), 16); 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci unsigned size = lrz_pitch * lrz_height * 2; 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci rsc->lrz_height = lrz_height; 221bf215546Sopenharmony_ci rsc->lrz_width = lrz_pitch; 222bf215546Sopenharmony_ci rsc->lrz_pitch = lrz_pitch; 223bf215546Sopenharmony_ci rsc->lrz = fd_bo_new(screen->dev, size, FD_BO_NOMAP, "lrz"); 224bf215546Sopenharmony_ci} 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_cistatic uint32_t 227bf215546Sopenharmony_cifd6_setup_slices(struct fd_resource *rsc) 228bf215546Sopenharmony_ci{ 229bf215546Sopenharmony_ci struct pipe_resource *prsc = &rsc->b.b; 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci if (!FD_DBG(NOLRZ) && has_depth(rsc->b.b.format)) 232bf215546Sopenharmony_ci setup_lrz(rsc); 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci if (rsc->layout.ubwc && !ok_ubwc_format(rsc->b.b.screen, rsc->b.b.format)) 235bf215546Sopenharmony_ci rsc->layout.ubwc = false; 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci fdl6_layout(&rsc->layout, prsc->format, fd_resource_nr_samples(prsc), 238bf215546Sopenharmony_ci prsc->width0, prsc->height0, prsc->depth0, prsc->last_level + 1, 239bf215546Sopenharmony_ci prsc->array_size, prsc->target == PIPE_TEXTURE_3D, NULL); 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci return rsc->layout.size; 242bf215546Sopenharmony_ci} 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_cistatic int 245bf215546Sopenharmony_cifill_ubwc_buffer_sizes(struct fd_resource *rsc) 246bf215546Sopenharmony_ci{ 247bf215546Sopenharmony_ci struct pipe_resource *prsc = &rsc->b.b; 248bf215546Sopenharmony_ci struct fdl_explicit_layout explicit = { 249bf215546Sopenharmony_ci .offset = rsc->layout.slices[0].offset, 250bf215546Sopenharmony_ci .pitch = rsc->layout.pitch0, 251bf215546Sopenharmony_ci }; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci if (!can_do_ubwc(prsc)) 254bf215546Sopenharmony_ci return -1; 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci rsc->layout.ubwc = true; 257bf215546Sopenharmony_ci rsc->layout.tile_mode = TILE6_3; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci if (!fdl6_layout(&rsc->layout, prsc->format, fd_resource_nr_samples(prsc), 260bf215546Sopenharmony_ci prsc->width0, prsc->height0, prsc->depth0, 261bf215546Sopenharmony_ci prsc->last_level + 1, prsc->array_size, false, &explicit)) 262bf215546Sopenharmony_ci return -1; 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci if (rsc->layout.size > fd_bo_size(rsc->bo)) 265bf215546Sopenharmony_ci return -1; 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci return 0; 268bf215546Sopenharmony_ci} 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_cistatic int 271bf215546Sopenharmony_cifd6_layout_resource_for_modifier(struct fd_resource *rsc, uint64_t modifier) 272bf215546Sopenharmony_ci{ 273bf215546Sopenharmony_ci switch (modifier) { 274bf215546Sopenharmony_ci case DRM_FORMAT_MOD_QCOM_COMPRESSED: 275bf215546Sopenharmony_ci return fill_ubwc_buffer_sizes(rsc); 276bf215546Sopenharmony_ci case DRM_FORMAT_MOD_LINEAR: 277bf215546Sopenharmony_ci if (can_do_ubwc(&rsc->b.b)) { 278bf215546Sopenharmony_ci perf_debug("%" PRSC_FMT 279bf215546Sopenharmony_ci ": not UBWC: imported with DRM_FORMAT_MOD_LINEAR!", 280bf215546Sopenharmony_ci PRSC_ARGS(&rsc->b.b)); 281bf215546Sopenharmony_ci } 282bf215546Sopenharmony_ci return 0; 283bf215546Sopenharmony_ci case DRM_FORMAT_MOD_INVALID: 284bf215546Sopenharmony_ci if (can_do_ubwc(&rsc->b.b)) { 285bf215546Sopenharmony_ci perf_debug("%" PRSC_FMT 286bf215546Sopenharmony_ci ": not UBWC: imported with DRM_FORMAT_MOD_INVALID!", 287bf215546Sopenharmony_ci PRSC_ARGS(&rsc->b.b)); 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci return 0; 290bf215546Sopenharmony_ci default: 291bf215546Sopenharmony_ci return -1; 292bf215546Sopenharmony_ci } 293bf215546Sopenharmony_ci} 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_cistatic const uint64_t supported_modifiers[] = { 296bf215546Sopenharmony_ci DRM_FORMAT_MOD_LINEAR, 297bf215546Sopenharmony_ci DRM_FORMAT_MOD_QCOM_COMPRESSED, 298bf215546Sopenharmony_ci}; 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_civoid 301bf215546Sopenharmony_cifd6_resource_screen_init(struct pipe_screen *pscreen) 302bf215546Sopenharmony_ci{ 303bf215546Sopenharmony_ci struct fd_screen *screen = fd_screen(pscreen); 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci screen->setup_slices = fd6_setup_slices; 306bf215546Sopenharmony_ci screen->layout_resource_for_modifier = fd6_layout_resource_for_modifier; 307bf215546Sopenharmony_ci screen->supported_modifiers = supported_modifiers; 308bf215546Sopenharmony_ci screen->num_supported_modifiers = ARRAY_SIZE(supported_modifiers); 309bf215546Sopenharmony_ci} 310