1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2018 Rob Clark <robclark@freedesktop.org> 3bf215546Sopenharmony_ci * Copyright © 2018-2019 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 <stdio.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "freedreno_layout.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_civoid 33bf215546Sopenharmony_cifdl5_layout(struct fdl_layout *layout, enum pipe_format format, 34bf215546Sopenharmony_ci uint32_t nr_samples, uint32_t width0, uint32_t height0, 35bf215546Sopenharmony_ci uint32_t depth0, uint32_t mip_levels, uint32_t array_size, 36bf215546Sopenharmony_ci bool is_3d) 37bf215546Sopenharmony_ci{ 38bf215546Sopenharmony_ci assert(nr_samples > 0); 39bf215546Sopenharmony_ci layout->width0 = width0; 40bf215546Sopenharmony_ci layout->height0 = height0; 41bf215546Sopenharmony_ci layout->depth0 = depth0; 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci layout->cpp = util_format_get_blocksize(format); 44bf215546Sopenharmony_ci layout->cpp *= nr_samples; 45bf215546Sopenharmony_ci layout->cpp_shift = ffs(layout->cpp) - 1; 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci layout->format = format; 48bf215546Sopenharmony_ci layout->nr_samples = nr_samples; 49bf215546Sopenharmony_ci layout->layer_first = !is_3d; 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci uint32_t heightalign = layout->cpp == 1 ? 32 : 16; 52bf215546Sopenharmony_ci /* in layer_first layout, the level (slice) contains just one 53bf215546Sopenharmony_ci * layer (since in fact the layer contains the slices) 54bf215546Sopenharmony_ci */ 55bf215546Sopenharmony_ci uint32_t layers_in_level = layout->layer_first ? 1 : array_size; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci /* use 128 pixel alignment for cpp=1 and cpp=2 */ 58bf215546Sopenharmony_ci if (layout->cpp < 4 && layout->tile_mode) 59bf215546Sopenharmony_ci fdl_set_pitchalign(layout, fdl_cpp_shift(layout) + 7); 60bf215546Sopenharmony_ci else 61bf215546Sopenharmony_ci fdl_set_pitchalign(layout, fdl_cpp_shift(layout) + 6); 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci for (uint32_t level = 0; level < mip_levels; level++) { 64bf215546Sopenharmony_ci uint32_t depth = u_minify(depth0, level); 65bf215546Sopenharmony_ci struct fdl_slice *slice = &layout->slices[level]; 66bf215546Sopenharmony_ci uint32_t tile_mode = fdl_tile_mode(layout, level); 67bf215546Sopenharmony_ci uint32_t pitch = fdl_pitch(layout, level); 68bf215546Sopenharmony_ci uint32_t nblocksy = 69bf215546Sopenharmony_ci util_format_get_nblocksy(format, u_minify(height0, level)); 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci if (tile_mode) { 72bf215546Sopenharmony_ci nblocksy = align(nblocksy, heightalign); 73bf215546Sopenharmony_ci } else { 74bf215546Sopenharmony_ci /* The blits used for mem<->gmem work at a granularity of 75bf215546Sopenharmony_ci * 32x32, which can cause faults due to over-fetch on the 76bf215546Sopenharmony_ci * last level. The simple solution is to over-allocate a 77bf215546Sopenharmony_ci * bit the last level to ensure any over-fetch is harmless. 78bf215546Sopenharmony_ci * The pitch is already sufficiently aligned, but height 79bf215546Sopenharmony_ci * may not be: 80bf215546Sopenharmony_ci */ 81bf215546Sopenharmony_ci if (level == mip_levels - 1) 82bf215546Sopenharmony_ci nblocksy = align(nblocksy, 32); 83bf215546Sopenharmony_ci } 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci slice->offset = layout->size; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci /* 1d array and 2d array textures must all have the same layer size 88bf215546Sopenharmony_ci * for each miplevel on a3xx. 3d textures can have different layer 89bf215546Sopenharmony_ci * sizes for high levels, but the hw auto-sizer is buggy (or at least 90bf215546Sopenharmony_ci * different than what this code does), so as soon as the layer size 91bf215546Sopenharmony_ci * range gets into range, we stop reducing it. 92bf215546Sopenharmony_ci */ 93bf215546Sopenharmony_ci if (is_3d) { 94bf215546Sopenharmony_ci if (level <= 1 || layout->slices[level - 1].size0 > 0xf000) { 95bf215546Sopenharmony_ci slice->size0 = align(nblocksy * pitch, 4096); 96bf215546Sopenharmony_ci } else { 97bf215546Sopenharmony_ci slice->size0 = layout->slices[level - 1].size0; 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci } else { 100bf215546Sopenharmony_ci slice->size0 = nblocksy * pitch; 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci layout->size += slice->size0 * depth * layers_in_level; 104bf215546Sopenharmony_ci } 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci if (layout->layer_first) { 107bf215546Sopenharmony_ci layout->layer_size = align(layout->size, 4096); 108bf215546Sopenharmony_ci layout->size = layout->layer_size * array_size; 109bf215546Sopenharmony_ci } 110bf215546Sopenharmony_ci} 111