101e04c3fSmrg/* 201e04c3fSmrg * Copyright 2015 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 2401e04c3fSmrg#include <assert.h> 2501e04c3fSmrg#include <stdarg.h> 2601e04c3fSmrg#include <stdio.h> 2701e04c3fSmrg 2801e04c3fSmrg#include "genxml/genX_bits.h" 2901e04c3fSmrg 3001e04c3fSmrg#include "isl.h" 317ec681f3Smrg#include "isl_gfx4.h" 327ec681f3Smrg#include "isl_gfx6.h" 337ec681f3Smrg#include "isl_gfx7.h" 347ec681f3Smrg#include "isl_gfx8.h" 357ec681f3Smrg#include "isl_gfx9.h" 367ec681f3Smrg#include "isl_gfx12.h" 3701e04c3fSmrg#include "isl_priv.h" 3801e04c3fSmrg 399f464c52Smayavoid 409f464c52Smayaisl_memcpy_linear_to_tiled(uint32_t xt1, uint32_t xt2, 419f464c52Smaya uint32_t yt1, uint32_t yt2, 429f464c52Smaya char *dst, const char *src, 439f464c52Smaya uint32_t dst_pitch, int32_t src_pitch, 449f464c52Smaya bool has_swizzling, 459f464c52Smaya enum isl_tiling tiling, 469f464c52Smaya isl_memcpy_type copy_type) 479f464c52Smaya{ 489f464c52Smaya#ifdef USE_SSE41 499f464c52Smaya if (copy_type == ISL_MEMCPY_STREAMING_LOAD) { 509f464c52Smaya _isl_memcpy_linear_to_tiled_sse41( 519f464c52Smaya xt1, xt2, yt1, yt2, dst, src, dst_pitch, src_pitch, has_swizzling, 529f464c52Smaya tiling, copy_type); 539f464c52Smaya return; 549f464c52Smaya } 559f464c52Smaya#endif 569f464c52Smaya 579f464c52Smaya _isl_memcpy_linear_to_tiled( 589f464c52Smaya xt1, xt2, yt1, yt2, dst, src, dst_pitch, src_pitch, has_swizzling, 599f464c52Smaya tiling, copy_type); 609f464c52Smaya} 619f464c52Smaya 629f464c52Smayavoid 639f464c52Smayaisl_memcpy_tiled_to_linear(uint32_t xt1, uint32_t xt2, 649f464c52Smaya uint32_t yt1, uint32_t yt2, 659f464c52Smaya char *dst, const char *src, 669f464c52Smaya int32_t dst_pitch, uint32_t src_pitch, 679f464c52Smaya bool has_swizzling, 689f464c52Smaya enum isl_tiling tiling, 699f464c52Smaya isl_memcpy_type copy_type) 709f464c52Smaya{ 719f464c52Smaya#ifdef USE_SSE41 729f464c52Smaya if (copy_type == ISL_MEMCPY_STREAMING_LOAD) { 739f464c52Smaya _isl_memcpy_tiled_to_linear_sse41( 749f464c52Smaya xt1, xt2, yt1, yt2, dst, src, dst_pitch, src_pitch, has_swizzling, 759f464c52Smaya tiling, copy_type); 769f464c52Smaya return; 779f464c52Smaya } 789f464c52Smaya#endif 799f464c52Smaya 809f464c52Smaya _isl_memcpy_tiled_to_linear( 819f464c52Smaya xt1, xt2, yt1, yt2, dst, src, dst_pitch, src_pitch, has_swizzling, 829f464c52Smaya tiling, copy_type); 839f464c52Smaya} 849f464c52Smaya 8501e04c3fSmrgvoid PRINTFLIKE(3, 4) UNUSED 8601e04c3fSmrg__isl_finishme(const char *file, int line, const char *fmt, ...) 8701e04c3fSmrg{ 8801e04c3fSmrg va_list ap; 8901e04c3fSmrg char buf[512]; 9001e04c3fSmrg 9101e04c3fSmrg va_start(ap, fmt); 9201e04c3fSmrg vsnprintf(buf, sizeof(buf), fmt, ap); 9301e04c3fSmrg va_end(ap); 9401e04c3fSmrg 9501e04c3fSmrg fprintf(stderr, "%s:%d: FINISHME: %s\n", file, line, buf); 9601e04c3fSmrg} 9701e04c3fSmrg 987ec681f3Smrgstatic void 997ec681f3Smrgisl_device_setup_mocs(struct isl_device *dev) 1007ec681f3Smrg{ 1017ec681f3Smrg if (dev->info->ver >= 12) { 1027ec681f3Smrg if (dev->info->is_dg2) { 1037ec681f3Smrg /* L3CC=WB; BSpec: 45101 */ 1047ec681f3Smrg dev->mocs.internal = 3 << 1; 1057ec681f3Smrg dev->mocs.external = 3 << 1; 1067ec681f3Smrg } else if (dev->info->is_dg1) { 1077ec681f3Smrg /* L3CC=WB */ 1087ec681f3Smrg dev->mocs.internal = 5 << 1; 1097ec681f3Smrg /* Displayables on DG1 are free to cache in L3 since L3 is transient 1107ec681f3Smrg * and flushed at bottom of each submission. 1117ec681f3Smrg */ 1127ec681f3Smrg dev->mocs.external = 5 << 1; 1137ec681f3Smrg } else { 1147ec681f3Smrg /* TC=1/LLC Only, LeCC=1/UC, LRUM=0, L3CC=3/WB */ 1157ec681f3Smrg dev->mocs.external = 61 << 1; 1167ec681f3Smrg /* TC=LLC/eLLC, LeCC=WB, LRUM=3, L3CC=WB */ 1177ec681f3Smrg dev->mocs.internal = 2 << 1; 1187ec681f3Smrg 1197ec681f3Smrg /* L1 - HDC:L1 + L3 + LLC */ 1207ec681f3Smrg dev->mocs.l1_hdc_l3_llc = 48 << 1; 1217ec681f3Smrg } 1227ec681f3Smrg } else if (dev->info->ver >= 9) { 1237ec681f3Smrg /* TC=LLC/eLLC, LeCC=PTE, LRUM=3, L3CC=WB */ 1247ec681f3Smrg dev->mocs.external = 1 << 1; 1257ec681f3Smrg /* TC=LLC/eLLC, LeCC=WB, LRUM=3, L3CC=WB */ 1267ec681f3Smrg dev->mocs.internal = 2 << 1; 1277ec681f3Smrg } else if (dev->info->ver >= 8) { 1287ec681f3Smrg /* MEMORY_OBJECT_CONTROL_STATE: 1297ec681f3Smrg * .MemoryTypeLLCeLLCCacheabilityControl = UCwithFenceifcoherentcycle, 1307ec681f3Smrg * .TargetCache = L3DefertoPATforLLCeLLCselection, 1317ec681f3Smrg * .AgeforQUADLRU = 0 1327ec681f3Smrg */ 1337ec681f3Smrg dev->mocs.external = 0x18; 1347ec681f3Smrg /* MEMORY_OBJECT_CONTROL_STATE: 1357ec681f3Smrg * .MemoryTypeLLCeLLCCacheabilityControl = WB, 1367ec681f3Smrg * .TargetCache = L3DefertoPATforLLCeLLCselection, 1377ec681f3Smrg * .AgeforQUADLRU = 0 1387ec681f3Smrg */ 1397ec681f3Smrg dev->mocs.internal = 0x78; 1407ec681f3Smrg } else if (dev->info->ver >= 7) { 1417ec681f3Smrg if (dev->info->is_haswell) { 1427ec681f3Smrg /* MEMORY_OBJECT_CONTROL_STATE: 1437ec681f3Smrg * .LLCeLLCCacheabilityControlLLCCC = 0, 1447ec681f3Smrg * .L3CacheabilityControlL3CC = 1, 1457ec681f3Smrg */ 1467ec681f3Smrg dev->mocs.internal = 1; 1477ec681f3Smrg dev->mocs.external = 1; 1487ec681f3Smrg } else { 1497ec681f3Smrg /* MEMORY_OBJECT_CONTROL_STATE: 1507ec681f3Smrg * .GraphicsDataTypeGFDT = 0, 1517ec681f3Smrg * .LLCCacheabilityControlLLCCC = 0, 1527ec681f3Smrg * .L3CacheabilityControlL3CC = 1, 1537ec681f3Smrg */ 1547ec681f3Smrg dev->mocs.internal = 1; 1557ec681f3Smrg dev->mocs.external = 1; 1567ec681f3Smrg } 1577ec681f3Smrg } else { 1587ec681f3Smrg dev->mocs.internal = 0; 1597ec681f3Smrg dev->mocs.external = 0; 1607ec681f3Smrg } 1617ec681f3Smrg} 1627ec681f3Smrg 1637ec681f3Smrg/** 1647ec681f3Smrg * Return an appropriate MOCS entry for the given usage flags. 1657ec681f3Smrg */ 1667ec681f3Smrguint32_t 1677ec681f3Smrgisl_mocs(const struct isl_device *dev, isl_surf_usage_flags_t usage, 1687ec681f3Smrg bool external) 1697ec681f3Smrg{ 1707ec681f3Smrg if (external) 1717ec681f3Smrg return dev->mocs.external; 1727ec681f3Smrg 1737ec681f3Smrg if (dev->info->ver >= 12 && !dev->info->is_dg1) { 1747ec681f3Smrg if (usage & ISL_SURF_USAGE_STAGING_BIT) 1757ec681f3Smrg return dev->mocs.internal; 1767ec681f3Smrg 1777ec681f3Smrg /* Using L1:HDC for storage buffers breaks Vulkan memory model 1787ec681f3Smrg * tests that use shader atomics. This isn't likely to work out, 1797ec681f3Smrg * and we can't know a priori whether they'll be used. So just 1807ec681f3Smrg * continue with ordinary internal MOCS for now. 1817ec681f3Smrg */ 1827ec681f3Smrg if (usage & ISL_SURF_USAGE_STORAGE_BIT) 1837ec681f3Smrg return dev->mocs.internal; 1847ec681f3Smrg 1857ec681f3Smrg if (usage & (ISL_SURF_USAGE_CONSTANT_BUFFER_BIT | 1867ec681f3Smrg ISL_SURF_USAGE_RENDER_TARGET_BIT | 1877ec681f3Smrg ISL_SURF_USAGE_TEXTURE_BIT)) 1887ec681f3Smrg return dev->mocs.l1_hdc_l3_llc; 1897ec681f3Smrg } 1907ec681f3Smrg 1917ec681f3Smrg return dev->mocs.internal; 1927ec681f3Smrg} 1937ec681f3Smrg 19401e04c3fSmrgvoid 19501e04c3fSmrgisl_device_init(struct isl_device *dev, 1967ec681f3Smrg const struct intel_device_info *info, 19701e04c3fSmrg bool has_bit6_swizzling) 19801e04c3fSmrg{ 1997ec681f3Smrg /* Gfx8+ don't have bit6 swizzling, ensure callsite is not confused. */ 2007ec681f3Smrg assert(!(has_bit6_swizzling && info->ver >= 8)); 2019f464c52Smaya 20201e04c3fSmrg dev->info = info; 2037ec681f3Smrg dev->use_separate_stencil = ISL_GFX_VER(dev) >= 6; 20401e04c3fSmrg dev->has_bit6_swizzling = has_bit6_swizzling; 20501e04c3fSmrg 20601e04c3fSmrg /* The ISL_DEV macros may be defined in the CFLAGS, thus hardcoding some 20701e04c3fSmrg * device properties at buildtime. Verify that the macros with the device 20801e04c3fSmrg * properties chosen during runtime. 20901e04c3fSmrg */ 2107ec681f3Smrg ISL_GFX_VER_SANITIZE(dev); 21101e04c3fSmrg ISL_DEV_USE_SEPARATE_STENCIL_SANITIZE(dev); 21201e04c3fSmrg 21301e04c3fSmrg /* Did we break hiz or stencil? */ 21401e04c3fSmrg if (ISL_DEV_USE_SEPARATE_STENCIL(dev)) 21501e04c3fSmrg assert(info->has_hiz_and_separate_stencil); 21601e04c3fSmrg if (info->must_use_separate_stencil) 21701e04c3fSmrg assert(ISL_DEV_USE_SEPARATE_STENCIL(dev)); 21801e04c3fSmrg 21901e04c3fSmrg dev->ss.size = RENDER_SURFACE_STATE_length(info) * 4; 22001e04c3fSmrg dev->ss.align = isl_align(dev->ss.size, 32); 22101e04c3fSmrg 2229f464c52Smaya dev->ss.clear_color_state_size = 2239f464c52Smaya isl_align(CLEAR_COLOR_length(info) * 4, 64); 22401e04c3fSmrg dev->ss.clear_color_state_offset = 22501e04c3fSmrg RENDER_SURFACE_STATE_ClearValueAddress_start(info) / 32 * 4; 22601e04c3fSmrg 22701e04c3fSmrg dev->ss.clear_value_size = 22801e04c3fSmrg isl_align(RENDER_SURFACE_STATE_RedClearColor_bits(info) + 22901e04c3fSmrg RENDER_SURFACE_STATE_GreenClearColor_bits(info) + 23001e04c3fSmrg RENDER_SURFACE_STATE_BlueClearColor_bits(info) + 23101e04c3fSmrg RENDER_SURFACE_STATE_AlphaClearColor_bits(info), 32) / 8; 23201e04c3fSmrg 23301e04c3fSmrg dev->ss.clear_value_offset = 23401e04c3fSmrg RENDER_SURFACE_STATE_RedClearColor_start(info) / 32 * 4; 23501e04c3fSmrg 23601e04c3fSmrg assert(RENDER_SURFACE_STATE_SurfaceBaseAddress_start(info) % 8 == 0); 23701e04c3fSmrg dev->ss.addr_offset = 23801e04c3fSmrg RENDER_SURFACE_STATE_SurfaceBaseAddress_start(info) / 8; 23901e04c3fSmrg 24001e04c3fSmrg /* The "Auxiliary Surface Base Address" field starts a bit higher up 24101e04c3fSmrg * because the bottom 12 bits are used for other things. Round down to 24201e04c3fSmrg * the nearest dword before. 24301e04c3fSmrg */ 24401e04c3fSmrg dev->ss.aux_addr_offset = 24501e04c3fSmrg (RENDER_SURFACE_STATE_AuxiliarySurfaceBaseAddress_start(info) & ~31) / 8; 24601e04c3fSmrg 24701e04c3fSmrg dev->ds.size = _3DSTATE_DEPTH_BUFFER_length(info) * 4; 24801e04c3fSmrg assert(_3DSTATE_DEPTH_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); 24901e04c3fSmrg dev->ds.depth_offset = 25001e04c3fSmrg _3DSTATE_DEPTH_BUFFER_SurfaceBaseAddress_start(info) / 8; 25101e04c3fSmrg 25201e04c3fSmrg if (dev->use_separate_stencil) { 25301e04c3fSmrg dev->ds.size += _3DSTATE_STENCIL_BUFFER_length(info) * 4 + 25401e04c3fSmrg _3DSTATE_HIER_DEPTH_BUFFER_length(info) * 4 + 25501e04c3fSmrg _3DSTATE_CLEAR_PARAMS_length(info) * 4; 25601e04c3fSmrg 25701e04c3fSmrg assert(_3DSTATE_STENCIL_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); 25801e04c3fSmrg dev->ds.stencil_offset = 25901e04c3fSmrg _3DSTATE_DEPTH_BUFFER_length(info) * 4 + 26001e04c3fSmrg _3DSTATE_STENCIL_BUFFER_SurfaceBaseAddress_start(info) / 8; 26101e04c3fSmrg 26201e04c3fSmrg assert(_3DSTATE_HIER_DEPTH_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); 26301e04c3fSmrg dev->ds.hiz_offset = 26401e04c3fSmrg _3DSTATE_DEPTH_BUFFER_length(info) * 4 + 26501e04c3fSmrg _3DSTATE_STENCIL_BUFFER_length(info) * 4 + 26601e04c3fSmrg _3DSTATE_HIER_DEPTH_BUFFER_SurfaceBaseAddress_start(info) / 8; 26701e04c3fSmrg } else { 26801e04c3fSmrg dev->ds.stencil_offset = 0; 26901e04c3fSmrg dev->ds.hiz_offset = 0; 27001e04c3fSmrg } 2717ec681f3Smrg 2727ec681f3Smrg if (ISL_GFX_VER(dev) >= 7) { 2737ec681f3Smrg /* From the IVB PRM, SURFACE_STATE::Height, 2747ec681f3Smrg * 2757ec681f3Smrg * For typed buffer and structured buffer surfaces, the number 2767ec681f3Smrg * of entries in the buffer ranges from 1 to 2^27. For raw buffer 2777ec681f3Smrg * surfaces, the number of entries in the buffer is the number of bytes 2787ec681f3Smrg * which can range from 1 to 2^30. 2797ec681f3Smrg * 2807ec681f3Smrg * This limit is only concerned with raw buffers. 2817ec681f3Smrg */ 2827ec681f3Smrg dev->max_buffer_size = 1ull << 30; 2837ec681f3Smrg } else { 2847ec681f3Smrg dev->max_buffer_size = 1ull << 27; 2857ec681f3Smrg } 2867ec681f3Smrg 2877ec681f3Smrg isl_device_setup_mocs(dev); 28801e04c3fSmrg} 28901e04c3fSmrg 29001e04c3fSmrg/** 29101e04c3fSmrg * @brief Query the set of multisamples supported by the device. 29201e04c3fSmrg * 29301e04c3fSmrg * This function always returns non-zero, as ISL_SAMPLE_COUNT_1_BIT is always 29401e04c3fSmrg * supported. 29501e04c3fSmrg */ 29601e04c3fSmrgisl_sample_count_mask_t ATTRIBUTE_CONST 29701e04c3fSmrgisl_device_get_sample_counts(struct isl_device *dev) 29801e04c3fSmrg{ 2997ec681f3Smrg if (ISL_GFX_VER(dev) >= 9) { 30001e04c3fSmrg return ISL_SAMPLE_COUNT_1_BIT | 30101e04c3fSmrg ISL_SAMPLE_COUNT_2_BIT | 30201e04c3fSmrg ISL_SAMPLE_COUNT_4_BIT | 30301e04c3fSmrg ISL_SAMPLE_COUNT_8_BIT | 30401e04c3fSmrg ISL_SAMPLE_COUNT_16_BIT; 3057ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 8) { 30601e04c3fSmrg return ISL_SAMPLE_COUNT_1_BIT | 30701e04c3fSmrg ISL_SAMPLE_COUNT_2_BIT | 30801e04c3fSmrg ISL_SAMPLE_COUNT_4_BIT | 30901e04c3fSmrg ISL_SAMPLE_COUNT_8_BIT; 3107ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 7) { 31101e04c3fSmrg return ISL_SAMPLE_COUNT_1_BIT | 31201e04c3fSmrg ISL_SAMPLE_COUNT_4_BIT | 31301e04c3fSmrg ISL_SAMPLE_COUNT_8_BIT; 3147ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 6) { 31501e04c3fSmrg return ISL_SAMPLE_COUNT_1_BIT | 31601e04c3fSmrg ISL_SAMPLE_COUNT_4_BIT; 31701e04c3fSmrg } else { 31801e04c3fSmrg return ISL_SAMPLE_COUNT_1_BIT; 31901e04c3fSmrg } 32001e04c3fSmrg} 32101e04c3fSmrg 32201e04c3fSmrg/** 3237ec681f3Smrg * Returns an isl_tile_info representation of the given isl_tiling when 3247ec681f3Smrg * combined when used in the given configuration. 3257ec681f3Smrg * 3267ec681f3Smrg * @param[in] tiling The tiling format to introspect 3277ec681f3Smrg * @param[in] dim The dimensionality of the surface being tiled 3287ec681f3Smrg * @param[in] msaa_layout The layout of samples in the surface being tiled 3297ec681f3Smrg * @param[in] format_bpb The number of bits per surface element (block) for 3307ec681f3Smrg * the surface being tiled 3317ec681f3Smrg * @param[in] samples The samples in the surface being tiled 3327ec681f3Smrg * @param[out] tile_info Return parameter for the tiling information 33301e04c3fSmrg */ 3347ec681f3Smrgvoid 33501e04c3fSmrgisl_tiling_get_info(enum isl_tiling tiling, 3367ec681f3Smrg enum isl_surf_dim dim, 3377ec681f3Smrg enum isl_msaa_layout msaa_layout, 33801e04c3fSmrg uint32_t format_bpb, 3397ec681f3Smrg uint32_t samples, 34001e04c3fSmrg struct isl_tile_info *tile_info) 34101e04c3fSmrg{ 34201e04c3fSmrg const uint32_t bs = format_bpb / 8; 3437ec681f3Smrg struct isl_extent4d logical_el; 3447ec681f3Smrg struct isl_extent2d phys_B; 34501e04c3fSmrg 34601e04c3fSmrg if (tiling != ISL_TILING_LINEAR && !isl_is_pow2(format_bpb)) { 34701e04c3fSmrg /* It is possible to have non-power-of-two formats in a tiled buffer. 34801e04c3fSmrg * The easiest way to handle this is to treat the tile as if it is three 34901e04c3fSmrg * times as wide. This way no pixel will ever cross a tile boundary. 3507ec681f3Smrg * This really only works on a subset of tiling formats. 35101e04c3fSmrg */ 3527ec681f3Smrg assert(tiling == ISL_TILING_X || tiling == ISL_TILING_Y0 || 3537ec681f3Smrg tiling == ISL_TILING_4); 35401e04c3fSmrg assert(bs % 3 == 0 && isl_is_pow2(format_bpb / 3)); 3557ec681f3Smrg isl_tiling_get_info(tiling, dim, msaa_layout, format_bpb / 3, samples, 3567ec681f3Smrg tile_info); 35701e04c3fSmrg return; 35801e04c3fSmrg } 35901e04c3fSmrg 36001e04c3fSmrg switch (tiling) { 36101e04c3fSmrg case ISL_TILING_LINEAR: 36201e04c3fSmrg assert(bs > 0); 3637ec681f3Smrg logical_el = isl_extent4d(1, 1, 1, 1); 36401e04c3fSmrg phys_B = isl_extent2d(bs, 1); 36501e04c3fSmrg break; 36601e04c3fSmrg 36701e04c3fSmrg case ISL_TILING_X: 36801e04c3fSmrg assert(bs > 0); 3697ec681f3Smrg logical_el = isl_extent4d(512 / bs, 8, 1, 1); 37001e04c3fSmrg phys_B = isl_extent2d(512, 8); 37101e04c3fSmrg break; 37201e04c3fSmrg 37301e04c3fSmrg case ISL_TILING_Y0: 3747ec681f3Smrg case ISL_TILING_4: 37501e04c3fSmrg assert(bs > 0); 3767ec681f3Smrg logical_el = isl_extent4d(128 / bs, 32, 1, 1); 37701e04c3fSmrg phys_B = isl_extent2d(128, 32); 37801e04c3fSmrg break; 37901e04c3fSmrg 38001e04c3fSmrg case ISL_TILING_W: 38101e04c3fSmrg assert(bs == 1); 3827ec681f3Smrg logical_el = isl_extent4d(64, 64, 1, 1); 38301e04c3fSmrg /* From the Broadwell PRM Vol 2d, RENDER_SURFACE_STATE::SurfacePitch: 38401e04c3fSmrg * 38501e04c3fSmrg * "If the surface is a stencil buffer (and thus has Tile Mode set 38601e04c3fSmrg * to TILEMODE_WMAJOR), the pitch must be set to 2x the value 38701e04c3fSmrg * computed based on width, as the stencil buffer is stored with two 38801e04c3fSmrg * rows interleaved." 38901e04c3fSmrg * 39001e04c3fSmrg * This, together with the fact that stencil buffers are referred to as 39101e04c3fSmrg * being Y-tiled in the PRMs for older hardware implies that the 39201e04c3fSmrg * physical size of a W-tile is actually the same as for a Y-tile. 39301e04c3fSmrg */ 39401e04c3fSmrg phys_B = isl_extent2d(128, 32); 39501e04c3fSmrg break; 39601e04c3fSmrg 39701e04c3fSmrg case ISL_TILING_Yf: 39801e04c3fSmrg case ISL_TILING_Ys: { 39901e04c3fSmrg bool is_Ys = tiling == ISL_TILING_Ys; 40001e04c3fSmrg 40101e04c3fSmrg assert(bs > 0); 40201e04c3fSmrg unsigned width = 1 << (6 + (ffs(bs) / 2) + (2 * is_Ys)); 40301e04c3fSmrg unsigned height = 1 << (6 - (ffs(bs) / 2) + (2 * is_Ys)); 40401e04c3fSmrg 4057ec681f3Smrg logical_el = isl_extent4d(width / bs, height, 1, 1); 40601e04c3fSmrg phys_B = isl_extent2d(width, height); 40701e04c3fSmrg break; 40801e04c3fSmrg } 4097ec681f3Smrg case ISL_TILING_64: 4107ec681f3Smrg /* The tables below are taken from the "2D Surfaces" page in the Bspec 4117ec681f3Smrg * which are formulated in terms of the Cv and Cu constants. This is 4127ec681f3Smrg * different from the tables in the "Tile64 Format" page which should be 4137ec681f3Smrg * equivalent but are usually in terms of pixels. Also note that Cv and 4147ec681f3Smrg * Cu are HxW order to match the Bspec table, not WxH order like you 4157ec681f3Smrg * might expect. 4167ec681f3Smrg * 4177ec681f3Smrg * From the Bspec's "Tile64 Format" page: 4187ec681f3Smrg * 4197ec681f3Smrg * MSAA Depth/Stencil surface use IMS (Interleaved Multi Samples) 4207ec681f3Smrg * which means: 4217ec681f3Smrg * 4227ec681f3Smrg * - Use the 1X MSAA (non-MSRT) version of the Tile64 equations and 4237ec681f3Smrg * let the client unit do the swizzling internally 4247ec681f3Smrg * 4257ec681f3Smrg * Surfaces using the IMS layout will use the mapping for 1x MSAA. 4267ec681f3Smrg */ 4277ec681f3Smrg#define tile_extent(bs, cv, cu, a) \ 4287ec681f3Smrg isl_extent4d((1 << cu) / bs, 1 << cv, 1, a) 4297ec681f3Smrg 4307ec681f3Smrg /* Only 2D surfaces are handled. */ 4317ec681f3Smrg assert(dim == ISL_SURF_DIM_2D); 4327ec681f3Smrg 4337ec681f3Smrg if (samples == 1 || msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED) { 4347ec681f3Smrg switch (format_bpb) { 4357ec681f3Smrg case 128: logical_el = tile_extent(bs, 6, 10, 1); break; 4367ec681f3Smrg case 64: logical_el = tile_extent(bs, 6, 10, 1); break; 4377ec681f3Smrg case 32: logical_el = tile_extent(bs, 7, 9, 1); break; 4387ec681f3Smrg case 16: logical_el = tile_extent(bs, 7, 9, 1); break; 4397ec681f3Smrg case 8: logical_el = tile_extent(bs, 8, 8, 1); break; 4407ec681f3Smrg default: unreachable("Unsupported format size."); 4417ec681f3Smrg } 4427ec681f3Smrg } else if (samples == 2) { 4437ec681f3Smrg switch (format_bpb) { 4447ec681f3Smrg case 128: logical_el = tile_extent(bs, 6, 9, 2); break; 4457ec681f3Smrg case 64: logical_el = tile_extent(bs, 6, 9, 2); break; 4467ec681f3Smrg case 32: logical_el = tile_extent(bs, 7, 8, 2); break; 4477ec681f3Smrg case 16: logical_el = tile_extent(bs, 7, 8, 2); break; 4487ec681f3Smrg case 8: logical_el = tile_extent(bs, 8, 7, 2); break; 4497ec681f3Smrg default: unreachable("Unsupported format size."); 4507ec681f3Smrg } 4517ec681f3Smrg } else { 4527ec681f3Smrg switch (format_bpb) { 4537ec681f3Smrg case 128: logical_el = tile_extent(bs, 5, 9, 4); break; 4547ec681f3Smrg case 64: logical_el = tile_extent(bs, 5, 9, 4); break; 4557ec681f3Smrg case 32: logical_el = tile_extent(bs, 6, 8, 4); break; 4567ec681f3Smrg case 16: logical_el = tile_extent(bs, 6, 8, 4); break; 4577ec681f3Smrg case 8: logical_el = tile_extent(bs, 7, 7, 4); break; 4587ec681f3Smrg default: unreachable("Unsupported format size."); 4597ec681f3Smrg } 4607ec681f3Smrg } 4617ec681f3Smrg 4627ec681f3Smrg#undef tile_extent 4637ec681f3Smrg 4647ec681f3Smrg phys_B.w = logical_el.w * bs; 4657ec681f3Smrg phys_B.h = 64 * 1024 / phys_B.w; 4667ec681f3Smrg break; 46701e04c3fSmrg 46801e04c3fSmrg case ISL_TILING_HIZ: 46901e04c3fSmrg /* HiZ buffers are required to have ISL_FORMAT_HIZ which is an 8x4 47001e04c3fSmrg * 128bpb format. The tiling has the same physical dimensions as 47101e04c3fSmrg * Y-tiling but actually has two HiZ columns per Y-tiled column. 47201e04c3fSmrg */ 47301e04c3fSmrg assert(bs == 16); 4747ec681f3Smrg logical_el = isl_extent4d(16, 16, 1, 1); 47501e04c3fSmrg phys_B = isl_extent2d(128, 32); 47601e04c3fSmrg break; 47701e04c3fSmrg 47801e04c3fSmrg case ISL_TILING_CCS: 47901e04c3fSmrg /* CCS surfaces are required to have one of the GENX_CCS_* formats which 48001e04c3fSmrg * have a block size of 1 or 2 bits per block and each CCS element 48101e04c3fSmrg * corresponds to one cache-line pair in the main surface. From the Sky 48201e04c3fSmrg * Lake PRM Vol. 12 in the section on planes: 48301e04c3fSmrg * 48401e04c3fSmrg * "The Color Control Surface (CCS) contains the compression status 48501e04c3fSmrg * of the cache-line pairs. The compression state of the cache-line 48601e04c3fSmrg * pair is specified by 2 bits in the CCS. Each CCS cache-line 48701e04c3fSmrg * represents an area on the main surface of 16x16 sets of 128 byte 48801e04c3fSmrg * Y-tiled cache-line-pairs. CCS is always Y tiled." 48901e04c3fSmrg * 49001e04c3fSmrg * The CCS being Y-tiled implies that it's an 8x8 grid of cache-lines. 49101e04c3fSmrg * Since each cache line corresponds to a 16x16 set of cache-line pairs, 49201e04c3fSmrg * that yields total tile area of 128x128 cache-line pairs or CCS 49301e04c3fSmrg * elements. On older hardware, each CCS element is 1 bit and the tile 49401e04c3fSmrg * is 128x256 elements. 49501e04c3fSmrg */ 49601e04c3fSmrg assert(format_bpb == 1 || format_bpb == 2); 4977ec681f3Smrg logical_el = isl_extent4d(128, 256 / format_bpb, 1, 1); 49801e04c3fSmrg phys_B = isl_extent2d(128, 32); 49901e04c3fSmrg break; 50001e04c3fSmrg 5017ec681f3Smrg case ISL_TILING_GFX12_CCS: 5027ec681f3Smrg /* From the Bspec, Gen Graphics > Gfx12 > Memory Data Formats > Memory 5037ec681f3Smrg * Compression > Memory Compression - Gfx12: 5047ec681f3Smrg * 5057ec681f3Smrg * 4 bits of auxiliary plane data are required for 2 cachelines of 5067ec681f3Smrg * main surface data. This results in a single cacheline of auxiliary 5077ec681f3Smrg * plane data mapping to 4 4K pages of main surface data for the 4K 5087ec681f3Smrg * pages (tile Y ) and 1 64K Tile Ys page. 5097ec681f3Smrg * 5107ec681f3Smrg * The Y-tiled pairing bit of 9 shown in the table below that Bspec 5117ec681f3Smrg * section expresses that the 2 cachelines of main surface data are 5127ec681f3Smrg * horizontally adjacent. 5137ec681f3Smrg * 5147ec681f3Smrg * TODO: Handle Ys, Yf and their pairing bits. 5157ec681f3Smrg * 5167ec681f3Smrg * Therefore, each CCS cacheline represents a 512Bx32 row area and each 5177ec681f3Smrg * element represents a 32Bx4 row area. 5187ec681f3Smrg */ 5197ec681f3Smrg assert(format_bpb == 4); 5207ec681f3Smrg logical_el = isl_extent4d(16, 8, 1, 1); 5217ec681f3Smrg phys_B = isl_extent2d(64, 1); 5227ec681f3Smrg break; 5237ec681f3Smrg 52401e04c3fSmrg default: 52501e04c3fSmrg unreachable("not reached"); 52601e04c3fSmrg } /* end switch */ 52701e04c3fSmrg 52801e04c3fSmrg *tile_info = (struct isl_tile_info) { 52901e04c3fSmrg .tiling = tiling, 53001e04c3fSmrg .format_bpb = format_bpb, 53101e04c3fSmrg .logical_extent_el = logical_el, 53201e04c3fSmrg .phys_extent_B = phys_B, 53301e04c3fSmrg }; 53401e04c3fSmrg} 53501e04c3fSmrg 53601e04c3fSmrgbool 53701e04c3fSmrgisl_color_value_is_zero(union isl_color_value value, 53801e04c3fSmrg enum isl_format format) 53901e04c3fSmrg{ 54001e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(format); 54101e04c3fSmrg 54201e04c3fSmrg#define RETURN_FALSE_IF_NOT_0(c, i) \ 54301e04c3fSmrg if (fmtl->channels.c.bits && value.u32[i] != 0) \ 54401e04c3fSmrg return false 54501e04c3fSmrg 54601e04c3fSmrg RETURN_FALSE_IF_NOT_0(r, 0); 54701e04c3fSmrg RETURN_FALSE_IF_NOT_0(g, 1); 54801e04c3fSmrg RETURN_FALSE_IF_NOT_0(b, 2); 54901e04c3fSmrg RETURN_FALSE_IF_NOT_0(a, 3); 55001e04c3fSmrg 55101e04c3fSmrg#undef RETURN_FALSE_IF_NOT_0 55201e04c3fSmrg 55301e04c3fSmrg return true; 55401e04c3fSmrg} 55501e04c3fSmrg 55601e04c3fSmrgbool 55701e04c3fSmrgisl_color_value_is_zero_one(union isl_color_value value, 55801e04c3fSmrg enum isl_format format) 55901e04c3fSmrg{ 56001e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(format); 56101e04c3fSmrg 56201e04c3fSmrg#define RETURN_FALSE_IF_NOT_0_1(c, i, field) \ 56301e04c3fSmrg if (fmtl->channels.c.bits && value.field[i] != 0 && value.field[i] != 1) \ 56401e04c3fSmrg return false 56501e04c3fSmrg 56601e04c3fSmrg if (isl_format_has_int_channel(format)) { 56701e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(r, 0, u32); 56801e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(g, 1, u32); 56901e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(b, 2, u32); 57001e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(a, 3, u32); 57101e04c3fSmrg } else { 57201e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(r, 0, f32); 57301e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(g, 1, f32); 57401e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(b, 2, f32); 57501e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(a, 3, f32); 57601e04c3fSmrg } 57701e04c3fSmrg 57801e04c3fSmrg#undef RETURN_FALSE_IF_NOT_0_1 57901e04c3fSmrg 58001e04c3fSmrg return true; 58101e04c3fSmrg} 58201e04c3fSmrg 58301e04c3fSmrg/** 58401e04c3fSmrg * @param[out] tiling is set only on success 58501e04c3fSmrg */ 58601e04c3fSmrgstatic bool 58701e04c3fSmrgisl_surf_choose_tiling(const struct isl_device *dev, 58801e04c3fSmrg const struct isl_surf_init_info *restrict info, 58901e04c3fSmrg enum isl_tiling *tiling) 59001e04c3fSmrg{ 59101e04c3fSmrg isl_tiling_flags_t tiling_flags = info->tiling_flags; 59201e04c3fSmrg 59301e04c3fSmrg /* HiZ surfaces always use the HiZ tiling */ 59401e04c3fSmrg if (info->usage & ISL_SURF_USAGE_HIZ_BIT) { 59501e04c3fSmrg assert(info->format == ISL_FORMAT_HIZ); 59601e04c3fSmrg assert(tiling_flags == ISL_TILING_HIZ_BIT); 5977ec681f3Smrg *tiling = isl_tiling_flag_to_enum(tiling_flags); 59801e04c3fSmrg return true; 59901e04c3fSmrg } 60001e04c3fSmrg 60101e04c3fSmrg /* CCS surfaces always use the CCS tiling */ 60201e04c3fSmrg if (info->usage & ISL_SURF_USAGE_CCS_BIT) { 60301e04c3fSmrg assert(isl_format_get_layout(info->format)->txc == ISL_TXC_CCS); 6047ec681f3Smrg UNUSED bool ivb_ccs = ISL_GFX_VER(dev) < 12 && 6057ec681f3Smrg tiling_flags == ISL_TILING_CCS_BIT; 6067ec681f3Smrg UNUSED bool tgl_ccs = ISL_GFX_VER(dev) >= 12 && 6077ec681f3Smrg tiling_flags == ISL_TILING_GFX12_CCS_BIT; 6087ec681f3Smrg assert(ivb_ccs != tgl_ccs); 6097ec681f3Smrg *tiling = isl_tiling_flag_to_enum(tiling_flags); 61001e04c3fSmrg return true; 61101e04c3fSmrg } 61201e04c3fSmrg 6137ec681f3Smrg if (ISL_GFX_VERX10(dev) >= 125) { 6147ec681f3Smrg isl_gfx125_filter_tiling(dev, info, &tiling_flags); 6157ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 6) { 6167ec681f3Smrg isl_gfx6_filter_tiling(dev, info, &tiling_flags); 61701e04c3fSmrg } else { 6187ec681f3Smrg isl_gfx4_filter_tiling(dev, info, &tiling_flags); 61901e04c3fSmrg } 62001e04c3fSmrg 62101e04c3fSmrg #define CHOOSE(__tiling) \ 62201e04c3fSmrg do { \ 62301e04c3fSmrg if (tiling_flags & (1u << (__tiling))) { \ 62401e04c3fSmrg *tiling = (__tiling); \ 62501e04c3fSmrg return true; \ 62601e04c3fSmrg } \ 62701e04c3fSmrg } while (0) 62801e04c3fSmrg 62901e04c3fSmrg /* Of the tiling modes remaining, choose the one that offers the best 63001e04c3fSmrg * performance. 63101e04c3fSmrg */ 63201e04c3fSmrg 63301e04c3fSmrg if (info->dim == ISL_SURF_DIM_1D) { 63401e04c3fSmrg /* Prefer linear for 1D surfaces because they do not benefit from 63501e04c3fSmrg * tiling. To the contrary, tiling leads to wasted memory and poor 63601e04c3fSmrg * memory locality due to the swizzling and alignment restrictions 63701e04c3fSmrg * required in tiled surfaces. 63801e04c3fSmrg */ 63901e04c3fSmrg CHOOSE(ISL_TILING_LINEAR); 64001e04c3fSmrg } 64101e04c3fSmrg 6427ec681f3Smrg CHOOSE(ISL_TILING_4); 6437ec681f3Smrg CHOOSE(ISL_TILING_64); 64401e04c3fSmrg CHOOSE(ISL_TILING_Ys); 64501e04c3fSmrg CHOOSE(ISL_TILING_Yf); 64601e04c3fSmrg CHOOSE(ISL_TILING_Y0); 64701e04c3fSmrg CHOOSE(ISL_TILING_X); 64801e04c3fSmrg CHOOSE(ISL_TILING_W); 64901e04c3fSmrg CHOOSE(ISL_TILING_LINEAR); 65001e04c3fSmrg 65101e04c3fSmrg #undef CHOOSE 65201e04c3fSmrg 65301e04c3fSmrg /* No tiling mode accomodates the inputs. */ 65401e04c3fSmrg return false; 65501e04c3fSmrg} 65601e04c3fSmrg 65701e04c3fSmrgstatic bool 65801e04c3fSmrgisl_choose_msaa_layout(const struct isl_device *dev, 65901e04c3fSmrg const struct isl_surf_init_info *info, 66001e04c3fSmrg enum isl_tiling tiling, 66101e04c3fSmrg enum isl_msaa_layout *msaa_layout) 66201e04c3fSmrg{ 6637ec681f3Smrg if (ISL_GFX_VER(dev) >= 8) { 6647ec681f3Smrg return isl_gfx8_choose_msaa_layout(dev, info, tiling, msaa_layout); 6657ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 7) { 6667ec681f3Smrg return isl_gfx7_choose_msaa_layout(dev, info, tiling, msaa_layout); 6677ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 6) { 6687ec681f3Smrg return isl_gfx6_choose_msaa_layout(dev, info, tiling, msaa_layout); 66901e04c3fSmrg } else { 6707ec681f3Smrg return isl_gfx4_choose_msaa_layout(dev, info, tiling, msaa_layout); 67101e04c3fSmrg } 67201e04c3fSmrg} 67301e04c3fSmrg 67401e04c3fSmrgstruct isl_extent2d 67501e04c3fSmrgisl_get_interleaved_msaa_px_size_sa(uint32_t samples) 67601e04c3fSmrg{ 67701e04c3fSmrg assert(isl_is_pow2(samples)); 67801e04c3fSmrg 67901e04c3fSmrg /* From the Broadwell PRM >> Volume 5: Memory Views >> Computing Mip Level 68001e04c3fSmrg * Sizes (p133): 68101e04c3fSmrg * 68201e04c3fSmrg * If the surface is multisampled and it is a depth or stencil surface 68301e04c3fSmrg * or Multisampled Surface StorageFormat in SURFACE_STATE is 68401e04c3fSmrg * MSFMT_DEPTH_STENCIL, W_L and H_L must be adjusted as follows before 68501e04c3fSmrg * proceeding: [...] 68601e04c3fSmrg */ 68701e04c3fSmrg return (struct isl_extent2d) { 68801e04c3fSmrg .width = 1 << ((ffs(samples) - 0) / 2), 68901e04c3fSmrg .height = 1 << ((ffs(samples) - 1) / 2), 69001e04c3fSmrg }; 69101e04c3fSmrg} 69201e04c3fSmrg 69301e04c3fSmrgstatic void 69401e04c3fSmrgisl_msaa_interleaved_scale_px_to_sa(uint32_t samples, 69501e04c3fSmrg uint32_t *width, uint32_t *height) 69601e04c3fSmrg{ 69701e04c3fSmrg const struct isl_extent2d px_size_sa = 69801e04c3fSmrg isl_get_interleaved_msaa_px_size_sa(samples); 69901e04c3fSmrg 70001e04c3fSmrg if (width) 70101e04c3fSmrg *width = isl_align(*width, 2) * px_size_sa.width; 70201e04c3fSmrg if (height) 70301e04c3fSmrg *height = isl_align(*height, 2) * px_size_sa.height; 70401e04c3fSmrg} 70501e04c3fSmrg 70601e04c3fSmrgstatic enum isl_array_pitch_span 70701e04c3fSmrgisl_choose_array_pitch_span(const struct isl_device *dev, 70801e04c3fSmrg const struct isl_surf_init_info *restrict info, 70901e04c3fSmrg enum isl_dim_layout dim_layout, 71001e04c3fSmrg const struct isl_extent4d *phys_level0_sa) 71101e04c3fSmrg{ 71201e04c3fSmrg switch (dim_layout) { 7137ec681f3Smrg case ISL_DIM_LAYOUT_GFX9_1D: 7147ec681f3Smrg case ISL_DIM_LAYOUT_GFX4_2D: 7157ec681f3Smrg if (ISL_GFX_VER(dev) >= 8) { 71601e04c3fSmrg /* QPitch becomes programmable in Broadwell. So choose the 71701e04c3fSmrg * most compact QPitch possible in order to conserve memory. 71801e04c3fSmrg * 71901e04c3fSmrg * From the Broadwell PRM >> Volume 2d: Command Reference: Structures 72001e04c3fSmrg * >> RENDER_SURFACE_STATE Surface QPitch (p325): 72101e04c3fSmrg * 72201e04c3fSmrg * - Software must ensure that this field is set to a value 72301e04c3fSmrg * sufficiently large such that the array slices in the surface 72401e04c3fSmrg * do not overlap. Refer to the Memory Data Formats section for 72501e04c3fSmrg * information on how surfaces are stored in memory. 72601e04c3fSmrg * 72701e04c3fSmrg * - This field specifies the distance in rows between array 72801e04c3fSmrg * slices. It is used only in the following cases: 72901e04c3fSmrg * 73001e04c3fSmrg * - Surface Array is enabled OR 73101e04c3fSmrg * - Number of Mulitsamples is not NUMSAMPLES_1 and 73201e04c3fSmrg * Multisampled Surface Storage Format set to MSFMT_MSS OR 73301e04c3fSmrg * - Surface Type is SURFTYPE_CUBE 73401e04c3fSmrg */ 73501e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 7367ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 7) { 73701e04c3fSmrg /* Note that Ivybridge introduces 73801e04c3fSmrg * RENDER_SURFACE_STATE.SurfaceArraySpacing, which provides the 73901e04c3fSmrg * driver more control over the QPitch. 74001e04c3fSmrg */ 74101e04c3fSmrg 74201e04c3fSmrg if (phys_level0_sa->array_len == 1) { 74301e04c3fSmrg /* The hardware will never use the QPitch. So choose the most 74401e04c3fSmrg * compact QPitch possible in order to conserve memory. 74501e04c3fSmrg */ 74601e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 74701e04c3fSmrg } 74801e04c3fSmrg 74901e04c3fSmrg if (isl_surf_usage_is_depth_or_stencil(info->usage) || 75001e04c3fSmrg (info->usage & ISL_SURF_USAGE_HIZ_BIT)) { 75101e04c3fSmrg /* From the Ivybridge PRM >> Volume 1 Part 1: Graphics Core >> 75201e04c3fSmrg * Section 6.18.4.7: Surface Arrays (p112): 75301e04c3fSmrg * 75401e04c3fSmrg * If Surface Array Spacing is set to ARYSPC_FULL (note that 75501e04c3fSmrg * the depth buffer and stencil buffer have an implied value of 75601e04c3fSmrg * ARYSPC_FULL): 75701e04c3fSmrg */ 75801e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_FULL; 75901e04c3fSmrg } 76001e04c3fSmrg 76101e04c3fSmrg if (info->levels == 1) { 76201e04c3fSmrg /* We are able to set RENDER_SURFACE_STATE.SurfaceArraySpacing 76301e04c3fSmrg * to ARYSPC_LOD0. 76401e04c3fSmrg */ 76501e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 76601e04c3fSmrg } 76701e04c3fSmrg 76801e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_FULL; 7697ec681f3Smrg } else if ((ISL_GFX_VER(dev) == 5 || ISL_GFX_VER(dev) == 6) && 77001e04c3fSmrg ISL_DEV_USE_SEPARATE_STENCIL(dev) && 77101e04c3fSmrg isl_surf_usage_is_stencil(info->usage)) { 77201e04c3fSmrg /* [ILK-SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1: 77301e04c3fSmrg * Graphics Core >> Section 7.18.3.7: Surface Arrays: 77401e04c3fSmrg * 77501e04c3fSmrg * The separate stencil buffer does not support mip mapping, thus 77601e04c3fSmrg * the storage for LODs other than LOD 0 is not needed. 77701e04c3fSmrg */ 77801e04c3fSmrg assert(info->levels == 1); 77901e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 78001e04c3fSmrg } else { 7817ec681f3Smrg if ((ISL_GFX_VER(dev) == 5 || ISL_GFX_VER(dev) == 6) && 78201e04c3fSmrg ISL_DEV_USE_SEPARATE_STENCIL(dev) && 78301e04c3fSmrg isl_surf_usage_is_stencil(info->usage)) { 78401e04c3fSmrg /* [ILK-SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1: 78501e04c3fSmrg * Graphics Core >> Section 7.18.3.7: Surface Arrays: 78601e04c3fSmrg * 78701e04c3fSmrg * The separate stencil buffer does not support mip mapping, 78801e04c3fSmrg * thus the storage for LODs other than LOD 0 is not needed. 78901e04c3fSmrg */ 79001e04c3fSmrg assert(info->levels == 1); 79101e04c3fSmrg assert(phys_level0_sa->array_len == 1); 79201e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 79301e04c3fSmrg } 79401e04c3fSmrg 79501e04c3fSmrg if (phys_level0_sa->array_len == 1) { 79601e04c3fSmrg /* The hardware will never use the QPitch. So choose the most 79701e04c3fSmrg * compact QPitch possible in order to conserve memory. 79801e04c3fSmrg */ 79901e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 80001e04c3fSmrg } 80101e04c3fSmrg 80201e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_FULL; 80301e04c3fSmrg } 80401e04c3fSmrg 8057ec681f3Smrg case ISL_DIM_LAYOUT_GFX4_3D: 80601e04c3fSmrg /* The hardware will never use the QPitch. So choose the most 80701e04c3fSmrg * compact QPitch possible in order to conserve memory. 80801e04c3fSmrg */ 80901e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 81001e04c3fSmrg 8117ec681f3Smrg case ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ: 8127ec681f3Smrg /* Each array image in the gfx6 stencil of HiZ surface is compact in the 81301e04c3fSmrg * sense that every LOD is a compact array of the same size as LOD0. 81401e04c3fSmrg */ 81501e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 81601e04c3fSmrg } 81701e04c3fSmrg 81801e04c3fSmrg unreachable("bad isl_dim_layout"); 81901e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_FULL; 82001e04c3fSmrg} 82101e04c3fSmrg 82201e04c3fSmrgstatic void 82301e04c3fSmrgisl_choose_image_alignment_el(const struct isl_device *dev, 82401e04c3fSmrg const struct isl_surf_init_info *restrict info, 82501e04c3fSmrg enum isl_tiling tiling, 82601e04c3fSmrg enum isl_dim_layout dim_layout, 82701e04c3fSmrg enum isl_msaa_layout msaa_layout, 82801e04c3fSmrg struct isl_extent3d *image_align_el) 82901e04c3fSmrg{ 83001e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 83101e04c3fSmrg if (fmtl->txc == ISL_TXC_MCS) { 83201e04c3fSmrg assert(tiling == ISL_TILING_Y0); 83301e04c3fSmrg 83401e04c3fSmrg /* 83501e04c3fSmrg * IvyBrigde PRM Vol 2, Part 1, "11.7 MCS Buffer for Render Target(s)": 83601e04c3fSmrg * 83701e04c3fSmrg * Height, width, and layout of MCS buffer in this case must match with 83801e04c3fSmrg * Render Target height, width, and layout. MCS buffer is tiledY. 83901e04c3fSmrg * 84001e04c3fSmrg * To avoid wasting memory, choose the smallest alignment possible: 84101e04c3fSmrg * HALIGN_4 and VALIGN_4. 84201e04c3fSmrg */ 84301e04c3fSmrg *image_align_el = isl_extent3d(4, 4, 1); 84401e04c3fSmrg return; 84501e04c3fSmrg } else if (info->format == ISL_FORMAT_HIZ) { 8467ec681f3Smrg assert(ISL_GFX_VER(dev) >= 6); 8477ec681f3Smrg if (ISL_GFX_VER(dev) == 6) { 84801e04c3fSmrg /* HiZ surfaces on Sandy Bridge are packed tightly. */ 84901e04c3fSmrg *image_align_el = isl_extent3d(1, 1, 1); 8507ec681f3Smrg } else if (ISL_GFX_VER(dev) < 12) { 8517ec681f3Smrg /* On gfx7+, HiZ surfaces are always aligned to 16x8 pixels in the 85201e04c3fSmrg * primary surface which works out to 2x2 HiZ elments. 85301e04c3fSmrg */ 85401e04c3fSmrg *image_align_el = isl_extent3d(2, 2, 1); 8557ec681f3Smrg } else { 8567ec681f3Smrg /* On gfx12+, HiZ surfaces are always aligned to 16x16 pixels in the 8577ec681f3Smrg * primary surface which works out to 2x4 HiZ elments. 8587ec681f3Smrg * TODO: Verify 8597ec681f3Smrg */ 8607ec681f3Smrg *image_align_el = isl_extent3d(2, 4, 1); 86101e04c3fSmrg } 86201e04c3fSmrg return; 86301e04c3fSmrg } 86401e04c3fSmrg 8657ec681f3Smrg if (ISL_GFX_VERX10(dev) >= 125) { 8667ec681f3Smrg isl_gfx125_choose_image_alignment_el(dev, info, tiling, dim_layout, 8677ec681f3Smrg msaa_layout, image_align_el); 8687ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 12) { 8697ec681f3Smrg isl_gfx12_choose_image_alignment_el(dev, info, tiling, dim_layout, 8707ec681f3Smrg msaa_layout, image_align_el); 8717ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 9) { 8727ec681f3Smrg isl_gfx9_choose_image_alignment_el(dev, info, tiling, dim_layout, 87301e04c3fSmrg msaa_layout, image_align_el); 8747ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 8) { 8757ec681f3Smrg isl_gfx8_choose_image_alignment_el(dev, info, tiling, dim_layout, 87601e04c3fSmrg msaa_layout, image_align_el); 8777ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 7) { 8787ec681f3Smrg isl_gfx7_choose_image_alignment_el(dev, info, tiling, dim_layout, 87901e04c3fSmrg msaa_layout, image_align_el); 8807ec681f3Smrg } else if (ISL_GFX_VER(dev) >= 6) { 8817ec681f3Smrg isl_gfx6_choose_image_alignment_el(dev, info, tiling, dim_layout, 88201e04c3fSmrg msaa_layout, image_align_el); 88301e04c3fSmrg } else { 8847ec681f3Smrg isl_gfx4_choose_image_alignment_el(dev, info, tiling, dim_layout, 88501e04c3fSmrg msaa_layout, image_align_el); 88601e04c3fSmrg } 88701e04c3fSmrg} 88801e04c3fSmrg 88901e04c3fSmrgstatic enum isl_dim_layout 89001e04c3fSmrgisl_surf_choose_dim_layout(const struct isl_device *dev, 89101e04c3fSmrg enum isl_surf_dim logical_dim, 89201e04c3fSmrg enum isl_tiling tiling, 89301e04c3fSmrg isl_surf_usage_flags_t usage) 89401e04c3fSmrg{ 89501e04c3fSmrg /* Sandy bridge needs a special layout for HiZ and stencil. */ 8967ec681f3Smrg if (ISL_GFX_VER(dev) == 6 && 89701e04c3fSmrg (tiling == ISL_TILING_W || tiling == ISL_TILING_HIZ)) 8987ec681f3Smrg return ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ; 89901e04c3fSmrg 9007ec681f3Smrg if (ISL_GFX_VER(dev) >= 9) { 90101e04c3fSmrg switch (logical_dim) { 90201e04c3fSmrg case ISL_SURF_DIM_1D: 90301e04c3fSmrg /* From the Sky Lake PRM Vol. 5, "1D Surfaces": 90401e04c3fSmrg * 90501e04c3fSmrg * One-dimensional surfaces use a tiling mode of linear. 90601e04c3fSmrg * Technically, they are not tiled resources, but the Tiled 90701e04c3fSmrg * Resource Mode field in RENDER_SURFACE_STATE is still used to 90801e04c3fSmrg * indicate the alignment requirements for this linear surface 90901e04c3fSmrg * (See 1D Alignment requirements for how 4K and 64KB Tiled 91001e04c3fSmrg * Resource Modes impact alignment). Alternatively, a 1D surface 91101e04c3fSmrg * can be defined as a 2D tiled surface (e.g. TileY or TileX) with 91201e04c3fSmrg * a height of 0. 91301e04c3fSmrg * 9147ec681f3Smrg * In other words, ISL_DIM_LAYOUT_GFX9_1D is only used for linear 9157ec681f3Smrg * surfaces and, for tiled surfaces, ISL_DIM_LAYOUT_GFX4_2D is used. 91601e04c3fSmrg */ 91701e04c3fSmrg if (tiling == ISL_TILING_LINEAR) 9187ec681f3Smrg return ISL_DIM_LAYOUT_GFX9_1D; 91901e04c3fSmrg else 9207ec681f3Smrg return ISL_DIM_LAYOUT_GFX4_2D; 92101e04c3fSmrg case ISL_SURF_DIM_2D: 92201e04c3fSmrg case ISL_SURF_DIM_3D: 9237ec681f3Smrg return ISL_DIM_LAYOUT_GFX4_2D; 92401e04c3fSmrg } 92501e04c3fSmrg } else { 92601e04c3fSmrg switch (logical_dim) { 92701e04c3fSmrg case ISL_SURF_DIM_1D: 92801e04c3fSmrg case ISL_SURF_DIM_2D: 92901e04c3fSmrg /* From the G45 PRM Vol. 1a, "6.17.4.1 Hardware Cube Map Layout": 93001e04c3fSmrg * 93101e04c3fSmrg * The cube face textures are stored in the same way as 3D surfaces 93201e04c3fSmrg * are stored (see section 6.17.5 for details). For cube surfaces, 93301e04c3fSmrg * however, the depth is equal to the number of faces (always 6) and 93401e04c3fSmrg * is not reduced for each MIP. 93501e04c3fSmrg */ 9367ec681f3Smrg if (ISL_GFX_VER(dev) == 4 && (usage & ISL_SURF_USAGE_CUBE_BIT)) 9377ec681f3Smrg return ISL_DIM_LAYOUT_GFX4_3D; 93801e04c3fSmrg 9397ec681f3Smrg return ISL_DIM_LAYOUT_GFX4_2D; 94001e04c3fSmrg case ISL_SURF_DIM_3D: 9417ec681f3Smrg return ISL_DIM_LAYOUT_GFX4_3D; 94201e04c3fSmrg } 94301e04c3fSmrg } 94401e04c3fSmrg 94501e04c3fSmrg unreachable("bad isl_surf_dim"); 9467ec681f3Smrg return ISL_DIM_LAYOUT_GFX4_2D; 94701e04c3fSmrg} 94801e04c3fSmrg 94901e04c3fSmrg/** 95001e04c3fSmrg * Calculate the physical extent of the surface's first level, in units of 9519f464c52Smaya * surface samples. 95201e04c3fSmrg */ 95301e04c3fSmrgstatic void 95401e04c3fSmrgisl_calc_phys_level0_extent_sa(const struct isl_device *dev, 95501e04c3fSmrg const struct isl_surf_init_info *restrict info, 95601e04c3fSmrg enum isl_dim_layout dim_layout, 95701e04c3fSmrg enum isl_tiling tiling, 95801e04c3fSmrg enum isl_msaa_layout msaa_layout, 95901e04c3fSmrg struct isl_extent4d *phys_level0_sa) 96001e04c3fSmrg{ 96101e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 96201e04c3fSmrg 9637ec681f3Smrg if (isl_format_is_planar(info->format)) 9647ec681f3Smrg unreachable("Planar formats unsupported"); 96501e04c3fSmrg 96601e04c3fSmrg switch (info->dim) { 96701e04c3fSmrg case ISL_SURF_DIM_1D: 96801e04c3fSmrg assert(info->height == 1); 96901e04c3fSmrg assert(info->depth == 1); 97001e04c3fSmrg assert(info->samples == 1); 97101e04c3fSmrg 97201e04c3fSmrg switch (dim_layout) { 9737ec681f3Smrg case ISL_DIM_LAYOUT_GFX4_3D: 97401e04c3fSmrg unreachable("bad isl_dim_layout"); 97501e04c3fSmrg 9767ec681f3Smrg case ISL_DIM_LAYOUT_GFX9_1D: 9777ec681f3Smrg case ISL_DIM_LAYOUT_GFX4_2D: 9787ec681f3Smrg case ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ: 97901e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 9809f464c52Smaya .w = info->width, 9819f464c52Smaya .h = 1, 98201e04c3fSmrg .d = 1, 98301e04c3fSmrg .a = info->array_len, 98401e04c3fSmrg }; 98501e04c3fSmrg break; 98601e04c3fSmrg } 98701e04c3fSmrg break; 98801e04c3fSmrg 98901e04c3fSmrg case ISL_SURF_DIM_2D: 9907ec681f3Smrg if (ISL_GFX_VER(dev) == 4 && (info->usage & ISL_SURF_USAGE_CUBE_BIT)) 9917ec681f3Smrg assert(dim_layout == ISL_DIM_LAYOUT_GFX4_3D); 99201e04c3fSmrg else 9937ec681f3Smrg assert(dim_layout == ISL_DIM_LAYOUT_GFX4_2D || 9947ec681f3Smrg dim_layout == ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ); 99501e04c3fSmrg 99601e04c3fSmrg if (tiling == ISL_TILING_Ys && info->samples > 1) 99701e04c3fSmrg isl_finishme("%s:%s: multisample TileYs layout", __FILE__, __func__); 99801e04c3fSmrg 99901e04c3fSmrg switch (msaa_layout) { 100001e04c3fSmrg case ISL_MSAA_LAYOUT_NONE: 100101e04c3fSmrg assert(info->depth == 1); 100201e04c3fSmrg assert(info->samples == 1); 100301e04c3fSmrg 100401e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 10059f464c52Smaya .w = info->width, 10069f464c52Smaya .h = info->height, 100701e04c3fSmrg .d = 1, 100801e04c3fSmrg .a = info->array_len, 100901e04c3fSmrg }; 101001e04c3fSmrg break; 101101e04c3fSmrg 101201e04c3fSmrg case ISL_MSAA_LAYOUT_ARRAY: 101301e04c3fSmrg assert(info->depth == 1); 101401e04c3fSmrg assert(info->levels == 1); 101501e04c3fSmrg assert(isl_format_supports_multisampling(dev->info, info->format)); 101601e04c3fSmrg assert(fmtl->bw == 1 && fmtl->bh == 1); 101701e04c3fSmrg 101801e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 101901e04c3fSmrg .w = info->width, 102001e04c3fSmrg .h = info->height, 102101e04c3fSmrg .d = 1, 102201e04c3fSmrg .a = info->array_len * info->samples, 102301e04c3fSmrg }; 102401e04c3fSmrg break; 102501e04c3fSmrg 102601e04c3fSmrg case ISL_MSAA_LAYOUT_INTERLEAVED: 102701e04c3fSmrg assert(info->depth == 1); 102801e04c3fSmrg assert(info->levels == 1); 102901e04c3fSmrg assert(isl_format_supports_multisampling(dev->info, info->format)); 103001e04c3fSmrg 103101e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 103201e04c3fSmrg .w = info->width, 103301e04c3fSmrg .h = info->height, 103401e04c3fSmrg .d = 1, 103501e04c3fSmrg .a = info->array_len, 103601e04c3fSmrg }; 103701e04c3fSmrg 103801e04c3fSmrg isl_msaa_interleaved_scale_px_to_sa(info->samples, 103901e04c3fSmrg &phys_level0_sa->w, 104001e04c3fSmrg &phys_level0_sa->h); 104101e04c3fSmrg break; 104201e04c3fSmrg } 104301e04c3fSmrg break; 104401e04c3fSmrg 104501e04c3fSmrg case ISL_SURF_DIM_3D: 104601e04c3fSmrg assert(info->array_len == 1); 104701e04c3fSmrg assert(info->samples == 1); 104801e04c3fSmrg 104901e04c3fSmrg if (fmtl->bd > 1) { 105001e04c3fSmrg isl_finishme("%s:%s: compression block with depth > 1", 105101e04c3fSmrg __FILE__, __func__); 105201e04c3fSmrg } 105301e04c3fSmrg 105401e04c3fSmrg switch (dim_layout) { 10557ec681f3Smrg case ISL_DIM_LAYOUT_GFX9_1D: 10567ec681f3Smrg case ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ: 105701e04c3fSmrg unreachable("bad isl_dim_layout"); 105801e04c3fSmrg 10597ec681f3Smrg case ISL_DIM_LAYOUT_GFX4_2D: 10607ec681f3Smrg assert(ISL_GFX_VER(dev) >= 9); 106101e04c3fSmrg 106201e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 10639f464c52Smaya .w = info->width, 10649f464c52Smaya .h = info->height, 106501e04c3fSmrg .d = 1, 106601e04c3fSmrg .a = info->depth, 106701e04c3fSmrg }; 106801e04c3fSmrg break; 106901e04c3fSmrg 10707ec681f3Smrg case ISL_DIM_LAYOUT_GFX4_3D: 10717ec681f3Smrg assert(ISL_GFX_VER(dev) < 9); 107201e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 10739f464c52Smaya .w = info->width, 10749f464c52Smaya .h = info->height, 107501e04c3fSmrg .d = info->depth, 107601e04c3fSmrg .a = 1, 107701e04c3fSmrg }; 107801e04c3fSmrg break; 107901e04c3fSmrg } 108001e04c3fSmrg break; 108101e04c3fSmrg } 108201e04c3fSmrg} 108301e04c3fSmrg 108401e04c3fSmrg/** 108501e04c3fSmrg * Calculate the pitch between physical array slices, in units of rows of 108601e04c3fSmrg * surface elements. 108701e04c3fSmrg */ 108801e04c3fSmrgstatic uint32_t 10897ec681f3Smrgisl_calc_array_pitch_el_rows_gfx4_2d( 109001e04c3fSmrg const struct isl_device *dev, 109101e04c3fSmrg const struct isl_surf_init_info *restrict info, 109201e04c3fSmrg const struct isl_tile_info *tile_info, 109301e04c3fSmrg const struct isl_extent3d *image_align_sa, 109401e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 109501e04c3fSmrg enum isl_array_pitch_span array_pitch_span, 109601e04c3fSmrg const struct isl_extent2d *phys_slice0_sa) 109701e04c3fSmrg{ 109801e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 109901e04c3fSmrg uint32_t pitch_sa_rows = 0; 110001e04c3fSmrg 110101e04c3fSmrg switch (array_pitch_span) { 110201e04c3fSmrg case ISL_ARRAY_PITCH_SPAN_COMPACT: 110301e04c3fSmrg pitch_sa_rows = isl_align_npot(phys_slice0_sa->h, image_align_sa->h); 110401e04c3fSmrg break; 110501e04c3fSmrg case ISL_ARRAY_PITCH_SPAN_FULL: { 110601e04c3fSmrg /* The QPitch equation is found in the Broadwell PRM >> Volume 5: 110701e04c3fSmrg * Memory Views >> Common Surface Formats >> Surface Layout >> 2D 110801e04c3fSmrg * Surfaces >> Surface Arrays. 110901e04c3fSmrg */ 111001e04c3fSmrg uint32_t H0_sa = phys_level0_sa->h; 111101e04c3fSmrg uint32_t H1_sa = isl_minify(H0_sa, 1); 111201e04c3fSmrg 111301e04c3fSmrg uint32_t h0_sa = isl_align_npot(H0_sa, image_align_sa->h); 111401e04c3fSmrg uint32_t h1_sa = isl_align_npot(H1_sa, image_align_sa->h); 111501e04c3fSmrg 111601e04c3fSmrg uint32_t m; 11177ec681f3Smrg if (ISL_GFX_VER(dev) >= 7) { 111801e04c3fSmrg /* The QPitch equation changed slightly in Ivybridge. */ 111901e04c3fSmrg m = 12; 112001e04c3fSmrg } else { 112101e04c3fSmrg m = 11; 112201e04c3fSmrg } 112301e04c3fSmrg 112401e04c3fSmrg pitch_sa_rows = h0_sa + h1_sa + (m * image_align_sa->h); 112501e04c3fSmrg 11267ec681f3Smrg if (ISL_GFX_VER(dev) == 6 && info->samples > 1 && 112701e04c3fSmrg (info->height % 4 == 1)) { 112801e04c3fSmrg /* [SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1: 112901e04c3fSmrg * Graphics Core >> Section 7.18.3.7: Surface Arrays: 113001e04c3fSmrg * 113101e04c3fSmrg * [SNB] Errata: Sampler MSAA Qpitch will be 4 greater than 113201e04c3fSmrg * the value calculated in the equation above , for every 113301e04c3fSmrg * other odd Surface Height starting from 1 i.e. 1,5,9,13. 113401e04c3fSmrg * 113501e04c3fSmrg * XXX(chadv): Is the errata natural corollary of the physical 113601e04c3fSmrg * layout of interleaved samples? 113701e04c3fSmrg */ 113801e04c3fSmrg pitch_sa_rows += 4; 113901e04c3fSmrg } 114001e04c3fSmrg 114101e04c3fSmrg pitch_sa_rows = isl_align_npot(pitch_sa_rows, fmtl->bh); 114201e04c3fSmrg } /* end case */ 114301e04c3fSmrg break; 114401e04c3fSmrg } 114501e04c3fSmrg 114601e04c3fSmrg assert(pitch_sa_rows % fmtl->bh == 0); 114701e04c3fSmrg uint32_t pitch_el_rows = pitch_sa_rows / fmtl->bh; 114801e04c3fSmrg 11497ec681f3Smrg if (ISL_GFX_VER(dev) >= 9 && ISL_GFX_VER(dev) <= 11 && 11507ec681f3Smrg fmtl->txc == ISL_TXC_CCS) { 115101e04c3fSmrg /* 115201e04c3fSmrg * From the Sky Lake PRM Vol 7, "MCS Buffer for Render Target(s)" (p. 632): 115301e04c3fSmrg * 115401e04c3fSmrg * "Mip-mapped and arrayed surfaces are supported with MCS buffer 115501e04c3fSmrg * layout with these alignments in the RT space: Horizontal 115601e04c3fSmrg * Alignment = 128 and Vertical Alignment = 64." 115701e04c3fSmrg * 115801e04c3fSmrg * From the Sky Lake PRM Vol. 2d, "RENDER_SURFACE_STATE" (p. 435): 115901e04c3fSmrg * 116001e04c3fSmrg * "For non-multisampled render target's CCS auxiliary surface, 116101e04c3fSmrg * QPitch must be computed with Horizontal Alignment = 128 and 116201e04c3fSmrg * Surface Vertical Alignment = 256. These alignments are only for 116301e04c3fSmrg * CCS buffer and not for associated render target." 116401e04c3fSmrg * 116501e04c3fSmrg * The first restriction is already handled by isl_choose_image_alignment_el 116601e04c3fSmrg * but the second restriction, which is an extension of the first, only 116701e04c3fSmrg * applies to qpitch and must be applied here. 11687ec681f3Smrg * 11697ec681f3Smrg * The second restriction disappears on Gfx12. 117001e04c3fSmrg */ 117101e04c3fSmrg assert(fmtl->bh == 4); 117201e04c3fSmrg pitch_el_rows = isl_align(pitch_el_rows, 256 / 4); 117301e04c3fSmrg } 117401e04c3fSmrg 11757ec681f3Smrg if (ISL_GFX_VER(dev) >= 9 && 117601e04c3fSmrg info->dim == ISL_SURF_DIM_3D && 117701e04c3fSmrg tile_info->tiling != ISL_TILING_LINEAR) { 117801e04c3fSmrg /* From the Skylake BSpec >> RENDER_SURFACE_STATE >> Surface QPitch: 117901e04c3fSmrg * 118001e04c3fSmrg * Tile Mode != Linear: This field must be set to an integer multiple 118101e04c3fSmrg * of the tile height 118201e04c3fSmrg */ 118301e04c3fSmrg pitch_el_rows = isl_align(pitch_el_rows, tile_info->logical_extent_el.height); 118401e04c3fSmrg } 118501e04c3fSmrg 118601e04c3fSmrg return pitch_el_rows; 118701e04c3fSmrg} 118801e04c3fSmrg 118901e04c3fSmrg/** 119001e04c3fSmrg * A variant of isl_calc_phys_slice0_extent_sa() specific to 11917ec681f3Smrg * ISL_DIM_LAYOUT_GFX4_2D. 119201e04c3fSmrg */ 119301e04c3fSmrgstatic void 11947ec681f3Smrgisl_calc_phys_slice0_extent_sa_gfx4_2d( 119501e04c3fSmrg const struct isl_device *dev, 119601e04c3fSmrg const struct isl_surf_init_info *restrict info, 119701e04c3fSmrg enum isl_msaa_layout msaa_layout, 119801e04c3fSmrg const struct isl_extent3d *image_align_sa, 119901e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 120001e04c3fSmrg struct isl_extent2d *phys_slice0_sa) 120101e04c3fSmrg{ 120201e04c3fSmrg assert(phys_level0_sa->depth == 1); 120301e04c3fSmrg 120401e04c3fSmrg if (info->levels == 1) { 12059f464c52Smaya /* Do not pad the surface to the image alignment. 120601e04c3fSmrg * 120701e04c3fSmrg * For tiled surfaces, using a reduced alignment here avoids wasting CPU 120801e04c3fSmrg * cycles on the below mipmap layout caluclations. Reducing the 120901e04c3fSmrg * alignment here is safe because we later align the row pitch and array 121001e04c3fSmrg * pitch to the tile boundary. It is safe even for 121101e04c3fSmrg * ISL_MSAA_LAYOUT_INTERLEAVED, because phys_level0_sa is already scaled 121201e04c3fSmrg * to accomodate the interleaved samples. 121301e04c3fSmrg * 121401e04c3fSmrg * For linear surfaces, reducing the alignment here permits us to later 121501e04c3fSmrg * choose an arbitrary, non-aligned row pitch. If the surface backs 121601e04c3fSmrg * a VkBuffer, then an arbitrary pitch may be needed to accomodate 121701e04c3fSmrg * VkBufferImageCopy::bufferRowLength. 121801e04c3fSmrg */ 121901e04c3fSmrg *phys_slice0_sa = (struct isl_extent2d) { 12209f464c52Smaya .w = phys_level0_sa->w, 12219f464c52Smaya .h = phys_level0_sa->h, 122201e04c3fSmrg }; 122301e04c3fSmrg return; 122401e04c3fSmrg } 122501e04c3fSmrg 122601e04c3fSmrg uint32_t slice_top_w = 0; 122701e04c3fSmrg uint32_t slice_bottom_w = 0; 122801e04c3fSmrg uint32_t slice_left_h = 0; 122901e04c3fSmrg uint32_t slice_right_h = 0; 123001e04c3fSmrg 123101e04c3fSmrg uint32_t W0 = phys_level0_sa->w; 123201e04c3fSmrg uint32_t H0 = phys_level0_sa->h; 123301e04c3fSmrg 123401e04c3fSmrg for (uint32_t l = 0; l < info->levels; ++l) { 123501e04c3fSmrg uint32_t W = isl_minify(W0, l); 123601e04c3fSmrg uint32_t H = isl_minify(H0, l); 123701e04c3fSmrg 123801e04c3fSmrg uint32_t w = isl_align_npot(W, image_align_sa->w); 123901e04c3fSmrg uint32_t h = isl_align_npot(H, image_align_sa->h); 124001e04c3fSmrg 124101e04c3fSmrg if (l == 0) { 124201e04c3fSmrg slice_top_w = w; 124301e04c3fSmrg slice_left_h = h; 124401e04c3fSmrg slice_right_h = h; 124501e04c3fSmrg } else if (l == 1) { 124601e04c3fSmrg slice_bottom_w = w; 124701e04c3fSmrg slice_left_h += h; 124801e04c3fSmrg } else if (l == 2) { 124901e04c3fSmrg slice_bottom_w += w; 125001e04c3fSmrg slice_right_h += h; 125101e04c3fSmrg } else { 125201e04c3fSmrg slice_right_h += h; 125301e04c3fSmrg } 125401e04c3fSmrg } 125501e04c3fSmrg 125601e04c3fSmrg *phys_slice0_sa = (struct isl_extent2d) { 125701e04c3fSmrg .w = MAX(slice_top_w, slice_bottom_w), 125801e04c3fSmrg .h = MAX(slice_left_h, slice_right_h), 125901e04c3fSmrg }; 126001e04c3fSmrg} 126101e04c3fSmrg 126201e04c3fSmrgstatic void 12637ec681f3Smrgisl_calc_phys_total_extent_el_gfx4_2d( 126401e04c3fSmrg const struct isl_device *dev, 126501e04c3fSmrg const struct isl_surf_init_info *restrict info, 126601e04c3fSmrg const struct isl_tile_info *tile_info, 126701e04c3fSmrg enum isl_msaa_layout msaa_layout, 126801e04c3fSmrg const struct isl_extent3d *image_align_sa, 126901e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 127001e04c3fSmrg enum isl_array_pitch_span array_pitch_span, 127101e04c3fSmrg uint32_t *array_pitch_el_rows, 12727ec681f3Smrg struct isl_extent4d *phys_total_el) 127301e04c3fSmrg{ 127401e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 127501e04c3fSmrg 127601e04c3fSmrg struct isl_extent2d phys_slice0_sa; 12777ec681f3Smrg isl_calc_phys_slice0_extent_sa_gfx4_2d(dev, info, msaa_layout, 127801e04c3fSmrg image_align_sa, phys_level0_sa, 127901e04c3fSmrg &phys_slice0_sa); 128001e04c3fSmrg *array_pitch_el_rows = 12817ec681f3Smrg isl_calc_array_pitch_el_rows_gfx4_2d(dev, info, tile_info, 128201e04c3fSmrg image_align_sa, phys_level0_sa, 128301e04c3fSmrg array_pitch_span, 128401e04c3fSmrg &phys_slice0_sa); 12857ec681f3Smrg 12867ec681f3Smrg if (tile_info->tiling == ISL_TILING_64) { 12877ec681f3Smrg *phys_total_el = (struct isl_extent4d) { 12887ec681f3Smrg .w = isl_align_div_npot(phys_slice0_sa.w, fmtl->bw), 12897ec681f3Smrg .h = isl_align_div_npot(phys_slice0_sa.h, fmtl->bh), 12907ec681f3Smrg .d = isl_align_div_npot(phys_level0_sa->d, fmtl->bd), 12917ec681f3Smrg .a = phys_level0_sa->array_len, 12927ec681f3Smrg }; 12937ec681f3Smrg } else { 12947ec681f3Smrg *phys_total_el = (struct isl_extent4d) { 12957ec681f3Smrg .w = isl_align_div_npot(phys_slice0_sa.w, fmtl->bw), 12967ec681f3Smrg .h = *array_pitch_el_rows * (phys_level0_sa->array_len - 1) + 12977ec681f3Smrg isl_align_div_npot(phys_slice0_sa.h, fmtl->bh), 12987ec681f3Smrg .d = 1, 12997ec681f3Smrg .a = 1, 13007ec681f3Smrg }; 13017ec681f3Smrg } 130201e04c3fSmrg} 130301e04c3fSmrg 130401e04c3fSmrg/** 130501e04c3fSmrg * A variant of isl_calc_phys_slice0_extent_sa() specific to 13067ec681f3Smrg * ISL_DIM_LAYOUT_GFX4_3D. 130701e04c3fSmrg */ 130801e04c3fSmrgstatic void 13097ec681f3Smrgisl_calc_phys_total_extent_el_gfx4_3d( 131001e04c3fSmrg const struct isl_device *dev, 131101e04c3fSmrg const struct isl_surf_init_info *restrict info, 131201e04c3fSmrg const struct isl_extent3d *image_align_sa, 131301e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 131401e04c3fSmrg uint32_t *array_pitch_el_rows, 13157ec681f3Smrg struct isl_extent4d *phys_total_el) 131601e04c3fSmrg{ 131701e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 131801e04c3fSmrg 131901e04c3fSmrg assert(info->samples == 1); 132001e04c3fSmrg 132101e04c3fSmrg if (info->dim != ISL_SURF_DIM_3D) { 132201e04c3fSmrg /* From the G45 PRM Vol. 1a, "6.17.4.1 Hardware Cube Map Layout": 132301e04c3fSmrg * 132401e04c3fSmrg * The cube face textures are stored in the same way as 3D surfaces 132501e04c3fSmrg * are stored (see section 6.17.5 for details). For cube surfaces, 132601e04c3fSmrg * however, the depth is equal to the number of faces (always 6) and 132701e04c3fSmrg * is not reduced for each MIP. 132801e04c3fSmrg */ 13297ec681f3Smrg assert(ISL_GFX_VER(dev) == 4); 133001e04c3fSmrg assert(info->usage & ISL_SURF_USAGE_CUBE_BIT); 133101e04c3fSmrg assert(phys_level0_sa->array_len == 6); 133201e04c3fSmrg } else { 133301e04c3fSmrg assert(phys_level0_sa->array_len == 1); 133401e04c3fSmrg } 133501e04c3fSmrg 133601e04c3fSmrg uint32_t total_w = 0; 133701e04c3fSmrg uint32_t total_h = 0; 133801e04c3fSmrg 133901e04c3fSmrg uint32_t W0 = phys_level0_sa->w; 134001e04c3fSmrg uint32_t H0 = phys_level0_sa->h; 134101e04c3fSmrg uint32_t D0 = phys_level0_sa->d; 134201e04c3fSmrg uint32_t A0 = phys_level0_sa->a; 134301e04c3fSmrg 134401e04c3fSmrg for (uint32_t l = 0; l < info->levels; ++l) { 134501e04c3fSmrg uint32_t level_w = isl_align_npot(isl_minify(W0, l), image_align_sa->w); 134601e04c3fSmrg uint32_t level_h = isl_align_npot(isl_minify(H0, l), image_align_sa->h); 134701e04c3fSmrg uint32_t level_d = info->dim == ISL_SURF_DIM_3D ? isl_minify(D0, l) : A0; 134801e04c3fSmrg 134901e04c3fSmrg uint32_t max_layers_horiz = MIN(level_d, 1u << l); 135001e04c3fSmrg uint32_t max_layers_vert = isl_align(level_d, 1u << l) / (1u << l); 135101e04c3fSmrg 135201e04c3fSmrg total_w = MAX(total_w, level_w * max_layers_horiz); 135301e04c3fSmrg total_h += level_h * max_layers_vert; 135401e04c3fSmrg } 135501e04c3fSmrg 13567ec681f3Smrg /* GFX4_3D layouts don't really have an array pitch since each LOD has a 135701e04c3fSmrg * different number of horizontal and vertical layers. We have to set it 135801e04c3fSmrg * to something, so at least make it true for LOD0. 135901e04c3fSmrg */ 136001e04c3fSmrg *array_pitch_el_rows = 136101e04c3fSmrg isl_align_npot(phys_level0_sa->h, image_align_sa->h) / fmtl->bw; 13627ec681f3Smrg *phys_total_el = (struct isl_extent4d) { 136301e04c3fSmrg .w = isl_assert_div(total_w, fmtl->bw), 136401e04c3fSmrg .h = isl_assert_div(total_h, fmtl->bh), 13657ec681f3Smrg .d = 1, 13667ec681f3Smrg .a = 1, 136701e04c3fSmrg }; 136801e04c3fSmrg} 136901e04c3fSmrg 137001e04c3fSmrg/** 137101e04c3fSmrg * A variant of isl_calc_phys_slice0_extent_sa() specific to 13727ec681f3Smrg * ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ. 137301e04c3fSmrg */ 137401e04c3fSmrgstatic void 13757ec681f3Smrgisl_calc_phys_total_extent_el_gfx6_stencil_hiz( 137601e04c3fSmrg const struct isl_device *dev, 137701e04c3fSmrg const struct isl_surf_init_info *restrict info, 137801e04c3fSmrg const struct isl_tile_info *tile_info, 137901e04c3fSmrg const struct isl_extent3d *image_align_sa, 138001e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 138101e04c3fSmrg uint32_t *array_pitch_el_rows, 13827ec681f3Smrg struct isl_extent4d *phys_total_el) 138301e04c3fSmrg{ 138401e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 138501e04c3fSmrg 138601e04c3fSmrg const struct isl_extent2d tile_extent_sa = { 138701e04c3fSmrg .w = tile_info->logical_extent_el.w * fmtl->bw, 138801e04c3fSmrg .h = tile_info->logical_extent_el.h * fmtl->bh, 138901e04c3fSmrg }; 139001e04c3fSmrg /* Tile size is a multiple of image alignment */ 139101e04c3fSmrg assert(tile_extent_sa.w % image_align_sa->w == 0); 139201e04c3fSmrg assert(tile_extent_sa.h % image_align_sa->h == 0); 139301e04c3fSmrg 139401e04c3fSmrg const uint32_t W0 = phys_level0_sa->w; 139501e04c3fSmrg const uint32_t H0 = phys_level0_sa->h; 139601e04c3fSmrg 139701e04c3fSmrg /* Each image has the same height as LOD0 because the hardware thinks 139801e04c3fSmrg * everything is LOD0 139901e04c3fSmrg */ 140001e04c3fSmrg const uint32_t H = isl_align(H0, image_align_sa->h) * phys_level0_sa->a; 140101e04c3fSmrg 140201e04c3fSmrg uint32_t total_top_w = 0; 140301e04c3fSmrg uint32_t total_bottom_w = 0; 140401e04c3fSmrg uint32_t total_h = 0; 140501e04c3fSmrg 140601e04c3fSmrg for (uint32_t l = 0; l < info->levels; ++l) { 140701e04c3fSmrg const uint32_t W = isl_minify(W0, l); 140801e04c3fSmrg 140901e04c3fSmrg const uint32_t w = isl_align(W, tile_extent_sa.w); 141001e04c3fSmrg const uint32_t h = isl_align(H, tile_extent_sa.h); 141101e04c3fSmrg 141201e04c3fSmrg if (l == 0) { 141301e04c3fSmrg total_top_w = w; 141401e04c3fSmrg total_h = h; 141501e04c3fSmrg } else if (l == 1) { 141601e04c3fSmrg total_bottom_w = w; 141701e04c3fSmrg total_h += h; 141801e04c3fSmrg } else { 141901e04c3fSmrg total_bottom_w += w; 142001e04c3fSmrg } 142101e04c3fSmrg } 142201e04c3fSmrg 142301e04c3fSmrg *array_pitch_el_rows = 142401e04c3fSmrg isl_assert_div(isl_align(H0, image_align_sa->h), fmtl->bh); 14257ec681f3Smrg *phys_total_el = (struct isl_extent4d) { 142601e04c3fSmrg .w = isl_assert_div(MAX(total_top_w, total_bottom_w), fmtl->bw), 142701e04c3fSmrg .h = isl_assert_div(total_h, fmtl->bh), 14287ec681f3Smrg .d = 1, 14297ec681f3Smrg .a = 1, 143001e04c3fSmrg }; 143101e04c3fSmrg} 143201e04c3fSmrg 143301e04c3fSmrg/** 143401e04c3fSmrg * A variant of isl_calc_phys_slice0_extent_sa() specific to 14357ec681f3Smrg * ISL_DIM_LAYOUT_GFX9_1D. 143601e04c3fSmrg */ 143701e04c3fSmrgstatic void 14387ec681f3Smrgisl_calc_phys_total_extent_el_gfx9_1d( 143901e04c3fSmrg const struct isl_device *dev, 144001e04c3fSmrg const struct isl_surf_init_info *restrict info, 144101e04c3fSmrg const struct isl_extent3d *image_align_sa, 144201e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 144301e04c3fSmrg uint32_t *array_pitch_el_rows, 14447ec681f3Smrg struct isl_extent4d *phys_total_el) 144501e04c3fSmrg{ 14467ec681f3Smrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 144701e04c3fSmrg 14489f464c52Smaya assert(phys_level0_sa->height == 1); 144901e04c3fSmrg assert(phys_level0_sa->depth == 1); 145001e04c3fSmrg assert(info->samples == 1); 145101e04c3fSmrg assert(image_align_sa->w >= fmtl->bw); 145201e04c3fSmrg 145301e04c3fSmrg uint32_t slice_w = 0; 145401e04c3fSmrg const uint32_t W0 = phys_level0_sa->w; 145501e04c3fSmrg 145601e04c3fSmrg for (uint32_t l = 0; l < info->levels; ++l) { 145701e04c3fSmrg uint32_t W = isl_minify(W0, l); 145801e04c3fSmrg uint32_t w = isl_align_npot(W, image_align_sa->w); 145901e04c3fSmrg 146001e04c3fSmrg slice_w += w; 146101e04c3fSmrg } 146201e04c3fSmrg 146301e04c3fSmrg *array_pitch_el_rows = 1; 14647ec681f3Smrg *phys_total_el = (struct isl_extent4d) { 146501e04c3fSmrg .w = isl_assert_div(slice_w, fmtl->bw), 146601e04c3fSmrg .h = phys_level0_sa->array_len, 14677ec681f3Smrg .d = 1, 14687ec681f3Smrg .a = 1, 146901e04c3fSmrg }; 147001e04c3fSmrg} 147101e04c3fSmrg 147201e04c3fSmrg/** 147301e04c3fSmrg * Calculate the two-dimensional total physical extent of the surface, in 147401e04c3fSmrg * units of surface elements. 147501e04c3fSmrg */ 147601e04c3fSmrgstatic void 147701e04c3fSmrgisl_calc_phys_total_extent_el(const struct isl_device *dev, 147801e04c3fSmrg const struct isl_surf_init_info *restrict info, 147901e04c3fSmrg const struct isl_tile_info *tile_info, 148001e04c3fSmrg enum isl_dim_layout dim_layout, 148101e04c3fSmrg enum isl_msaa_layout msaa_layout, 148201e04c3fSmrg const struct isl_extent3d *image_align_sa, 148301e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 148401e04c3fSmrg enum isl_array_pitch_span array_pitch_span, 148501e04c3fSmrg uint32_t *array_pitch_el_rows, 14867ec681f3Smrg struct isl_extent4d *phys_total_el) 148701e04c3fSmrg{ 148801e04c3fSmrg switch (dim_layout) { 14897ec681f3Smrg case ISL_DIM_LAYOUT_GFX9_1D: 149001e04c3fSmrg assert(array_pitch_span == ISL_ARRAY_PITCH_SPAN_COMPACT); 14917ec681f3Smrg isl_calc_phys_total_extent_el_gfx9_1d(dev, info, 149201e04c3fSmrg image_align_sa, phys_level0_sa, 149301e04c3fSmrg array_pitch_el_rows, 14947ec681f3Smrg phys_total_el); 149501e04c3fSmrg return; 14967ec681f3Smrg case ISL_DIM_LAYOUT_GFX4_2D: 14977ec681f3Smrg isl_calc_phys_total_extent_el_gfx4_2d(dev, info, tile_info, msaa_layout, 149801e04c3fSmrg image_align_sa, phys_level0_sa, 149901e04c3fSmrg array_pitch_span, 150001e04c3fSmrg array_pitch_el_rows, 15017ec681f3Smrg phys_total_el); 150201e04c3fSmrg return; 15037ec681f3Smrg case ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ: 150401e04c3fSmrg assert(array_pitch_span == ISL_ARRAY_PITCH_SPAN_COMPACT); 15057ec681f3Smrg isl_calc_phys_total_extent_el_gfx6_stencil_hiz(dev, info, tile_info, 150601e04c3fSmrg image_align_sa, 150701e04c3fSmrg phys_level0_sa, 150801e04c3fSmrg array_pitch_el_rows, 15097ec681f3Smrg phys_total_el); 151001e04c3fSmrg return; 15117ec681f3Smrg case ISL_DIM_LAYOUT_GFX4_3D: 151201e04c3fSmrg assert(array_pitch_span == ISL_ARRAY_PITCH_SPAN_COMPACT); 15137ec681f3Smrg isl_calc_phys_total_extent_el_gfx4_3d(dev, info, 151401e04c3fSmrg image_align_sa, phys_level0_sa, 151501e04c3fSmrg array_pitch_el_rows, 15167ec681f3Smrg phys_total_el); 151701e04c3fSmrg return; 151801e04c3fSmrg } 15197ec681f3Smrg 15207ec681f3Smrg unreachable("invalid value for dim_layout"); 152101e04c3fSmrg} 152201e04c3fSmrg 152301e04c3fSmrgstatic uint32_t 15247ec681f3Smrgisl_calc_row_pitch_alignment(const struct isl_device *dev, 15257ec681f3Smrg const struct isl_surf_init_info *surf_info, 152601e04c3fSmrg const struct isl_tile_info *tile_info) 152701e04c3fSmrg{ 15287ec681f3Smrg if (tile_info->tiling != ISL_TILING_LINEAR) { 15297ec681f3Smrg /* According to BSpec: 44930, Gfx12's CCS-compressed surface pitches must 15307ec681f3Smrg * be 512B-aligned. CCS is only support on Y tilings. 15317ec681f3Smrg * 15327ec681f3Smrg * Only consider 512B alignment when : 15337ec681f3Smrg * - AUX is not explicitly disabled 15347ec681f3Smrg * - the caller has specified no pitch 15357ec681f3Smrg * 15367ec681f3Smrg * isl_surf_get_ccs_surf() will check that the main surface alignment 15377ec681f3Smrg * matches CCS expectations. 15387ec681f3Smrg */ 15397ec681f3Smrg if (ISL_GFX_VER(dev) >= 12 && 15407ec681f3Smrg isl_format_supports_ccs_e(dev->info, surf_info->format) && 15417ec681f3Smrg tile_info->tiling != ISL_TILING_X && 15427ec681f3Smrg !(surf_info->usage & ISL_SURF_USAGE_DISABLE_AUX_BIT) && 15437ec681f3Smrg surf_info->row_pitch_B == 0) { 15447ec681f3Smrg return isl_align(tile_info->phys_extent_B.width, 512); 15457ec681f3Smrg } 15467ec681f3Smrg 154701e04c3fSmrg return tile_info->phys_extent_B.width; 15487ec681f3Smrg } 154901e04c3fSmrg 155001e04c3fSmrg /* From the Broadwel PRM >> Volume 2d: Command Reference: Structures >> 155101e04c3fSmrg * RENDER_SURFACE_STATE Surface Pitch (p349): 155201e04c3fSmrg * 155301e04c3fSmrg * - For linear render target surfaces and surfaces accessed with the 155401e04c3fSmrg * typed data port messages, the pitch must be a multiple of the 155501e04c3fSmrg * element size for non-YUV surface formats. Pitch must be 155601e04c3fSmrg * a multiple of 2 * element size for YUV surface formats. 155701e04c3fSmrg * 155801e04c3fSmrg * - [Requirements for SURFTYPE_BUFFER and SURFTYPE_STRBUF, which we 155901e04c3fSmrg * ignore because isl doesn't do buffers.] 156001e04c3fSmrg * 156101e04c3fSmrg * - For other linear surfaces, the pitch can be any multiple of 156201e04c3fSmrg * bytes. 156301e04c3fSmrg */ 156401e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf_info->format); 156501e04c3fSmrg const uint32_t bs = fmtl->bpb / 8; 15667ec681f3Smrg uint32_t alignment; 156701e04c3fSmrg 156801e04c3fSmrg if (surf_info->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) { 156901e04c3fSmrg if (isl_format_is_yuv(surf_info->format)) { 15707ec681f3Smrg alignment = 2 * bs; 157101e04c3fSmrg } else { 15727ec681f3Smrg alignment = bs; 157301e04c3fSmrg } 15747ec681f3Smrg } else { 15757ec681f3Smrg alignment = 1; 157601e04c3fSmrg } 157701e04c3fSmrg 15787ec681f3Smrg /* From the Broadwell PRM >> Volume 2c: Command Reference: Registers >> 15797ec681f3Smrg * PRI_STRIDE Stride (p1254): 15807ec681f3Smrg * 15817ec681f3Smrg * "When using linear memory, this must be at least 64 byte aligned." 15827ec681f3Smrg * 15837ec681f3Smrg * However, when displaying on NVIDIA and recent AMD GPUs via PRIME, 15847ec681f3Smrg * we need a larger pitch of 256 bytes. 15857ec681f3Smrg * 15867ec681f3Smrg * If the ISL caller didn't specify a row_pitch_B, then we should assume 15877ec681f3Smrg * the NVIDIA/AMD requirements. Otherwise, if we have a specified 15887ec681f3Smrg * row_pitch_B, this is probably because the caller is trying to import a 15897ec681f3Smrg * buffer. In that case we limit the minimum row pitch to the Intel HW 15907ec681f3Smrg * requirement. 15917ec681f3Smrg */ 15927ec681f3Smrg if (surf_info->usage & ISL_SURF_USAGE_DISPLAY_BIT) { 15937ec681f3Smrg if (surf_info->row_pitch_B == 0) 15947ec681f3Smrg alignment = isl_align(alignment, 256); 15957ec681f3Smrg else 15967ec681f3Smrg alignment = isl_align(alignment, 64); 15977ec681f3Smrg } 15987ec681f3Smrg 15997ec681f3Smrg return alignment; 160001e04c3fSmrg} 160101e04c3fSmrg 160201e04c3fSmrgstatic uint32_t 160301e04c3fSmrgisl_calc_linear_min_row_pitch(const struct isl_device *dev, 160401e04c3fSmrg const struct isl_surf_init_info *info, 16057ec681f3Smrg const struct isl_extent4d *phys_total_el, 160601e04c3fSmrg uint32_t alignment_B) 160701e04c3fSmrg{ 160801e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 160901e04c3fSmrg const uint32_t bs = fmtl->bpb / 8; 161001e04c3fSmrg 161101e04c3fSmrg return isl_align_npot(bs * phys_total_el->w, alignment_B); 161201e04c3fSmrg} 161301e04c3fSmrg 161401e04c3fSmrgstatic uint32_t 161501e04c3fSmrgisl_calc_tiled_min_row_pitch(const struct isl_device *dev, 161601e04c3fSmrg const struct isl_surf_init_info *surf_info, 161701e04c3fSmrg const struct isl_tile_info *tile_info, 16187ec681f3Smrg const struct isl_extent4d *phys_total_el, 161901e04c3fSmrg uint32_t alignment_B) 162001e04c3fSmrg{ 162101e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf_info->format); 162201e04c3fSmrg 162301e04c3fSmrg assert(fmtl->bpb % tile_info->format_bpb == 0); 162401e04c3fSmrg 162501e04c3fSmrg const uint32_t tile_el_scale = fmtl->bpb / tile_info->format_bpb; 162601e04c3fSmrg const uint32_t total_w_tl = 162701e04c3fSmrg isl_align_div(phys_total_el->w * tile_el_scale, 162801e04c3fSmrg tile_info->logical_extent_el.width); 162901e04c3fSmrg 16307ec681f3Smrg /* In some cases the alignment of the pitch might be > to the tile size 16317ec681f3Smrg * (for example Gfx12 CCS requires 512B alignment while the tile's width 16327ec681f3Smrg * can be 128B), so align the row pitch to the alignment. 16337ec681f3Smrg */ 16347ec681f3Smrg assert(alignment_B >= tile_info->phys_extent_B.width); 16357ec681f3Smrg return isl_align(total_w_tl * tile_info->phys_extent_B.width, alignment_B); 163601e04c3fSmrg} 163701e04c3fSmrg 163801e04c3fSmrgstatic uint32_t 163901e04c3fSmrgisl_calc_min_row_pitch(const struct isl_device *dev, 164001e04c3fSmrg const struct isl_surf_init_info *surf_info, 164101e04c3fSmrg const struct isl_tile_info *tile_info, 16427ec681f3Smrg const struct isl_extent4d *phys_total_el, 164301e04c3fSmrg uint32_t alignment_B) 164401e04c3fSmrg{ 164501e04c3fSmrg if (tile_info->tiling == ISL_TILING_LINEAR) { 164601e04c3fSmrg return isl_calc_linear_min_row_pitch(dev, surf_info, phys_total_el, 164701e04c3fSmrg alignment_B); 164801e04c3fSmrg } else { 164901e04c3fSmrg return isl_calc_tiled_min_row_pitch(dev, surf_info, tile_info, 165001e04c3fSmrg phys_total_el, alignment_B); 165101e04c3fSmrg } 165201e04c3fSmrg} 165301e04c3fSmrg 165401e04c3fSmrg/** 165501e04c3fSmrg * Is `pitch` in the valid range for a hardware bitfield, if the bitfield's 165601e04c3fSmrg * size is `bits` bits? 165701e04c3fSmrg * 165801e04c3fSmrg * Hardware pitch fields are offset by 1. For example, if the size of 165901e04c3fSmrg * RENDER_SURFACE_STATE::SurfacePitch is B bits, then the range of valid 166001e04c3fSmrg * pitches is [1, 2^b] inclusive. If the surface pitch is N, then 166101e04c3fSmrg * RENDER_SURFACE_STATE::SurfacePitch must be set to N-1. 166201e04c3fSmrg */ 166301e04c3fSmrgstatic bool 166401e04c3fSmrgpitch_in_range(uint32_t n, uint32_t bits) 166501e04c3fSmrg{ 166601e04c3fSmrg assert(n != 0); 166701e04c3fSmrg return likely(bits != 0 && 1 <= n && n <= (1 << bits)); 166801e04c3fSmrg} 166901e04c3fSmrg 167001e04c3fSmrgstatic bool 167101e04c3fSmrgisl_calc_row_pitch(const struct isl_device *dev, 167201e04c3fSmrg const struct isl_surf_init_info *surf_info, 167301e04c3fSmrg const struct isl_tile_info *tile_info, 167401e04c3fSmrg enum isl_dim_layout dim_layout, 16757ec681f3Smrg const struct isl_extent4d *phys_total_el, 167601e04c3fSmrg uint32_t *out_row_pitch_B) 167701e04c3fSmrg{ 167801e04c3fSmrg uint32_t alignment_B = 16797ec681f3Smrg isl_calc_row_pitch_alignment(dev, surf_info, tile_info); 168001e04c3fSmrg 168101e04c3fSmrg const uint32_t min_row_pitch_B = 168201e04c3fSmrg isl_calc_min_row_pitch(dev, surf_info, tile_info, phys_total_el, 168301e04c3fSmrg alignment_B); 168401e04c3fSmrg 168501e04c3fSmrg if (surf_info->row_pitch_B != 0) { 16867ec681f3Smrg if (surf_info->row_pitch_B < min_row_pitch_B) 168701e04c3fSmrg return false; 168801e04c3fSmrg 16897ec681f3Smrg if (surf_info->row_pitch_B % alignment_B != 0) 169001e04c3fSmrg return false; 169101e04c3fSmrg } 169201e04c3fSmrg 16937ec681f3Smrg const uint32_t row_pitch_B = 16947ec681f3Smrg surf_info->row_pitch_B != 0 ? surf_info->row_pitch_B : min_row_pitch_B; 16957ec681f3Smrg 169601e04c3fSmrg const uint32_t row_pitch_tl = row_pitch_B / tile_info->phys_extent_B.width; 169701e04c3fSmrg 169801e04c3fSmrg if (row_pitch_B == 0) 169901e04c3fSmrg return false; 170001e04c3fSmrg 17017ec681f3Smrg if (dim_layout == ISL_DIM_LAYOUT_GFX9_1D) { 170201e04c3fSmrg /* SurfacePitch is ignored for this layout. */ 170301e04c3fSmrg goto done; 170401e04c3fSmrg } 170501e04c3fSmrg 170601e04c3fSmrg if ((surf_info->usage & (ISL_SURF_USAGE_RENDER_TARGET_BIT | 170701e04c3fSmrg ISL_SURF_USAGE_TEXTURE_BIT | 170801e04c3fSmrg ISL_SURF_USAGE_STORAGE_BIT)) && 170901e04c3fSmrg !pitch_in_range(row_pitch_B, RENDER_SURFACE_STATE_SurfacePitch_bits(dev->info))) 171001e04c3fSmrg return false; 171101e04c3fSmrg 171201e04c3fSmrg if ((surf_info->usage & (ISL_SURF_USAGE_CCS_BIT | 171301e04c3fSmrg ISL_SURF_USAGE_MCS_BIT)) && 171401e04c3fSmrg !pitch_in_range(row_pitch_tl, RENDER_SURFACE_STATE_AuxiliarySurfacePitch_bits(dev->info))) 171501e04c3fSmrg return false; 171601e04c3fSmrg 171701e04c3fSmrg if ((surf_info->usage & ISL_SURF_USAGE_DEPTH_BIT) && 171801e04c3fSmrg !pitch_in_range(row_pitch_B, _3DSTATE_DEPTH_BUFFER_SurfacePitch_bits(dev->info))) 171901e04c3fSmrg return false; 172001e04c3fSmrg 172101e04c3fSmrg if ((surf_info->usage & ISL_SURF_USAGE_HIZ_BIT) && 172201e04c3fSmrg !pitch_in_range(row_pitch_B, _3DSTATE_HIER_DEPTH_BUFFER_SurfacePitch_bits(dev->info))) 172301e04c3fSmrg return false; 172401e04c3fSmrg 172501e04c3fSmrg const uint32_t stencil_pitch_bits = dev->use_separate_stencil ? 172601e04c3fSmrg _3DSTATE_STENCIL_BUFFER_SurfacePitch_bits(dev->info) : 172701e04c3fSmrg _3DSTATE_DEPTH_BUFFER_SurfacePitch_bits(dev->info); 172801e04c3fSmrg 172901e04c3fSmrg if ((surf_info->usage & ISL_SURF_USAGE_STENCIL_BIT) && 173001e04c3fSmrg !pitch_in_range(row_pitch_B, stencil_pitch_bits)) 173101e04c3fSmrg return false; 173201e04c3fSmrg 173301e04c3fSmrg done: 173401e04c3fSmrg *out_row_pitch_B = row_pitch_B; 173501e04c3fSmrg return true; 173601e04c3fSmrg} 173701e04c3fSmrg 173801e04c3fSmrgbool 173901e04c3fSmrgisl_surf_init_s(const struct isl_device *dev, 174001e04c3fSmrg struct isl_surf *surf, 174101e04c3fSmrg const struct isl_surf_init_info *restrict info) 174201e04c3fSmrg{ 174301e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 174401e04c3fSmrg 174501e04c3fSmrg const struct isl_extent4d logical_level0_px = { 174601e04c3fSmrg .w = info->width, 174701e04c3fSmrg .h = info->height, 174801e04c3fSmrg .d = info->depth, 174901e04c3fSmrg .a = info->array_len, 175001e04c3fSmrg }; 175101e04c3fSmrg 175201e04c3fSmrg enum isl_tiling tiling; 175301e04c3fSmrg if (!isl_surf_choose_tiling(dev, info, &tiling)) 175401e04c3fSmrg return false; 175501e04c3fSmrg 175601e04c3fSmrg const enum isl_dim_layout dim_layout = 175701e04c3fSmrg isl_surf_choose_dim_layout(dev, info->dim, tiling, info->usage); 175801e04c3fSmrg 175901e04c3fSmrg enum isl_msaa_layout msaa_layout; 176001e04c3fSmrg if (!isl_choose_msaa_layout(dev, info, tiling, &msaa_layout)) 176101e04c3fSmrg return false; 176201e04c3fSmrg 17637ec681f3Smrg struct isl_tile_info tile_info; 17647ec681f3Smrg isl_tiling_get_info(tiling, info->dim, msaa_layout, fmtl->bpb, 17657ec681f3Smrg info->samples, &tile_info); 17667ec681f3Smrg 176701e04c3fSmrg struct isl_extent3d image_align_el; 176801e04c3fSmrg isl_choose_image_alignment_el(dev, info, tiling, dim_layout, msaa_layout, 176901e04c3fSmrg &image_align_el); 177001e04c3fSmrg 177101e04c3fSmrg struct isl_extent3d image_align_sa = 177201e04c3fSmrg isl_extent3d_el_to_sa(info->format, image_align_el); 177301e04c3fSmrg 177401e04c3fSmrg struct isl_extent4d phys_level0_sa; 177501e04c3fSmrg isl_calc_phys_level0_extent_sa(dev, info, dim_layout, tiling, msaa_layout, 177601e04c3fSmrg &phys_level0_sa); 177701e04c3fSmrg 177801e04c3fSmrg enum isl_array_pitch_span array_pitch_span = 177901e04c3fSmrg isl_choose_array_pitch_span(dev, info, dim_layout, &phys_level0_sa); 178001e04c3fSmrg 178101e04c3fSmrg uint32_t array_pitch_el_rows; 17827ec681f3Smrg struct isl_extent4d phys_total_el; 178301e04c3fSmrg isl_calc_phys_total_extent_el(dev, info, &tile_info, 178401e04c3fSmrg dim_layout, msaa_layout, 178501e04c3fSmrg &image_align_sa, &phys_level0_sa, 178601e04c3fSmrg array_pitch_span, &array_pitch_el_rows, 178701e04c3fSmrg &phys_total_el); 178801e04c3fSmrg 178901e04c3fSmrg uint32_t row_pitch_B; 179001e04c3fSmrg if (!isl_calc_row_pitch(dev, info, &tile_info, dim_layout, 179101e04c3fSmrg &phys_total_el, &row_pitch_B)) 179201e04c3fSmrg return false; 179301e04c3fSmrg 179401e04c3fSmrg uint32_t base_alignment_B; 179501e04c3fSmrg uint64_t size_B; 179601e04c3fSmrg if (tiling == ISL_TILING_LINEAR) { 17977ec681f3Smrg /* LINEAR tiling has no concept of intra-tile arrays */ 17987ec681f3Smrg assert(phys_total_el.d == 1 && phys_total_el.a == 1); 17997ec681f3Smrg 180001e04c3fSmrg size_B = (uint64_t) row_pitch_B * phys_total_el.h; 180101e04c3fSmrg 180201e04c3fSmrg /* From the Broadwell PRM Vol 2d, RENDER_SURFACE_STATE::SurfaceBaseAddress: 180301e04c3fSmrg * 180401e04c3fSmrg * "The Base Address for linear render target surfaces and surfaces 180501e04c3fSmrg * accessed with the typed surface read/write data port messages must 180601e04c3fSmrg * be element-size aligned, for non-YUV surface formats, or a 180701e04c3fSmrg * multiple of 2 element-sizes for YUV surface formats. Other linear 180801e04c3fSmrg * surfaces have no alignment requirements (byte alignment is 180901e04c3fSmrg * sufficient.)" 181001e04c3fSmrg */ 181101e04c3fSmrg base_alignment_B = MAX(1, info->min_alignment_B); 181201e04c3fSmrg if (info->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) { 181301e04c3fSmrg if (isl_format_is_yuv(info->format)) { 181401e04c3fSmrg base_alignment_B = MAX(base_alignment_B, fmtl->bpb / 4); 181501e04c3fSmrg } else { 181601e04c3fSmrg base_alignment_B = MAX(base_alignment_B, fmtl->bpb / 8); 181701e04c3fSmrg } 181801e04c3fSmrg } 181901e04c3fSmrg base_alignment_B = isl_round_up_to_power_of_two(base_alignment_B); 18209f464c52Smaya 18219f464c52Smaya /* From the Skylake PRM Vol 2c, PLANE_STRIDE::Stride: 18229f464c52Smaya * 18239f464c52Smaya * "For Linear memory, this field specifies the stride in chunks of 18249f464c52Smaya * 64 bytes (1 cache line)." 18259f464c52Smaya */ 18269f464c52Smaya if (isl_surf_usage_is_display(info->usage)) 18279f464c52Smaya base_alignment_B = MAX(base_alignment_B, 64); 182801e04c3fSmrg } else { 18297ec681f3Smrg /* Pitches must make sense with the tiling */ 18307ec681f3Smrg assert(row_pitch_B % tile_info.phys_extent_B.width == 0); 18317ec681f3Smrg 18327ec681f3Smrg uint32_t array_slices, array_pitch_tl_rows; 18337ec681f3Smrg if (phys_total_el.d > 1) { 18347ec681f3Smrg assert(phys_total_el.a == 1); 18357ec681f3Smrg array_pitch_tl_rows = isl_assert_div(array_pitch_el_rows, 18367ec681f3Smrg tile_info.logical_extent_el.h); 18377ec681f3Smrg array_slices = isl_align_div(phys_total_el.d, 18387ec681f3Smrg tile_info.logical_extent_el.d); 18397ec681f3Smrg } else if (phys_total_el.a > 1) { 18407ec681f3Smrg assert(phys_total_el.d == 1); 18417ec681f3Smrg array_pitch_tl_rows = isl_assert_div(array_pitch_el_rows, 18427ec681f3Smrg tile_info.logical_extent_el.h); 18437ec681f3Smrg array_slices = isl_align_div(phys_total_el.a, 18447ec681f3Smrg tile_info.logical_extent_el.a); 18457ec681f3Smrg } else { 18467ec681f3Smrg assert(phys_total_el.d == 1 && phys_total_el.a == 1); 18477ec681f3Smrg array_pitch_tl_rows = 0; 18487ec681f3Smrg array_slices = 1; 18497ec681f3Smrg } 18507ec681f3Smrg 185101e04c3fSmrg const uint32_t total_h_tl = 18527ec681f3Smrg (array_slices - 1) * array_pitch_tl_rows + 185301e04c3fSmrg isl_align_div(phys_total_el.h, tile_info.logical_extent_el.height); 185401e04c3fSmrg 185501e04c3fSmrg size_B = (uint64_t) total_h_tl * tile_info.phys_extent_B.height * row_pitch_B; 185601e04c3fSmrg 185701e04c3fSmrg const uint32_t tile_size_B = tile_info.phys_extent_B.width * 185801e04c3fSmrg tile_info.phys_extent_B.height; 185901e04c3fSmrg assert(isl_is_pow2(info->min_alignment_B) && isl_is_pow2(tile_size_B)); 186001e04c3fSmrg base_alignment_B = MAX(info->min_alignment_B, tile_size_B); 18617ec681f3Smrg 18627ec681f3Smrg /* The diagram in the Bspec section Memory Compression - Gfx12, shows 18637ec681f3Smrg * that the CCS is indexed in 256B chunks. However, the 18647ec681f3Smrg * PLANE_AUX_DIST::Auxiliary Surface Distance field is in units of 4K 18657ec681f3Smrg * pages. We currently don't assign the usage field like we do for main 18667ec681f3Smrg * surfaces, so just use 4K for now. 18677ec681f3Smrg */ 18687ec681f3Smrg if (tiling == ISL_TILING_GFX12_CCS) 18697ec681f3Smrg base_alignment_B = MAX(base_alignment_B, 4096); 18707ec681f3Smrg 18717ec681f3Smrg /* Gfx12+ requires that images be 64K-aligned if they're going to used 18727ec681f3Smrg * with CCS. This is because the Aux translation table maps main 18737ec681f3Smrg * surface addresses to aux addresses at a 64K (in the main surface) 18747ec681f3Smrg * granularity. Because we don't know for sure in ISL if a surface will 18757ec681f3Smrg * use CCS, we have to guess based on the DISABLE_AUX usage bit. The 18767ec681f3Smrg * one thing we do know is that we haven't enable CCS on linear images 18777ec681f3Smrg * yet so we can avoid the extra alignment there. 18787ec681f3Smrg */ 18797ec681f3Smrg if (ISL_GFX_VER(dev) >= 12 && 18807ec681f3Smrg !(info->usage & ISL_SURF_USAGE_DISABLE_AUX_BIT)) { 18817ec681f3Smrg base_alignment_B = MAX(base_alignment_B, 64 * 1024); 18827ec681f3Smrg } 188301e04c3fSmrg } 188401e04c3fSmrg 18857ec681f3Smrg if (ISL_GFX_VER(dev) < 9) { 188601e04c3fSmrg /* From the Broadwell PRM Vol 5, Surface Layout: 188701e04c3fSmrg * 188801e04c3fSmrg * "In addition to restrictions on maximum height, width, and depth, 188901e04c3fSmrg * surfaces are also restricted to a maximum size in bytes. This 189001e04c3fSmrg * maximum is 2 GB for all products and all surface types." 189101e04c3fSmrg * 18927ec681f3Smrg * This comment is applicable to all Pre-gfx9 platforms. 189301e04c3fSmrg */ 189401e04c3fSmrg if (size_B > (uint64_t) 1 << 31) 189501e04c3fSmrg return false; 18967ec681f3Smrg } else if (ISL_GFX_VER(dev) < 11) { 189701e04c3fSmrg /* From the Skylake PRM Vol 5, Maximum Surface Size in Bytes: 189801e04c3fSmrg * "In addition to restrictions on maximum height, width, and depth, 189901e04c3fSmrg * surfaces are also restricted to a maximum size of 2^38 bytes. 190001e04c3fSmrg * All pixels within the surface must be contained within 2^38 bytes 190101e04c3fSmrg * of the base address." 190201e04c3fSmrg */ 190301e04c3fSmrg if (size_B > (uint64_t) 1 << 38) 190401e04c3fSmrg return false; 190501e04c3fSmrg } else { 19067ec681f3Smrg /* gfx11+ platforms raised this limit to 2^44 bytes. */ 190701e04c3fSmrg if (size_B > (uint64_t) 1 << 44) 190801e04c3fSmrg return false; 190901e04c3fSmrg } 191001e04c3fSmrg 191101e04c3fSmrg *surf = (struct isl_surf) { 191201e04c3fSmrg .dim = info->dim, 191301e04c3fSmrg .dim_layout = dim_layout, 191401e04c3fSmrg .msaa_layout = msaa_layout, 191501e04c3fSmrg .tiling = tiling, 191601e04c3fSmrg .format = info->format, 191701e04c3fSmrg 191801e04c3fSmrg .levels = info->levels, 191901e04c3fSmrg .samples = info->samples, 192001e04c3fSmrg 192101e04c3fSmrg .image_alignment_el = image_align_el, 192201e04c3fSmrg .logical_level0_px = logical_level0_px, 192301e04c3fSmrg .phys_level0_sa = phys_level0_sa, 192401e04c3fSmrg 192501e04c3fSmrg .size_B = size_B, 192601e04c3fSmrg .alignment_B = base_alignment_B, 192701e04c3fSmrg .row_pitch_B = row_pitch_B, 192801e04c3fSmrg .array_pitch_el_rows = array_pitch_el_rows, 192901e04c3fSmrg .array_pitch_span = array_pitch_span, 193001e04c3fSmrg 193101e04c3fSmrg .usage = info->usage, 193201e04c3fSmrg }; 193301e04c3fSmrg 193401e04c3fSmrg return true; 193501e04c3fSmrg} 193601e04c3fSmrg 193701e04c3fSmrgvoid 193801e04c3fSmrgisl_surf_get_tile_info(const struct isl_surf *surf, 193901e04c3fSmrg struct isl_tile_info *tile_info) 194001e04c3fSmrg{ 194101e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); 19427ec681f3Smrg isl_tiling_get_info(surf->tiling, surf->dim, surf->msaa_layout, fmtl->bpb, 19437ec681f3Smrg surf->samples, tile_info); 194401e04c3fSmrg} 194501e04c3fSmrg 194601e04c3fSmrgbool 194701e04c3fSmrgisl_surf_get_hiz_surf(const struct isl_device *dev, 194801e04c3fSmrg const struct isl_surf *surf, 194901e04c3fSmrg struct isl_surf *hiz_surf) 195001e04c3fSmrg{ 19517ec681f3Smrg assert(ISL_GFX_VER(dev) >= 5 && ISL_DEV_USE_SEPARATE_STENCIL(dev)); 19527ec681f3Smrg 19537ec681f3Smrg if (!isl_surf_usage_is_depth(surf->usage)) 19547ec681f3Smrg return false; 19557ec681f3Smrg 19567ec681f3Smrg /* HiZ only works with Y-tiled depth buffers */ 19577ec681f3Smrg if (!isl_tiling_is_any_y(surf->tiling)) 19587ec681f3Smrg return false; 19597ec681f3Smrg 19607ec681f3Smrg /* On SNB+, compressed depth buffers cannot be interleaved with stencil. */ 19617ec681f3Smrg switch (surf->format) { 19627ec681f3Smrg case ISL_FORMAT_R24_UNORM_X8_TYPELESS: 19637ec681f3Smrg if (isl_surf_usage_is_depth_and_stencil(surf->usage)) { 19647ec681f3Smrg assert(ISL_GFX_VER(dev) == 5); 19657ec681f3Smrg unreachable("This should work, but is untested"); 19667ec681f3Smrg } 19677ec681f3Smrg FALLTHROUGH; 19687ec681f3Smrg case ISL_FORMAT_R16_UNORM: 19697ec681f3Smrg case ISL_FORMAT_R32_FLOAT: 19707ec681f3Smrg break; 19717ec681f3Smrg case ISL_FORMAT_R32_FLOAT_X8X24_TYPELESS: 19727ec681f3Smrg if (ISL_GFX_VER(dev) == 5) { 19737ec681f3Smrg assert(isl_surf_usage_is_depth_and_stencil(surf->usage)); 19747ec681f3Smrg unreachable("This should work, but is untested"); 19757ec681f3Smrg } 19767ec681f3Smrg FALLTHROUGH; 19777ec681f3Smrg default: 19787ec681f3Smrg return false; 19797ec681f3Smrg } 198001e04c3fSmrg 198101e04c3fSmrg /* Multisampled depth is always interleaved */ 198201e04c3fSmrg assert(surf->msaa_layout == ISL_MSAA_LAYOUT_NONE || 198301e04c3fSmrg surf->msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED); 198401e04c3fSmrg 198501e04c3fSmrg /* From the Broadwell PRM Vol. 7, "Hierarchical Depth Buffer": 198601e04c3fSmrg * 198701e04c3fSmrg * "The Surface Type, Height, Width, Depth, Minimum Array Element, Render 198801e04c3fSmrg * Target View Extent, and Depth Coordinate Offset X/Y of the 198901e04c3fSmrg * hierarchical depth buffer are inherited from the depth buffer. The 199001e04c3fSmrg * height and width of the hierarchical depth buffer that must be 199101e04c3fSmrg * allocated are computed by the following formulas, where HZ is the 199201e04c3fSmrg * hierarchical depth buffer and Z is the depth buffer. The Z_Height, 199301e04c3fSmrg * Z_Width, and Z_Depth values given in these formulas are those present 199401e04c3fSmrg * in 3DSTATE_DEPTH_BUFFER incremented by one. 199501e04c3fSmrg * 199601e04c3fSmrg * "The value of Z_Height and Z_Width must each be multiplied by 2 before 199701e04c3fSmrg * being applied to the table below if Number of Multisamples is set to 199801e04c3fSmrg * NUMSAMPLES_4. The value of Z_Height must be multiplied by 2 and 199901e04c3fSmrg * Z_Width must be multiplied by 4 before being applied to the table 200001e04c3fSmrg * below if Number of Multisamples is set to NUMSAMPLES_8." 200101e04c3fSmrg * 200201e04c3fSmrg * In the Sky Lake PRM, the second paragraph is replaced with this: 200301e04c3fSmrg * 200401e04c3fSmrg * "The Z_Height and Z_Width values must equal those present in 200501e04c3fSmrg * 3DSTATE_DEPTH_BUFFER incremented by one." 200601e04c3fSmrg * 200701e04c3fSmrg * In other words, on Sandy Bridge through Broadwell, each 128-bit HiZ 200801e04c3fSmrg * block corresponds to a region of 8x4 samples in the primary depth 200901e04c3fSmrg * surface. On Sky Lake, on the other hand, each HiZ block corresponds to 201001e04c3fSmrg * a region of 8x4 pixels in the primary depth surface regardless of the 201101e04c3fSmrg * number of samples. The dimensions of a HiZ block in both pixels and 201201e04c3fSmrg * samples are given in the table below: 201301e04c3fSmrg * 201401e04c3fSmrg * | SNB - BDW | SKL+ 201501e04c3fSmrg * ------+-----------+------------- 201601e04c3fSmrg * 1x | 8 x 4 sa | 8 x 4 sa 201701e04c3fSmrg * MSAA | 8 x 4 px | 8 x 4 px 201801e04c3fSmrg * ------+-----------+------------- 201901e04c3fSmrg * 2x | 8 x 4 sa | 16 x 4 sa 202001e04c3fSmrg * MSAA | 4 x 4 px | 8 x 4 px 202101e04c3fSmrg * ------+-----------+------------- 202201e04c3fSmrg * 4x | 8 x 4 sa | 16 x 8 sa 202301e04c3fSmrg * MSAA | 4 x 2 px | 8 x 4 px 202401e04c3fSmrg * ------+-----------+------------- 202501e04c3fSmrg * 8x | 8 x 4 sa | 32 x 8 sa 202601e04c3fSmrg * MSAA | 2 x 2 px | 8 x 4 px 202701e04c3fSmrg * ------+-----------+------------- 202801e04c3fSmrg * 16x | N/A | 32 x 16 sa 202901e04c3fSmrg * MSAA | N/A | 8 x 4 px 203001e04c3fSmrg * ------+-----------+------------- 203101e04c3fSmrg * 203201e04c3fSmrg * There are a number of different ways that this discrepency could be 203301e04c3fSmrg * handled. The way we have chosen is to simply make MSAA HiZ have the 203401e04c3fSmrg * same number of samples as the parent surface pre-Sky Lake and always be 203501e04c3fSmrg * single-sampled on Sky Lake and above. Since the block sizes of 203601e04c3fSmrg * compressed formats are given in samples, this neatly handles everything 203701e04c3fSmrg * without the need for additional HiZ formats with different block sizes 203801e04c3fSmrg * on SKL+. 203901e04c3fSmrg */ 20407ec681f3Smrg const unsigned samples = ISL_GFX_VER(dev) >= 9 ? 1 : surf->samples; 204101e04c3fSmrg 204201e04c3fSmrg return isl_surf_init(dev, hiz_surf, 204301e04c3fSmrg .dim = surf->dim, 204401e04c3fSmrg .format = ISL_FORMAT_HIZ, 204501e04c3fSmrg .width = surf->logical_level0_px.width, 204601e04c3fSmrg .height = surf->logical_level0_px.height, 204701e04c3fSmrg .depth = surf->logical_level0_px.depth, 204801e04c3fSmrg .levels = surf->levels, 204901e04c3fSmrg .array_len = surf->logical_level0_px.array_len, 205001e04c3fSmrg .samples = samples, 205101e04c3fSmrg .usage = ISL_SURF_USAGE_HIZ_BIT, 205201e04c3fSmrg .tiling_flags = ISL_TILING_HIZ_BIT); 205301e04c3fSmrg} 205401e04c3fSmrg 205501e04c3fSmrgbool 205601e04c3fSmrgisl_surf_get_mcs_surf(const struct isl_device *dev, 205701e04c3fSmrg const struct isl_surf *surf, 205801e04c3fSmrg struct isl_surf *mcs_surf) 205901e04c3fSmrg{ 206001e04c3fSmrg /* It must be multisampled with an array layout */ 20617ec681f3Smrg if (surf->msaa_layout != ISL_MSAA_LAYOUT_ARRAY) 20627ec681f3Smrg return false; 20637ec681f3Smrg 20647ec681f3Smrg if (mcs_surf->size_B > 0) 20657ec681f3Smrg return false; 206601e04c3fSmrg 206701e04c3fSmrg /* The following are true of all multisampled surfaces */ 20687ec681f3Smrg assert(surf->samples > 1); 206901e04c3fSmrg assert(surf->dim == ISL_SURF_DIM_2D); 207001e04c3fSmrg assert(surf->levels == 1); 207101e04c3fSmrg assert(surf->logical_level0_px.depth == 1); 207201e04c3fSmrg 20737ec681f3Smrg /* From the Ivy Bridge PRM, Vol4 Part1 p77 ("MCS Enable"): 20747ec681f3Smrg * 20757ec681f3Smrg * This field must be set to 0 for all SINT MSRTs when all RT channels 20767ec681f3Smrg * are not written 20777ec681f3Smrg * 20787ec681f3Smrg * In practice this means that we have to disable MCS for all signed 20797ec681f3Smrg * integer MSAA buffers. The alternative, to disable MCS only when one 20807ec681f3Smrg * of the render target channels is disabled, is impractical because it 20817ec681f3Smrg * would require converting between CMS and UMS MSAA layouts on the fly, 20827ec681f3Smrg * which is expensive. 20837ec681f3Smrg */ 20847ec681f3Smrg if (ISL_GFX_VER(dev) == 7 && isl_format_has_sint_channel(surf->format)) 20857ec681f3Smrg return false; 20867ec681f3Smrg 208701e04c3fSmrg /* The "Auxiliary Surface Pitch" field in RENDER_SURFACE_STATE is only 9 208801e04c3fSmrg * bits which means the maximum pitch of a compression surface is 512 208901e04c3fSmrg * tiles or 64KB (since MCS is always Y-tiled). Since a 16x MCS buffer is 209001e04c3fSmrg * 64bpp, this gives us a maximum width of 8192 pixels. We can create 209101e04c3fSmrg * larger multisampled surfaces, we just can't compress them. For 2x, 4x, 209201e04c3fSmrg * and 8x, we have enough room for the full 16k supported by the hardware. 209301e04c3fSmrg */ 209401e04c3fSmrg if (surf->samples == 16 && surf->logical_level0_px.width > 8192) 209501e04c3fSmrg return false; 209601e04c3fSmrg 209701e04c3fSmrg enum isl_format mcs_format; 209801e04c3fSmrg switch (surf->samples) { 209901e04c3fSmrg case 2: mcs_format = ISL_FORMAT_MCS_2X; break; 210001e04c3fSmrg case 4: mcs_format = ISL_FORMAT_MCS_4X; break; 210101e04c3fSmrg case 8: mcs_format = ISL_FORMAT_MCS_8X; break; 210201e04c3fSmrg case 16: mcs_format = ISL_FORMAT_MCS_16X; break; 210301e04c3fSmrg default: 210401e04c3fSmrg unreachable("Invalid sample count"); 210501e04c3fSmrg } 210601e04c3fSmrg 210701e04c3fSmrg return isl_surf_init(dev, mcs_surf, 210801e04c3fSmrg .dim = ISL_SURF_DIM_2D, 210901e04c3fSmrg .format = mcs_format, 211001e04c3fSmrg .width = surf->logical_level0_px.width, 211101e04c3fSmrg .height = surf->logical_level0_px.height, 211201e04c3fSmrg .depth = 1, 211301e04c3fSmrg .levels = 1, 211401e04c3fSmrg .array_len = surf->logical_level0_px.array_len, 211501e04c3fSmrg .samples = 1, /* MCS surfaces are really single-sampled */ 211601e04c3fSmrg .usage = ISL_SURF_USAGE_MCS_BIT, 211701e04c3fSmrg .tiling_flags = ISL_TILING_Y0_BIT); 211801e04c3fSmrg} 211901e04c3fSmrg 212001e04c3fSmrgbool 21217ec681f3Smrgisl_surf_supports_ccs(const struct isl_device *dev, 212201e04c3fSmrg const struct isl_surf *surf, 21237ec681f3Smrg const struct isl_surf *hiz_or_mcs_surf) 212401e04c3fSmrg{ 21257ec681f3Smrg /* CCS support does not exist prior to Gfx7 */ 21267ec681f3Smrg if (ISL_GFX_VER(dev) <= 6) 21277ec681f3Smrg return false; 21287ec681f3Smrg 21297ec681f3Smrg /* Wa_22011186057: Disable compression on ADL-P A0 */ 21307ec681f3Smrg if (dev->info->is_alderlake && dev->info->gt == 2 && 21317ec681f3Smrg dev->info->revision == 0) 21327ec681f3Smrg return false; 213301e04c3fSmrg 213401e04c3fSmrg if (surf->usage & ISL_SURF_USAGE_DISABLE_AUX_BIT) 213501e04c3fSmrg return false; 213601e04c3fSmrg 21377ec681f3Smrg if (isl_format_is_compressed(surf->format)) 213801e04c3fSmrg return false; 213901e04c3fSmrg 21407ec681f3Smrg if (!isl_is_pow2(isl_format_get_layout(surf->format)->bpb)) 21417ec681f3Smrg return false; 21427ec681f3Smrg 21437ec681f3Smrg /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render 21447ec681f3Smrg * Target(s)", beneath the "Fast Color Clear" bullet (p326): 21457ec681f3Smrg * 21467ec681f3Smrg * - Support is limited to tiled render targets. 21477ec681f3Smrg * 21487ec681f3Smrg * From the Skylake documentation, it is made clear that X-tiling is no 21497ec681f3Smrg * longer supported: 21507ec681f3Smrg * 21517ec681f3Smrg * - MCS and Lossless compression is supported for 21527ec681f3Smrg * TiledY/TileYs/TileYf non-MSRTs only. 215301e04c3fSmrg * 21547ec681f3Smrg * From the BSpec (44930) for Gfx12: 215501e04c3fSmrg * 21567ec681f3Smrg * Linear CCS is only allowed for Untyped Buffers but only via HDC 21577ec681f3Smrg * Data-Port messages. 21587ec681f3Smrg * 21597ec681f3Smrg * We never use untyped messages on surfaces created by ISL on Gfx9+ so 21607ec681f3Smrg * this means linear is out on Gfx12+ as well. 216101e04c3fSmrg */ 21627ec681f3Smrg if (surf->tiling == ISL_TILING_LINEAR) 216301e04c3fSmrg return false; 216401e04c3fSmrg 21657ec681f3Smrg if (ISL_GFX_VER(dev) >= 12) { 21667ec681f3Smrg if (isl_surf_usage_is_stencil(surf->usage)) { 21677ec681f3Smrg /* HiZ and MCS aren't allowed with stencil */ 21687ec681f3Smrg assert(hiz_or_mcs_surf == NULL || hiz_or_mcs_surf->size_B == 0); 21697ec681f3Smrg 21707ec681f3Smrg /* Multi-sampled stencil cannot have CCS */ 21717ec681f3Smrg if (surf->samples > 1) 21727ec681f3Smrg return false; 21737ec681f3Smrg } else if (isl_surf_usage_is_depth(surf->usage)) { 21747ec681f3Smrg const struct isl_surf *hiz_surf = hiz_or_mcs_surf; 21757ec681f3Smrg 21767ec681f3Smrg /* With depth surfaces, HIZ is required for CCS. */ 21777ec681f3Smrg if (hiz_surf == NULL || hiz_surf->size_B == 0) 21787ec681f3Smrg return false; 21797ec681f3Smrg 21807ec681f3Smrg assert(hiz_surf->usage & ISL_SURF_USAGE_HIZ_BIT); 21817ec681f3Smrg assert(hiz_surf->tiling == ISL_TILING_HIZ); 21827ec681f3Smrg assert(hiz_surf->format == ISL_FORMAT_HIZ); 21837ec681f3Smrg } else if (surf->samples > 1) { 21847ec681f3Smrg const struct isl_surf *mcs_surf = hiz_or_mcs_surf; 21857ec681f3Smrg 21867ec681f3Smrg /* With multisampled color, CCS requires MCS */ 21877ec681f3Smrg if (mcs_surf == NULL || mcs_surf->size_B == 0) 21887ec681f3Smrg return false; 21897ec681f3Smrg 21907ec681f3Smrg assert(mcs_surf->usage & ISL_SURF_USAGE_MCS_BIT); 21917ec681f3Smrg assert(isl_tiling_is_any_y(mcs_surf->tiling)); 21927ec681f3Smrg assert(isl_format_is_mcs(mcs_surf->format)); 21937ec681f3Smrg } else { 21947ec681f3Smrg /* Single-sampled color can't have MCS or HiZ */ 21957ec681f3Smrg assert(hiz_or_mcs_surf == NULL || hiz_or_mcs_surf->size_B == 0); 21967ec681f3Smrg } 219701e04c3fSmrg 21987ec681f3Smrg /* On Gfx12, all CCS-compressed surface pitches must be multiples of 21997ec681f3Smrg * 512B. 22007ec681f3Smrg */ 22017ec681f3Smrg if (surf->row_pitch_B % 512 != 0) 220201e04c3fSmrg return false; 220301e04c3fSmrg 22047ec681f3Smrg /* According to Wa_1406738321, 3D textures need a blit to a new 22057ec681f3Smrg * surface in order to perform a resolve. For now, just disable CCS. 22067ec681f3Smrg */ 22077ec681f3Smrg if (surf->dim == ISL_SURF_DIM_3D) { 22087ec681f3Smrg isl_finishme("%s:%s: CCS for 3D textures is disabled, but a workaround" 22097ec681f3Smrg " is available.", __FILE__, __func__); 221001e04c3fSmrg return false; 221101e04c3fSmrg } 22127ec681f3Smrg 22137ec681f3Smrg /* Wa_1207137018 22147ec681f3Smrg * 22157ec681f3Smrg * TODO: implement following workaround currently covered by the 22167ec681f3Smrg * restriction above. If following conditions are met: 22177ec681f3Smrg * 22187ec681f3Smrg * - RENDER_SURFACE_STATE.Surface Type == 3D 22197ec681f3Smrg * - RENDER_SURFACE_STATE.Auxiliary Surface Mode != AUX_NONE 22207ec681f3Smrg * - RENDER_SURFACE_STATE.Tiled ResourceMode is TYF or TYS 22217ec681f3Smrg * 22227ec681f3Smrg * Set the value of RENDER_SURFACE_STATE.Mip Tail Start LOD to a mip 22237ec681f3Smrg * that larger than those present in the surface (i.e. 15) 22247ec681f3Smrg */ 22257ec681f3Smrg 22267ec681f3Smrg /* TODO: Handle the other tiling formats */ 22277ec681f3Smrg if (surf->tiling != ISL_TILING_Y0) 222801e04c3fSmrg return false; 22297ec681f3Smrg } else { 22307ec681f3Smrg /* ISL_GFX_VER(dev) < 12 */ 22317ec681f3Smrg if (surf->samples > 1) 22327ec681f3Smrg return false; 22337ec681f3Smrg 22347ec681f3Smrg /* CCS is only for color images on Gfx7-11 */ 22357ec681f3Smrg if (isl_surf_usage_is_depth_or_stencil(surf->usage)) 22367ec681f3Smrg return false; 22377ec681f3Smrg 22387ec681f3Smrg /* We're single-sampled color so having HiZ or MCS makes no sense */ 22397ec681f3Smrg assert(hiz_or_mcs_surf == NULL || hiz_or_mcs_surf->size_B == 0); 22407ec681f3Smrg 22417ec681f3Smrg /* The PRM doesn't say this explicitly, but fast-clears don't appear to 22427ec681f3Smrg * work for 3D textures until gfx9 where the layout of 3D textures 22437ec681f3Smrg * changes to match 2D array textures. 22447ec681f3Smrg */ 22457ec681f3Smrg if (ISL_GFX_VER(dev) <= 8 && surf->dim != ISL_SURF_DIM_2D) 22467ec681f3Smrg return false; 22477ec681f3Smrg 22487ec681f3Smrg /* From the HSW PRM Volume 7: 3D-Media-GPGPU, page 652 (Color Clear of 22497ec681f3Smrg * Non-MultiSampler Render Target Restrictions): 22507ec681f3Smrg * 22517ec681f3Smrg * "Support is for non-mip-mapped and non-array surface types only." 22527ec681f3Smrg * 22537ec681f3Smrg * This restriction is lifted on gfx8+. Technically, it may be possible 22547ec681f3Smrg * to create a CCS for an arrayed or mipmapped image and only enable 22557ec681f3Smrg * CCS_D when rendering to the base slice. However, there is no 22567ec681f3Smrg * documentation tell us what the hardware would do in that case or what 22577ec681f3Smrg * it does if you walk off the bases slice. (Does it ignore CCS or does 22587ec681f3Smrg * it start scribbling over random memory?) We play it safe and just 22597ec681f3Smrg * follow the docs and don't allow CCS_D for arrayed or mip-mapped 22607ec681f3Smrg * surfaces. 22617ec681f3Smrg */ 22627ec681f3Smrg if (ISL_GFX_VER(dev) <= 7 && 22637ec681f3Smrg (surf->levels > 1 || surf->logical_level0_px.array_len > 1)) 22647ec681f3Smrg return false; 22657ec681f3Smrg 22667ec681f3Smrg /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render 22677ec681f3Smrg * Target(s)", beneath the "Fast Color Clear" bullet (p326): 22687ec681f3Smrg * 22697ec681f3Smrg * - MCS buffer for non-MSRT is supported only for RT formats 32bpp, 22707ec681f3Smrg * 64bpp, and 128bpp. 22717ec681f3Smrg */ 22727ec681f3Smrg if (isl_format_get_layout(surf->format)->bpb < 32) 22737ec681f3Smrg return false; 22747ec681f3Smrg 22757ec681f3Smrg /* From the Skylake documentation, it is made clear that X-tiling is no 22767ec681f3Smrg * longer supported: 22777ec681f3Smrg * 22787ec681f3Smrg * - MCS and Lossless compression is supported for 22797ec681f3Smrg * TiledY/TileYs/TileYf non-MSRTs only. 22807ec681f3Smrg */ 22817ec681f3Smrg if (ISL_GFX_VER(dev) >= 9 && !isl_tiling_is_any_y(surf->tiling)) 22827ec681f3Smrg return false; 22837ec681f3Smrg } 22847ec681f3Smrg 22857ec681f3Smrg return true; 22867ec681f3Smrg} 22877ec681f3Smrg 22887ec681f3Smrgbool 22897ec681f3Smrgisl_surf_get_ccs_surf(const struct isl_device *dev, 22907ec681f3Smrg const struct isl_surf *surf, 22917ec681f3Smrg const struct isl_surf *hiz_or_mcs_surf, 22927ec681f3Smrg struct isl_surf *ccs_surf, 22937ec681f3Smrg uint32_t row_pitch_B) 22947ec681f3Smrg{ 22957ec681f3Smrg if (!isl_surf_supports_ccs(dev, surf, hiz_or_mcs_surf)) 22967ec681f3Smrg return false; 22977ec681f3Smrg 22987ec681f3Smrg if (ISL_GFX_VER(dev) >= 12) { 22997ec681f3Smrg enum isl_format ccs_format; 230001e04c3fSmrg switch (isl_format_get_layout(surf->format)->bpb) { 23017ec681f3Smrg case 8: ccs_format = ISL_FORMAT_GFX12_CCS_8BPP_Y0; break; 23027ec681f3Smrg case 16: ccs_format = ISL_FORMAT_GFX12_CCS_16BPP_Y0; break; 23037ec681f3Smrg case 32: ccs_format = ISL_FORMAT_GFX12_CCS_32BPP_Y0; break; 23047ec681f3Smrg case 64: ccs_format = ISL_FORMAT_GFX12_CCS_64BPP_Y0; break; 23057ec681f3Smrg case 128: ccs_format = ISL_FORMAT_GFX12_CCS_128BPP_Y0; break; 230601e04c3fSmrg default: 230701e04c3fSmrg return false; 230801e04c3fSmrg } 23097ec681f3Smrg 23107ec681f3Smrg /* On Gfx12, the CCS is a scaled-down version of the main surface. We 23117ec681f3Smrg * model this as the CCS compressing a 2D-view of the entire surface. 23127ec681f3Smrg */ 23137ec681f3Smrg const bool ok = 23147ec681f3Smrg isl_surf_init(dev, ccs_surf, 23157ec681f3Smrg .dim = ISL_SURF_DIM_2D, 23167ec681f3Smrg .format = ccs_format, 23177ec681f3Smrg .width = isl_surf_get_row_pitch_el(surf), 23187ec681f3Smrg .height = surf->size_B / surf->row_pitch_B, 23197ec681f3Smrg .depth = 1, 23207ec681f3Smrg .levels = 1, 23217ec681f3Smrg .array_len = 1, 23227ec681f3Smrg .samples = 1, 23237ec681f3Smrg .row_pitch_B = row_pitch_B, 23247ec681f3Smrg .usage = ISL_SURF_USAGE_CCS_BIT, 23257ec681f3Smrg .tiling_flags = ISL_TILING_GFX12_CCS_BIT); 23267ec681f3Smrg assert(!ok || ccs_surf->size_B == surf->size_B / 256); 23277ec681f3Smrg return ok; 232801e04c3fSmrg } else { 23297ec681f3Smrg enum isl_format ccs_format; 23307ec681f3Smrg if (ISL_GFX_VER(dev) >= 9) { 23317ec681f3Smrg switch (isl_format_get_layout(surf->format)->bpb) { 23327ec681f3Smrg case 32: ccs_format = ISL_FORMAT_GFX9_CCS_32BPP; break; 23337ec681f3Smrg case 64: ccs_format = ISL_FORMAT_GFX9_CCS_64BPP; break; 23347ec681f3Smrg case 128: ccs_format = ISL_FORMAT_GFX9_CCS_128BPP; break; 23357ec681f3Smrg default: unreachable("Unsupported CCS format"); 23367ec681f3Smrg return false; 23377ec681f3Smrg } 23387ec681f3Smrg } else if (surf->tiling == ISL_TILING_Y0) { 23397ec681f3Smrg switch (isl_format_get_layout(surf->format)->bpb) { 23407ec681f3Smrg case 32: ccs_format = ISL_FORMAT_GFX7_CCS_32BPP_Y; break; 23417ec681f3Smrg case 64: ccs_format = ISL_FORMAT_GFX7_CCS_64BPP_Y; break; 23427ec681f3Smrg case 128: ccs_format = ISL_FORMAT_GFX7_CCS_128BPP_Y; break; 23437ec681f3Smrg default: unreachable("Unsupported CCS format"); 23447ec681f3Smrg } 23457ec681f3Smrg } else if (surf->tiling == ISL_TILING_X) { 23467ec681f3Smrg switch (isl_format_get_layout(surf->format)->bpb) { 23477ec681f3Smrg case 32: ccs_format = ISL_FORMAT_GFX7_CCS_32BPP_X; break; 23487ec681f3Smrg case 64: ccs_format = ISL_FORMAT_GFX7_CCS_64BPP_X; break; 23497ec681f3Smrg case 128: ccs_format = ISL_FORMAT_GFX7_CCS_128BPP_X; break; 23507ec681f3Smrg default: unreachable("Unsupported CCS format"); 23517ec681f3Smrg } 23527ec681f3Smrg } else { 23537ec681f3Smrg unreachable("Invalid tiling format"); 23547ec681f3Smrg } 235501e04c3fSmrg 23567ec681f3Smrg return isl_surf_init(dev, ccs_surf, 23577ec681f3Smrg .dim = surf->dim, 23587ec681f3Smrg .format = ccs_format, 23597ec681f3Smrg .width = surf->logical_level0_px.width, 23607ec681f3Smrg .height = surf->logical_level0_px.height, 23617ec681f3Smrg .depth = surf->logical_level0_px.depth, 23627ec681f3Smrg .levels = surf->levels, 23637ec681f3Smrg .array_len = surf->logical_level0_px.array_len, 23647ec681f3Smrg .samples = 1, 23657ec681f3Smrg .row_pitch_B = row_pitch_B, 23667ec681f3Smrg .usage = ISL_SURF_USAGE_CCS_BIT, 23677ec681f3Smrg .tiling_flags = ISL_TILING_CCS_BIT); 23687ec681f3Smrg } 236901e04c3fSmrg} 237001e04c3fSmrg 237101e04c3fSmrg#define isl_genX_call(dev, func, ...) \ 23727ec681f3Smrg switch (ISL_GFX_VERX10(dev)) { \ 23737ec681f3Smrg case 40: \ 23747ec681f3Smrg isl_gfx4_##func(__VA_ARGS__); \ 237501e04c3fSmrg break; \ 23767ec681f3Smrg case 45: \ 23777ec681f3Smrg /* G45 surface state is the same as gfx5 */ \ 23787ec681f3Smrg case 50: \ 23797ec681f3Smrg isl_gfx5_##func(__VA_ARGS__); \ 238001e04c3fSmrg break; \ 23817ec681f3Smrg case 60: \ 23827ec681f3Smrg isl_gfx6_##func(__VA_ARGS__); \ 238301e04c3fSmrg break; \ 23847ec681f3Smrg case 70: \ 23857ec681f3Smrg isl_gfx7_##func(__VA_ARGS__); \ 238601e04c3fSmrg break; \ 23877ec681f3Smrg case 75: \ 23887ec681f3Smrg isl_gfx75_##func(__VA_ARGS__); \ 238901e04c3fSmrg break; \ 23907ec681f3Smrg case 80: \ 23917ec681f3Smrg isl_gfx8_##func(__VA_ARGS__); \ 239201e04c3fSmrg break; \ 23937ec681f3Smrg case 90: \ 23947ec681f3Smrg isl_gfx9_##func(__VA_ARGS__); \ 239501e04c3fSmrg break; \ 23967ec681f3Smrg case 110: \ 23977ec681f3Smrg isl_gfx11_##func(__VA_ARGS__); \ 23987ec681f3Smrg break; \ 23997ec681f3Smrg case 120: \ 24007ec681f3Smrg isl_gfx12_##func(__VA_ARGS__); \ 24017ec681f3Smrg break; \ 24027ec681f3Smrg case 125: \ 24037ec681f3Smrg isl_gfx125_##func(__VA_ARGS__); \ 240401e04c3fSmrg break; \ 240501e04c3fSmrg default: \ 240601e04c3fSmrg assert(!"Unknown hardware generation"); \ 240701e04c3fSmrg } 240801e04c3fSmrg 240901e04c3fSmrgvoid 241001e04c3fSmrgisl_surf_fill_state_s(const struct isl_device *dev, void *state, 241101e04c3fSmrg const struct isl_surf_fill_state_info *restrict info) 241201e04c3fSmrg{ 241301e04c3fSmrg#ifndef NDEBUG 241401e04c3fSmrg isl_surf_usage_flags_t _base_usage = 241501e04c3fSmrg info->view->usage & (ISL_SURF_USAGE_RENDER_TARGET_BIT | 241601e04c3fSmrg ISL_SURF_USAGE_TEXTURE_BIT | 241701e04c3fSmrg ISL_SURF_USAGE_STORAGE_BIT); 241801e04c3fSmrg /* They may only specify one of the above bits at a time */ 241901e04c3fSmrg assert(__builtin_popcount(_base_usage) == 1); 242001e04c3fSmrg /* The only other allowed bit is ISL_SURF_USAGE_CUBE_BIT */ 242101e04c3fSmrg assert((info->view->usage & ~ISL_SURF_USAGE_CUBE_BIT) == _base_usage); 242201e04c3fSmrg#endif 242301e04c3fSmrg 242401e04c3fSmrg if (info->surf->dim == ISL_SURF_DIM_3D) { 242501e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 242601e04c3fSmrg info->surf->logical_level0_px.depth); 242701e04c3fSmrg } else { 242801e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 242901e04c3fSmrg info->surf->logical_level0_px.array_len); 243001e04c3fSmrg } 243101e04c3fSmrg 243201e04c3fSmrg isl_genX_call(dev, surf_fill_state_s, dev, state, info); 243301e04c3fSmrg} 243401e04c3fSmrg 243501e04c3fSmrgvoid 243601e04c3fSmrgisl_buffer_fill_state_s(const struct isl_device *dev, void *state, 243701e04c3fSmrg const struct isl_buffer_fill_state_info *restrict info) 243801e04c3fSmrg{ 24397ec681f3Smrg isl_genX_call(dev, buffer_fill_state_s, dev, state, info); 244001e04c3fSmrg} 244101e04c3fSmrg 244201e04c3fSmrgvoid 24437ec681f3Smrgisl_null_fill_state_s(const struct isl_device *dev, void *state, 24447ec681f3Smrg const struct isl_null_fill_state_info *restrict info) 244501e04c3fSmrg{ 24467ec681f3Smrg isl_genX_call(dev, null_fill_state, state, info); 244701e04c3fSmrg} 244801e04c3fSmrg 244901e04c3fSmrgvoid 245001e04c3fSmrgisl_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, 245101e04c3fSmrg const struct isl_depth_stencil_hiz_emit_info *restrict info) 245201e04c3fSmrg{ 245301e04c3fSmrg if (info->depth_surf && info->stencil_surf) { 245401e04c3fSmrg if (!dev->info->has_hiz_and_separate_stencil) { 245501e04c3fSmrg assert(info->depth_surf == info->stencil_surf); 245601e04c3fSmrg assert(info->depth_address == info->stencil_address); 245701e04c3fSmrg } 245801e04c3fSmrg assert(info->depth_surf->dim == info->stencil_surf->dim); 245901e04c3fSmrg } 246001e04c3fSmrg 246101e04c3fSmrg if (info->depth_surf) { 246201e04c3fSmrg assert((info->depth_surf->usage & ISL_SURF_USAGE_DEPTH_BIT)); 246301e04c3fSmrg if (info->depth_surf->dim == ISL_SURF_DIM_3D) { 246401e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 246501e04c3fSmrg info->depth_surf->logical_level0_px.depth); 246601e04c3fSmrg } else { 246701e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 246801e04c3fSmrg info->depth_surf->logical_level0_px.array_len); 246901e04c3fSmrg } 247001e04c3fSmrg } 247101e04c3fSmrg 247201e04c3fSmrg if (info->stencil_surf) { 247301e04c3fSmrg assert((info->stencil_surf->usage & ISL_SURF_USAGE_STENCIL_BIT)); 247401e04c3fSmrg if (info->stencil_surf->dim == ISL_SURF_DIM_3D) { 247501e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 247601e04c3fSmrg info->stencil_surf->logical_level0_px.depth); 247701e04c3fSmrg } else { 247801e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 247901e04c3fSmrg info->stencil_surf->logical_level0_px.array_len); 248001e04c3fSmrg } 248101e04c3fSmrg } 248201e04c3fSmrg 248301e04c3fSmrg isl_genX_call(dev, emit_depth_stencil_hiz_s, dev, batch, info); 248401e04c3fSmrg} 248501e04c3fSmrg 248601e04c3fSmrg/** 248701e04c3fSmrg * A variant of isl_surf_get_image_offset_sa() specific to 24887ec681f3Smrg * ISL_DIM_LAYOUT_GFX4_2D. 248901e04c3fSmrg */ 249001e04c3fSmrgstatic void 24917ec681f3Smrgget_image_offset_sa_gfx4_2d(const struct isl_surf *surf, 249201e04c3fSmrg uint32_t level, uint32_t logical_array_layer, 249301e04c3fSmrg uint32_t *x_offset_sa, 249401e04c3fSmrg uint32_t *y_offset_sa) 249501e04c3fSmrg{ 249601e04c3fSmrg assert(level < surf->levels); 249701e04c3fSmrg if (surf->dim == ISL_SURF_DIM_3D) 249801e04c3fSmrg assert(logical_array_layer < surf->logical_level0_px.depth); 249901e04c3fSmrg else 250001e04c3fSmrg assert(logical_array_layer < surf->logical_level0_px.array_len); 250101e04c3fSmrg 250201e04c3fSmrg const struct isl_extent3d image_align_sa = 250301e04c3fSmrg isl_surf_get_image_alignment_sa(surf); 250401e04c3fSmrg 250501e04c3fSmrg const uint32_t W0 = surf->phys_level0_sa.width; 250601e04c3fSmrg const uint32_t H0 = surf->phys_level0_sa.height; 250701e04c3fSmrg 250801e04c3fSmrg const uint32_t phys_layer = logical_array_layer * 250901e04c3fSmrg (surf->msaa_layout == ISL_MSAA_LAYOUT_ARRAY ? surf->samples : 1); 251001e04c3fSmrg 251101e04c3fSmrg uint32_t x = 0; 251201e04c3fSmrg uint32_t y = phys_layer * isl_surf_get_array_pitch_sa_rows(surf); 251301e04c3fSmrg 251401e04c3fSmrg for (uint32_t l = 0; l < level; ++l) { 251501e04c3fSmrg if (l == 1) { 251601e04c3fSmrg uint32_t W = isl_minify(W0, l); 251701e04c3fSmrg x += isl_align_npot(W, image_align_sa.w); 251801e04c3fSmrg } else { 251901e04c3fSmrg uint32_t H = isl_minify(H0, l); 252001e04c3fSmrg y += isl_align_npot(H, image_align_sa.h); 252101e04c3fSmrg } 252201e04c3fSmrg } 252301e04c3fSmrg 252401e04c3fSmrg *x_offset_sa = x; 252501e04c3fSmrg *y_offset_sa = y; 252601e04c3fSmrg} 252701e04c3fSmrg 252801e04c3fSmrg/** 252901e04c3fSmrg * A variant of isl_surf_get_image_offset_sa() specific to 25307ec681f3Smrg * ISL_DIM_LAYOUT_GFX4_3D. 253101e04c3fSmrg */ 253201e04c3fSmrgstatic void 25337ec681f3Smrgget_image_offset_sa_gfx4_3d(const struct isl_surf *surf, 253401e04c3fSmrg uint32_t level, uint32_t logical_z_offset_px, 253501e04c3fSmrg uint32_t *x_offset_sa, 253601e04c3fSmrg uint32_t *y_offset_sa) 253701e04c3fSmrg{ 253801e04c3fSmrg assert(level < surf->levels); 253901e04c3fSmrg if (surf->dim == ISL_SURF_DIM_3D) { 254001e04c3fSmrg assert(surf->phys_level0_sa.array_len == 1); 254101e04c3fSmrg assert(logical_z_offset_px < isl_minify(surf->phys_level0_sa.depth, level)); 254201e04c3fSmrg } else { 254301e04c3fSmrg assert(surf->dim == ISL_SURF_DIM_2D); 254401e04c3fSmrg assert(surf->usage & ISL_SURF_USAGE_CUBE_BIT); 254501e04c3fSmrg assert(surf->phys_level0_sa.array_len == 6); 254601e04c3fSmrg assert(logical_z_offset_px < surf->phys_level0_sa.array_len); 254701e04c3fSmrg } 254801e04c3fSmrg 254901e04c3fSmrg const struct isl_extent3d image_align_sa = 255001e04c3fSmrg isl_surf_get_image_alignment_sa(surf); 255101e04c3fSmrg 255201e04c3fSmrg const uint32_t W0 = surf->phys_level0_sa.width; 255301e04c3fSmrg const uint32_t H0 = surf->phys_level0_sa.height; 255401e04c3fSmrg const uint32_t D0 = surf->phys_level0_sa.depth; 255501e04c3fSmrg const uint32_t AL = surf->phys_level0_sa.array_len; 255601e04c3fSmrg 255701e04c3fSmrg uint32_t x = 0; 255801e04c3fSmrg uint32_t y = 0; 255901e04c3fSmrg 256001e04c3fSmrg for (uint32_t l = 0; l < level; ++l) { 256101e04c3fSmrg const uint32_t level_h = isl_align_npot(isl_minify(H0, l), image_align_sa.h); 256201e04c3fSmrg const uint32_t level_d = 256301e04c3fSmrg isl_align_npot(surf->dim == ISL_SURF_DIM_3D ? isl_minify(D0, l) : AL, 256401e04c3fSmrg image_align_sa.d); 256501e04c3fSmrg const uint32_t max_layers_vert = isl_align(level_d, 1u << l) / (1u << l); 256601e04c3fSmrg 256701e04c3fSmrg y += level_h * max_layers_vert; 256801e04c3fSmrg } 256901e04c3fSmrg 257001e04c3fSmrg const uint32_t level_w = isl_align_npot(isl_minify(W0, level), image_align_sa.w); 257101e04c3fSmrg const uint32_t level_h = isl_align_npot(isl_minify(H0, level), image_align_sa.h); 257201e04c3fSmrg const uint32_t level_d = 257301e04c3fSmrg isl_align_npot(surf->dim == ISL_SURF_DIM_3D ? isl_minify(D0, level) : AL, 257401e04c3fSmrg image_align_sa.d); 257501e04c3fSmrg 257601e04c3fSmrg const uint32_t max_layers_horiz = MIN(level_d, 1u << level); 257701e04c3fSmrg 257801e04c3fSmrg x += level_w * (logical_z_offset_px % max_layers_horiz); 257901e04c3fSmrg y += level_h * (logical_z_offset_px / max_layers_horiz); 258001e04c3fSmrg 258101e04c3fSmrg *x_offset_sa = x; 258201e04c3fSmrg *y_offset_sa = y; 258301e04c3fSmrg} 258401e04c3fSmrg 258501e04c3fSmrgstatic void 25867ec681f3Smrgget_image_offset_sa_gfx6_stencil_hiz(const struct isl_surf *surf, 258701e04c3fSmrg uint32_t level, 258801e04c3fSmrg uint32_t logical_array_layer, 258901e04c3fSmrg uint32_t *x_offset_sa, 259001e04c3fSmrg uint32_t *y_offset_sa) 259101e04c3fSmrg{ 259201e04c3fSmrg assert(level < surf->levels); 259301e04c3fSmrg assert(surf->logical_level0_px.depth == 1); 259401e04c3fSmrg assert(logical_array_layer < surf->logical_level0_px.array_len); 259501e04c3fSmrg 259601e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); 259701e04c3fSmrg 259801e04c3fSmrg const struct isl_extent3d image_align_sa = 259901e04c3fSmrg isl_surf_get_image_alignment_sa(surf); 260001e04c3fSmrg 260101e04c3fSmrg struct isl_tile_info tile_info; 26027ec681f3Smrg isl_surf_get_tile_info(surf, &tile_info); 260301e04c3fSmrg const struct isl_extent2d tile_extent_sa = { 260401e04c3fSmrg .w = tile_info.logical_extent_el.w * fmtl->bw, 260501e04c3fSmrg .h = tile_info.logical_extent_el.h * fmtl->bh, 260601e04c3fSmrg }; 260701e04c3fSmrg /* Tile size is a multiple of image alignment */ 260801e04c3fSmrg assert(tile_extent_sa.w % image_align_sa.w == 0); 260901e04c3fSmrg assert(tile_extent_sa.h % image_align_sa.h == 0); 261001e04c3fSmrg 261101e04c3fSmrg const uint32_t W0 = surf->phys_level0_sa.w; 261201e04c3fSmrg const uint32_t H0 = surf->phys_level0_sa.h; 261301e04c3fSmrg 261401e04c3fSmrg /* Each image has the same height as LOD0 because the hardware thinks 261501e04c3fSmrg * everything is LOD0 261601e04c3fSmrg */ 261701e04c3fSmrg const uint32_t H = isl_align(H0, image_align_sa.h); 261801e04c3fSmrg 261901e04c3fSmrg /* Quick sanity check for consistency */ 262001e04c3fSmrg if (surf->phys_level0_sa.array_len > 1) 262101e04c3fSmrg assert(surf->array_pitch_el_rows == isl_assert_div(H, fmtl->bh)); 262201e04c3fSmrg 262301e04c3fSmrg uint32_t x = 0, y = 0; 262401e04c3fSmrg for (uint32_t l = 0; l < level; ++l) { 262501e04c3fSmrg const uint32_t W = isl_minify(W0, l); 262601e04c3fSmrg 262701e04c3fSmrg const uint32_t w = isl_align(W, tile_extent_sa.w); 262801e04c3fSmrg const uint32_t h = isl_align(H * surf->phys_level0_sa.a, 262901e04c3fSmrg tile_extent_sa.h); 263001e04c3fSmrg 263101e04c3fSmrg if (l == 0) { 263201e04c3fSmrg y += h; 263301e04c3fSmrg } else { 263401e04c3fSmrg x += w; 263501e04c3fSmrg } 263601e04c3fSmrg } 263701e04c3fSmrg 263801e04c3fSmrg y += H * logical_array_layer; 263901e04c3fSmrg 264001e04c3fSmrg *x_offset_sa = x; 264101e04c3fSmrg *y_offset_sa = y; 264201e04c3fSmrg} 264301e04c3fSmrg 264401e04c3fSmrg/** 264501e04c3fSmrg * A variant of isl_surf_get_image_offset_sa() specific to 26467ec681f3Smrg * ISL_DIM_LAYOUT_GFX9_1D. 264701e04c3fSmrg */ 264801e04c3fSmrgstatic void 26497ec681f3Smrgget_image_offset_sa_gfx9_1d(const struct isl_surf *surf, 265001e04c3fSmrg uint32_t level, uint32_t layer, 265101e04c3fSmrg uint32_t *x_offset_sa, 265201e04c3fSmrg uint32_t *y_offset_sa) 265301e04c3fSmrg{ 265401e04c3fSmrg assert(level < surf->levels); 265501e04c3fSmrg assert(layer < surf->phys_level0_sa.array_len); 265601e04c3fSmrg assert(surf->phys_level0_sa.height == 1); 265701e04c3fSmrg assert(surf->phys_level0_sa.depth == 1); 265801e04c3fSmrg assert(surf->samples == 1); 265901e04c3fSmrg 266001e04c3fSmrg const uint32_t W0 = surf->phys_level0_sa.width; 266101e04c3fSmrg const struct isl_extent3d image_align_sa = 266201e04c3fSmrg isl_surf_get_image_alignment_sa(surf); 266301e04c3fSmrg 266401e04c3fSmrg uint32_t x = 0; 266501e04c3fSmrg 266601e04c3fSmrg for (uint32_t l = 0; l < level; ++l) { 266701e04c3fSmrg uint32_t W = isl_minify(W0, l); 266801e04c3fSmrg uint32_t w = isl_align_npot(W, image_align_sa.w); 266901e04c3fSmrg 267001e04c3fSmrg x += w; 267101e04c3fSmrg } 267201e04c3fSmrg 267301e04c3fSmrg *x_offset_sa = x; 267401e04c3fSmrg *y_offset_sa = layer * isl_surf_get_array_pitch_sa_rows(surf); 267501e04c3fSmrg} 267601e04c3fSmrg 267701e04c3fSmrg/** 267801e04c3fSmrg * Calculate the offset, in units of surface samples, to a subimage in the 267901e04c3fSmrg * surface. 268001e04c3fSmrg * 268101e04c3fSmrg * @invariant level < surface levels 268201e04c3fSmrg * @invariant logical_array_layer < logical array length of surface 268301e04c3fSmrg * @invariant logical_z_offset_px < logical depth of surface at level 268401e04c3fSmrg */ 268501e04c3fSmrgvoid 268601e04c3fSmrgisl_surf_get_image_offset_sa(const struct isl_surf *surf, 268701e04c3fSmrg uint32_t level, 268801e04c3fSmrg uint32_t logical_array_layer, 268901e04c3fSmrg uint32_t logical_z_offset_px, 269001e04c3fSmrg uint32_t *x_offset_sa, 26917ec681f3Smrg uint32_t *y_offset_sa, 26927ec681f3Smrg uint32_t *z_offset_sa, 26937ec681f3Smrg uint32_t *array_offset) 269401e04c3fSmrg{ 269501e04c3fSmrg assert(level < surf->levels); 269601e04c3fSmrg assert(logical_array_layer < surf->logical_level0_px.array_len); 269701e04c3fSmrg assert(logical_z_offset_px 269801e04c3fSmrg < isl_minify(surf->logical_level0_px.depth, level)); 269901e04c3fSmrg 270001e04c3fSmrg switch (surf->dim_layout) { 27017ec681f3Smrg case ISL_DIM_LAYOUT_GFX9_1D: 27027ec681f3Smrg get_image_offset_sa_gfx9_1d(surf, level, logical_array_layer, 270301e04c3fSmrg x_offset_sa, y_offset_sa); 27047ec681f3Smrg *z_offset_sa = 0; 27057ec681f3Smrg *array_offset = 0; 270601e04c3fSmrg break; 27077ec681f3Smrg case ISL_DIM_LAYOUT_GFX4_2D: 27087ec681f3Smrg get_image_offset_sa_gfx4_2d(surf, level, logical_array_layer 270901e04c3fSmrg + logical_z_offset_px, 271001e04c3fSmrg x_offset_sa, y_offset_sa); 27117ec681f3Smrg *z_offset_sa = 0; 27127ec681f3Smrg *array_offset = 0; 271301e04c3fSmrg break; 27147ec681f3Smrg case ISL_DIM_LAYOUT_GFX4_3D: 27157ec681f3Smrg get_image_offset_sa_gfx4_3d(surf, level, logical_array_layer + 271601e04c3fSmrg logical_z_offset_px, 271701e04c3fSmrg x_offset_sa, y_offset_sa); 27187ec681f3Smrg *z_offset_sa = 0; 27197ec681f3Smrg *array_offset = 0; 272001e04c3fSmrg break; 27217ec681f3Smrg case ISL_DIM_LAYOUT_GFX6_STENCIL_HIZ: 27227ec681f3Smrg get_image_offset_sa_gfx6_stencil_hiz(surf, level, logical_array_layer + 272301e04c3fSmrg logical_z_offset_px, 272401e04c3fSmrg x_offset_sa, y_offset_sa); 27257ec681f3Smrg *z_offset_sa = 0; 27267ec681f3Smrg *array_offset = 0; 272701e04c3fSmrg break; 272801e04c3fSmrg 272901e04c3fSmrg default: 273001e04c3fSmrg unreachable("not reached"); 273101e04c3fSmrg } 273201e04c3fSmrg} 273301e04c3fSmrg 273401e04c3fSmrgvoid 273501e04c3fSmrgisl_surf_get_image_offset_el(const struct isl_surf *surf, 273601e04c3fSmrg uint32_t level, 273701e04c3fSmrg uint32_t logical_array_layer, 273801e04c3fSmrg uint32_t logical_z_offset_px, 273901e04c3fSmrg uint32_t *x_offset_el, 27407ec681f3Smrg uint32_t *y_offset_el, 27417ec681f3Smrg uint32_t *z_offset_el, 27427ec681f3Smrg uint32_t *array_offset) 274301e04c3fSmrg{ 274401e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); 274501e04c3fSmrg 274601e04c3fSmrg assert(level < surf->levels); 274701e04c3fSmrg assert(logical_array_layer < surf->logical_level0_px.array_len); 274801e04c3fSmrg assert(logical_z_offset_px 274901e04c3fSmrg < isl_minify(surf->logical_level0_px.depth, level)); 275001e04c3fSmrg 27517ec681f3Smrg uint32_t x_offset_sa, y_offset_sa, z_offset_sa; 275201e04c3fSmrg isl_surf_get_image_offset_sa(surf, level, 275301e04c3fSmrg logical_array_layer, 275401e04c3fSmrg logical_z_offset_px, 275501e04c3fSmrg &x_offset_sa, 27567ec681f3Smrg &y_offset_sa, 27577ec681f3Smrg &z_offset_sa, 27587ec681f3Smrg array_offset); 275901e04c3fSmrg 276001e04c3fSmrg *x_offset_el = x_offset_sa / fmtl->bw; 276101e04c3fSmrg *y_offset_el = y_offset_sa / fmtl->bh; 27627ec681f3Smrg *z_offset_el = z_offset_sa / fmtl->bd; 276301e04c3fSmrg} 276401e04c3fSmrg 276501e04c3fSmrgvoid 276601e04c3fSmrgisl_surf_get_image_offset_B_tile_sa(const struct isl_surf *surf, 276701e04c3fSmrg uint32_t level, 276801e04c3fSmrg uint32_t logical_array_layer, 276901e04c3fSmrg uint32_t logical_z_offset_px, 27707ec681f3Smrg uint64_t *offset_B, 277101e04c3fSmrg uint32_t *x_offset_sa, 277201e04c3fSmrg uint32_t *y_offset_sa) 277301e04c3fSmrg{ 277401e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); 277501e04c3fSmrg 277601e04c3fSmrg uint32_t x_offset_el, y_offset_el; 27777ec681f3Smrg isl_surf_get_image_offset_B_tile_el(surf, level, 27787ec681f3Smrg logical_array_layer, 27797ec681f3Smrg logical_z_offset_px, 27807ec681f3Smrg offset_B, 27817ec681f3Smrg &x_offset_el, 27827ec681f3Smrg &y_offset_el); 278301e04c3fSmrg 278401e04c3fSmrg if (x_offset_sa) { 278501e04c3fSmrg *x_offset_sa = x_offset_el * fmtl->bw; 278601e04c3fSmrg } else { 278701e04c3fSmrg assert(x_offset_el == 0); 278801e04c3fSmrg } 278901e04c3fSmrg 279001e04c3fSmrg if (y_offset_sa) { 279101e04c3fSmrg *y_offset_sa = y_offset_el * fmtl->bh; 279201e04c3fSmrg } else { 279301e04c3fSmrg assert(y_offset_el == 0); 279401e04c3fSmrg } 279501e04c3fSmrg} 279601e04c3fSmrg 27977ec681f3Smrgvoid 27987ec681f3Smrgisl_surf_get_image_offset_B_tile_el(const struct isl_surf *surf, 27997ec681f3Smrg uint32_t level, 28007ec681f3Smrg uint32_t logical_array_layer, 28017ec681f3Smrg uint32_t logical_z_offset_px, 28027ec681f3Smrg uint64_t *offset_B, 28037ec681f3Smrg uint32_t *x_offset_el, 28047ec681f3Smrg uint32_t *y_offset_el) 28057ec681f3Smrg{ 28067ec681f3Smrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); 28077ec681f3Smrg 28087ec681f3Smrg uint32_t total_x_offset_el, total_y_offset_el; 28097ec681f3Smrg uint32_t total_z_offset_el, total_array_offset; 28107ec681f3Smrg isl_surf_get_image_offset_el(surf, level, logical_array_layer, 28117ec681f3Smrg logical_z_offset_px, 28127ec681f3Smrg &total_x_offset_el, 28137ec681f3Smrg &total_y_offset_el, 28147ec681f3Smrg &total_z_offset_el, 28157ec681f3Smrg &total_array_offset); 28167ec681f3Smrg 28177ec681f3Smrg uint32_t z_offset_el, array_offset; 28187ec681f3Smrg isl_tiling_get_intratile_offset_el(surf->tiling, surf->dim, 28197ec681f3Smrg surf->msaa_layout, fmtl->bpb, 28207ec681f3Smrg surf->samples, 28217ec681f3Smrg surf->row_pitch_B, 28227ec681f3Smrg surf->array_pitch_el_rows, 28237ec681f3Smrg total_x_offset_el, 28247ec681f3Smrg total_y_offset_el, 28257ec681f3Smrg total_z_offset_el, 28267ec681f3Smrg total_array_offset, 28277ec681f3Smrg offset_B, 28287ec681f3Smrg x_offset_el, 28297ec681f3Smrg y_offset_el, 28307ec681f3Smrg &z_offset_el, 28317ec681f3Smrg &array_offset); 28327ec681f3Smrg assert(z_offset_el == 0); 28337ec681f3Smrg assert(array_offset == 0); 28347ec681f3Smrg} 28357ec681f3Smrg 28367ec681f3Smrgvoid 28377ec681f3Smrgisl_surf_get_image_range_B_tile(const struct isl_surf *surf, 28387ec681f3Smrg uint32_t level, 28397ec681f3Smrg uint32_t logical_array_layer, 28407ec681f3Smrg uint32_t logical_z_offset_px, 28417ec681f3Smrg uint64_t *start_tile_B, 28427ec681f3Smrg uint64_t *end_tile_B) 28437ec681f3Smrg{ 28447ec681f3Smrg uint32_t start_x_offset_el, start_y_offset_el; 28457ec681f3Smrg uint32_t start_z_offset_el, start_array_slice; 28467ec681f3Smrg isl_surf_get_image_offset_el(surf, level, logical_array_layer, 28477ec681f3Smrg logical_z_offset_px, 28487ec681f3Smrg &start_x_offset_el, 28497ec681f3Smrg &start_y_offset_el, 28507ec681f3Smrg &start_z_offset_el, 28517ec681f3Smrg &start_array_slice); 28527ec681f3Smrg 28537ec681f3Smrg /* Compute the size of the subimage in surface elements */ 28547ec681f3Smrg const uint32_t subimage_w_sa = isl_minify(surf->phys_level0_sa.w, level); 28557ec681f3Smrg const uint32_t subimage_h_sa = isl_minify(surf->phys_level0_sa.h, level); 28567ec681f3Smrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); 28577ec681f3Smrg const uint32_t subimage_w_el = isl_align_div_npot(subimage_w_sa, fmtl->bw); 28587ec681f3Smrg const uint32_t subimage_h_el = isl_align_div_npot(subimage_h_sa, fmtl->bh); 28597ec681f3Smrg 28607ec681f3Smrg /* Find the last pixel */ 28617ec681f3Smrg uint32_t end_x_offset_el = start_x_offset_el + subimage_w_el - 1; 28627ec681f3Smrg uint32_t end_y_offset_el = start_y_offset_el + subimage_h_el - 1; 28637ec681f3Smrg 28647ec681f3Smrg /* We only consider one Z or array slice */ 28657ec681f3Smrg const uint32_t end_z_offset_el = start_z_offset_el; 28667ec681f3Smrg const uint32_t end_array_slice = start_array_slice; 28677ec681f3Smrg 28687ec681f3Smrg UNUSED uint32_t x_offset_el, y_offset_el, z_offset_el, array_slice; 28697ec681f3Smrg isl_tiling_get_intratile_offset_el(surf->tiling, surf->dim, 28707ec681f3Smrg surf->msaa_layout, fmtl->bpb, 28717ec681f3Smrg surf->samples, 28727ec681f3Smrg surf->row_pitch_B, 28737ec681f3Smrg surf->array_pitch_el_rows, 28747ec681f3Smrg start_x_offset_el, 28757ec681f3Smrg start_y_offset_el, 28767ec681f3Smrg start_z_offset_el, 28777ec681f3Smrg start_array_slice, 28787ec681f3Smrg start_tile_B, 28797ec681f3Smrg &x_offset_el, 28807ec681f3Smrg &y_offset_el, 28817ec681f3Smrg &z_offset_el, 28827ec681f3Smrg &array_slice); 28837ec681f3Smrg 28847ec681f3Smrg isl_tiling_get_intratile_offset_el(surf->tiling, surf->dim, 28857ec681f3Smrg surf->msaa_layout, fmtl->bpb, 28867ec681f3Smrg surf->samples, 28877ec681f3Smrg surf->row_pitch_B, 28887ec681f3Smrg surf->array_pitch_el_rows, 28897ec681f3Smrg end_x_offset_el, 28907ec681f3Smrg end_y_offset_el, 28917ec681f3Smrg end_z_offset_el, 28927ec681f3Smrg end_array_slice, 28937ec681f3Smrg end_tile_B, 28947ec681f3Smrg &x_offset_el, 28957ec681f3Smrg &y_offset_el, 28967ec681f3Smrg &z_offset_el, 28977ec681f3Smrg &array_slice); 28987ec681f3Smrg 28997ec681f3Smrg /* We want the range we return to be exclusive but the tile containing the 29007ec681f3Smrg * last pixel (what we just calculated) is inclusive. Add one. 29017ec681f3Smrg */ 29027ec681f3Smrg (*end_tile_B)++; 29037ec681f3Smrg 29047ec681f3Smrg assert(*end_tile_B <= surf->size_B); 29057ec681f3Smrg} 29067ec681f3Smrg 290701e04c3fSmrgvoid 290801e04c3fSmrgisl_surf_get_image_surf(const struct isl_device *dev, 290901e04c3fSmrg const struct isl_surf *surf, 291001e04c3fSmrg uint32_t level, 291101e04c3fSmrg uint32_t logical_array_layer, 291201e04c3fSmrg uint32_t logical_z_offset_px, 291301e04c3fSmrg struct isl_surf *image_surf, 29147ec681f3Smrg uint64_t *offset_B, 291501e04c3fSmrg uint32_t *x_offset_sa, 291601e04c3fSmrg uint32_t *y_offset_sa) 291701e04c3fSmrg{ 291801e04c3fSmrg isl_surf_get_image_offset_B_tile_sa(surf, 291901e04c3fSmrg level, 292001e04c3fSmrg logical_array_layer, 292101e04c3fSmrg logical_z_offset_px, 292201e04c3fSmrg offset_B, 292301e04c3fSmrg x_offset_sa, 292401e04c3fSmrg y_offset_sa); 292501e04c3fSmrg 292601e04c3fSmrg /* Even for cube maps there will be only single face, therefore drop the 292701e04c3fSmrg * corresponding flag if present. 292801e04c3fSmrg */ 292901e04c3fSmrg const isl_surf_usage_flags_t usage = 293001e04c3fSmrg surf->usage & (~ISL_SURF_USAGE_CUBE_BIT); 293101e04c3fSmrg 293201e04c3fSmrg bool ok UNUSED; 293301e04c3fSmrg ok = isl_surf_init(dev, image_surf, 293401e04c3fSmrg .dim = ISL_SURF_DIM_2D, 293501e04c3fSmrg .format = surf->format, 293601e04c3fSmrg .width = isl_minify(surf->logical_level0_px.w, level), 293701e04c3fSmrg .height = isl_minify(surf->logical_level0_px.h, level), 293801e04c3fSmrg .depth = 1, 293901e04c3fSmrg .levels = 1, 294001e04c3fSmrg .array_len = 1, 294101e04c3fSmrg .samples = surf->samples, 294201e04c3fSmrg .row_pitch_B = surf->row_pitch_B, 294301e04c3fSmrg .usage = usage, 294401e04c3fSmrg .tiling_flags = (1 << surf->tiling)); 294501e04c3fSmrg assert(ok); 294601e04c3fSmrg} 294701e04c3fSmrg 29487ec681f3Smrgbool 29497ec681f3Smrgisl_surf_get_uncompressed_surf(const struct isl_device *dev, 29507ec681f3Smrg const struct isl_surf *surf, 29517ec681f3Smrg const struct isl_view *view, 29527ec681f3Smrg struct isl_surf *ucompr_surf, 29537ec681f3Smrg struct isl_view *ucompr_view, 29547ec681f3Smrg uint64_t *offset_B, 29557ec681f3Smrg uint32_t *x_offset_el, 29567ec681f3Smrg uint32_t *y_offset_el) 29577ec681f3Smrg{ 29587ec681f3Smrg const struct isl_format_layout *fmtl = 29597ec681f3Smrg isl_format_get_layout(surf->format); 29607ec681f3Smrg const enum isl_format view_format = view->format; 29617ec681f3Smrg 29627ec681f3Smrg assert(fmtl->bw > 1 || fmtl->bh > 1 || fmtl->bd > 1); 29637ec681f3Smrg assert(isl_format_is_compressed(surf->format)); 29647ec681f3Smrg assert(!isl_format_is_compressed(view->format)); 29657ec681f3Smrg assert(isl_format_get_layout(view->format)->bpb == fmtl->bpb); 29667ec681f3Smrg assert(view->levels == 1); 29677ec681f3Smrg 29687ec681f3Smrg const uint32_t view_width_px = 29697ec681f3Smrg isl_minify(surf->logical_level0_px.width, view->base_level); 29707ec681f3Smrg const uint32_t view_height_px = 29717ec681f3Smrg isl_minify(surf->logical_level0_px.height, view->base_level); 29727ec681f3Smrg 29737ec681f3Smrg assert(surf->samples == 1); 29747ec681f3Smrg const uint32_t view_width_el = isl_align_div_npot(view_width_px, fmtl->bw); 29757ec681f3Smrg const uint32_t view_height_el = isl_align_div_npot(view_height_px, fmtl->bh); 29767ec681f3Smrg 29777ec681f3Smrg /* If we ever enable 3D block formats, we'll need to re-think this */ 29787ec681f3Smrg assert(fmtl->bd == 1); 29797ec681f3Smrg 29807ec681f3Smrg if (view->array_len > 1) { 29817ec681f3Smrg /* The Skylake PRM Vol. 2d, "RENDER_SURFACE_STATE::X Offset" says: 29827ec681f3Smrg * 29837ec681f3Smrg * "If Surface Array is enabled, this field must be zero." 29847ec681f3Smrg * 29857ec681f3Smrg * The PRMs for other hardware have similar text. This is also tricky 29867ec681f3Smrg * to handle with things like BLORP's SW offsetting because the 29877ec681f3Smrg * increased surface size required for the offset may result in an image 29887ec681f3Smrg * height greater than qpitch. 29897ec681f3Smrg */ 29907ec681f3Smrg if (view->base_level > 0) 29917ec681f3Smrg return false; 29927ec681f3Smrg 29937ec681f3Smrg /* On Haswell and earlier, RENDER_SURFACE_STATE doesn't have a QPitch 29947ec681f3Smrg * field; it only has "array pitch span" which means the QPitch is 29957ec681f3Smrg * automatically calculated. Since we're smashing the surface format 29967ec681f3Smrg * (block formats are subtly different) and the number of miplevels, 29977ec681f3Smrg * that calculation will get thrown off. This means we can't do arrays 29987ec681f3Smrg * even at LOD0 29997ec681f3Smrg * 30007ec681f3Smrg * On Broadwell, we do have a QPitch field which we can control. 30017ec681f3Smrg * However, HALIGN and VALIGN are specified in pixels and are 30027ec681f3Smrg * hard-coded to align to exactly the block size of the compressed 30037ec681f3Smrg * texture. This means that, when reinterpreted as a non-compressed 30047ec681f3Smrg * the QPitch may be anything but the HW requires it to be properly 30057ec681f3Smrg * aligned. 30067ec681f3Smrg */ 30077ec681f3Smrg if (ISL_GFX_VER(dev) < 9) 30087ec681f3Smrg return false; 30097ec681f3Smrg 30107ec681f3Smrg *ucompr_surf = *surf; 30117ec681f3Smrg ucompr_surf->levels = 1; 30127ec681f3Smrg ucompr_surf->format = view_format; 30137ec681f3Smrg 30147ec681f3Smrg /* We're making an uncompressed view here. The image dimensions 30157ec681f3Smrg * need to be scaled down by the block size. 30167ec681f3Smrg */ 30177ec681f3Smrg assert(ucompr_surf->logical_level0_px.width == view_width_px); 30187ec681f3Smrg assert(ucompr_surf->logical_level0_px.height == view_height_px); 30197ec681f3Smrg ucompr_surf->logical_level0_px.width = view_width_el; 30207ec681f3Smrg ucompr_surf->logical_level0_px.height = view_height_el; 30217ec681f3Smrg ucompr_surf->phys_level0_sa = isl_surf_get_phys_level0_el(surf); 30227ec681f3Smrg 30237ec681f3Smrg /* The surface mostly stays as-is; there is no offset */ 30247ec681f3Smrg *offset_B = 0; 30257ec681f3Smrg *x_offset_el = 0; 30267ec681f3Smrg *y_offset_el = 0; 30277ec681f3Smrg 30287ec681f3Smrg /* The view remains the same */ 30297ec681f3Smrg *ucompr_view = *view; 30307ec681f3Smrg } else { 30317ec681f3Smrg /* If only one array slice is requested, directly offset to that slice. 30327ec681f3Smrg * We could, in theory, still use arrays in some cases but BLORP isn't 30337ec681f3Smrg * prepared for this and everyone who calls this function should be 30347ec681f3Smrg * prepared to handle an X/Y offset. 30357ec681f3Smrg */ 30367ec681f3Smrg isl_surf_get_image_offset_B_tile_el(surf, 30377ec681f3Smrg view->base_level, 30387ec681f3Smrg surf->dim == ISL_SURF_DIM_3D ? 30397ec681f3Smrg 0 : view->base_array_layer, 30407ec681f3Smrg surf->dim == ISL_SURF_DIM_3D ? 30417ec681f3Smrg view->base_array_layer : 0, 30427ec681f3Smrg offset_B, 30437ec681f3Smrg x_offset_el, 30447ec681f3Smrg y_offset_el); 30457ec681f3Smrg 30467ec681f3Smrg /* Even for cube maps there will be only single face, therefore drop the 30477ec681f3Smrg * corresponding flag if present. 30487ec681f3Smrg */ 30497ec681f3Smrg const isl_surf_usage_flags_t usage = 30507ec681f3Smrg surf->usage & (~ISL_SURF_USAGE_CUBE_BIT); 30517ec681f3Smrg 30527ec681f3Smrg bool ok UNUSED; 30537ec681f3Smrg ok = isl_surf_init(dev, ucompr_surf, 30547ec681f3Smrg .dim = ISL_SURF_DIM_2D, 30557ec681f3Smrg .format = view_format, 30567ec681f3Smrg .width = view_width_el, 30577ec681f3Smrg .height = view_height_el, 30587ec681f3Smrg .depth = 1, 30597ec681f3Smrg .levels = 1, 30607ec681f3Smrg .array_len = 1, 30617ec681f3Smrg .samples = 1, 30627ec681f3Smrg .row_pitch_B = surf->row_pitch_B, 30637ec681f3Smrg .usage = usage, 30647ec681f3Smrg .tiling_flags = (1 << surf->tiling)); 30657ec681f3Smrg assert(ok); 30667ec681f3Smrg 30677ec681f3Smrg /* The newly created image represents the one subimage we're 30687ec681f3Smrg * referencing with this view so it only has one array slice and 30697ec681f3Smrg * miplevel. 30707ec681f3Smrg */ 30717ec681f3Smrg *ucompr_view = *view; 30727ec681f3Smrg ucompr_view->base_array_layer = 0; 30737ec681f3Smrg ucompr_view->base_level = 0; 30747ec681f3Smrg } 30757ec681f3Smrg 30767ec681f3Smrg return true; 30777ec681f3Smrg} 30787ec681f3Smrg 307901e04c3fSmrgvoid 308001e04c3fSmrgisl_tiling_get_intratile_offset_el(enum isl_tiling tiling, 30817ec681f3Smrg enum isl_surf_dim dim, 30827ec681f3Smrg enum isl_msaa_layout msaa_layout, 308301e04c3fSmrg uint32_t bpb, 30847ec681f3Smrg uint32_t samples, 308501e04c3fSmrg uint32_t row_pitch_B, 30867ec681f3Smrg uint32_t array_pitch_el_rows, 308701e04c3fSmrg uint32_t total_x_offset_el, 308801e04c3fSmrg uint32_t total_y_offset_el, 30897ec681f3Smrg uint32_t total_z_offset_el, 30907ec681f3Smrg uint32_t total_array_offset, 30917ec681f3Smrg uint64_t *tile_offset_B, 309201e04c3fSmrg uint32_t *x_offset_el, 30937ec681f3Smrg uint32_t *y_offset_el, 30947ec681f3Smrg uint32_t *z_offset_el, 30957ec681f3Smrg uint32_t *array_offset) 309601e04c3fSmrg{ 309701e04c3fSmrg if (tiling == ISL_TILING_LINEAR) { 309801e04c3fSmrg assert(bpb % 8 == 0); 30997ec681f3Smrg assert(samples == 1); 31007ec681f3Smrg assert(total_z_offset_el == 0 && total_array_offset == 0); 31017ec681f3Smrg *tile_offset_B = (uint64_t)total_y_offset_el * row_pitch_B + 31027ec681f3Smrg (uint64_t)total_x_offset_el * (bpb / 8); 310301e04c3fSmrg *x_offset_el = 0; 310401e04c3fSmrg *y_offset_el = 0; 31057ec681f3Smrg *z_offset_el = 0; 31067ec681f3Smrg *array_offset = 0; 310701e04c3fSmrg return; 310801e04c3fSmrg } 310901e04c3fSmrg 311001e04c3fSmrg struct isl_tile_info tile_info; 31117ec681f3Smrg isl_tiling_get_info(tiling, dim, msaa_layout, bpb, samples, &tile_info); 311201e04c3fSmrg 31137ec681f3Smrg /* Pitches must make sense with the tiling */ 311401e04c3fSmrg assert(row_pitch_B % tile_info.phys_extent_B.width == 0); 31157ec681f3Smrg if (tile_info.logical_extent_el.d > 1 || tile_info.logical_extent_el.a > 1) 31167ec681f3Smrg assert(array_pitch_el_rows % tile_info.logical_extent_el.h == 0); 311701e04c3fSmrg 311801e04c3fSmrg /* For non-power-of-two formats, we need the address to be both tile and 311901e04c3fSmrg * element-aligned. The easiest way to achieve this is to work with a tile 312001e04c3fSmrg * that is three times as wide as the regular tile. 312101e04c3fSmrg * 312201e04c3fSmrg * The tile info returned by get_tile_info has a logical size that is an 312301e04c3fSmrg * integer number of tile_info.format_bpb size elements. To scale the 312401e04c3fSmrg * tile, we scale up the physical width and then treat the logical tile 312501e04c3fSmrg * size as if it has bpb size elements. 312601e04c3fSmrg */ 312701e04c3fSmrg const uint32_t tile_el_scale = bpb / tile_info.format_bpb; 312801e04c3fSmrg tile_info.phys_extent_B.width *= tile_el_scale; 312901e04c3fSmrg 313001e04c3fSmrg /* Compute the offset into the tile */ 313101e04c3fSmrg *x_offset_el = total_x_offset_el % tile_info.logical_extent_el.w; 313201e04c3fSmrg *y_offset_el = total_y_offset_el % tile_info.logical_extent_el.h; 31337ec681f3Smrg *z_offset_el = total_z_offset_el % tile_info.logical_extent_el.d; 31347ec681f3Smrg *array_offset = total_array_offset % tile_info.logical_extent_el.a; 313501e04c3fSmrg 313601e04c3fSmrg /* Compute the offset of the tile in units of whole tiles */ 313701e04c3fSmrg uint32_t x_offset_tl = total_x_offset_el / tile_info.logical_extent_el.w; 313801e04c3fSmrg uint32_t y_offset_tl = total_y_offset_el / tile_info.logical_extent_el.h; 31397ec681f3Smrg uint32_t z_offset_tl = total_z_offset_el / tile_info.logical_extent_el.d; 31407ec681f3Smrg uint32_t a_offset_tl = total_array_offset / tile_info.logical_extent_el.a; 31417ec681f3Smrg 31427ec681f3Smrg /* Compute an array pitch in number of tiles */ 31437ec681f3Smrg uint32_t array_pitch_tl_rows = 31447ec681f3Smrg array_pitch_el_rows / tile_info.logical_extent_el.h; 314501e04c3fSmrg 31467ec681f3Smrg /* Add the Z and array offset to the Y offset to get a 2D offset */ 31477ec681f3Smrg y_offset_tl += (z_offset_tl + a_offset_tl) * array_pitch_tl_rows; 31487ec681f3Smrg 31497ec681f3Smrg *tile_offset_B = 31507ec681f3Smrg (uint64_t)y_offset_tl * tile_info.phys_extent_B.h * row_pitch_B + 31517ec681f3Smrg (uint64_t)x_offset_tl * tile_info.phys_extent_B.h * tile_info.phys_extent_B.w; 315201e04c3fSmrg} 315301e04c3fSmrg 315401e04c3fSmrguint32_t 315501e04c3fSmrgisl_surf_get_depth_format(const struct isl_device *dev, 315601e04c3fSmrg const struct isl_surf *surf) 315701e04c3fSmrg{ 31587ec681f3Smrg /* Support for separate stencil buffers began in gfx5. Support for 31597ec681f3Smrg * interleaved depthstencil buffers ceased in gfx7. The intermediate gens, 31607ec681f3Smrg * those that supported separate and interleaved stencil, were gfx5 and 31617ec681f3Smrg * gfx6. 316201e04c3fSmrg * 316301e04c3fSmrg * For a list of all available formats, see the Sandybridge PRM >> Volume 316401e04c3fSmrg * 2 Part 1: 3D/Media - 3D Pipeline >> 3DSTATE_DEPTH_BUFFER >> Surface 316501e04c3fSmrg * Format (p321). 316601e04c3fSmrg */ 316701e04c3fSmrg 316801e04c3fSmrg bool has_stencil = surf->usage & ISL_SURF_USAGE_STENCIL_BIT; 316901e04c3fSmrg 317001e04c3fSmrg assert(surf->usage & ISL_SURF_USAGE_DEPTH_BIT); 317101e04c3fSmrg 317201e04c3fSmrg if (has_stencil) 31737ec681f3Smrg assert(ISL_GFX_VER(dev) < 7); 317401e04c3fSmrg 317501e04c3fSmrg switch (surf->format) { 317601e04c3fSmrg default: 317701e04c3fSmrg unreachable("bad isl depth format"); 317801e04c3fSmrg case ISL_FORMAT_R32_FLOAT_X8X24_TYPELESS: 31797ec681f3Smrg assert(ISL_GFX_VER(dev) < 7); 318001e04c3fSmrg return 0; /* D32_FLOAT_S8X24_UINT */ 318101e04c3fSmrg case ISL_FORMAT_R32_FLOAT: 318201e04c3fSmrg assert(!has_stencil); 318301e04c3fSmrg return 1; /* D32_FLOAT */ 318401e04c3fSmrg case ISL_FORMAT_R24_UNORM_X8_TYPELESS: 318501e04c3fSmrg if (has_stencil) { 31867ec681f3Smrg assert(ISL_GFX_VER(dev) < 7); 318701e04c3fSmrg return 2; /* D24_UNORM_S8_UINT */ 318801e04c3fSmrg } else { 31897ec681f3Smrg assert(ISL_GFX_VER(dev) >= 5); 319001e04c3fSmrg return 3; /* D24_UNORM_X8_UINT */ 319101e04c3fSmrg } 319201e04c3fSmrg case ISL_FORMAT_R16_UNORM: 319301e04c3fSmrg assert(!has_stencil); 319401e04c3fSmrg return 5; /* D16_UNORM */ 319501e04c3fSmrg } 319601e04c3fSmrg} 319701e04c3fSmrg 319801e04c3fSmrgbool 31997ec681f3Smrgisl_swizzle_supports_rendering(const struct intel_device_info *devinfo, 320001e04c3fSmrg struct isl_swizzle swizzle) 320101e04c3fSmrg{ 320201e04c3fSmrg if (devinfo->is_haswell) { 320301e04c3fSmrg /* From the Haswell PRM, 320401e04c3fSmrg * RENDER_SURFACE_STATE::Shader Channel Select Red 320501e04c3fSmrg * 320601e04c3fSmrg * "The Shader channel selects also define which shader channels are 320701e04c3fSmrg * written to which surface channel. If the Shader channel select is 320801e04c3fSmrg * SCS_ZERO or SCS_ONE then it is not written to the surface. If the 320901e04c3fSmrg * shader channel select is SCS_RED it is written to the surface red 321001e04c3fSmrg * channel and so on. If more than one shader channel select is set 321101e04c3fSmrg * to the same surface channel only the first shader channel in RGBA 321201e04c3fSmrg * order will be written." 321301e04c3fSmrg */ 321401e04c3fSmrg return true; 32157ec681f3Smrg } else if (devinfo->ver <= 7) { 321601e04c3fSmrg /* Ivy Bridge and early doesn't have any swizzling */ 321701e04c3fSmrg return isl_swizzle_is_identity(swizzle); 321801e04c3fSmrg } else { 321901e04c3fSmrg /* From the Sky Lake PRM Vol. 2d, 322001e04c3fSmrg * RENDER_SURFACE_STATE::Shader Channel Select Red 322101e04c3fSmrg * 322201e04c3fSmrg * "For Render Target, Red, Green and Blue Shader Channel Selects 322301e04c3fSmrg * MUST be such that only valid components can be swapped i.e. only 322401e04c3fSmrg * change the order of components in the pixel. Any other values for 322501e04c3fSmrg * these Shader Channel Select fields are not valid for Render 322601e04c3fSmrg * Targets. This also means that there MUST not be multiple shader 322701e04c3fSmrg * channels mapped to the same RT channel." 322801e04c3fSmrg * 322901e04c3fSmrg * From the Sky Lake PRM Vol. 2d, 323001e04c3fSmrg * RENDER_SURFACE_STATE::Shader Channel Select Alpha 323101e04c3fSmrg * 323201e04c3fSmrg * "For Render Target, this field MUST be programmed to 323301e04c3fSmrg * value = SCS_ALPHA." 323401e04c3fSmrg */ 323501e04c3fSmrg return (swizzle.r == ISL_CHANNEL_SELECT_RED || 323601e04c3fSmrg swizzle.r == ISL_CHANNEL_SELECT_GREEN || 323701e04c3fSmrg swizzle.r == ISL_CHANNEL_SELECT_BLUE) && 323801e04c3fSmrg (swizzle.g == ISL_CHANNEL_SELECT_RED || 323901e04c3fSmrg swizzle.g == ISL_CHANNEL_SELECT_GREEN || 324001e04c3fSmrg swizzle.g == ISL_CHANNEL_SELECT_BLUE) && 324101e04c3fSmrg (swizzle.b == ISL_CHANNEL_SELECT_RED || 324201e04c3fSmrg swizzle.b == ISL_CHANNEL_SELECT_GREEN || 324301e04c3fSmrg swizzle.b == ISL_CHANNEL_SELECT_BLUE) && 324401e04c3fSmrg swizzle.r != swizzle.g && 324501e04c3fSmrg swizzle.r != swizzle.b && 324601e04c3fSmrg swizzle.g != swizzle.b && 324701e04c3fSmrg swizzle.a == ISL_CHANNEL_SELECT_ALPHA; 324801e04c3fSmrg } 324901e04c3fSmrg} 325001e04c3fSmrg 325101e04c3fSmrgstatic enum isl_channel_select 325201e04c3fSmrgswizzle_select(enum isl_channel_select chan, struct isl_swizzle swizzle) 325301e04c3fSmrg{ 325401e04c3fSmrg switch (chan) { 325501e04c3fSmrg case ISL_CHANNEL_SELECT_ZERO: 325601e04c3fSmrg case ISL_CHANNEL_SELECT_ONE: 325701e04c3fSmrg return chan; 325801e04c3fSmrg case ISL_CHANNEL_SELECT_RED: 325901e04c3fSmrg return swizzle.r; 326001e04c3fSmrg case ISL_CHANNEL_SELECT_GREEN: 326101e04c3fSmrg return swizzle.g; 326201e04c3fSmrg case ISL_CHANNEL_SELECT_BLUE: 326301e04c3fSmrg return swizzle.b; 326401e04c3fSmrg case ISL_CHANNEL_SELECT_ALPHA: 326501e04c3fSmrg return swizzle.a; 326601e04c3fSmrg default: 326701e04c3fSmrg unreachable("Invalid swizzle component"); 326801e04c3fSmrg } 326901e04c3fSmrg} 327001e04c3fSmrg 327101e04c3fSmrg/** 327201e04c3fSmrg * Returns the single swizzle that is equivalent to applying the two given 327301e04c3fSmrg * swizzles in sequence. 327401e04c3fSmrg */ 327501e04c3fSmrgstruct isl_swizzle 327601e04c3fSmrgisl_swizzle_compose(struct isl_swizzle first, struct isl_swizzle second) 327701e04c3fSmrg{ 327801e04c3fSmrg return (struct isl_swizzle) { 327901e04c3fSmrg .r = swizzle_select(first.r, second), 328001e04c3fSmrg .g = swizzle_select(first.g, second), 328101e04c3fSmrg .b = swizzle_select(first.b, second), 328201e04c3fSmrg .a = swizzle_select(first.a, second), 328301e04c3fSmrg }; 328401e04c3fSmrg} 328501e04c3fSmrg 328601e04c3fSmrg/** 328701e04c3fSmrg * Returns a swizzle that is the pseudo-inverse of this swizzle. 328801e04c3fSmrg */ 328901e04c3fSmrgstruct isl_swizzle 329001e04c3fSmrgisl_swizzle_invert(struct isl_swizzle swizzle) 329101e04c3fSmrg{ 329201e04c3fSmrg /* Default to zero for channels which do not show up in the swizzle */ 329301e04c3fSmrg enum isl_channel_select chans[4] = { 329401e04c3fSmrg ISL_CHANNEL_SELECT_ZERO, 329501e04c3fSmrg ISL_CHANNEL_SELECT_ZERO, 329601e04c3fSmrg ISL_CHANNEL_SELECT_ZERO, 329701e04c3fSmrg ISL_CHANNEL_SELECT_ZERO, 329801e04c3fSmrg }; 329901e04c3fSmrg 330001e04c3fSmrg /* We go in ABGR order so that, if there are any duplicates, the first one 330101e04c3fSmrg * is taken if you look at it in RGBA order. This is what Haswell hardware 330201e04c3fSmrg * does for render target swizzles. 330301e04c3fSmrg */ 330401e04c3fSmrg if ((unsigned)(swizzle.a - ISL_CHANNEL_SELECT_RED) < 4) 330501e04c3fSmrg chans[swizzle.a - ISL_CHANNEL_SELECT_RED] = ISL_CHANNEL_SELECT_ALPHA; 330601e04c3fSmrg if ((unsigned)(swizzle.b - ISL_CHANNEL_SELECT_RED) < 4) 330701e04c3fSmrg chans[swizzle.b - ISL_CHANNEL_SELECT_RED] = ISL_CHANNEL_SELECT_BLUE; 330801e04c3fSmrg if ((unsigned)(swizzle.g - ISL_CHANNEL_SELECT_RED) < 4) 330901e04c3fSmrg chans[swizzle.g - ISL_CHANNEL_SELECT_RED] = ISL_CHANNEL_SELECT_GREEN; 331001e04c3fSmrg if ((unsigned)(swizzle.r - ISL_CHANNEL_SELECT_RED) < 4) 331101e04c3fSmrg chans[swizzle.r - ISL_CHANNEL_SELECT_RED] = ISL_CHANNEL_SELECT_RED; 331201e04c3fSmrg 331301e04c3fSmrg return (struct isl_swizzle) { chans[0], chans[1], chans[2], chans[3] }; 331401e04c3fSmrg} 33157ec681f3Smrg 33167ec681f3Smrg/** Applies an inverse swizzle to a color value */ 33177ec681f3Smrgunion isl_color_value 33187ec681f3Smrgisl_color_value_swizzle_inv(union isl_color_value src, 33197ec681f3Smrg struct isl_swizzle swizzle) 33207ec681f3Smrg{ 33217ec681f3Smrg union isl_color_value dst = { .u32 = { 0, } }; 33227ec681f3Smrg 33237ec681f3Smrg /* We assign colors in ABGR order so that the first one will be taken in 33247ec681f3Smrg * RGBA precedence order. According to the PRM docs for shader channel 33257ec681f3Smrg * select, this matches Haswell hardware behavior. 33267ec681f3Smrg */ 33277ec681f3Smrg if ((unsigned)(swizzle.a - ISL_CHANNEL_SELECT_RED) < 4) 33287ec681f3Smrg dst.u32[swizzle.a - ISL_CHANNEL_SELECT_RED] = src.u32[3]; 33297ec681f3Smrg if ((unsigned)(swizzle.b - ISL_CHANNEL_SELECT_RED) < 4) 33307ec681f3Smrg dst.u32[swizzle.b - ISL_CHANNEL_SELECT_RED] = src.u32[2]; 33317ec681f3Smrg if ((unsigned)(swizzle.g - ISL_CHANNEL_SELECT_RED) < 4) 33327ec681f3Smrg dst.u32[swizzle.g - ISL_CHANNEL_SELECT_RED] = src.u32[1]; 33337ec681f3Smrg if ((unsigned)(swizzle.r - ISL_CHANNEL_SELECT_RED) < 4) 33347ec681f3Smrg dst.u32[swizzle.r - ISL_CHANNEL_SELECT_RED] = src.u32[0]; 33357ec681f3Smrg 33367ec681f3Smrg return dst; 33377ec681f3Smrg} 33387ec681f3Smrg 33397ec681f3Smrguint8_t 33407ec681f3Smrgisl_format_get_aux_map_encoding(enum isl_format format) 33417ec681f3Smrg{ 33427ec681f3Smrg switch(format) { 33437ec681f3Smrg case ISL_FORMAT_R32G32B32A32_FLOAT: return 0x11; 33447ec681f3Smrg case ISL_FORMAT_R32G32B32X32_FLOAT: return 0x11; 33457ec681f3Smrg case ISL_FORMAT_R32G32B32A32_SINT: return 0x12; 33467ec681f3Smrg case ISL_FORMAT_R32G32B32A32_UINT: return 0x13; 33477ec681f3Smrg case ISL_FORMAT_R16G16B16A16_UNORM: return 0x14; 33487ec681f3Smrg case ISL_FORMAT_R16G16B16A16_SNORM: return 0x15; 33497ec681f3Smrg case ISL_FORMAT_R16G16B16A16_SINT: return 0x16; 33507ec681f3Smrg case ISL_FORMAT_R16G16B16A16_UINT: return 0x17; 33517ec681f3Smrg case ISL_FORMAT_R16G16B16A16_FLOAT: return 0x10; 33527ec681f3Smrg case ISL_FORMAT_R16G16B16X16_FLOAT: return 0x10; 33537ec681f3Smrg case ISL_FORMAT_R32G32_FLOAT: return 0x11; 33547ec681f3Smrg case ISL_FORMAT_R32G32_SINT: return 0x12; 33557ec681f3Smrg case ISL_FORMAT_R32G32_UINT: return 0x13; 33567ec681f3Smrg case ISL_FORMAT_B8G8R8A8_UNORM: return 0xA; 33577ec681f3Smrg case ISL_FORMAT_B8G8R8X8_UNORM: return 0xA; 33587ec681f3Smrg case ISL_FORMAT_B8G8R8A8_UNORM_SRGB: return 0xA; 33597ec681f3Smrg case ISL_FORMAT_B8G8R8X8_UNORM_SRGB: return 0xA; 33607ec681f3Smrg case ISL_FORMAT_R10G10B10A2_UNORM: return 0x18; 33617ec681f3Smrg case ISL_FORMAT_R10G10B10A2_UNORM_SRGB: return 0x18; 33627ec681f3Smrg case ISL_FORMAT_R10G10B10_FLOAT_A2_UNORM: return 0x19; 33637ec681f3Smrg case ISL_FORMAT_R10G10B10A2_UINT: return 0x1A; 33647ec681f3Smrg case ISL_FORMAT_R8G8B8A8_UNORM: return 0xA; 33657ec681f3Smrg case ISL_FORMAT_R8G8B8A8_UNORM_SRGB: return 0xA; 33667ec681f3Smrg case ISL_FORMAT_R8G8B8A8_SNORM: return 0x1B; 33677ec681f3Smrg case ISL_FORMAT_R8G8B8A8_SINT: return 0x1C; 33687ec681f3Smrg case ISL_FORMAT_R8G8B8A8_UINT: return 0x1D; 33697ec681f3Smrg case ISL_FORMAT_R16G16_UNORM: return 0x14; 33707ec681f3Smrg case ISL_FORMAT_R16G16_SNORM: return 0x15; 33717ec681f3Smrg case ISL_FORMAT_R16G16_SINT: return 0x16; 33727ec681f3Smrg case ISL_FORMAT_R16G16_UINT: return 0x17; 33737ec681f3Smrg case ISL_FORMAT_R16G16_FLOAT: return 0x10; 33747ec681f3Smrg case ISL_FORMAT_B10G10R10A2_UNORM: return 0x18; 33757ec681f3Smrg case ISL_FORMAT_B10G10R10A2_UNORM_SRGB: return 0x18; 33767ec681f3Smrg case ISL_FORMAT_R11G11B10_FLOAT: return 0x1E; 33777ec681f3Smrg case ISL_FORMAT_R32_SINT: return 0x12; 33787ec681f3Smrg case ISL_FORMAT_R32_UINT: return 0x13; 33797ec681f3Smrg case ISL_FORMAT_R32_FLOAT: return 0x11; 33807ec681f3Smrg case ISL_FORMAT_R24_UNORM_X8_TYPELESS: return 0x13; 33817ec681f3Smrg case ISL_FORMAT_B5G6R5_UNORM: return 0xA; 33827ec681f3Smrg case ISL_FORMAT_B5G6R5_UNORM_SRGB: return 0xA; 33837ec681f3Smrg case ISL_FORMAT_B5G5R5A1_UNORM: return 0xA; 33847ec681f3Smrg case ISL_FORMAT_B5G5R5A1_UNORM_SRGB: return 0xA; 33857ec681f3Smrg case ISL_FORMAT_B4G4R4A4_UNORM: return 0xA; 33867ec681f3Smrg case ISL_FORMAT_B4G4R4A4_UNORM_SRGB: return 0xA; 33877ec681f3Smrg case ISL_FORMAT_R8G8_UNORM: return 0xA; 33887ec681f3Smrg case ISL_FORMAT_R8G8_SNORM: return 0x1B; 33897ec681f3Smrg case ISL_FORMAT_R8G8_SINT: return 0x1C; 33907ec681f3Smrg case ISL_FORMAT_R8G8_UINT: return 0x1D; 33917ec681f3Smrg case ISL_FORMAT_R16_UNORM: return 0x14; 33927ec681f3Smrg case ISL_FORMAT_R16_SNORM: return 0x15; 33937ec681f3Smrg case ISL_FORMAT_R16_SINT: return 0x16; 33947ec681f3Smrg case ISL_FORMAT_R16_UINT: return 0x17; 33957ec681f3Smrg case ISL_FORMAT_R16_FLOAT: return 0x10; 33967ec681f3Smrg case ISL_FORMAT_B5G5R5X1_UNORM: return 0xA; 33977ec681f3Smrg case ISL_FORMAT_B5G5R5X1_UNORM_SRGB: return 0xA; 33987ec681f3Smrg case ISL_FORMAT_A1B5G5R5_UNORM: return 0xA; 33997ec681f3Smrg case ISL_FORMAT_A4B4G4R4_UNORM: return 0xA; 34007ec681f3Smrg case ISL_FORMAT_R8_UNORM: return 0xA; 34017ec681f3Smrg case ISL_FORMAT_R8_SNORM: return 0x1B; 34027ec681f3Smrg case ISL_FORMAT_R8_SINT: return 0x1C; 34037ec681f3Smrg case ISL_FORMAT_R8_UINT: return 0x1D; 34047ec681f3Smrg case ISL_FORMAT_A8_UNORM: return 0xA; 34057ec681f3Smrg case ISL_FORMAT_PLANAR_420_8: return 0xF; 34067ec681f3Smrg case ISL_FORMAT_PLANAR_420_10: return 0x7; 34077ec681f3Smrg case ISL_FORMAT_PLANAR_420_12: return 0x8; 34087ec681f3Smrg case ISL_FORMAT_PLANAR_420_16: return 0x8; 34097ec681f3Smrg case ISL_FORMAT_YCRCB_NORMAL: return 0x3; 34107ec681f3Smrg case ISL_FORMAT_YCRCB_SWAPY: return 0xB; 34117ec681f3Smrg default: 34127ec681f3Smrg unreachable("Unsupported aux-map format!"); 34137ec681f3Smrg return 0; 34147ec681f3Smrg } 34157ec681f3Smrg} 34167ec681f3Smrg 34177ec681f3Smrg/* 34187ec681f3Smrg * Returns compression format encoding for Unified Lossless Compression 34197ec681f3Smrg */ 34207ec681f3Smrguint8_t 34217ec681f3Smrgisl_get_render_compression_format(enum isl_format format) 34227ec681f3Smrg{ 34237ec681f3Smrg /* From the Bspec, Enumeration_RenderCompressionFormat section (53726): */ 34247ec681f3Smrg switch(format) { 34257ec681f3Smrg case ISL_FORMAT_R32G32B32A32_FLOAT: 34267ec681f3Smrg case ISL_FORMAT_R32G32B32X32_FLOAT: 34277ec681f3Smrg case ISL_FORMAT_R32G32B32A32_SINT: 34287ec681f3Smrg return 0x0; 34297ec681f3Smrg case ISL_FORMAT_R32G32B32A32_UINT: 34307ec681f3Smrg return 0x1; 34317ec681f3Smrg case ISL_FORMAT_R32G32_FLOAT: 34327ec681f3Smrg case ISL_FORMAT_R32G32_SINT: 34337ec681f3Smrg return 0x2; 34347ec681f3Smrg case ISL_FORMAT_R32G32_UINT: 34357ec681f3Smrg return 0x3; 34367ec681f3Smrg case ISL_FORMAT_R16G16B16A16_UNORM: 34377ec681f3Smrg case ISL_FORMAT_R16G16B16X16_UNORM: 34387ec681f3Smrg case ISL_FORMAT_R16G16B16A16_UINT: 34397ec681f3Smrg return 0x4; 34407ec681f3Smrg case ISL_FORMAT_R16G16B16A16_SNORM: 34417ec681f3Smrg case ISL_FORMAT_R16G16B16A16_SINT: 34427ec681f3Smrg case ISL_FORMAT_R16G16B16A16_FLOAT: 34437ec681f3Smrg case ISL_FORMAT_R16G16B16X16_FLOAT: 34447ec681f3Smrg return 0x5; 34457ec681f3Smrg case ISL_FORMAT_R16G16_UNORM: 34467ec681f3Smrg case ISL_FORMAT_R16G16_UINT: 34477ec681f3Smrg return 0x6; 34487ec681f3Smrg case ISL_FORMAT_R16G16_SNORM: 34497ec681f3Smrg case ISL_FORMAT_R16G16_SINT: 34507ec681f3Smrg case ISL_FORMAT_R16G16_FLOAT: 34517ec681f3Smrg return 0x7; 34527ec681f3Smrg case ISL_FORMAT_B8G8R8A8_UNORM: 34537ec681f3Smrg case ISL_FORMAT_B8G8R8X8_UNORM: 34547ec681f3Smrg case ISL_FORMAT_B8G8R8A8_UNORM_SRGB: 34557ec681f3Smrg case ISL_FORMAT_B8G8R8X8_UNORM_SRGB: 34567ec681f3Smrg case ISL_FORMAT_R8G8B8A8_UNORM: 34577ec681f3Smrg case ISL_FORMAT_R8G8B8X8_UNORM: 34587ec681f3Smrg case ISL_FORMAT_R8G8B8A8_UNORM_SRGB: 34597ec681f3Smrg case ISL_FORMAT_R8G8B8X8_UNORM_SRGB: 34607ec681f3Smrg case ISL_FORMAT_R8G8B8A8_UINT: 34617ec681f3Smrg return 0x8; 34627ec681f3Smrg case ISL_FORMAT_R8G8B8A8_SNORM: 34637ec681f3Smrg case ISL_FORMAT_R8G8B8A8_SINT: 34647ec681f3Smrg return 0x9; 34657ec681f3Smrg case ISL_FORMAT_B5G6R5_UNORM: 34667ec681f3Smrg case ISL_FORMAT_B5G6R5_UNORM_SRGB: 34677ec681f3Smrg case ISL_FORMAT_B5G5R5A1_UNORM: 34687ec681f3Smrg case ISL_FORMAT_B5G5R5A1_UNORM_SRGB: 34697ec681f3Smrg case ISL_FORMAT_B4G4R4A4_UNORM: 34707ec681f3Smrg case ISL_FORMAT_B4G4R4A4_UNORM_SRGB: 34717ec681f3Smrg case ISL_FORMAT_B5G5R5X1_UNORM: 34727ec681f3Smrg case ISL_FORMAT_B5G5R5X1_UNORM_SRGB: 34737ec681f3Smrg case ISL_FORMAT_A1B5G5R5_UNORM: 34747ec681f3Smrg case ISL_FORMAT_A4B4G4R4_UNORM: 34757ec681f3Smrg case ISL_FORMAT_R8G8_UNORM: 34767ec681f3Smrg case ISL_FORMAT_R8G8_UINT: 34777ec681f3Smrg return 0xA; 34787ec681f3Smrg case ISL_FORMAT_R8G8_SNORM: 34797ec681f3Smrg case ISL_FORMAT_R8G8_SINT: 34807ec681f3Smrg return 0xB; 34817ec681f3Smrg case ISL_FORMAT_R10G10B10A2_UNORM: 34827ec681f3Smrg case ISL_FORMAT_R10G10B10A2_UNORM_SRGB: 34837ec681f3Smrg case ISL_FORMAT_R10G10B10_FLOAT_A2_UNORM: 34847ec681f3Smrg case ISL_FORMAT_R10G10B10A2_UINT: 34857ec681f3Smrg case ISL_FORMAT_B10G10R10A2_UNORM: 34867ec681f3Smrg case ISL_FORMAT_B10G10R10X2_UNORM: 34877ec681f3Smrg case ISL_FORMAT_B10G10R10A2_UNORM_SRGB: 34887ec681f3Smrg return 0xC; 34897ec681f3Smrg case ISL_FORMAT_R11G11B10_FLOAT: 34907ec681f3Smrg return 0xD; 34917ec681f3Smrg case ISL_FORMAT_R32_SINT: 34927ec681f3Smrg case ISL_FORMAT_R32_FLOAT: 34937ec681f3Smrg return 0x10; 34947ec681f3Smrg case ISL_FORMAT_R32_UINT: 34957ec681f3Smrg case ISL_FORMAT_R24_UNORM_X8_TYPELESS: 34967ec681f3Smrg return 0x11; 34977ec681f3Smrg case ISL_FORMAT_R16_UNORM: 34987ec681f3Smrg case ISL_FORMAT_R16_UINT: 34997ec681f3Smrg return 0x14; 35007ec681f3Smrg case ISL_FORMAT_R16_SNORM: 35017ec681f3Smrg case ISL_FORMAT_R16_SINT: 35027ec681f3Smrg case ISL_FORMAT_R16_FLOAT: 35037ec681f3Smrg return 0x15; 35047ec681f3Smrg case ISL_FORMAT_R8_UNORM: 35057ec681f3Smrg case ISL_FORMAT_R8_UINT: 35067ec681f3Smrg case ISL_FORMAT_A8_UNORM: 35077ec681f3Smrg return 0x18; 35087ec681f3Smrg case ISL_FORMAT_R8_SNORM: 35097ec681f3Smrg case ISL_FORMAT_R8_SINT: 35107ec681f3Smrg return 0x19; 35117ec681f3Smrg default: 35127ec681f3Smrg unreachable("Unsupported render compression format!"); 35137ec681f3Smrg return 0; 35147ec681f3Smrg } 35157ec681f3Smrg} 3516