1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2016 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#ifndef ISL_SURFACE_STATE_H 25bf215546Sopenharmony_ci#define ISL_SURFACE_STATE_H 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include <stdint.h> 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci/** 30bf215546Sopenharmony_ci * @file isl_surface_state.h 31bf215546Sopenharmony_ci * 32bf215546Sopenharmony_ci * ============================= GENXML CODE ============================= 33bf215546Sopenharmony_ci * [This file is compiled once per generation.] 34bf215546Sopenharmony_ci * ======================================================================= 35bf215546Sopenharmony_ci * 36bf215546Sopenharmony_ci * Helpers for encoding SURFACE_STATE and XY_BLOCK_COPY_BLT commands. 37bf215546Sopenharmony_ci */ 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ciUNUSED static const uint8_t 40bf215546Sopenharmony_ciisl_encode_halign(uint8_t halign) 41bf215546Sopenharmony_ci{ 42bf215546Sopenharmony_ci switch (halign) { 43bf215546Sopenharmony_ci#if GFX_VERx10 >= 125 44bf215546Sopenharmony_ci case 16: return HALIGN_16; 45bf215546Sopenharmony_ci case 32: return HALIGN_32; 46bf215546Sopenharmony_ci case 64: return HALIGN_64; 47bf215546Sopenharmony_ci case 128: return HALIGN_128; 48bf215546Sopenharmony_ci#elif GFX_VER >= 8 49bf215546Sopenharmony_ci case 4: return HALIGN_4; 50bf215546Sopenharmony_ci case 8: return HALIGN_8; 51bf215546Sopenharmony_ci case 16: return HALIGN_16; 52bf215546Sopenharmony_ci#elif GFX_VER >= 7 53bf215546Sopenharmony_ci case 4: return HALIGN_4; 54bf215546Sopenharmony_ci case 8: return HALIGN_8; 55bf215546Sopenharmony_ci#endif 56bf215546Sopenharmony_ci default: unreachable("Invalid halign"); 57bf215546Sopenharmony_ci } 58bf215546Sopenharmony_ci} 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ciUNUSED static const uint8_t 61bf215546Sopenharmony_ciisl_encode_valign(uint8_t valign) 62bf215546Sopenharmony_ci{ 63bf215546Sopenharmony_ci switch (valign) { 64bf215546Sopenharmony_ci#if GFX_VER >= 8 65bf215546Sopenharmony_ci case 4: return VALIGN_4; 66bf215546Sopenharmony_ci case 8: return VALIGN_8; 67bf215546Sopenharmony_ci case 16: return VALIGN_16; 68bf215546Sopenharmony_ci#elif GFX_VER >= 6 69bf215546Sopenharmony_ci case 2: return VALIGN_2; 70bf215546Sopenharmony_ci case 4: return VALIGN_4; 71bf215546Sopenharmony_ci#endif 72bf215546Sopenharmony_ci default: unreachable("Invalid valign"); 73bf215546Sopenharmony_ci } 74bf215546Sopenharmony_ci} 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci/** 77bf215546Sopenharmony_ci * Get the horizontal and vertical alignment in the units expected by the 78bf215546Sopenharmony_ci * hardware. Note that this does NOT give you the actual hardware enum values 79bf215546Sopenharmony_ci * but an index into the isl_encode_[hv]align arrays above. 80bf215546Sopenharmony_ci */ 81bf215546Sopenharmony_ciUNUSED static struct isl_extent3d 82bf215546Sopenharmony_ciisl_get_image_alignment(const struct isl_surf *surf) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci if (GFX_VERx10 >= 125) { 85bf215546Sopenharmony_ci if (surf->tiling == ISL_TILING_64) { 86bf215546Sopenharmony_ci /* The hardware ignores the alignment values. Anyway, the surface's 87bf215546Sopenharmony_ci * true alignment is likely outside the enum range of HALIGN* and 88bf215546Sopenharmony_ci * VALIGN*. 89bf215546Sopenharmony_ci */ 90bf215546Sopenharmony_ci return isl_extent3d(128, 4, 1); 91bf215546Sopenharmony_ci } else if (isl_format_get_layout(surf->format)->bpb % 3 == 0) { 92bf215546Sopenharmony_ci /* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in 93bf215546Sopenharmony_ci * units of elements for 24, 48, and 96 bpb formats. 94bf215546Sopenharmony_ci */ 95bf215546Sopenharmony_ci return isl_surf_get_image_alignment_el(surf); 96bf215546Sopenharmony_ci } else { 97bf215546Sopenharmony_ci /* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in 98bf215546Sopenharmony_ci * units of bytes for formats that are powers of two. 99bf215546Sopenharmony_ci */ 100bf215546Sopenharmony_ci const uint32_t bs = isl_format_get_layout(surf->format)->bpb / 8; 101bf215546Sopenharmony_ci return isl_extent3d(surf->image_alignment_el.w * bs, 102bf215546Sopenharmony_ci surf->image_alignment_el.h, 103bf215546Sopenharmony_ci surf->image_alignment_el.d); 104bf215546Sopenharmony_ci } 105bf215546Sopenharmony_ci } else if (GFX_VER >= 9) { 106bf215546Sopenharmony_ci if (isl_tiling_is_std_y(surf->tiling) || 107bf215546Sopenharmony_ci surf->dim_layout == ISL_DIM_LAYOUT_GFX9_1D) { 108bf215546Sopenharmony_ci /* The hardware ignores the alignment values. Anyway, the surface's 109bf215546Sopenharmony_ci * true alignment is likely outside the enum range of HALIGN* and 110bf215546Sopenharmony_ci * VALIGN*. 111bf215546Sopenharmony_ci */ 112bf215546Sopenharmony_ci return isl_extent3d(4, 4, 1); 113bf215546Sopenharmony_ci } else { 114bf215546Sopenharmony_ci /* In Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in units 115bf215546Sopenharmony_ci * of surface elements (not pixels nor samples). For compressed formats, 116bf215546Sopenharmony_ci * a "surface element" is defined as a compression block. For example, 117bf215546Sopenharmony_ci * if SurfaceVerticalAlignment is VALIGN_4 and SurfaceFormat is an ETC2 118bf215546Sopenharmony_ci * format (ETC2 has a block height of 4), then the vertical alignment is 119bf215546Sopenharmony_ci * 4 compression blocks or, equivalently, 16 pixels. 120bf215546Sopenharmony_ci */ 121bf215546Sopenharmony_ci return isl_surf_get_image_alignment_el(surf); 122bf215546Sopenharmony_ci } 123bf215546Sopenharmony_ci } else { 124bf215546Sopenharmony_ci /* Pre-Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in 125bf215546Sopenharmony_ci * units of surface samples. For example, if SurfaceVerticalAlignment 126bf215546Sopenharmony_ci * is VALIGN_4 and the surface is singlesampled, then for any surface 127bf215546Sopenharmony_ci * format (compressed or not) the vertical alignment is 128bf215546Sopenharmony_ci * 4 pixels. 129bf215546Sopenharmony_ci */ 130bf215546Sopenharmony_ci return isl_surf_get_image_alignment_sa(surf); 131bf215546Sopenharmony_ci } 132bf215546Sopenharmony_ci} 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ciUNUSED static uint32_t 135bf215546Sopenharmony_ciisl_get_qpitch(const struct isl_surf *surf) 136bf215546Sopenharmony_ci{ 137bf215546Sopenharmony_ci switch (surf->dim_layout) { 138bf215546Sopenharmony_ci default: 139bf215546Sopenharmony_ci unreachable("Bad isl_surf_dim"); 140bf215546Sopenharmony_ci case ISL_DIM_LAYOUT_GFX4_2D: 141bf215546Sopenharmony_ci if (GFX_VER >= 9) { 142bf215546Sopenharmony_ci if (surf->dim == ISL_SURF_DIM_3D && surf->tiling == ISL_TILING_W) { 143bf215546Sopenharmony_ci /* This is rather annoying and completely undocumented. It 144bf215546Sopenharmony_ci * appears that the hardware has a bug (or undocumented feature) 145bf215546Sopenharmony_ci * regarding stencil buffers most likely related to the way 146bf215546Sopenharmony_ci * W-tiling is handled as modified Y-tiling. If you bind a 3-D 147bf215546Sopenharmony_ci * stencil buffer normally, and use texelFetch on it, the z or 148bf215546Sopenharmony_ci * array index will get implicitly multiplied by 2 for no obvious 149bf215546Sopenharmony_ci * reason. The fix appears to be to divide qpitch by 2 for 150bf215546Sopenharmony_ci * W-tiled surfaces. 151bf215546Sopenharmony_ci */ 152bf215546Sopenharmony_ci return isl_surf_get_array_pitch_el_rows(surf) / 2; 153bf215546Sopenharmony_ci } else { 154bf215546Sopenharmony_ci return isl_surf_get_array_pitch_el_rows(surf); 155bf215546Sopenharmony_ci } 156bf215546Sopenharmony_ci } else { 157bf215546Sopenharmony_ci /* From the Broadwell PRM for RENDER_SURFACE_STATE.QPitch 158bf215546Sopenharmony_ci * 159bf215546Sopenharmony_ci * "This field must be set to an integer multiple of the Surface 160bf215546Sopenharmony_ci * Vertical Alignment. For compressed textures (BC*, FXT1, 161bf215546Sopenharmony_ci * ETC*, and EAC* Surface Formats), this field is in units of 162bf215546Sopenharmony_ci * rows in the uncompressed surface, and must be set to an 163bf215546Sopenharmony_ci * integer multiple of the vertical alignment parameter "j" 164bf215546Sopenharmony_ci * defined in the Common Surface Formats section." 165bf215546Sopenharmony_ci */ 166bf215546Sopenharmony_ci return isl_surf_get_array_pitch_sa_rows(surf); 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci case ISL_DIM_LAYOUT_GFX9_1D: 169bf215546Sopenharmony_ci /* QPitch is usually expressed as rows of surface elements (where 170bf215546Sopenharmony_ci * a surface element is an compression block or a single surface 171bf215546Sopenharmony_ci * sample). Skylake 1D is an outlier. 172bf215546Sopenharmony_ci * 173bf215546Sopenharmony_ci * From the Skylake BSpec >> Memory Views >> Common Surface 174bf215546Sopenharmony_ci * Formats >> Surface Layout and Tiling >> 1D Surfaces: 175bf215546Sopenharmony_ci * 176bf215546Sopenharmony_ci * Surface QPitch specifies the distance in pixels between array 177bf215546Sopenharmony_ci * slices. 178bf215546Sopenharmony_ci */ 179bf215546Sopenharmony_ci return isl_surf_get_array_pitch_el(surf); 180bf215546Sopenharmony_ci case ISL_DIM_LAYOUT_GFX4_3D: 181bf215546Sopenharmony_ci /* QPitch doesn't make sense for ISL_DIM_LAYOUT_GFX4_3D since it uses a 182bf215546Sopenharmony_ci * different pitch at each LOD. Also, the QPitch field is ignored for 183bf215546Sopenharmony_ci * these surfaces. From the Broadwell PRM documentation for QPitch: 184bf215546Sopenharmony_ci * 185bf215546Sopenharmony_ci * This field specifies the distance in rows between array slices. It 186bf215546Sopenharmony_ci * is used only in the following cases: 187bf215546Sopenharmony_ci * - Surface Array is enabled OR 188bf215546Sopenharmony_ci * - Number of Mulitsamples is not NUMSAMPLES_1 and Multisampled 189bf215546Sopenharmony_ci * Surface Storage Format set to MSFMT_MSS OR 190bf215546Sopenharmony_ci * - Surface Type is SURFTYPE_CUBE 191bf215546Sopenharmony_ci * 192bf215546Sopenharmony_ci * None of the three conditions above can possibly apply to a 3D surface 193bf215546Sopenharmony_ci * so it is safe to just set QPitch to 0. 194bf215546Sopenharmony_ci */ 195bf215546Sopenharmony_ci return 0; 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci} 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci#endif 200