isl.c revision 9f464c52
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" 3101e04c3fSmrg#include "isl_gen4.h" 3201e04c3fSmrg#include "isl_gen6.h" 3301e04c3fSmrg#include "isl_gen7.h" 3401e04c3fSmrg#include "isl_gen8.h" 3501e04c3fSmrg#include "isl_gen9.h" 3601e04c3fSmrg#include "isl_priv.h" 3701e04c3fSmrg 389f464c52Smayavoid 399f464c52Smayaisl_memcpy_linear_to_tiled(uint32_t xt1, uint32_t xt2, 409f464c52Smaya uint32_t yt1, uint32_t yt2, 419f464c52Smaya char *dst, const char *src, 429f464c52Smaya uint32_t dst_pitch, int32_t src_pitch, 439f464c52Smaya bool has_swizzling, 449f464c52Smaya enum isl_tiling tiling, 459f464c52Smaya isl_memcpy_type copy_type) 469f464c52Smaya{ 479f464c52Smaya#ifdef USE_SSE41 489f464c52Smaya if (copy_type == ISL_MEMCPY_STREAMING_LOAD) { 499f464c52Smaya _isl_memcpy_linear_to_tiled_sse41( 509f464c52Smaya xt1, xt2, yt1, yt2, dst, src, dst_pitch, src_pitch, has_swizzling, 519f464c52Smaya tiling, copy_type); 529f464c52Smaya return; 539f464c52Smaya } 549f464c52Smaya#endif 559f464c52Smaya 569f464c52Smaya _isl_memcpy_linear_to_tiled( 579f464c52Smaya xt1, xt2, yt1, yt2, dst, src, dst_pitch, src_pitch, has_swizzling, 589f464c52Smaya tiling, copy_type); 599f464c52Smaya} 609f464c52Smaya 619f464c52Smayavoid 629f464c52Smayaisl_memcpy_tiled_to_linear(uint32_t xt1, uint32_t xt2, 639f464c52Smaya uint32_t yt1, uint32_t yt2, 649f464c52Smaya char *dst, const char *src, 659f464c52Smaya int32_t dst_pitch, uint32_t src_pitch, 669f464c52Smaya bool has_swizzling, 679f464c52Smaya enum isl_tiling tiling, 689f464c52Smaya isl_memcpy_type copy_type) 699f464c52Smaya{ 709f464c52Smaya#ifdef USE_SSE41 719f464c52Smaya if (copy_type == ISL_MEMCPY_STREAMING_LOAD) { 729f464c52Smaya _isl_memcpy_tiled_to_linear_sse41( 739f464c52Smaya xt1, xt2, yt1, yt2, dst, src, dst_pitch, src_pitch, has_swizzling, 749f464c52Smaya tiling, copy_type); 759f464c52Smaya return; 769f464c52Smaya } 779f464c52Smaya#endif 789f464c52Smaya 799f464c52Smaya _isl_memcpy_tiled_to_linear( 809f464c52Smaya xt1, xt2, yt1, yt2, dst, src, dst_pitch, src_pitch, has_swizzling, 819f464c52Smaya tiling, copy_type); 829f464c52Smaya} 839f464c52Smaya 8401e04c3fSmrgvoid PRINTFLIKE(3, 4) UNUSED 8501e04c3fSmrg__isl_finishme(const char *file, int line, const char *fmt, ...) 8601e04c3fSmrg{ 8701e04c3fSmrg va_list ap; 8801e04c3fSmrg char buf[512]; 8901e04c3fSmrg 9001e04c3fSmrg va_start(ap, fmt); 9101e04c3fSmrg vsnprintf(buf, sizeof(buf), fmt, ap); 9201e04c3fSmrg va_end(ap); 9301e04c3fSmrg 9401e04c3fSmrg fprintf(stderr, "%s:%d: FINISHME: %s\n", file, line, buf); 9501e04c3fSmrg} 9601e04c3fSmrg 9701e04c3fSmrgvoid 9801e04c3fSmrgisl_device_init(struct isl_device *dev, 9901e04c3fSmrg const struct gen_device_info *info, 10001e04c3fSmrg bool has_bit6_swizzling) 10101e04c3fSmrg{ 1029f464c52Smaya /* Gen8+ don't have bit6 swizzling, ensure callsite is not confused. */ 1039f464c52Smaya assert(!(has_bit6_swizzling && info->gen >= 8)); 1049f464c52Smaya 10501e04c3fSmrg dev->info = info; 10601e04c3fSmrg dev->use_separate_stencil = ISL_DEV_GEN(dev) >= 6; 10701e04c3fSmrg dev->has_bit6_swizzling = has_bit6_swizzling; 10801e04c3fSmrg 10901e04c3fSmrg /* The ISL_DEV macros may be defined in the CFLAGS, thus hardcoding some 11001e04c3fSmrg * device properties at buildtime. Verify that the macros with the device 11101e04c3fSmrg * properties chosen during runtime. 11201e04c3fSmrg */ 11301e04c3fSmrg ISL_DEV_GEN_SANITIZE(dev); 11401e04c3fSmrg ISL_DEV_USE_SEPARATE_STENCIL_SANITIZE(dev); 11501e04c3fSmrg 11601e04c3fSmrg /* Did we break hiz or stencil? */ 11701e04c3fSmrg if (ISL_DEV_USE_SEPARATE_STENCIL(dev)) 11801e04c3fSmrg assert(info->has_hiz_and_separate_stencil); 11901e04c3fSmrg if (info->must_use_separate_stencil) 12001e04c3fSmrg assert(ISL_DEV_USE_SEPARATE_STENCIL(dev)); 12101e04c3fSmrg 12201e04c3fSmrg dev->ss.size = RENDER_SURFACE_STATE_length(info) * 4; 12301e04c3fSmrg dev->ss.align = isl_align(dev->ss.size, 32); 12401e04c3fSmrg 1259f464c52Smaya dev->ss.clear_color_state_size = 1269f464c52Smaya isl_align(CLEAR_COLOR_length(info) * 4, 64); 12701e04c3fSmrg dev->ss.clear_color_state_offset = 12801e04c3fSmrg RENDER_SURFACE_STATE_ClearValueAddress_start(info) / 32 * 4; 12901e04c3fSmrg 13001e04c3fSmrg dev->ss.clear_value_size = 13101e04c3fSmrg isl_align(RENDER_SURFACE_STATE_RedClearColor_bits(info) + 13201e04c3fSmrg RENDER_SURFACE_STATE_GreenClearColor_bits(info) + 13301e04c3fSmrg RENDER_SURFACE_STATE_BlueClearColor_bits(info) + 13401e04c3fSmrg RENDER_SURFACE_STATE_AlphaClearColor_bits(info), 32) / 8; 13501e04c3fSmrg 13601e04c3fSmrg dev->ss.clear_value_offset = 13701e04c3fSmrg RENDER_SURFACE_STATE_RedClearColor_start(info) / 32 * 4; 13801e04c3fSmrg 13901e04c3fSmrg assert(RENDER_SURFACE_STATE_SurfaceBaseAddress_start(info) % 8 == 0); 14001e04c3fSmrg dev->ss.addr_offset = 14101e04c3fSmrg RENDER_SURFACE_STATE_SurfaceBaseAddress_start(info) / 8; 14201e04c3fSmrg 14301e04c3fSmrg /* The "Auxiliary Surface Base Address" field starts a bit higher up 14401e04c3fSmrg * because the bottom 12 bits are used for other things. Round down to 14501e04c3fSmrg * the nearest dword before. 14601e04c3fSmrg */ 14701e04c3fSmrg dev->ss.aux_addr_offset = 14801e04c3fSmrg (RENDER_SURFACE_STATE_AuxiliarySurfaceBaseAddress_start(info) & ~31) / 8; 14901e04c3fSmrg 15001e04c3fSmrg dev->ds.size = _3DSTATE_DEPTH_BUFFER_length(info) * 4; 15101e04c3fSmrg assert(_3DSTATE_DEPTH_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); 15201e04c3fSmrg dev->ds.depth_offset = 15301e04c3fSmrg _3DSTATE_DEPTH_BUFFER_SurfaceBaseAddress_start(info) / 8; 15401e04c3fSmrg 15501e04c3fSmrg if (dev->use_separate_stencil) { 15601e04c3fSmrg dev->ds.size += _3DSTATE_STENCIL_BUFFER_length(info) * 4 + 15701e04c3fSmrg _3DSTATE_HIER_DEPTH_BUFFER_length(info) * 4 + 15801e04c3fSmrg _3DSTATE_CLEAR_PARAMS_length(info) * 4; 15901e04c3fSmrg 16001e04c3fSmrg assert(_3DSTATE_STENCIL_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); 16101e04c3fSmrg dev->ds.stencil_offset = 16201e04c3fSmrg _3DSTATE_DEPTH_BUFFER_length(info) * 4 + 16301e04c3fSmrg _3DSTATE_STENCIL_BUFFER_SurfaceBaseAddress_start(info) / 8; 16401e04c3fSmrg 16501e04c3fSmrg assert(_3DSTATE_HIER_DEPTH_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); 16601e04c3fSmrg dev->ds.hiz_offset = 16701e04c3fSmrg _3DSTATE_DEPTH_BUFFER_length(info) * 4 + 16801e04c3fSmrg _3DSTATE_STENCIL_BUFFER_length(info) * 4 + 16901e04c3fSmrg _3DSTATE_HIER_DEPTH_BUFFER_SurfaceBaseAddress_start(info) / 8; 17001e04c3fSmrg } else { 17101e04c3fSmrg dev->ds.stencil_offset = 0; 17201e04c3fSmrg dev->ds.hiz_offset = 0; 17301e04c3fSmrg } 17401e04c3fSmrg} 17501e04c3fSmrg 17601e04c3fSmrg/** 17701e04c3fSmrg * @brief Query the set of multisamples supported by the device. 17801e04c3fSmrg * 17901e04c3fSmrg * This function always returns non-zero, as ISL_SAMPLE_COUNT_1_BIT is always 18001e04c3fSmrg * supported. 18101e04c3fSmrg */ 18201e04c3fSmrgisl_sample_count_mask_t ATTRIBUTE_CONST 18301e04c3fSmrgisl_device_get_sample_counts(struct isl_device *dev) 18401e04c3fSmrg{ 18501e04c3fSmrg if (ISL_DEV_GEN(dev) >= 9) { 18601e04c3fSmrg return ISL_SAMPLE_COUNT_1_BIT | 18701e04c3fSmrg ISL_SAMPLE_COUNT_2_BIT | 18801e04c3fSmrg ISL_SAMPLE_COUNT_4_BIT | 18901e04c3fSmrg ISL_SAMPLE_COUNT_8_BIT | 19001e04c3fSmrg ISL_SAMPLE_COUNT_16_BIT; 19101e04c3fSmrg } else if (ISL_DEV_GEN(dev) >= 8) { 19201e04c3fSmrg return ISL_SAMPLE_COUNT_1_BIT | 19301e04c3fSmrg ISL_SAMPLE_COUNT_2_BIT | 19401e04c3fSmrg ISL_SAMPLE_COUNT_4_BIT | 19501e04c3fSmrg ISL_SAMPLE_COUNT_8_BIT; 19601e04c3fSmrg } else if (ISL_DEV_GEN(dev) >= 7) { 19701e04c3fSmrg return ISL_SAMPLE_COUNT_1_BIT | 19801e04c3fSmrg ISL_SAMPLE_COUNT_4_BIT | 19901e04c3fSmrg ISL_SAMPLE_COUNT_8_BIT; 20001e04c3fSmrg } else if (ISL_DEV_GEN(dev) >= 6) { 20101e04c3fSmrg return ISL_SAMPLE_COUNT_1_BIT | 20201e04c3fSmrg ISL_SAMPLE_COUNT_4_BIT; 20301e04c3fSmrg } else { 20401e04c3fSmrg return ISL_SAMPLE_COUNT_1_BIT; 20501e04c3fSmrg } 20601e04c3fSmrg} 20701e04c3fSmrg 20801e04c3fSmrg/** 20901e04c3fSmrg * @param[out] info is written only on success 21001e04c3fSmrg */ 21101e04c3fSmrgstatic void 21201e04c3fSmrgisl_tiling_get_info(enum isl_tiling tiling, 21301e04c3fSmrg uint32_t format_bpb, 21401e04c3fSmrg struct isl_tile_info *tile_info) 21501e04c3fSmrg{ 21601e04c3fSmrg const uint32_t bs = format_bpb / 8; 21701e04c3fSmrg struct isl_extent2d logical_el, phys_B; 21801e04c3fSmrg 21901e04c3fSmrg if (tiling != ISL_TILING_LINEAR && !isl_is_pow2(format_bpb)) { 22001e04c3fSmrg /* It is possible to have non-power-of-two formats in a tiled buffer. 22101e04c3fSmrg * The easiest way to handle this is to treat the tile as if it is three 22201e04c3fSmrg * times as wide. This way no pixel will ever cross a tile boundary. 22301e04c3fSmrg * This really only works on legacy X and Y tiling formats. 22401e04c3fSmrg */ 22501e04c3fSmrg assert(tiling == ISL_TILING_X || tiling == ISL_TILING_Y0); 22601e04c3fSmrg assert(bs % 3 == 0 && isl_is_pow2(format_bpb / 3)); 22701e04c3fSmrg isl_tiling_get_info(tiling, format_bpb / 3, tile_info); 22801e04c3fSmrg return; 22901e04c3fSmrg } 23001e04c3fSmrg 23101e04c3fSmrg switch (tiling) { 23201e04c3fSmrg case ISL_TILING_LINEAR: 23301e04c3fSmrg assert(bs > 0); 23401e04c3fSmrg logical_el = isl_extent2d(1, 1); 23501e04c3fSmrg phys_B = isl_extent2d(bs, 1); 23601e04c3fSmrg break; 23701e04c3fSmrg 23801e04c3fSmrg case ISL_TILING_X: 23901e04c3fSmrg assert(bs > 0); 24001e04c3fSmrg logical_el = isl_extent2d(512 / bs, 8); 24101e04c3fSmrg phys_B = isl_extent2d(512, 8); 24201e04c3fSmrg break; 24301e04c3fSmrg 24401e04c3fSmrg case ISL_TILING_Y0: 24501e04c3fSmrg assert(bs > 0); 24601e04c3fSmrg logical_el = isl_extent2d(128 / bs, 32); 24701e04c3fSmrg phys_B = isl_extent2d(128, 32); 24801e04c3fSmrg break; 24901e04c3fSmrg 25001e04c3fSmrg case ISL_TILING_W: 25101e04c3fSmrg assert(bs == 1); 25201e04c3fSmrg logical_el = isl_extent2d(64, 64); 25301e04c3fSmrg /* From the Broadwell PRM Vol 2d, RENDER_SURFACE_STATE::SurfacePitch: 25401e04c3fSmrg * 25501e04c3fSmrg * "If the surface is a stencil buffer (and thus has Tile Mode set 25601e04c3fSmrg * to TILEMODE_WMAJOR), the pitch must be set to 2x the value 25701e04c3fSmrg * computed based on width, as the stencil buffer is stored with two 25801e04c3fSmrg * rows interleaved." 25901e04c3fSmrg * 26001e04c3fSmrg * This, together with the fact that stencil buffers are referred to as 26101e04c3fSmrg * being Y-tiled in the PRMs for older hardware implies that the 26201e04c3fSmrg * physical size of a W-tile is actually the same as for a Y-tile. 26301e04c3fSmrg */ 26401e04c3fSmrg phys_B = isl_extent2d(128, 32); 26501e04c3fSmrg break; 26601e04c3fSmrg 26701e04c3fSmrg case ISL_TILING_Yf: 26801e04c3fSmrg case ISL_TILING_Ys: { 26901e04c3fSmrg bool is_Ys = tiling == ISL_TILING_Ys; 27001e04c3fSmrg 27101e04c3fSmrg assert(bs > 0); 27201e04c3fSmrg unsigned width = 1 << (6 + (ffs(bs) / 2) + (2 * is_Ys)); 27301e04c3fSmrg unsigned height = 1 << (6 - (ffs(bs) / 2) + (2 * is_Ys)); 27401e04c3fSmrg 27501e04c3fSmrg logical_el = isl_extent2d(width / bs, height); 27601e04c3fSmrg phys_B = isl_extent2d(width, height); 27701e04c3fSmrg break; 27801e04c3fSmrg } 27901e04c3fSmrg 28001e04c3fSmrg case ISL_TILING_HIZ: 28101e04c3fSmrg /* HiZ buffers are required to have ISL_FORMAT_HIZ which is an 8x4 28201e04c3fSmrg * 128bpb format. The tiling has the same physical dimensions as 28301e04c3fSmrg * Y-tiling but actually has two HiZ columns per Y-tiled column. 28401e04c3fSmrg */ 28501e04c3fSmrg assert(bs == 16); 28601e04c3fSmrg logical_el = isl_extent2d(16, 16); 28701e04c3fSmrg phys_B = isl_extent2d(128, 32); 28801e04c3fSmrg break; 28901e04c3fSmrg 29001e04c3fSmrg case ISL_TILING_CCS: 29101e04c3fSmrg /* CCS surfaces are required to have one of the GENX_CCS_* formats which 29201e04c3fSmrg * have a block size of 1 or 2 bits per block and each CCS element 29301e04c3fSmrg * corresponds to one cache-line pair in the main surface. From the Sky 29401e04c3fSmrg * Lake PRM Vol. 12 in the section on planes: 29501e04c3fSmrg * 29601e04c3fSmrg * "The Color Control Surface (CCS) contains the compression status 29701e04c3fSmrg * of the cache-line pairs. The compression state of the cache-line 29801e04c3fSmrg * pair is specified by 2 bits in the CCS. Each CCS cache-line 29901e04c3fSmrg * represents an area on the main surface of 16x16 sets of 128 byte 30001e04c3fSmrg * Y-tiled cache-line-pairs. CCS is always Y tiled." 30101e04c3fSmrg * 30201e04c3fSmrg * The CCS being Y-tiled implies that it's an 8x8 grid of cache-lines. 30301e04c3fSmrg * Since each cache line corresponds to a 16x16 set of cache-line pairs, 30401e04c3fSmrg * that yields total tile area of 128x128 cache-line pairs or CCS 30501e04c3fSmrg * elements. On older hardware, each CCS element is 1 bit and the tile 30601e04c3fSmrg * is 128x256 elements. 30701e04c3fSmrg */ 30801e04c3fSmrg assert(format_bpb == 1 || format_bpb == 2); 30901e04c3fSmrg logical_el = isl_extent2d(128, 256 / format_bpb); 31001e04c3fSmrg phys_B = isl_extent2d(128, 32); 31101e04c3fSmrg break; 31201e04c3fSmrg 31301e04c3fSmrg default: 31401e04c3fSmrg unreachable("not reached"); 31501e04c3fSmrg } /* end switch */ 31601e04c3fSmrg 31701e04c3fSmrg *tile_info = (struct isl_tile_info) { 31801e04c3fSmrg .tiling = tiling, 31901e04c3fSmrg .format_bpb = format_bpb, 32001e04c3fSmrg .logical_extent_el = logical_el, 32101e04c3fSmrg .phys_extent_B = phys_B, 32201e04c3fSmrg }; 32301e04c3fSmrg} 32401e04c3fSmrg 32501e04c3fSmrgbool 32601e04c3fSmrgisl_color_value_is_zero(union isl_color_value value, 32701e04c3fSmrg enum isl_format format) 32801e04c3fSmrg{ 32901e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(format); 33001e04c3fSmrg 33101e04c3fSmrg#define RETURN_FALSE_IF_NOT_0(c, i) \ 33201e04c3fSmrg if (fmtl->channels.c.bits && value.u32[i] != 0) \ 33301e04c3fSmrg return false 33401e04c3fSmrg 33501e04c3fSmrg RETURN_FALSE_IF_NOT_0(r, 0); 33601e04c3fSmrg RETURN_FALSE_IF_NOT_0(g, 1); 33701e04c3fSmrg RETURN_FALSE_IF_NOT_0(b, 2); 33801e04c3fSmrg RETURN_FALSE_IF_NOT_0(a, 3); 33901e04c3fSmrg 34001e04c3fSmrg#undef RETURN_FALSE_IF_NOT_0 34101e04c3fSmrg 34201e04c3fSmrg return true; 34301e04c3fSmrg} 34401e04c3fSmrg 34501e04c3fSmrgbool 34601e04c3fSmrgisl_color_value_is_zero_one(union isl_color_value value, 34701e04c3fSmrg enum isl_format format) 34801e04c3fSmrg{ 34901e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(format); 35001e04c3fSmrg 35101e04c3fSmrg#define RETURN_FALSE_IF_NOT_0_1(c, i, field) \ 35201e04c3fSmrg if (fmtl->channels.c.bits && value.field[i] != 0 && value.field[i] != 1) \ 35301e04c3fSmrg return false 35401e04c3fSmrg 35501e04c3fSmrg if (isl_format_has_int_channel(format)) { 35601e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(r, 0, u32); 35701e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(g, 1, u32); 35801e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(b, 2, u32); 35901e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(a, 3, u32); 36001e04c3fSmrg } else { 36101e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(r, 0, f32); 36201e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(g, 1, f32); 36301e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(b, 2, f32); 36401e04c3fSmrg RETURN_FALSE_IF_NOT_0_1(a, 3, f32); 36501e04c3fSmrg } 36601e04c3fSmrg 36701e04c3fSmrg#undef RETURN_FALSE_IF_NOT_0_1 36801e04c3fSmrg 36901e04c3fSmrg return true; 37001e04c3fSmrg} 37101e04c3fSmrg 37201e04c3fSmrg/** 37301e04c3fSmrg * @param[out] tiling is set only on success 37401e04c3fSmrg */ 37501e04c3fSmrgstatic bool 37601e04c3fSmrgisl_surf_choose_tiling(const struct isl_device *dev, 37701e04c3fSmrg const struct isl_surf_init_info *restrict info, 37801e04c3fSmrg enum isl_tiling *tiling) 37901e04c3fSmrg{ 38001e04c3fSmrg isl_tiling_flags_t tiling_flags = info->tiling_flags; 38101e04c3fSmrg 38201e04c3fSmrg /* HiZ surfaces always use the HiZ tiling */ 38301e04c3fSmrg if (info->usage & ISL_SURF_USAGE_HIZ_BIT) { 38401e04c3fSmrg assert(info->format == ISL_FORMAT_HIZ); 38501e04c3fSmrg assert(tiling_flags == ISL_TILING_HIZ_BIT); 38601e04c3fSmrg *tiling = ISL_TILING_HIZ; 38701e04c3fSmrg return true; 38801e04c3fSmrg } 38901e04c3fSmrg 39001e04c3fSmrg /* CCS surfaces always use the CCS tiling */ 39101e04c3fSmrg if (info->usage & ISL_SURF_USAGE_CCS_BIT) { 39201e04c3fSmrg assert(isl_format_get_layout(info->format)->txc == ISL_TXC_CCS); 39301e04c3fSmrg assert(tiling_flags == ISL_TILING_CCS_BIT); 39401e04c3fSmrg *tiling = ISL_TILING_CCS; 39501e04c3fSmrg return true; 39601e04c3fSmrg } 39701e04c3fSmrg 39801e04c3fSmrg if (ISL_DEV_GEN(dev) >= 6) { 39901e04c3fSmrg isl_gen6_filter_tiling(dev, info, &tiling_flags); 40001e04c3fSmrg } else { 40101e04c3fSmrg isl_gen4_filter_tiling(dev, info, &tiling_flags); 40201e04c3fSmrg } 40301e04c3fSmrg 40401e04c3fSmrg #define CHOOSE(__tiling) \ 40501e04c3fSmrg do { \ 40601e04c3fSmrg if (tiling_flags & (1u << (__tiling))) { \ 40701e04c3fSmrg *tiling = (__tiling); \ 40801e04c3fSmrg return true; \ 40901e04c3fSmrg } \ 41001e04c3fSmrg } while (0) 41101e04c3fSmrg 41201e04c3fSmrg /* Of the tiling modes remaining, choose the one that offers the best 41301e04c3fSmrg * performance. 41401e04c3fSmrg */ 41501e04c3fSmrg 41601e04c3fSmrg if (info->dim == ISL_SURF_DIM_1D) { 41701e04c3fSmrg /* Prefer linear for 1D surfaces because they do not benefit from 41801e04c3fSmrg * tiling. To the contrary, tiling leads to wasted memory and poor 41901e04c3fSmrg * memory locality due to the swizzling and alignment restrictions 42001e04c3fSmrg * required in tiled surfaces. 42101e04c3fSmrg */ 42201e04c3fSmrg CHOOSE(ISL_TILING_LINEAR); 42301e04c3fSmrg } 42401e04c3fSmrg 42501e04c3fSmrg CHOOSE(ISL_TILING_Ys); 42601e04c3fSmrg CHOOSE(ISL_TILING_Yf); 42701e04c3fSmrg CHOOSE(ISL_TILING_Y0); 42801e04c3fSmrg CHOOSE(ISL_TILING_X); 42901e04c3fSmrg CHOOSE(ISL_TILING_W); 43001e04c3fSmrg CHOOSE(ISL_TILING_LINEAR); 43101e04c3fSmrg 43201e04c3fSmrg #undef CHOOSE 43301e04c3fSmrg 43401e04c3fSmrg /* No tiling mode accomodates the inputs. */ 43501e04c3fSmrg return false; 43601e04c3fSmrg} 43701e04c3fSmrg 43801e04c3fSmrgstatic bool 43901e04c3fSmrgisl_choose_msaa_layout(const struct isl_device *dev, 44001e04c3fSmrg const struct isl_surf_init_info *info, 44101e04c3fSmrg enum isl_tiling tiling, 44201e04c3fSmrg enum isl_msaa_layout *msaa_layout) 44301e04c3fSmrg{ 44401e04c3fSmrg if (ISL_DEV_GEN(dev) >= 8) { 44501e04c3fSmrg return isl_gen8_choose_msaa_layout(dev, info, tiling, msaa_layout); 44601e04c3fSmrg } else if (ISL_DEV_GEN(dev) >= 7) { 44701e04c3fSmrg return isl_gen7_choose_msaa_layout(dev, info, tiling, msaa_layout); 44801e04c3fSmrg } else if (ISL_DEV_GEN(dev) >= 6) { 44901e04c3fSmrg return isl_gen6_choose_msaa_layout(dev, info, tiling, msaa_layout); 45001e04c3fSmrg } else { 45101e04c3fSmrg return isl_gen4_choose_msaa_layout(dev, info, tiling, msaa_layout); 45201e04c3fSmrg } 45301e04c3fSmrg} 45401e04c3fSmrg 45501e04c3fSmrgstruct isl_extent2d 45601e04c3fSmrgisl_get_interleaved_msaa_px_size_sa(uint32_t samples) 45701e04c3fSmrg{ 45801e04c3fSmrg assert(isl_is_pow2(samples)); 45901e04c3fSmrg 46001e04c3fSmrg /* From the Broadwell PRM >> Volume 5: Memory Views >> Computing Mip Level 46101e04c3fSmrg * Sizes (p133): 46201e04c3fSmrg * 46301e04c3fSmrg * If the surface is multisampled and it is a depth or stencil surface 46401e04c3fSmrg * or Multisampled Surface StorageFormat in SURFACE_STATE is 46501e04c3fSmrg * MSFMT_DEPTH_STENCIL, W_L and H_L must be adjusted as follows before 46601e04c3fSmrg * proceeding: [...] 46701e04c3fSmrg */ 46801e04c3fSmrg return (struct isl_extent2d) { 46901e04c3fSmrg .width = 1 << ((ffs(samples) - 0) / 2), 47001e04c3fSmrg .height = 1 << ((ffs(samples) - 1) / 2), 47101e04c3fSmrg }; 47201e04c3fSmrg} 47301e04c3fSmrg 47401e04c3fSmrgstatic void 47501e04c3fSmrgisl_msaa_interleaved_scale_px_to_sa(uint32_t samples, 47601e04c3fSmrg uint32_t *width, uint32_t *height) 47701e04c3fSmrg{ 47801e04c3fSmrg const struct isl_extent2d px_size_sa = 47901e04c3fSmrg isl_get_interleaved_msaa_px_size_sa(samples); 48001e04c3fSmrg 48101e04c3fSmrg if (width) 48201e04c3fSmrg *width = isl_align(*width, 2) * px_size_sa.width; 48301e04c3fSmrg if (height) 48401e04c3fSmrg *height = isl_align(*height, 2) * px_size_sa.height; 48501e04c3fSmrg} 48601e04c3fSmrg 48701e04c3fSmrgstatic enum isl_array_pitch_span 48801e04c3fSmrgisl_choose_array_pitch_span(const struct isl_device *dev, 48901e04c3fSmrg const struct isl_surf_init_info *restrict info, 49001e04c3fSmrg enum isl_dim_layout dim_layout, 49101e04c3fSmrg const struct isl_extent4d *phys_level0_sa) 49201e04c3fSmrg{ 49301e04c3fSmrg switch (dim_layout) { 49401e04c3fSmrg case ISL_DIM_LAYOUT_GEN9_1D: 49501e04c3fSmrg case ISL_DIM_LAYOUT_GEN4_2D: 49601e04c3fSmrg if (ISL_DEV_GEN(dev) >= 8) { 49701e04c3fSmrg /* QPitch becomes programmable in Broadwell. So choose the 49801e04c3fSmrg * most compact QPitch possible in order to conserve memory. 49901e04c3fSmrg * 50001e04c3fSmrg * From the Broadwell PRM >> Volume 2d: Command Reference: Structures 50101e04c3fSmrg * >> RENDER_SURFACE_STATE Surface QPitch (p325): 50201e04c3fSmrg * 50301e04c3fSmrg * - Software must ensure that this field is set to a value 50401e04c3fSmrg * sufficiently large such that the array slices in the surface 50501e04c3fSmrg * do not overlap. Refer to the Memory Data Formats section for 50601e04c3fSmrg * information on how surfaces are stored in memory. 50701e04c3fSmrg * 50801e04c3fSmrg * - This field specifies the distance in rows between array 50901e04c3fSmrg * slices. It is used only in the following cases: 51001e04c3fSmrg * 51101e04c3fSmrg * - Surface Array is enabled OR 51201e04c3fSmrg * - Number of Mulitsamples is not NUMSAMPLES_1 and 51301e04c3fSmrg * Multisampled Surface Storage Format set to MSFMT_MSS OR 51401e04c3fSmrg * - Surface Type is SURFTYPE_CUBE 51501e04c3fSmrg */ 51601e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 51701e04c3fSmrg } else if (ISL_DEV_GEN(dev) >= 7) { 51801e04c3fSmrg /* Note that Ivybridge introduces 51901e04c3fSmrg * RENDER_SURFACE_STATE.SurfaceArraySpacing, which provides the 52001e04c3fSmrg * driver more control over the QPitch. 52101e04c3fSmrg */ 52201e04c3fSmrg 52301e04c3fSmrg if (phys_level0_sa->array_len == 1) { 52401e04c3fSmrg /* The hardware will never use the QPitch. So choose the most 52501e04c3fSmrg * compact QPitch possible in order to conserve memory. 52601e04c3fSmrg */ 52701e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 52801e04c3fSmrg } 52901e04c3fSmrg 53001e04c3fSmrg if (isl_surf_usage_is_depth_or_stencil(info->usage) || 53101e04c3fSmrg (info->usage & ISL_SURF_USAGE_HIZ_BIT)) { 53201e04c3fSmrg /* From the Ivybridge PRM >> Volume 1 Part 1: Graphics Core >> 53301e04c3fSmrg * Section 6.18.4.7: Surface Arrays (p112): 53401e04c3fSmrg * 53501e04c3fSmrg * If Surface Array Spacing is set to ARYSPC_FULL (note that 53601e04c3fSmrg * the depth buffer and stencil buffer have an implied value of 53701e04c3fSmrg * ARYSPC_FULL): 53801e04c3fSmrg */ 53901e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_FULL; 54001e04c3fSmrg } 54101e04c3fSmrg 54201e04c3fSmrg if (info->levels == 1) { 54301e04c3fSmrg /* We are able to set RENDER_SURFACE_STATE.SurfaceArraySpacing 54401e04c3fSmrg * to ARYSPC_LOD0. 54501e04c3fSmrg */ 54601e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 54701e04c3fSmrg } 54801e04c3fSmrg 54901e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_FULL; 55001e04c3fSmrg } else if ((ISL_DEV_GEN(dev) == 5 || ISL_DEV_GEN(dev) == 6) && 55101e04c3fSmrg ISL_DEV_USE_SEPARATE_STENCIL(dev) && 55201e04c3fSmrg isl_surf_usage_is_stencil(info->usage)) { 55301e04c3fSmrg /* [ILK-SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1: 55401e04c3fSmrg * Graphics Core >> Section 7.18.3.7: Surface Arrays: 55501e04c3fSmrg * 55601e04c3fSmrg * The separate stencil buffer does not support mip mapping, thus 55701e04c3fSmrg * the storage for LODs other than LOD 0 is not needed. 55801e04c3fSmrg */ 55901e04c3fSmrg assert(info->levels == 1); 56001e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 56101e04c3fSmrg } else { 56201e04c3fSmrg if ((ISL_DEV_GEN(dev) == 5 || ISL_DEV_GEN(dev) == 6) && 56301e04c3fSmrg ISL_DEV_USE_SEPARATE_STENCIL(dev) && 56401e04c3fSmrg isl_surf_usage_is_stencil(info->usage)) { 56501e04c3fSmrg /* [ILK-SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1: 56601e04c3fSmrg * Graphics Core >> Section 7.18.3.7: Surface Arrays: 56701e04c3fSmrg * 56801e04c3fSmrg * The separate stencil buffer does not support mip mapping, 56901e04c3fSmrg * thus the storage for LODs other than LOD 0 is not needed. 57001e04c3fSmrg */ 57101e04c3fSmrg assert(info->levels == 1); 57201e04c3fSmrg assert(phys_level0_sa->array_len == 1); 57301e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 57401e04c3fSmrg } 57501e04c3fSmrg 57601e04c3fSmrg if (phys_level0_sa->array_len == 1) { 57701e04c3fSmrg /* The hardware will never use the QPitch. So choose the most 57801e04c3fSmrg * compact QPitch possible in order to conserve memory. 57901e04c3fSmrg */ 58001e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 58101e04c3fSmrg } 58201e04c3fSmrg 58301e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_FULL; 58401e04c3fSmrg } 58501e04c3fSmrg 58601e04c3fSmrg case ISL_DIM_LAYOUT_GEN4_3D: 58701e04c3fSmrg /* The hardware will never use the QPitch. So choose the most 58801e04c3fSmrg * compact QPitch possible in order to conserve memory. 58901e04c3fSmrg */ 59001e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 59101e04c3fSmrg 59201e04c3fSmrg case ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ: 59301e04c3fSmrg /* Each array image in the gen6 stencil of HiZ surface is compact in the 59401e04c3fSmrg * sense that every LOD is a compact array of the same size as LOD0. 59501e04c3fSmrg */ 59601e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_COMPACT; 59701e04c3fSmrg } 59801e04c3fSmrg 59901e04c3fSmrg unreachable("bad isl_dim_layout"); 60001e04c3fSmrg return ISL_ARRAY_PITCH_SPAN_FULL; 60101e04c3fSmrg} 60201e04c3fSmrg 60301e04c3fSmrgstatic void 60401e04c3fSmrgisl_choose_image_alignment_el(const struct isl_device *dev, 60501e04c3fSmrg const struct isl_surf_init_info *restrict info, 60601e04c3fSmrg enum isl_tiling tiling, 60701e04c3fSmrg enum isl_dim_layout dim_layout, 60801e04c3fSmrg enum isl_msaa_layout msaa_layout, 60901e04c3fSmrg struct isl_extent3d *image_align_el) 61001e04c3fSmrg{ 61101e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 61201e04c3fSmrg if (fmtl->txc == ISL_TXC_MCS) { 61301e04c3fSmrg assert(tiling == ISL_TILING_Y0); 61401e04c3fSmrg 61501e04c3fSmrg /* 61601e04c3fSmrg * IvyBrigde PRM Vol 2, Part 1, "11.7 MCS Buffer for Render Target(s)": 61701e04c3fSmrg * 61801e04c3fSmrg * Height, width, and layout of MCS buffer in this case must match with 61901e04c3fSmrg * Render Target height, width, and layout. MCS buffer is tiledY. 62001e04c3fSmrg * 62101e04c3fSmrg * To avoid wasting memory, choose the smallest alignment possible: 62201e04c3fSmrg * HALIGN_4 and VALIGN_4. 62301e04c3fSmrg */ 62401e04c3fSmrg *image_align_el = isl_extent3d(4, 4, 1); 62501e04c3fSmrg return; 62601e04c3fSmrg } else if (info->format == ISL_FORMAT_HIZ) { 62701e04c3fSmrg assert(ISL_DEV_GEN(dev) >= 6); 62801e04c3fSmrg if (ISL_DEV_GEN(dev) == 6) { 62901e04c3fSmrg /* HiZ surfaces on Sandy Bridge are packed tightly. */ 63001e04c3fSmrg *image_align_el = isl_extent3d(1, 1, 1); 63101e04c3fSmrg } else { 63201e04c3fSmrg /* On gen7+, HiZ surfaces are always aligned to 16x8 pixels in the 63301e04c3fSmrg * primary surface which works out to 2x2 HiZ elments. 63401e04c3fSmrg */ 63501e04c3fSmrg *image_align_el = isl_extent3d(2, 2, 1); 63601e04c3fSmrg } 63701e04c3fSmrg return; 63801e04c3fSmrg } 63901e04c3fSmrg 64001e04c3fSmrg if (ISL_DEV_GEN(dev) >= 9) { 64101e04c3fSmrg isl_gen9_choose_image_alignment_el(dev, info, tiling, dim_layout, 64201e04c3fSmrg msaa_layout, image_align_el); 64301e04c3fSmrg } else if (ISL_DEV_GEN(dev) >= 8) { 64401e04c3fSmrg isl_gen8_choose_image_alignment_el(dev, info, tiling, dim_layout, 64501e04c3fSmrg msaa_layout, image_align_el); 64601e04c3fSmrg } else if (ISL_DEV_GEN(dev) >= 7) { 64701e04c3fSmrg isl_gen7_choose_image_alignment_el(dev, info, tiling, dim_layout, 64801e04c3fSmrg msaa_layout, image_align_el); 64901e04c3fSmrg } else if (ISL_DEV_GEN(dev) >= 6) { 65001e04c3fSmrg isl_gen6_choose_image_alignment_el(dev, info, tiling, dim_layout, 65101e04c3fSmrg msaa_layout, image_align_el); 65201e04c3fSmrg } else { 65301e04c3fSmrg isl_gen4_choose_image_alignment_el(dev, info, tiling, dim_layout, 65401e04c3fSmrg msaa_layout, image_align_el); 65501e04c3fSmrg } 65601e04c3fSmrg} 65701e04c3fSmrg 65801e04c3fSmrgstatic enum isl_dim_layout 65901e04c3fSmrgisl_surf_choose_dim_layout(const struct isl_device *dev, 66001e04c3fSmrg enum isl_surf_dim logical_dim, 66101e04c3fSmrg enum isl_tiling tiling, 66201e04c3fSmrg isl_surf_usage_flags_t usage) 66301e04c3fSmrg{ 66401e04c3fSmrg /* Sandy bridge needs a special layout for HiZ and stencil. */ 66501e04c3fSmrg if (ISL_DEV_GEN(dev) == 6 && 66601e04c3fSmrg (tiling == ISL_TILING_W || tiling == ISL_TILING_HIZ)) 66701e04c3fSmrg return ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ; 66801e04c3fSmrg 66901e04c3fSmrg if (ISL_DEV_GEN(dev) >= 9) { 67001e04c3fSmrg switch (logical_dim) { 67101e04c3fSmrg case ISL_SURF_DIM_1D: 67201e04c3fSmrg /* From the Sky Lake PRM Vol. 5, "1D Surfaces": 67301e04c3fSmrg * 67401e04c3fSmrg * One-dimensional surfaces use a tiling mode of linear. 67501e04c3fSmrg * Technically, they are not tiled resources, but the Tiled 67601e04c3fSmrg * Resource Mode field in RENDER_SURFACE_STATE is still used to 67701e04c3fSmrg * indicate the alignment requirements for this linear surface 67801e04c3fSmrg * (See 1D Alignment requirements for how 4K and 64KB Tiled 67901e04c3fSmrg * Resource Modes impact alignment). Alternatively, a 1D surface 68001e04c3fSmrg * can be defined as a 2D tiled surface (e.g. TileY or TileX) with 68101e04c3fSmrg * a height of 0. 68201e04c3fSmrg * 68301e04c3fSmrg * In other words, ISL_DIM_LAYOUT_GEN9_1D is only used for linear 68401e04c3fSmrg * surfaces and, for tiled surfaces, ISL_DIM_LAYOUT_GEN4_2D is used. 68501e04c3fSmrg */ 68601e04c3fSmrg if (tiling == ISL_TILING_LINEAR) 68701e04c3fSmrg return ISL_DIM_LAYOUT_GEN9_1D; 68801e04c3fSmrg else 68901e04c3fSmrg return ISL_DIM_LAYOUT_GEN4_2D; 69001e04c3fSmrg case ISL_SURF_DIM_2D: 69101e04c3fSmrg case ISL_SURF_DIM_3D: 69201e04c3fSmrg return ISL_DIM_LAYOUT_GEN4_2D; 69301e04c3fSmrg } 69401e04c3fSmrg } else { 69501e04c3fSmrg switch (logical_dim) { 69601e04c3fSmrg case ISL_SURF_DIM_1D: 69701e04c3fSmrg case ISL_SURF_DIM_2D: 69801e04c3fSmrg /* From the G45 PRM Vol. 1a, "6.17.4.1 Hardware Cube Map Layout": 69901e04c3fSmrg * 70001e04c3fSmrg * The cube face textures are stored in the same way as 3D surfaces 70101e04c3fSmrg * are stored (see section 6.17.5 for details). For cube surfaces, 70201e04c3fSmrg * however, the depth is equal to the number of faces (always 6) and 70301e04c3fSmrg * is not reduced for each MIP. 70401e04c3fSmrg */ 70501e04c3fSmrg if (ISL_DEV_GEN(dev) == 4 && (usage & ISL_SURF_USAGE_CUBE_BIT)) 70601e04c3fSmrg return ISL_DIM_LAYOUT_GEN4_3D; 70701e04c3fSmrg 70801e04c3fSmrg return ISL_DIM_LAYOUT_GEN4_2D; 70901e04c3fSmrg case ISL_SURF_DIM_3D: 71001e04c3fSmrg return ISL_DIM_LAYOUT_GEN4_3D; 71101e04c3fSmrg } 71201e04c3fSmrg } 71301e04c3fSmrg 71401e04c3fSmrg unreachable("bad isl_surf_dim"); 71501e04c3fSmrg return ISL_DIM_LAYOUT_GEN4_2D; 71601e04c3fSmrg} 71701e04c3fSmrg 71801e04c3fSmrg/** 71901e04c3fSmrg * Calculate the physical extent of the surface's first level, in units of 7209f464c52Smaya * surface samples. 72101e04c3fSmrg */ 72201e04c3fSmrgstatic void 72301e04c3fSmrgisl_calc_phys_level0_extent_sa(const struct isl_device *dev, 72401e04c3fSmrg const struct isl_surf_init_info *restrict info, 72501e04c3fSmrg enum isl_dim_layout dim_layout, 72601e04c3fSmrg enum isl_tiling tiling, 72701e04c3fSmrg enum isl_msaa_layout msaa_layout, 72801e04c3fSmrg struct isl_extent4d *phys_level0_sa) 72901e04c3fSmrg{ 73001e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 73101e04c3fSmrg 73201e04c3fSmrg if (isl_format_is_yuv(info->format)) 73301e04c3fSmrg isl_finishme("%s:%s: YUV format", __FILE__, __func__); 73401e04c3fSmrg 73501e04c3fSmrg switch (info->dim) { 73601e04c3fSmrg case ISL_SURF_DIM_1D: 73701e04c3fSmrg assert(info->height == 1); 73801e04c3fSmrg assert(info->depth == 1); 73901e04c3fSmrg assert(info->samples == 1); 74001e04c3fSmrg 74101e04c3fSmrg switch (dim_layout) { 74201e04c3fSmrg case ISL_DIM_LAYOUT_GEN4_3D: 74301e04c3fSmrg unreachable("bad isl_dim_layout"); 74401e04c3fSmrg 74501e04c3fSmrg case ISL_DIM_LAYOUT_GEN9_1D: 74601e04c3fSmrg case ISL_DIM_LAYOUT_GEN4_2D: 74701e04c3fSmrg case ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ: 74801e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 7499f464c52Smaya .w = info->width, 7509f464c52Smaya .h = 1, 75101e04c3fSmrg .d = 1, 75201e04c3fSmrg .a = info->array_len, 75301e04c3fSmrg }; 75401e04c3fSmrg break; 75501e04c3fSmrg } 75601e04c3fSmrg break; 75701e04c3fSmrg 75801e04c3fSmrg case ISL_SURF_DIM_2D: 75901e04c3fSmrg if (ISL_DEV_GEN(dev) == 4 && (info->usage & ISL_SURF_USAGE_CUBE_BIT)) 76001e04c3fSmrg assert(dim_layout == ISL_DIM_LAYOUT_GEN4_3D); 76101e04c3fSmrg else 76201e04c3fSmrg assert(dim_layout == ISL_DIM_LAYOUT_GEN4_2D || 76301e04c3fSmrg dim_layout == ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ); 76401e04c3fSmrg 76501e04c3fSmrg if (tiling == ISL_TILING_Ys && info->samples > 1) 76601e04c3fSmrg isl_finishme("%s:%s: multisample TileYs layout", __FILE__, __func__); 76701e04c3fSmrg 76801e04c3fSmrg switch (msaa_layout) { 76901e04c3fSmrg case ISL_MSAA_LAYOUT_NONE: 77001e04c3fSmrg assert(info->depth == 1); 77101e04c3fSmrg assert(info->samples == 1); 77201e04c3fSmrg 77301e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 7749f464c52Smaya .w = info->width, 7759f464c52Smaya .h = info->height, 77601e04c3fSmrg .d = 1, 77701e04c3fSmrg .a = info->array_len, 77801e04c3fSmrg }; 77901e04c3fSmrg break; 78001e04c3fSmrg 78101e04c3fSmrg case ISL_MSAA_LAYOUT_ARRAY: 78201e04c3fSmrg assert(info->depth == 1); 78301e04c3fSmrg assert(info->levels == 1); 78401e04c3fSmrg assert(isl_format_supports_multisampling(dev->info, info->format)); 78501e04c3fSmrg assert(fmtl->bw == 1 && fmtl->bh == 1); 78601e04c3fSmrg 78701e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 78801e04c3fSmrg .w = info->width, 78901e04c3fSmrg .h = info->height, 79001e04c3fSmrg .d = 1, 79101e04c3fSmrg .a = info->array_len * info->samples, 79201e04c3fSmrg }; 79301e04c3fSmrg break; 79401e04c3fSmrg 79501e04c3fSmrg case ISL_MSAA_LAYOUT_INTERLEAVED: 79601e04c3fSmrg assert(info->depth == 1); 79701e04c3fSmrg assert(info->levels == 1); 79801e04c3fSmrg assert(isl_format_supports_multisampling(dev->info, info->format)); 79901e04c3fSmrg 80001e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 80101e04c3fSmrg .w = info->width, 80201e04c3fSmrg .h = info->height, 80301e04c3fSmrg .d = 1, 80401e04c3fSmrg .a = info->array_len, 80501e04c3fSmrg }; 80601e04c3fSmrg 80701e04c3fSmrg isl_msaa_interleaved_scale_px_to_sa(info->samples, 80801e04c3fSmrg &phys_level0_sa->w, 80901e04c3fSmrg &phys_level0_sa->h); 81001e04c3fSmrg break; 81101e04c3fSmrg } 81201e04c3fSmrg break; 81301e04c3fSmrg 81401e04c3fSmrg case ISL_SURF_DIM_3D: 81501e04c3fSmrg assert(info->array_len == 1); 81601e04c3fSmrg assert(info->samples == 1); 81701e04c3fSmrg 81801e04c3fSmrg if (fmtl->bd > 1) { 81901e04c3fSmrg isl_finishme("%s:%s: compression block with depth > 1", 82001e04c3fSmrg __FILE__, __func__); 82101e04c3fSmrg } 82201e04c3fSmrg 82301e04c3fSmrg switch (dim_layout) { 82401e04c3fSmrg case ISL_DIM_LAYOUT_GEN9_1D: 82501e04c3fSmrg case ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ: 82601e04c3fSmrg unreachable("bad isl_dim_layout"); 82701e04c3fSmrg 82801e04c3fSmrg case ISL_DIM_LAYOUT_GEN4_2D: 82901e04c3fSmrg assert(ISL_DEV_GEN(dev) >= 9); 83001e04c3fSmrg 83101e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 8329f464c52Smaya .w = info->width, 8339f464c52Smaya .h = info->height, 83401e04c3fSmrg .d = 1, 83501e04c3fSmrg .a = info->depth, 83601e04c3fSmrg }; 83701e04c3fSmrg break; 83801e04c3fSmrg 83901e04c3fSmrg case ISL_DIM_LAYOUT_GEN4_3D: 84001e04c3fSmrg assert(ISL_DEV_GEN(dev) < 9); 84101e04c3fSmrg *phys_level0_sa = (struct isl_extent4d) { 8429f464c52Smaya .w = info->width, 8439f464c52Smaya .h = info->height, 84401e04c3fSmrg .d = info->depth, 84501e04c3fSmrg .a = 1, 84601e04c3fSmrg }; 84701e04c3fSmrg break; 84801e04c3fSmrg } 84901e04c3fSmrg break; 85001e04c3fSmrg } 85101e04c3fSmrg} 85201e04c3fSmrg 85301e04c3fSmrg/** 85401e04c3fSmrg * Calculate the pitch between physical array slices, in units of rows of 85501e04c3fSmrg * surface elements. 85601e04c3fSmrg */ 85701e04c3fSmrgstatic uint32_t 85801e04c3fSmrgisl_calc_array_pitch_el_rows_gen4_2d( 85901e04c3fSmrg const struct isl_device *dev, 86001e04c3fSmrg const struct isl_surf_init_info *restrict info, 86101e04c3fSmrg const struct isl_tile_info *tile_info, 86201e04c3fSmrg const struct isl_extent3d *image_align_sa, 86301e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 86401e04c3fSmrg enum isl_array_pitch_span array_pitch_span, 86501e04c3fSmrg const struct isl_extent2d *phys_slice0_sa) 86601e04c3fSmrg{ 86701e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 86801e04c3fSmrg uint32_t pitch_sa_rows = 0; 86901e04c3fSmrg 87001e04c3fSmrg switch (array_pitch_span) { 87101e04c3fSmrg case ISL_ARRAY_PITCH_SPAN_COMPACT: 87201e04c3fSmrg pitch_sa_rows = isl_align_npot(phys_slice0_sa->h, image_align_sa->h); 87301e04c3fSmrg break; 87401e04c3fSmrg case ISL_ARRAY_PITCH_SPAN_FULL: { 87501e04c3fSmrg /* The QPitch equation is found in the Broadwell PRM >> Volume 5: 87601e04c3fSmrg * Memory Views >> Common Surface Formats >> Surface Layout >> 2D 87701e04c3fSmrg * Surfaces >> Surface Arrays. 87801e04c3fSmrg */ 87901e04c3fSmrg uint32_t H0_sa = phys_level0_sa->h; 88001e04c3fSmrg uint32_t H1_sa = isl_minify(H0_sa, 1); 88101e04c3fSmrg 88201e04c3fSmrg uint32_t h0_sa = isl_align_npot(H0_sa, image_align_sa->h); 88301e04c3fSmrg uint32_t h1_sa = isl_align_npot(H1_sa, image_align_sa->h); 88401e04c3fSmrg 88501e04c3fSmrg uint32_t m; 88601e04c3fSmrg if (ISL_DEV_GEN(dev) >= 7) { 88701e04c3fSmrg /* The QPitch equation changed slightly in Ivybridge. */ 88801e04c3fSmrg m = 12; 88901e04c3fSmrg } else { 89001e04c3fSmrg m = 11; 89101e04c3fSmrg } 89201e04c3fSmrg 89301e04c3fSmrg pitch_sa_rows = h0_sa + h1_sa + (m * image_align_sa->h); 89401e04c3fSmrg 89501e04c3fSmrg if (ISL_DEV_GEN(dev) == 6 && info->samples > 1 && 89601e04c3fSmrg (info->height % 4 == 1)) { 89701e04c3fSmrg /* [SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1: 89801e04c3fSmrg * Graphics Core >> Section 7.18.3.7: Surface Arrays: 89901e04c3fSmrg * 90001e04c3fSmrg * [SNB] Errata: Sampler MSAA Qpitch will be 4 greater than 90101e04c3fSmrg * the value calculated in the equation above , for every 90201e04c3fSmrg * other odd Surface Height starting from 1 i.e. 1,5,9,13. 90301e04c3fSmrg * 90401e04c3fSmrg * XXX(chadv): Is the errata natural corollary of the physical 90501e04c3fSmrg * layout of interleaved samples? 90601e04c3fSmrg */ 90701e04c3fSmrg pitch_sa_rows += 4; 90801e04c3fSmrg } 90901e04c3fSmrg 91001e04c3fSmrg pitch_sa_rows = isl_align_npot(pitch_sa_rows, fmtl->bh); 91101e04c3fSmrg } /* end case */ 91201e04c3fSmrg break; 91301e04c3fSmrg } 91401e04c3fSmrg 91501e04c3fSmrg assert(pitch_sa_rows % fmtl->bh == 0); 91601e04c3fSmrg uint32_t pitch_el_rows = pitch_sa_rows / fmtl->bh; 91701e04c3fSmrg 91801e04c3fSmrg if (ISL_DEV_GEN(dev) >= 9 && fmtl->txc == ISL_TXC_CCS) { 91901e04c3fSmrg /* 92001e04c3fSmrg * From the Sky Lake PRM Vol 7, "MCS Buffer for Render Target(s)" (p. 632): 92101e04c3fSmrg * 92201e04c3fSmrg * "Mip-mapped and arrayed surfaces are supported with MCS buffer 92301e04c3fSmrg * layout with these alignments in the RT space: Horizontal 92401e04c3fSmrg * Alignment = 128 and Vertical Alignment = 64." 92501e04c3fSmrg * 92601e04c3fSmrg * From the Sky Lake PRM Vol. 2d, "RENDER_SURFACE_STATE" (p. 435): 92701e04c3fSmrg * 92801e04c3fSmrg * "For non-multisampled render target's CCS auxiliary surface, 92901e04c3fSmrg * QPitch must be computed with Horizontal Alignment = 128 and 93001e04c3fSmrg * Surface Vertical Alignment = 256. These alignments are only for 93101e04c3fSmrg * CCS buffer and not for associated render target." 93201e04c3fSmrg * 93301e04c3fSmrg * The first restriction is already handled by isl_choose_image_alignment_el 93401e04c3fSmrg * but the second restriction, which is an extension of the first, only 93501e04c3fSmrg * applies to qpitch and must be applied here. 93601e04c3fSmrg */ 93701e04c3fSmrg assert(fmtl->bh == 4); 93801e04c3fSmrg pitch_el_rows = isl_align(pitch_el_rows, 256 / 4); 93901e04c3fSmrg } 94001e04c3fSmrg 94101e04c3fSmrg if (ISL_DEV_GEN(dev) >= 9 && 94201e04c3fSmrg info->dim == ISL_SURF_DIM_3D && 94301e04c3fSmrg tile_info->tiling != ISL_TILING_LINEAR) { 94401e04c3fSmrg /* From the Skylake BSpec >> RENDER_SURFACE_STATE >> Surface QPitch: 94501e04c3fSmrg * 94601e04c3fSmrg * Tile Mode != Linear: This field must be set to an integer multiple 94701e04c3fSmrg * of the tile height 94801e04c3fSmrg */ 94901e04c3fSmrg pitch_el_rows = isl_align(pitch_el_rows, tile_info->logical_extent_el.height); 95001e04c3fSmrg } 95101e04c3fSmrg 95201e04c3fSmrg return pitch_el_rows; 95301e04c3fSmrg} 95401e04c3fSmrg 95501e04c3fSmrg/** 95601e04c3fSmrg * A variant of isl_calc_phys_slice0_extent_sa() specific to 95701e04c3fSmrg * ISL_DIM_LAYOUT_GEN4_2D. 95801e04c3fSmrg */ 95901e04c3fSmrgstatic void 96001e04c3fSmrgisl_calc_phys_slice0_extent_sa_gen4_2d( 96101e04c3fSmrg const struct isl_device *dev, 96201e04c3fSmrg const struct isl_surf_init_info *restrict info, 96301e04c3fSmrg enum isl_msaa_layout msaa_layout, 96401e04c3fSmrg const struct isl_extent3d *image_align_sa, 96501e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 96601e04c3fSmrg struct isl_extent2d *phys_slice0_sa) 96701e04c3fSmrg{ 96801e04c3fSmrg assert(phys_level0_sa->depth == 1); 96901e04c3fSmrg 97001e04c3fSmrg if (info->levels == 1) { 9719f464c52Smaya /* Do not pad the surface to the image alignment. 97201e04c3fSmrg * 97301e04c3fSmrg * For tiled surfaces, using a reduced alignment here avoids wasting CPU 97401e04c3fSmrg * cycles on the below mipmap layout caluclations. Reducing the 97501e04c3fSmrg * alignment here is safe because we later align the row pitch and array 97601e04c3fSmrg * pitch to the tile boundary. It is safe even for 97701e04c3fSmrg * ISL_MSAA_LAYOUT_INTERLEAVED, because phys_level0_sa is already scaled 97801e04c3fSmrg * to accomodate the interleaved samples. 97901e04c3fSmrg * 98001e04c3fSmrg * For linear surfaces, reducing the alignment here permits us to later 98101e04c3fSmrg * choose an arbitrary, non-aligned row pitch. If the surface backs 98201e04c3fSmrg * a VkBuffer, then an arbitrary pitch may be needed to accomodate 98301e04c3fSmrg * VkBufferImageCopy::bufferRowLength. 98401e04c3fSmrg */ 98501e04c3fSmrg *phys_slice0_sa = (struct isl_extent2d) { 9869f464c52Smaya .w = phys_level0_sa->w, 9879f464c52Smaya .h = phys_level0_sa->h, 98801e04c3fSmrg }; 98901e04c3fSmrg return; 99001e04c3fSmrg } 99101e04c3fSmrg 99201e04c3fSmrg uint32_t slice_top_w = 0; 99301e04c3fSmrg uint32_t slice_bottom_w = 0; 99401e04c3fSmrg uint32_t slice_left_h = 0; 99501e04c3fSmrg uint32_t slice_right_h = 0; 99601e04c3fSmrg 99701e04c3fSmrg uint32_t W0 = phys_level0_sa->w; 99801e04c3fSmrg uint32_t H0 = phys_level0_sa->h; 99901e04c3fSmrg 100001e04c3fSmrg for (uint32_t l = 0; l < info->levels; ++l) { 100101e04c3fSmrg uint32_t W = isl_minify(W0, l); 100201e04c3fSmrg uint32_t H = isl_minify(H0, l); 100301e04c3fSmrg 100401e04c3fSmrg uint32_t w = isl_align_npot(W, image_align_sa->w); 100501e04c3fSmrg uint32_t h = isl_align_npot(H, image_align_sa->h); 100601e04c3fSmrg 100701e04c3fSmrg if (l == 0) { 100801e04c3fSmrg slice_top_w = w; 100901e04c3fSmrg slice_left_h = h; 101001e04c3fSmrg slice_right_h = h; 101101e04c3fSmrg } else if (l == 1) { 101201e04c3fSmrg slice_bottom_w = w; 101301e04c3fSmrg slice_left_h += h; 101401e04c3fSmrg } else if (l == 2) { 101501e04c3fSmrg slice_bottom_w += w; 101601e04c3fSmrg slice_right_h += h; 101701e04c3fSmrg } else { 101801e04c3fSmrg slice_right_h += h; 101901e04c3fSmrg } 102001e04c3fSmrg } 102101e04c3fSmrg 102201e04c3fSmrg *phys_slice0_sa = (struct isl_extent2d) { 102301e04c3fSmrg .w = MAX(slice_top_w, slice_bottom_w), 102401e04c3fSmrg .h = MAX(slice_left_h, slice_right_h), 102501e04c3fSmrg }; 102601e04c3fSmrg} 102701e04c3fSmrg 102801e04c3fSmrgstatic void 102901e04c3fSmrgisl_calc_phys_total_extent_el_gen4_2d( 103001e04c3fSmrg const struct isl_device *dev, 103101e04c3fSmrg const struct isl_surf_init_info *restrict info, 103201e04c3fSmrg const struct isl_tile_info *tile_info, 103301e04c3fSmrg enum isl_msaa_layout msaa_layout, 103401e04c3fSmrg const struct isl_extent3d *image_align_sa, 103501e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 103601e04c3fSmrg enum isl_array_pitch_span array_pitch_span, 103701e04c3fSmrg uint32_t *array_pitch_el_rows, 103801e04c3fSmrg struct isl_extent2d *total_extent_el) 103901e04c3fSmrg{ 104001e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 104101e04c3fSmrg 104201e04c3fSmrg struct isl_extent2d phys_slice0_sa; 104301e04c3fSmrg isl_calc_phys_slice0_extent_sa_gen4_2d(dev, info, msaa_layout, 104401e04c3fSmrg image_align_sa, phys_level0_sa, 104501e04c3fSmrg &phys_slice0_sa); 104601e04c3fSmrg *array_pitch_el_rows = 104701e04c3fSmrg isl_calc_array_pitch_el_rows_gen4_2d(dev, info, tile_info, 104801e04c3fSmrg image_align_sa, phys_level0_sa, 104901e04c3fSmrg array_pitch_span, 105001e04c3fSmrg &phys_slice0_sa); 105101e04c3fSmrg *total_extent_el = (struct isl_extent2d) { 10529f464c52Smaya .w = isl_align_div_npot(phys_slice0_sa.w, fmtl->bw), 105301e04c3fSmrg .h = *array_pitch_el_rows * (phys_level0_sa->array_len - 1) + 10549f464c52Smaya isl_align_div_npot(phys_slice0_sa.h, fmtl->bh), 105501e04c3fSmrg }; 105601e04c3fSmrg} 105701e04c3fSmrg 105801e04c3fSmrg/** 105901e04c3fSmrg * A variant of isl_calc_phys_slice0_extent_sa() specific to 106001e04c3fSmrg * ISL_DIM_LAYOUT_GEN4_3D. 106101e04c3fSmrg */ 106201e04c3fSmrgstatic void 106301e04c3fSmrgisl_calc_phys_total_extent_el_gen4_3d( 106401e04c3fSmrg const struct isl_device *dev, 106501e04c3fSmrg const struct isl_surf_init_info *restrict info, 106601e04c3fSmrg const struct isl_extent3d *image_align_sa, 106701e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 106801e04c3fSmrg uint32_t *array_pitch_el_rows, 106901e04c3fSmrg struct isl_extent2d *phys_total_el) 107001e04c3fSmrg{ 107101e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 107201e04c3fSmrg 107301e04c3fSmrg assert(info->samples == 1); 107401e04c3fSmrg 107501e04c3fSmrg if (info->dim != ISL_SURF_DIM_3D) { 107601e04c3fSmrg /* From the G45 PRM Vol. 1a, "6.17.4.1 Hardware Cube Map Layout": 107701e04c3fSmrg * 107801e04c3fSmrg * The cube face textures are stored in the same way as 3D surfaces 107901e04c3fSmrg * are stored (see section 6.17.5 for details). For cube surfaces, 108001e04c3fSmrg * however, the depth is equal to the number of faces (always 6) and 108101e04c3fSmrg * is not reduced for each MIP. 108201e04c3fSmrg */ 108301e04c3fSmrg assert(ISL_DEV_GEN(dev) == 4); 108401e04c3fSmrg assert(info->usage & ISL_SURF_USAGE_CUBE_BIT); 108501e04c3fSmrg assert(phys_level0_sa->array_len == 6); 108601e04c3fSmrg } else { 108701e04c3fSmrg assert(phys_level0_sa->array_len == 1); 108801e04c3fSmrg } 108901e04c3fSmrg 109001e04c3fSmrg uint32_t total_w = 0; 109101e04c3fSmrg uint32_t total_h = 0; 109201e04c3fSmrg 109301e04c3fSmrg uint32_t W0 = phys_level0_sa->w; 109401e04c3fSmrg uint32_t H0 = phys_level0_sa->h; 109501e04c3fSmrg uint32_t D0 = phys_level0_sa->d; 109601e04c3fSmrg uint32_t A0 = phys_level0_sa->a; 109701e04c3fSmrg 109801e04c3fSmrg for (uint32_t l = 0; l < info->levels; ++l) { 109901e04c3fSmrg uint32_t level_w = isl_align_npot(isl_minify(W0, l), image_align_sa->w); 110001e04c3fSmrg uint32_t level_h = isl_align_npot(isl_minify(H0, l), image_align_sa->h); 110101e04c3fSmrg uint32_t level_d = info->dim == ISL_SURF_DIM_3D ? isl_minify(D0, l) : A0; 110201e04c3fSmrg 110301e04c3fSmrg uint32_t max_layers_horiz = MIN(level_d, 1u << l); 110401e04c3fSmrg uint32_t max_layers_vert = isl_align(level_d, 1u << l) / (1u << l); 110501e04c3fSmrg 110601e04c3fSmrg total_w = MAX(total_w, level_w * max_layers_horiz); 110701e04c3fSmrg total_h += level_h * max_layers_vert; 110801e04c3fSmrg } 110901e04c3fSmrg 111001e04c3fSmrg /* GEN4_3D layouts don't really have an array pitch since each LOD has a 111101e04c3fSmrg * different number of horizontal and vertical layers. We have to set it 111201e04c3fSmrg * to something, so at least make it true for LOD0. 111301e04c3fSmrg */ 111401e04c3fSmrg *array_pitch_el_rows = 111501e04c3fSmrg isl_align_npot(phys_level0_sa->h, image_align_sa->h) / fmtl->bw; 111601e04c3fSmrg *phys_total_el = (struct isl_extent2d) { 111701e04c3fSmrg .w = isl_assert_div(total_w, fmtl->bw), 111801e04c3fSmrg .h = isl_assert_div(total_h, fmtl->bh), 111901e04c3fSmrg }; 112001e04c3fSmrg} 112101e04c3fSmrg 112201e04c3fSmrg/** 112301e04c3fSmrg * A variant of isl_calc_phys_slice0_extent_sa() specific to 112401e04c3fSmrg * ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ. 112501e04c3fSmrg */ 112601e04c3fSmrgstatic void 112701e04c3fSmrgisl_calc_phys_total_extent_el_gen6_stencil_hiz( 112801e04c3fSmrg const struct isl_device *dev, 112901e04c3fSmrg const struct isl_surf_init_info *restrict info, 113001e04c3fSmrg const struct isl_tile_info *tile_info, 113101e04c3fSmrg const struct isl_extent3d *image_align_sa, 113201e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 113301e04c3fSmrg uint32_t *array_pitch_el_rows, 113401e04c3fSmrg struct isl_extent2d *phys_total_el) 113501e04c3fSmrg{ 113601e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 113701e04c3fSmrg 113801e04c3fSmrg const struct isl_extent2d tile_extent_sa = { 113901e04c3fSmrg .w = tile_info->logical_extent_el.w * fmtl->bw, 114001e04c3fSmrg .h = tile_info->logical_extent_el.h * fmtl->bh, 114101e04c3fSmrg }; 114201e04c3fSmrg /* Tile size is a multiple of image alignment */ 114301e04c3fSmrg assert(tile_extent_sa.w % image_align_sa->w == 0); 114401e04c3fSmrg assert(tile_extent_sa.h % image_align_sa->h == 0); 114501e04c3fSmrg 114601e04c3fSmrg const uint32_t W0 = phys_level0_sa->w; 114701e04c3fSmrg const uint32_t H0 = phys_level0_sa->h; 114801e04c3fSmrg 114901e04c3fSmrg /* Each image has the same height as LOD0 because the hardware thinks 115001e04c3fSmrg * everything is LOD0 115101e04c3fSmrg */ 115201e04c3fSmrg const uint32_t H = isl_align(H0, image_align_sa->h) * phys_level0_sa->a; 115301e04c3fSmrg 115401e04c3fSmrg uint32_t total_top_w = 0; 115501e04c3fSmrg uint32_t total_bottom_w = 0; 115601e04c3fSmrg uint32_t total_h = 0; 115701e04c3fSmrg 115801e04c3fSmrg for (uint32_t l = 0; l < info->levels; ++l) { 115901e04c3fSmrg const uint32_t W = isl_minify(W0, l); 116001e04c3fSmrg 116101e04c3fSmrg const uint32_t w = isl_align(W, tile_extent_sa.w); 116201e04c3fSmrg const uint32_t h = isl_align(H, tile_extent_sa.h); 116301e04c3fSmrg 116401e04c3fSmrg if (l == 0) { 116501e04c3fSmrg total_top_w = w; 116601e04c3fSmrg total_h = h; 116701e04c3fSmrg } else if (l == 1) { 116801e04c3fSmrg total_bottom_w = w; 116901e04c3fSmrg total_h += h; 117001e04c3fSmrg } else { 117101e04c3fSmrg total_bottom_w += w; 117201e04c3fSmrg } 117301e04c3fSmrg } 117401e04c3fSmrg 117501e04c3fSmrg *array_pitch_el_rows = 117601e04c3fSmrg isl_assert_div(isl_align(H0, image_align_sa->h), fmtl->bh); 117701e04c3fSmrg *phys_total_el = (struct isl_extent2d) { 117801e04c3fSmrg .w = isl_assert_div(MAX(total_top_w, total_bottom_w), fmtl->bw), 117901e04c3fSmrg .h = isl_assert_div(total_h, fmtl->bh), 118001e04c3fSmrg }; 118101e04c3fSmrg} 118201e04c3fSmrg 118301e04c3fSmrg/** 118401e04c3fSmrg * A variant of isl_calc_phys_slice0_extent_sa() specific to 118501e04c3fSmrg * ISL_DIM_LAYOUT_GEN9_1D. 118601e04c3fSmrg */ 118701e04c3fSmrgstatic void 118801e04c3fSmrgisl_calc_phys_total_extent_el_gen9_1d( 118901e04c3fSmrg const struct isl_device *dev, 119001e04c3fSmrg const struct isl_surf_init_info *restrict info, 119101e04c3fSmrg const struct isl_extent3d *image_align_sa, 119201e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 119301e04c3fSmrg uint32_t *array_pitch_el_rows, 119401e04c3fSmrg struct isl_extent2d *phys_total_el) 119501e04c3fSmrg{ 119601e04c3fSmrg MAYBE_UNUSED const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 119701e04c3fSmrg 11989f464c52Smaya assert(phys_level0_sa->height == 1); 119901e04c3fSmrg assert(phys_level0_sa->depth == 1); 120001e04c3fSmrg assert(info->samples == 1); 120101e04c3fSmrg assert(image_align_sa->w >= fmtl->bw); 120201e04c3fSmrg 120301e04c3fSmrg uint32_t slice_w = 0; 120401e04c3fSmrg const uint32_t W0 = phys_level0_sa->w; 120501e04c3fSmrg 120601e04c3fSmrg for (uint32_t l = 0; l < info->levels; ++l) { 120701e04c3fSmrg uint32_t W = isl_minify(W0, l); 120801e04c3fSmrg uint32_t w = isl_align_npot(W, image_align_sa->w); 120901e04c3fSmrg 121001e04c3fSmrg slice_w += w; 121101e04c3fSmrg } 121201e04c3fSmrg 121301e04c3fSmrg *array_pitch_el_rows = 1; 121401e04c3fSmrg *phys_total_el = (struct isl_extent2d) { 121501e04c3fSmrg .w = isl_assert_div(slice_w, fmtl->bw), 121601e04c3fSmrg .h = phys_level0_sa->array_len, 121701e04c3fSmrg }; 121801e04c3fSmrg} 121901e04c3fSmrg 122001e04c3fSmrg/** 122101e04c3fSmrg * Calculate the two-dimensional total physical extent of the surface, in 122201e04c3fSmrg * units of surface elements. 122301e04c3fSmrg */ 122401e04c3fSmrgstatic void 122501e04c3fSmrgisl_calc_phys_total_extent_el(const struct isl_device *dev, 122601e04c3fSmrg const struct isl_surf_init_info *restrict info, 122701e04c3fSmrg const struct isl_tile_info *tile_info, 122801e04c3fSmrg enum isl_dim_layout dim_layout, 122901e04c3fSmrg enum isl_msaa_layout msaa_layout, 123001e04c3fSmrg const struct isl_extent3d *image_align_sa, 123101e04c3fSmrg const struct isl_extent4d *phys_level0_sa, 123201e04c3fSmrg enum isl_array_pitch_span array_pitch_span, 123301e04c3fSmrg uint32_t *array_pitch_el_rows, 123401e04c3fSmrg struct isl_extent2d *total_extent_el) 123501e04c3fSmrg{ 123601e04c3fSmrg switch (dim_layout) { 123701e04c3fSmrg case ISL_DIM_LAYOUT_GEN9_1D: 123801e04c3fSmrg assert(array_pitch_span == ISL_ARRAY_PITCH_SPAN_COMPACT); 123901e04c3fSmrg isl_calc_phys_total_extent_el_gen9_1d(dev, info, 124001e04c3fSmrg image_align_sa, phys_level0_sa, 124101e04c3fSmrg array_pitch_el_rows, 124201e04c3fSmrg total_extent_el); 124301e04c3fSmrg return; 124401e04c3fSmrg case ISL_DIM_LAYOUT_GEN4_2D: 124501e04c3fSmrg isl_calc_phys_total_extent_el_gen4_2d(dev, info, tile_info, msaa_layout, 124601e04c3fSmrg image_align_sa, phys_level0_sa, 124701e04c3fSmrg array_pitch_span, 124801e04c3fSmrg array_pitch_el_rows, 124901e04c3fSmrg total_extent_el); 125001e04c3fSmrg return; 125101e04c3fSmrg case ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ: 125201e04c3fSmrg assert(array_pitch_span == ISL_ARRAY_PITCH_SPAN_COMPACT); 125301e04c3fSmrg isl_calc_phys_total_extent_el_gen6_stencil_hiz(dev, info, tile_info, 125401e04c3fSmrg image_align_sa, 125501e04c3fSmrg phys_level0_sa, 125601e04c3fSmrg array_pitch_el_rows, 125701e04c3fSmrg total_extent_el); 125801e04c3fSmrg return; 125901e04c3fSmrg case ISL_DIM_LAYOUT_GEN4_3D: 126001e04c3fSmrg assert(array_pitch_span == ISL_ARRAY_PITCH_SPAN_COMPACT); 126101e04c3fSmrg isl_calc_phys_total_extent_el_gen4_3d(dev, info, 126201e04c3fSmrg image_align_sa, phys_level0_sa, 126301e04c3fSmrg array_pitch_el_rows, 126401e04c3fSmrg total_extent_el); 126501e04c3fSmrg return; 126601e04c3fSmrg } 126701e04c3fSmrg} 126801e04c3fSmrg 126901e04c3fSmrgstatic uint32_t 127001e04c3fSmrgisl_calc_row_pitch_alignment(const struct isl_surf_init_info *surf_info, 127101e04c3fSmrg const struct isl_tile_info *tile_info) 127201e04c3fSmrg{ 127301e04c3fSmrg if (tile_info->tiling != ISL_TILING_LINEAR) 127401e04c3fSmrg return tile_info->phys_extent_B.width; 127501e04c3fSmrg 127601e04c3fSmrg /* From the Broadwel PRM >> Volume 2d: Command Reference: Structures >> 127701e04c3fSmrg * RENDER_SURFACE_STATE Surface Pitch (p349): 127801e04c3fSmrg * 127901e04c3fSmrg * - For linear render target surfaces and surfaces accessed with the 128001e04c3fSmrg * typed data port messages, the pitch must be a multiple of the 128101e04c3fSmrg * element size for non-YUV surface formats. Pitch must be 128201e04c3fSmrg * a multiple of 2 * element size for YUV surface formats. 128301e04c3fSmrg * 128401e04c3fSmrg * - [Requirements for SURFTYPE_BUFFER and SURFTYPE_STRBUF, which we 128501e04c3fSmrg * ignore because isl doesn't do buffers.] 128601e04c3fSmrg * 128701e04c3fSmrg * - For other linear surfaces, the pitch can be any multiple of 128801e04c3fSmrg * bytes. 128901e04c3fSmrg */ 129001e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf_info->format); 129101e04c3fSmrg const uint32_t bs = fmtl->bpb / 8; 129201e04c3fSmrg 129301e04c3fSmrg if (surf_info->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) { 129401e04c3fSmrg if (isl_format_is_yuv(surf_info->format)) { 129501e04c3fSmrg return 2 * bs; 129601e04c3fSmrg } else { 129701e04c3fSmrg return bs; 129801e04c3fSmrg } 129901e04c3fSmrg } 130001e04c3fSmrg 130101e04c3fSmrg return 1; 130201e04c3fSmrg} 130301e04c3fSmrg 130401e04c3fSmrgstatic uint32_t 130501e04c3fSmrgisl_calc_linear_min_row_pitch(const struct isl_device *dev, 130601e04c3fSmrg const struct isl_surf_init_info *info, 130701e04c3fSmrg const struct isl_extent2d *phys_total_el, 130801e04c3fSmrg uint32_t alignment_B) 130901e04c3fSmrg{ 131001e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 131101e04c3fSmrg const uint32_t bs = fmtl->bpb / 8; 131201e04c3fSmrg 131301e04c3fSmrg return isl_align_npot(bs * phys_total_el->w, alignment_B); 131401e04c3fSmrg} 131501e04c3fSmrg 131601e04c3fSmrgstatic uint32_t 131701e04c3fSmrgisl_calc_tiled_min_row_pitch(const struct isl_device *dev, 131801e04c3fSmrg const struct isl_surf_init_info *surf_info, 131901e04c3fSmrg const struct isl_tile_info *tile_info, 132001e04c3fSmrg const struct isl_extent2d *phys_total_el, 132101e04c3fSmrg uint32_t alignment_B) 132201e04c3fSmrg{ 132301e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf_info->format); 132401e04c3fSmrg 132501e04c3fSmrg assert(fmtl->bpb % tile_info->format_bpb == 0); 132601e04c3fSmrg 132701e04c3fSmrg const uint32_t tile_el_scale = fmtl->bpb / tile_info->format_bpb; 132801e04c3fSmrg const uint32_t total_w_tl = 132901e04c3fSmrg isl_align_div(phys_total_el->w * tile_el_scale, 133001e04c3fSmrg tile_info->logical_extent_el.width); 133101e04c3fSmrg 133201e04c3fSmrg assert(alignment_B == tile_info->phys_extent_B.width); 133301e04c3fSmrg return total_w_tl * tile_info->phys_extent_B.width; 133401e04c3fSmrg} 133501e04c3fSmrg 133601e04c3fSmrgstatic uint32_t 133701e04c3fSmrgisl_calc_min_row_pitch(const struct isl_device *dev, 133801e04c3fSmrg const struct isl_surf_init_info *surf_info, 133901e04c3fSmrg const struct isl_tile_info *tile_info, 134001e04c3fSmrg const struct isl_extent2d *phys_total_el, 134101e04c3fSmrg uint32_t alignment_B) 134201e04c3fSmrg{ 134301e04c3fSmrg if (tile_info->tiling == ISL_TILING_LINEAR) { 134401e04c3fSmrg return isl_calc_linear_min_row_pitch(dev, surf_info, phys_total_el, 134501e04c3fSmrg alignment_B); 134601e04c3fSmrg } else { 134701e04c3fSmrg return isl_calc_tiled_min_row_pitch(dev, surf_info, tile_info, 134801e04c3fSmrg phys_total_el, alignment_B); 134901e04c3fSmrg } 135001e04c3fSmrg} 135101e04c3fSmrg 135201e04c3fSmrg/** 135301e04c3fSmrg * Is `pitch` in the valid range for a hardware bitfield, if the bitfield's 135401e04c3fSmrg * size is `bits` bits? 135501e04c3fSmrg * 135601e04c3fSmrg * Hardware pitch fields are offset by 1. For example, if the size of 135701e04c3fSmrg * RENDER_SURFACE_STATE::SurfacePitch is B bits, then the range of valid 135801e04c3fSmrg * pitches is [1, 2^b] inclusive. If the surface pitch is N, then 135901e04c3fSmrg * RENDER_SURFACE_STATE::SurfacePitch must be set to N-1. 136001e04c3fSmrg */ 136101e04c3fSmrgstatic bool 136201e04c3fSmrgpitch_in_range(uint32_t n, uint32_t bits) 136301e04c3fSmrg{ 136401e04c3fSmrg assert(n != 0); 136501e04c3fSmrg return likely(bits != 0 && 1 <= n && n <= (1 << bits)); 136601e04c3fSmrg} 136701e04c3fSmrg 136801e04c3fSmrgstatic bool 136901e04c3fSmrgisl_calc_row_pitch(const struct isl_device *dev, 137001e04c3fSmrg const struct isl_surf_init_info *surf_info, 137101e04c3fSmrg const struct isl_tile_info *tile_info, 137201e04c3fSmrg enum isl_dim_layout dim_layout, 137301e04c3fSmrg const struct isl_extent2d *phys_total_el, 137401e04c3fSmrg uint32_t *out_row_pitch_B) 137501e04c3fSmrg{ 137601e04c3fSmrg uint32_t alignment_B = 137701e04c3fSmrg isl_calc_row_pitch_alignment(surf_info, tile_info); 137801e04c3fSmrg 137901e04c3fSmrg const uint32_t min_row_pitch_B = 138001e04c3fSmrg isl_calc_min_row_pitch(dev, surf_info, tile_info, phys_total_el, 138101e04c3fSmrg alignment_B); 138201e04c3fSmrg 138301e04c3fSmrg uint32_t row_pitch_B = min_row_pitch_B; 138401e04c3fSmrg 138501e04c3fSmrg if (surf_info->row_pitch_B != 0) { 138601e04c3fSmrg row_pitch_B = surf_info->row_pitch_B; 138701e04c3fSmrg 138801e04c3fSmrg if (row_pitch_B < min_row_pitch_B) 138901e04c3fSmrg return false; 139001e04c3fSmrg 139101e04c3fSmrg if (row_pitch_B % alignment_B != 0) 139201e04c3fSmrg return false; 139301e04c3fSmrg } 139401e04c3fSmrg 139501e04c3fSmrg const uint32_t row_pitch_tl = row_pitch_B / tile_info->phys_extent_B.width; 139601e04c3fSmrg 139701e04c3fSmrg if (row_pitch_B == 0) 139801e04c3fSmrg return false; 139901e04c3fSmrg 140001e04c3fSmrg if (dim_layout == ISL_DIM_LAYOUT_GEN9_1D) { 140101e04c3fSmrg /* SurfacePitch is ignored for this layout. */ 140201e04c3fSmrg goto done; 140301e04c3fSmrg } 140401e04c3fSmrg 140501e04c3fSmrg if ((surf_info->usage & (ISL_SURF_USAGE_RENDER_TARGET_BIT | 140601e04c3fSmrg ISL_SURF_USAGE_TEXTURE_BIT | 140701e04c3fSmrg ISL_SURF_USAGE_STORAGE_BIT)) && 140801e04c3fSmrg !pitch_in_range(row_pitch_B, RENDER_SURFACE_STATE_SurfacePitch_bits(dev->info))) 140901e04c3fSmrg return false; 141001e04c3fSmrg 141101e04c3fSmrg if ((surf_info->usage & (ISL_SURF_USAGE_CCS_BIT | 141201e04c3fSmrg ISL_SURF_USAGE_MCS_BIT)) && 141301e04c3fSmrg !pitch_in_range(row_pitch_tl, RENDER_SURFACE_STATE_AuxiliarySurfacePitch_bits(dev->info))) 141401e04c3fSmrg return false; 141501e04c3fSmrg 141601e04c3fSmrg if ((surf_info->usage & ISL_SURF_USAGE_DEPTH_BIT) && 141701e04c3fSmrg !pitch_in_range(row_pitch_B, _3DSTATE_DEPTH_BUFFER_SurfacePitch_bits(dev->info))) 141801e04c3fSmrg return false; 141901e04c3fSmrg 142001e04c3fSmrg if ((surf_info->usage & ISL_SURF_USAGE_HIZ_BIT) && 142101e04c3fSmrg !pitch_in_range(row_pitch_B, _3DSTATE_HIER_DEPTH_BUFFER_SurfacePitch_bits(dev->info))) 142201e04c3fSmrg return false; 142301e04c3fSmrg 142401e04c3fSmrg const uint32_t stencil_pitch_bits = dev->use_separate_stencil ? 142501e04c3fSmrg _3DSTATE_STENCIL_BUFFER_SurfacePitch_bits(dev->info) : 142601e04c3fSmrg _3DSTATE_DEPTH_BUFFER_SurfacePitch_bits(dev->info); 142701e04c3fSmrg 142801e04c3fSmrg if ((surf_info->usage & ISL_SURF_USAGE_STENCIL_BIT) && 142901e04c3fSmrg !pitch_in_range(row_pitch_B, stencil_pitch_bits)) 143001e04c3fSmrg return false; 143101e04c3fSmrg 143201e04c3fSmrg done: 143301e04c3fSmrg *out_row_pitch_B = row_pitch_B; 143401e04c3fSmrg return true; 143501e04c3fSmrg} 143601e04c3fSmrg 143701e04c3fSmrgbool 143801e04c3fSmrgisl_surf_init_s(const struct isl_device *dev, 143901e04c3fSmrg struct isl_surf *surf, 144001e04c3fSmrg const struct isl_surf_init_info *restrict info) 144101e04c3fSmrg{ 144201e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 144301e04c3fSmrg 144401e04c3fSmrg const struct isl_extent4d logical_level0_px = { 144501e04c3fSmrg .w = info->width, 144601e04c3fSmrg .h = info->height, 144701e04c3fSmrg .d = info->depth, 144801e04c3fSmrg .a = info->array_len, 144901e04c3fSmrg }; 145001e04c3fSmrg 145101e04c3fSmrg enum isl_tiling tiling; 145201e04c3fSmrg if (!isl_surf_choose_tiling(dev, info, &tiling)) 145301e04c3fSmrg return false; 145401e04c3fSmrg 145501e04c3fSmrg struct isl_tile_info tile_info; 145601e04c3fSmrg isl_tiling_get_info(tiling, fmtl->bpb, &tile_info); 145701e04c3fSmrg 145801e04c3fSmrg const enum isl_dim_layout dim_layout = 145901e04c3fSmrg isl_surf_choose_dim_layout(dev, info->dim, tiling, info->usage); 146001e04c3fSmrg 146101e04c3fSmrg enum isl_msaa_layout msaa_layout; 146201e04c3fSmrg if (!isl_choose_msaa_layout(dev, info, tiling, &msaa_layout)) 146301e04c3fSmrg return false; 146401e04c3fSmrg 146501e04c3fSmrg struct isl_extent3d image_align_el; 146601e04c3fSmrg isl_choose_image_alignment_el(dev, info, tiling, dim_layout, msaa_layout, 146701e04c3fSmrg &image_align_el); 146801e04c3fSmrg 146901e04c3fSmrg struct isl_extent3d image_align_sa = 147001e04c3fSmrg isl_extent3d_el_to_sa(info->format, image_align_el); 147101e04c3fSmrg 147201e04c3fSmrg struct isl_extent4d phys_level0_sa; 147301e04c3fSmrg isl_calc_phys_level0_extent_sa(dev, info, dim_layout, tiling, msaa_layout, 147401e04c3fSmrg &phys_level0_sa); 147501e04c3fSmrg 147601e04c3fSmrg enum isl_array_pitch_span array_pitch_span = 147701e04c3fSmrg isl_choose_array_pitch_span(dev, info, dim_layout, &phys_level0_sa); 147801e04c3fSmrg 147901e04c3fSmrg uint32_t array_pitch_el_rows; 148001e04c3fSmrg struct isl_extent2d phys_total_el; 148101e04c3fSmrg isl_calc_phys_total_extent_el(dev, info, &tile_info, 148201e04c3fSmrg dim_layout, msaa_layout, 148301e04c3fSmrg &image_align_sa, &phys_level0_sa, 148401e04c3fSmrg array_pitch_span, &array_pitch_el_rows, 148501e04c3fSmrg &phys_total_el); 148601e04c3fSmrg 148701e04c3fSmrg uint32_t row_pitch_B; 148801e04c3fSmrg if (!isl_calc_row_pitch(dev, info, &tile_info, dim_layout, 148901e04c3fSmrg &phys_total_el, &row_pitch_B)) 149001e04c3fSmrg return false; 149101e04c3fSmrg 149201e04c3fSmrg uint32_t base_alignment_B; 149301e04c3fSmrg uint64_t size_B; 149401e04c3fSmrg if (tiling == ISL_TILING_LINEAR) { 149501e04c3fSmrg size_B = (uint64_t) row_pitch_B * phys_total_el.h; 149601e04c3fSmrg 149701e04c3fSmrg /* From the Broadwell PRM Vol 2d, RENDER_SURFACE_STATE::SurfaceBaseAddress: 149801e04c3fSmrg * 149901e04c3fSmrg * "The Base Address for linear render target surfaces and surfaces 150001e04c3fSmrg * accessed with the typed surface read/write data port messages must 150101e04c3fSmrg * be element-size aligned, for non-YUV surface formats, or a 150201e04c3fSmrg * multiple of 2 element-sizes for YUV surface formats. Other linear 150301e04c3fSmrg * surfaces have no alignment requirements (byte alignment is 150401e04c3fSmrg * sufficient.)" 150501e04c3fSmrg */ 150601e04c3fSmrg base_alignment_B = MAX(1, info->min_alignment_B); 150701e04c3fSmrg if (info->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) { 150801e04c3fSmrg if (isl_format_is_yuv(info->format)) { 150901e04c3fSmrg base_alignment_B = MAX(base_alignment_B, fmtl->bpb / 4); 151001e04c3fSmrg } else { 151101e04c3fSmrg base_alignment_B = MAX(base_alignment_B, fmtl->bpb / 8); 151201e04c3fSmrg } 151301e04c3fSmrg } 151401e04c3fSmrg base_alignment_B = isl_round_up_to_power_of_two(base_alignment_B); 15159f464c52Smaya 15169f464c52Smaya /* From the Skylake PRM Vol 2c, PLANE_STRIDE::Stride: 15179f464c52Smaya * 15189f464c52Smaya * "For Linear memory, this field specifies the stride in chunks of 15199f464c52Smaya * 64 bytes (1 cache line)." 15209f464c52Smaya */ 15219f464c52Smaya if (isl_surf_usage_is_display(info->usage)) 15229f464c52Smaya base_alignment_B = MAX(base_alignment_B, 64); 152301e04c3fSmrg } else { 152401e04c3fSmrg const uint32_t total_h_tl = 152501e04c3fSmrg isl_align_div(phys_total_el.h, tile_info.logical_extent_el.height); 152601e04c3fSmrg 152701e04c3fSmrg size_B = (uint64_t) total_h_tl * tile_info.phys_extent_B.height * row_pitch_B; 152801e04c3fSmrg 152901e04c3fSmrg const uint32_t tile_size_B = tile_info.phys_extent_B.width * 153001e04c3fSmrg tile_info.phys_extent_B.height; 153101e04c3fSmrg assert(isl_is_pow2(info->min_alignment_B) && isl_is_pow2(tile_size_B)); 153201e04c3fSmrg base_alignment_B = MAX(info->min_alignment_B, tile_size_B); 153301e04c3fSmrg } 153401e04c3fSmrg 153501e04c3fSmrg if (ISL_DEV_GEN(dev) < 9) { 153601e04c3fSmrg /* From the Broadwell PRM Vol 5, Surface Layout: 153701e04c3fSmrg * 153801e04c3fSmrg * "In addition to restrictions on maximum height, width, and depth, 153901e04c3fSmrg * surfaces are also restricted to a maximum size in bytes. This 154001e04c3fSmrg * maximum is 2 GB for all products and all surface types." 154101e04c3fSmrg * 154201e04c3fSmrg * This comment is applicable to all Pre-gen9 platforms. 154301e04c3fSmrg */ 154401e04c3fSmrg if (size_B > (uint64_t) 1 << 31) 154501e04c3fSmrg return false; 154601e04c3fSmrg } else if (ISL_DEV_GEN(dev) < 11) { 154701e04c3fSmrg /* From the Skylake PRM Vol 5, Maximum Surface Size in Bytes: 154801e04c3fSmrg * "In addition to restrictions on maximum height, width, and depth, 154901e04c3fSmrg * surfaces are also restricted to a maximum size of 2^38 bytes. 155001e04c3fSmrg * All pixels within the surface must be contained within 2^38 bytes 155101e04c3fSmrg * of the base address." 155201e04c3fSmrg */ 155301e04c3fSmrg if (size_B > (uint64_t) 1 << 38) 155401e04c3fSmrg return false; 155501e04c3fSmrg } else { 155601e04c3fSmrg /* gen11+ platforms raised this limit to 2^44 bytes. */ 155701e04c3fSmrg if (size_B > (uint64_t) 1 << 44) 155801e04c3fSmrg return false; 155901e04c3fSmrg } 156001e04c3fSmrg 156101e04c3fSmrg *surf = (struct isl_surf) { 156201e04c3fSmrg .dim = info->dim, 156301e04c3fSmrg .dim_layout = dim_layout, 156401e04c3fSmrg .msaa_layout = msaa_layout, 156501e04c3fSmrg .tiling = tiling, 156601e04c3fSmrg .format = info->format, 156701e04c3fSmrg 156801e04c3fSmrg .levels = info->levels, 156901e04c3fSmrg .samples = info->samples, 157001e04c3fSmrg 157101e04c3fSmrg .image_alignment_el = image_align_el, 157201e04c3fSmrg .logical_level0_px = logical_level0_px, 157301e04c3fSmrg .phys_level0_sa = phys_level0_sa, 157401e04c3fSmrg 157501e04c3fSmrg .size_B = size_B, 157601e04c3fSmrg .alignment_B = base_alignment_B, 157701e04c3fSmrg .row_pitch_B = row_pitch_B, 157801e04c3fSmrg .array_pitch_el_rows = array_pitch_el_rows, 157901e04c3fSmrg .array_pitch_span = array_pitch_span, 158001e04c3fSmrg 158101e04c3fSmrg .usage = info->usage, 158201e04c3fSmrg }; 158301e04c3fSmrg 158401e04c3fSmrg return true; 158501e04c3fSmrg} 158601e04c3fSmrg 158701e04c3fSmrgvoid 158801e04c3fSmrgisl_surf_get_tile_info(const struct isl_surf *surf, 158901e04c3fSmrg struct isl_tile_info *tile_info) 159001e04c3fSmrg{ 159101e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); 159201e04c3fSmrg isl_tiling_get_info(surf->tiling, fmtl->bpb, tile_info); 159301e04c3fSmrg} 159401e04c3fSmrg 159501e04c3fSmrgbool 159601e04c3fSmrgisl_surf_get_hiz_surf(const struct isl_device *dev, 159701e04c3fSmrg const struct isl_surf *surf, 159801e04c3fSmrg struct isl_surf *hiz_surf) 159901e04c3fSmrg{ 160001e04c3fSmrg assert(ISL_DEV_GEN(dev) >= 5 && ISL_DEV_USE_SEPARATE_STENCIL(dev)); 160101e04c3fSmrg 160201e04c3fSmrg /* Multisampled depth is always interleaved */ 160301e04c3fSmrg assert(surf->msaa_layout == ISL_MSAA_LAYOUT_NONE || 160401e04c3fSmrg surf->msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED); 160501e04c3fSmrg 160601e04c3fSmrg /* From the Broadwell PRM Vol. 7, "Hierarchical Depth Buffer": 160701e04c3fSmrg * 160801e04c3fSmrg * "The Surface Type, Height, Width, Depth, Minimum Array Element, Render 160901e04c3fSmrg * Target View Extent, and Depth Coordinate Offset X/Y of the 161001e04c3fSmrg * hierarchical depth buffer are inherited from the depth buffer. The 161101e04c3fSmrg * height and width of the hierarchical depth buffer that must be 161201e04c3fSmrg * allocated are computed by the following formulas, where HZ is the 161301e04c3fSmrg * hierarchical depth buffer and Z is the depth buffer. The Z_Height, 161401e04c3fSmrg * Z_Width, and Z_Depth values given in these formulas are those present 161501e04c3fSmrg * in 3DSTATE_DEPTH_BUFFER incremented by one. 161601e04c3fSmrg * 161701e04c3fSmrg * "The value of Z_Height and Z_Width must each be multiplied by 2 before 161801e04c3fSmrg * being applied to the table below if Number of Multisamples is set to 161901e04c3fSmrg * NUMSAMPLES_4. The value of Z_Height must be multiplied by 2 and 162001e04c3fSmrg * Z_Width must be multiplied by 4 before being applied to the table 162101e04c3fSmrg * below if Number of Multisamples is set to NUMSAMPLES_8." 162201e04c3fSmrg * 162301e04c3fSmrg * In the Sky Lake PRM, the second paragraph is replaced with this: 162401e04c3fSmrg * 162501e04c3fSmrg * "The Z_Height and Z_Width values must equal those present in 162601e04c3fSmrg * 3DSTATE_DEPTH_BUFFER incremented by one." 162701e04c3fSmrg * 162801e04c3fSmrg * In other words, on Sandy Bridge through Broadwell, each 128-bit HiZ 162901e04c3fSmrg * block corresponds to a region of 8x4 samples in the primary depth 163001e04c3fSmrg * surface. On Sky Lake, on the other hand, each HiZ block corresponds to 163101e04c3fSmrg * a region of 8x4 pixels in the primary depth surface regardless of the 163201e04c3fSmrg * number of samples. The dimensions of a HiZ block in both pixels and 163301e04c3fSmrg * samples are given in the table below: 163401e04c3fSmrg * 163501e04c3fSmrg * | SNB - BDW | SKL+ 163601e04c3fSmrg * ------+-----------+------------- 163701e04c3fSmrg * 1x | 8 x 4 sa | 8 x 4 sa 163801e04c3fSmrg * MSAA | 8 x 4 px | 8 x 4 px 163901e04c3fSmrg * ------+-----------+------------- 164001e04c3fSmrg * 2x | 8 x 4 sa | 16 x 4 sa 164101e04c3fSmrg * MSAA | 4 x 4 px | 8 x 4 px 164201e04c3fSmrg * ------+-----------+------------- 164301e04c3fSmrg * 4x | 8 x 4 sa | 16 x 8 sa 164401e04c3fSmrg * MSAA | 4 x 2 px | 8 x 4 px 164501e04c3fSmrg * ------+-----------+------------- 164601e04c3fSmrg * 8x | 8 x 4 sa | 32 x 8 sa 164701e04c3fSmrg * MSAA | 2 x 2 px | 8 x 4 px 164801e04c3fSmrg * ------+-----------+------------- 164901e04c3fSmrg * 16x | N/A | 32 x 16 sa 165001e04c3fSmrg * MSAA | N/A | 8 x 4 px 165101e04c3fSmrg * ------+-----------+------------- 165201e04c3fSmrg * 165301e04c3fSmrg * There are a number of different ways that this discrepency could be 165401e04c3fSmrg * handled. The way we have chosen is to simply make MSAA HiZ have the 165501e04c3fSmrg * same number of samples as the parent surface pre-Sky Lake and always be 165601e04c3fSmrg * single-sampled on Sky Lake and above. Since the block sizes of 165701e04c3fSmrg * compressed formats are given in samples, this neatly handles everything 165801e04c3fSmrg * without the need for additional HiZ formats with different block sizes 165901e04c3fSmrg * on SKL+. 166001e04c3fSmrg */ 166101e04c3fSmrg const unsigned samples = ISL_DEV_GEN(dev) >= 9 ? 1 : surf->samples; 166201e04c3fSmrg 166301e04c3fSmrg return isl_surf_init(dev, hiz_surf, 166401e04c3fSmrg .dim = surf->dim, 166501e04c3fSmrg .format = ISL_FORMAT_HIZ, 166601e04c3fSmrg .width = surf->logical_level0_px.width, 166701e04c3fSmrg .height = surf->logical_level0_px.height, 166801e04c3fSmrg .depth = surf->logical_level0_px.depth, 166901e04c3fSmrg .levels = surf->levels, 167001e04c3fSmrg .array_len = surf->logical_level0_px.array_len, 167101e04c3fSmrg .samples = samples, 167201e04c3fSmrg .usage = ISL_SURF_USAGE_HIZ_BIT, 167301e04c3fSmrg .tiling_flags = ISL_TILING_HIZ_BIT); 167401e04c3fSmrg} 167501e04c3fSmrg 167601e04c3fSmrgbool 167701e04c3fSmrgisl_surf_get_mcs_surf(const struct isl_device *dev, 167801e04c3fSmrg const struct isl_surf *surf, 167901e04c3fSmrg struct isl_surf *mcs_surf) 168001e04c3fSmrg{ 168101e04c3fSmrg assert(ISL_DEV_GEN(dev) >= 7); 168201e04c3fSmrg 168301e04c3fSmrg /* It must be multisampled with an array layout */ 168401e04c3fSmrg assert(surf->samples > 1 && surf->msaa_layout == ISL_MSAA_LAYOUT_ARRAY); 168501e04c3fSmrg 168601e04c3fSmrg /* The following are true of all multisampled surfaces */ 168701e04c3fSmrg assert(surf->dim == ISL_SURF_DIM_2D); 168801e04c3fSmrg assert(surf->levels == 1); 168901e04c3fSmrg assert(surf->logical_level0_px.depth == 1); 169001e04c3fSmrg 169101e04c3fSmrg /* The "Auxiliary Surface Pitch" field in RENDER_SURFACE_STATE is only 9 169201e04c3fSmrg * bits which means the maximum pitch of a compression surface is 512 169301e04c3fSmrg * tiles or 64KB (since MCS is always Y-tiled). Since a 16x MCS buffer is 169401e04c3fSmrg * 64bpp, this gives us a maximum width of 8192 pixels. We can create 169501e04c3fSmrg * larger multisampled surfaces, we just can't compress them. For 2x, 4x, 169601e04c3fSmrg * and 8x, we have enough room for the full 16k supported by the hardware. 169701e04c3fSmrg */ 169801e04c3fSmrg if (surf->samples == 16 && surf->logical_level0_px.width > 8192) 169901e04c3fSmrg return false; 170001e04c3fSmrg 170101e04c3fSmrg enum isl_format mcs_format; 170201e04c3fSmrg switch (surf->samples) { 170301e04c3fSmrg case 2: mcs_format = ISL_FORMAT_MCS_2X; break; 170401e04c3fSmrg case 4: mcs_format = ISL_FORMAT_MCS_4X; break; 170501e04c3fSmrg case 8: mcs_format = ISL_FORMAT_MCS_8X; break; 170601e04c3fSmrg case 16: mcs_format = ISL_FORMAT_MCS_16X; break; 170701e04c3fSmrg default: 170801e04c3fSmrg unreachable("Invalid sample count"); 170901e04c3fSmrg } 171001e04c3fSmrg 171101e04c3fSmrg return isl_surf_init(dev, mcs_surf, 171201e04c3fSmrg .dim = ISL_SURF_DIM_2D, 171301e04c3fSmrg .format = mcs_format, 171401e04c3fSmrg .width = surf->logical_level0_px.width, 171501e04c3fSmrg .height = surf->logical_level0_px.height, 171601e04c3fSmrg .depth = 1, 171701e04c3fSmrg .levels = 1, 171801e04c3fSmrg .array_len = surf->logical_level0_px.array_len, 171901e04c3fSmrg .samples = 1, /* MCS surfaces are really single-sampled */ 172001e04c3fSmrg .usage = ISL_SURF_USAGE_MCS_BIT, 172101e04c3fSmrg .tiling_flags = ISL_TILING_Y0_BIT); 172201e04c3fSmrg} 172301e04c3fSmrg 172401e04c3fSmrgbool 172501e04c3fSmrgisl_surf_get_ccs_surf(const struct isl_device *dev, 172601e04c3fSmrg const struct isl_surf *surf, 172701e04c3fSmrg struct isl_surf *ccs_surf, 172801e04c3fSmrg uint32_t row_pitch_B) 172901e04c3fSmrg{ 173001e04c3fSmrg assert(surf->samples == 1 && surf->msaa_layout == ISL_MSAA_LAYOUT_NONE); 173101e04c3fSmrg assert(ISL_DEV_GEN(dev) >= 7); 173201e04c3fSmrg 173301e04c3fSmrg if (surf->usage & ISL_SURF_USAGE_DISABLE_AUX_BIT) 173401e04c3fSmrg return false; 173501e04c3fSmrg 173601e04c3fSmrg /* The PRM doesn't say this explicitly, but fast-clears don't appear to 173701e04c3fSmrg * work for 3D textures until gen9 where the layout of 3D textures changes 173801e04c3fSmrg * to match 2D array textures. 173901e04c3fSmrg */ 174001e04c3fSmrg if (ISL_DEV_GEN(dev) <= 8 && surf->dim != ISL_SURF_DIM_2D) 174101e04c3fSmrg return false; 174201e04c3fSmrg 174301e04c3fSmrg /* From the HSW PRM Volume 7: 3D-Media-GPGPU, page 652 (Color Clear of 174401e04c3fSmrg * Non-MultiSampler Render Target Restrictions): 174501e04c3fSmrg * 174601e04c3fSmrg * "Support is for non-mip-mapped and non-array surface types only." 174701e04c3fSmrg * 174801e04c3fSmrg * This restriction is lifted on gen8+. Technically, it may be possible to 174901e04c3fSmrg * create a CCS for an arrayed or mipmapped image and only enable CCS_D 175001e04c3fSmrg * when rendering to the base slice. However, there is no documentation 175101e04c3fSmrg * tell us what the hardware would do in that case or what it does if you 175201e04c3fSmrg * walk off the bases slice. (Does it ignore CCS or does it start 175301e04c3fSmrg * scribbling over random memory?) We play it safe and just follow the 175401e04c3fSmrg * docs and don't allow CCS_D for arrayed or mip-mapped surfaces. 175501e04c3fSmrg */ 175601e04c3fSmrg if (ISL_DEV_GEN(dev) <= 7 && 175701e04c3fSmrg (surf->levels > 1 || surf->logical_level0_px.array_len > 1)) 175801e04c3fSmrg return false; 175901e04c3fSmrg 176001e04c3fSmrg if (isl_format_is_compressed(surf->format)) 176101e04c3fSmrg return false; 176201e04c3fSmrg 176301e04c3fSmrg /* TODO: More conditions where it can fail. */ 176401e04c3fSmrg 176501e04c3fSmrg enum isl_format ccs_format; 176601e04c3fSmrg if (ISL_DEV_GEN(dev) >= 9) { 176701e04c3fSmrg if (!isl_tiling_is_any_y(surf->tiling)) 176801e04c3fSmrg return false; 176901e04c3fSmrg 177001e04c3fSmrg switch (isl_format_get_layout(surf->format)->bpb) { 177101e04c3fSmrg case 32: ccs_format = ISL_FORMAT_GEN9_CCS_32BPP; break; 177201e04c3fSmrg case 64: ccs_format = ISL_FORMAT_GEN9_CCS_64BPP; break; 177301e04c3fSmrg case 128: ccs_format = ISL_FORMAT_GEN9_CCS_128BPP; break; 177401e04c3fSmrg default: 177501e04c3fSmrg return false; 177601e04c3fSmrg } 177701e04c3fSmrg } else if (surf->tiling == ISL_TILING_Y0) { 177801e04c3fSmrg switch (isl_format_get_layout(surf->format)->bpb) { 177901e04c3fSmrg case 32: ccs_format = ISL_FORMAT_GEN7_CCS_32BPP_Y; break; 178001e04c3fSmrg case 64: ccs_format = ISL_FORMAT_GEN7_CCS_64BPP_Y; break; 178101e04c3fSmrg case 128: ccs_format = ISL_FORMAT_GEN7_CCS_128BPP_Y; break; 178201e04c3fSmrg default: 178301e04c3fSmrg return false; 178401e04c3fSmrg } 178501e04c3fSmrg } else if (surf->tiling == ISL_TILING_X) { 178601e04c3fSmrg switch (isl_format_get_layout(surf->format)->bpb) { 178701e04c3fSmrg case 32: ccs_format = ISL_FORMAT_GEN7_CCS_32BPP_X; break; 178801e04c3fSmrg case 64: ccs_format = ISL_FORMAT_GEN7_CCS_64BPP_X; break; 178901e04c3fSmrg case 128: ccs_format = ISL_FORMAT_GEN7_CCS_128BPP_X; break; 179001e04c3fSmrg default: 179101e04c3fSmrg return false; 179201e04c3fSmrg } 179301e04c3fSmrg } else { 179401e04c3fSmrg return false; 179501e04c3fSmrg } 179601e04c3fSmrg 179701e04c3fSmrg return isl_surf_init(dev, ccs_surf, 179801e04c3fSmrg .dim = surf->dim, 179901e04c3fSmrg .format = ccs_format, 180001e04c3fSmrg .width = surf->logical_level0_px.width, 180101e04c3fSmrg .height = surf->logical_level0_px.height, 180201e04c3fSmrg .depth = surf->logical_level0_px.depth, 180301e04c3fSmrg .levels = surf->levels, 180401e04c3fSmrg .array_len = surf->logical_level0_px.array_len, 180501e04c3fSmrg .samples = 1, 180601e04c3fSmrg .row_pitch_B = row_pitch_B, 180701e04c3fSmrg .usage = ISL_SURF_USAGE_CCS_BIT, 180801e04c3fSmrg .tiling_flags = ISL_TILING_CCS_BIT); 180901e04c3fSmrg} 181001e04c3fSmrg 181101e04c3fSmrg#define isl_genX_call(dev, func, ...) \ 181201e04c3fSmrg switch (ISL_DEV_GEN(dev)) { \ 181301e04c3fSmrg case 4: \ 181401e04c3fSmrg /* G45 surface state is the same as gen5 */ \ 181501e04c3fSmrg if (ISL_DEV_IS_G4X(dev)) { \ 181601e04c3fSmrg isl_gen5_##func(__VA_ARGS__); \ 181701e04c3fSmrg } else { \ 181801e04c3fSmrg isl_gen4_##func(__VA_ARGS__); \ 181901e04c3fSmrg } \ 182001e04c3fSmrg break; \ 182101e04c3fSmrg case 5: \ 182201e04c3fSmrg isl_gen5_##func(__VA_ARGS__); \ 182301e04c3fSmrg break; \ 182401e04c3fSmrg case 6: \ 182501e04c3fSmrg isl_gen6_##func(__VA_ARGS__); \ 182601e04c3fSmrg break; \ 182701e04c3fSmrg case 7: \ 182801e04c3fSmrg if (ISL_DEV_IS_HASWELL(dev)) { \ 182901e04c3fSmrg isl_gen75_##func(__VA_ARGS__); \ 183001e04c3fSmrg } else { \ 183101e04c3fSmrg isl_gen7_##func(__VA_ARGS__); \ 183201e04c3fSmrg } \ 183301e04c3fSmrg break; \ 183401e04c3fSmrg case 8: \ 183501e04c3fSmrg isl_gen8_##func(__VA_ARGS__); \ 183601e04c3fSmrg break; \ 183701e04c3fSmrg case 9: \ 183801e04c3fSmrg isl_gen9_##func(__VA_ARGS__); \ 183901e04c3fSmrg break; \ 184001e04c3fSmrg case 10: \ 184101e04c3fSmrg isl_gen10_##func(__VA_ARGS__); \ 184201e04c3fSmrg break; \ 184301e04c3fSmrg case 11: \ 184401e04c3fSmrg isl_gen11_##func(__VA_ARGS__); \ 184501e04c3fSmrg break; \ 184601e04c3fSmrg default: \ 184701e04c3fSmrg assert(!"Unknown hardware generation"); \ 184801e04c3fSmrg } 184901e04c3fSmrg 185001e04c3fSmrgvoid 185101e04c3fSmrgisl_surf_fill_state_s(const struct isl_device *dev, void *state, 185201e04c3fSmrg const struct isl_surf_fill_state_info *restrict info) 185301e04c3fSmrg{ 185401e04c3fSmrg#ifndef NDEBUG 185501e04c3fSmrg isl_surf_usage_flags_t _base_usage = 185601e04c3fSmrg info->view->usage & (ISL_SURF_USAGE_RENDER_TARGET_BIT | 185701e04c3fSmrg ISL_SURF_USAGE_TEXTURE_BIT | 185801e04c3fSmrg ISL_SURF_USAGE_STORAGE_BIT); 185901e04c3fSmrg /* They may only specify one of the above bits at a time */ 186001e04c3fSmrg assert(__builtin_popcount(_base_usage) == 1); 186101e04c3fSmrg /* The only other allowed bit is ISL_SURF_USAGE_CUBE_BIT */ 186201e04c3fSmrg assert((info->view->usage & ~ISL_SURF_USAGE_CUBE_BIT) == _base_usage); 186301e04c3fSmrg#endif 186401e04c3fSmrg 186501e04c3fSmrg if (info->surf->dim == ISL_SURF_DIM_3D) { 186601e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 186701e04c3fSmrg info->surf->logical_level0_px.depth); 186801e04c3fSmrg } else { 186901e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 187001e04c3fSmrg info->surf->logical_level0_px.array_len); 187101e04c3fSmrg } 187201e04c3fSmrg 187301e04c3fSmrg isl_genX_call(dev, surf_fill_state_s, dev, state, info); 187401e04c3fSmrg} 187501e04c3fSmrg 187601e04c3fSmrgvoid 187701e04c3fSmrgisl_buffer_fill_state_s(const struct isl_device *dev, void *state, 187801e04c3fSmrg const struct isl_buffer_fill_state_info *restrict info) 187901e04c3fSmrg{ 188001e04c3fSmrg isl_genX_call(dev, buffer_fill_state_s, state, info); 188101e04c3fSmrg} 188201e04c3fSmrg 188301e04c3fSmrgvoid 188401e04c3fSmrgisl_null_fill_state(const struct isl_device *dev, void *state, 188501e04c3fSmrg struct isl_extent3d size) 188601e04c3fSmrg{ 188701e04c3fSmrg isl_genX_call(dev, null_fill_state, state, size); 188801e04c3fSmrg} 188901e04c3fSmrg 189001e04c3fSmrgvoid 189101e04c3fSmrgisl_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, 189201e04c3fSmrg const struct isl_depth_stencil_hiz_emit_info *restrict info) 189301e04c3fSmrg{ 189401e04c3fSmrg if (info->depth_surf && info->stencil_surf) { 189501e04c3fSmrg if (!dev->info->has_hiz_and_separate_stencil) { 189601e04c3fSmrg assert(info->depth_surf == info->stencil_surf); 189701e04c3fSmrg assert(info->depth_address == info->stencil_address); 189801e04c3fSmrg } 189901e04c3fSmrg assert(info->depth_surf->dim == info->stencil_surf->dim); 190001e04c3fSmrg } 190101e04c3fSmrg 190201e04c3fSmrg if (info->depth_surf) { 190301e04c3fSmrg assert((info->depth_surf->usage & ISL_SURF_USAGE_DEPTH_BIT)); 190401e04c3fSmrg if (info->depth_surf->dim == ISL_SURF_DIM_3D) { 190501e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 190601e04c3fSmrg info->depth_surf->logical_level0_px.depth); 190701e04c3fSmrg } else { 190801e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 190901e04c3fSmrg info->depth_surf->logical_level0_px.array_len); 191001e04c3fSmrg } 191101e04c3fSmrg } 191201e04c3fSmrg 191301e04c3fSmrg if (info->stencil_surf) { 191401e04c3fSmrg assert((info->stencil_surf->usage & ISL_SURF_USAGE_STENCIL_BIT)); 191501e04c3fSmrg if (info->stencil_surf->dim == ISL_SURF_DIM_3D) { 191601e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 191701e04c3fSmrg info->stencil_surf->logical_level0_px.depth); 191801e04c3fSmrg } else { 191901e04c3fSmrg assert(info->view->base_array_layer + info->view->array_len <= 192001e04c3fSmrg info->stencil_surf->logical_level0_px.array_len); 192101e04c3fSmrg } 192201e04c3fSmrg } 192301e04c3fSmrg 192401e04c3fSmrg isl_genX_call(dev, emit_depth_stencil_hiz_s, dev, batch, info); 192501e04c3fSmrg} 192601e04c3fSmrg 192701e04c3fSmrg/** 192801e04c3fSmrg * A variant of isl_surf_get_image_offset_sa() specific to 192901e04c3fSmrg * ISL_DIM_LAYOUT_GEN4_2D. 193001e04c3fSmrg */ 193101e04c3fSmrgstatic void 193201e04c3fSmrgget_image_offset_sa_gen4_2d(const struct isl_surf *surf, 193301e04c3fSmrg uint32_t level, uint32_t logical_array_layer, 193401e04c3fSmrg uint32_t *x_offset_sa, 193501e04c3fSmrg uint32_t *y_offset_sa) 193601e04c3fSmrg{ 193701e04c3fSmrg assert(level < surf->levels); 193801e04c3fSmrg if (surf->dim == ISL_SURF_DIM_3D) 193901e04c3fSmrg assert(logical_array_layer < surf->logical_level0_px.depth); 194001e04c3fSmrg else 194101e04c3fSmrg assert(logical_array_layer < surf->logical_level0_px.array_len); 194201e04c3fSmrg 194301e04c3fSmrg const struct isl_extent3d image_align_sa = 194401e04c3fSmrg isl_surf_get_image_alignment_sa(surf); 194501e04c3fSmrg 194601e04c3fSmrg const uint32_t W0 = surf->phys_level0_sa.width; 194701e04c3fSmrg const uint32_t H0 = surf->phys_level0_sa.height; 194801e04c3fSmrg 194901e04c3fSmrg const uint32_t phys_layer = logical_array_layer * 195001e04c3fSmrg (surf->msaa_layout == ISL_MSAA_LAYOUT_ARRAY ? surf->samples : 1); 195101e04c3fSmrg 195201e04c3fSmrg uint32_t x = 0; 195301e04c3fSmrg uint32_t y = phys_layer * isl_surf_get_array_pitch_sa_rows(surf); 195401e04c3fSmrg 195501e04c3fSmrg for (uint32_t l = 0; l < level; ++l) { 195601e04c3fSmrg if (l == 1) { 195701e04c3fSmrg uint32_t W = isl_minify(W0, l); 195801e04c3fSmrg x += isl_align_npot(W, image_align_sa.w); 195901e04c3fSmrg } else { 196001e04c3fSmrg uint32_t H = isl_minify(H0, l); 196101e04c3fSmrg y += isl_align_npot(H, image_align_sa.h); 196201e04c3fSmrg } 196301e04c3fSmrg } 196401e04c3fSmrg 196501e04c3fSmrg *x_offset_sa = x; 196601e04c3fSmrg *y_offset_sa = y; 196701e04c3fSmrg} 196801e04c3fSmrg 196901e04c3fSmrg/** 197001e04c3fSmrg * A variant of isl_surf_get_image_offset_sa() specific to 197101e04c3fSmrg * ISL_DIM_LAYOUT_GEN4_3D. 197201e04c3fSmrg */ 197301e04c3fSmrgstatic void 197401e04c3fSmrgget_image_offset_sa_gen4_3d(const struct isl_surf *surf, 197501e04c3fSmrg uint32_t level, uint32_t logical_z_offset_px, 197601e04c3fSmrg uint32_t *x_offset_sa, 197701e04c3fSmrg uint32_t *y_offset_sa) 197801e04c3fSmrg{ 197901e04c3fSmrg assert(level < surf->levels); 198001e04c3fSmrg if (surf->dim == ISL_SURF_DIM_3D) { 198101e04c3fSmrg assert(surf->phys_level0_sa.array_len == 1); 198201e04c3fSmrg assert(logical_z_offset_px < isl_minify(surf->phys_level0_sa.depth, level)); 198301e04c3fSmrg } else { 198401e04c3fSmrg assert(surf->dim == ISL_SURF_DIM_2D); 198501e04c3fSmrg assert(surf->usage & ISL_SURF_USAGE_CUBE_BIT); 198601e04c3fSmrg assert(surf->phys_level0_sa.array_len == 6); 198701e04c3fSmrg assert(logical_z_offset_px < surf->phys_level0_sa.array_len); 198801e04c3fSmrg } 198901e04c3fSmrg 199001e04c3fSmrg const struct isl_extent3d image_align_sa = 199101e04c3fSmrg isl_surf_get_image_alignment_sa(surf); 199201e04c3fSmrg 199301e04c3fSmrg const uint32_t W0 = surf->phys_level0_sa.width; 199401e04c3fSmrg const uint32_t H0 = surf->phys_level0_sa.height; 199501e04c3fSmrg const uint32_t D0 = surf->phys_level0_sa.depth; 199601e04c3fSmrg const uint32_t AL = surf->phys_level0_sa.array_len; 199701e04c3fSmrg 199801e04c3fSmrg uint32_t x = 0; 199901e04c3fSmrg uint32_t y = 0; 200001e04c3fSmrg 200101e04c3fSmrg for (uint32_t l = 0; l < level; ++l) { 200201e04c3fSmrg const uint32_t level_h = isl_align_npot(isl_minify(H0, l), image_align_sa.h); 200301e04c3fSmrg const uint32_t level_d = 200401e04c3fSmrg isl_align_npot(surf->dim == ISL_SURF_DIM_3D ? isl_minify(D0, l) : AL, 200501e04c3fSmrg image_align_sa.d); 200601e04c3fSmrg const uint32_t max_layers_vert = isl_align(level_d, 1u << l) / (1u << l); 200701e04c3fSmrg 200801e04c3fSmrg y += level_h * max_layers_vert; 200901e04c3fSmrg } 201001e04c3fSmrg 201101e04c3fSmrg const uint32_t level_w = isl_align_npot(isl_minify(W0, level), image_align_sa.w); 201201e04c3fSmrg const uint32_t level_h = isl_align_npot(isl_minify(H0, level), image_align_sa.h); 201301e04c3fSmrg const uint32_t level_d = 201401e04c3fSmrg isl_align_npot(surf->dim == ISL_SURF_DIM_3D ? isl_minify(D0, level) : AL, 201501e04c3fSmrg image_align_sa.d); 201601e04c3fSmrg 201701e04c3fSmrg const uint32_t max_layers_horiz = MIN(level_d, 1u << level); 201801e04c3fSmrg 201901e04c3fSmrg x += level_w * (logical_z_offset_px % max_layers_horiz); 202001e04c3fSmrg y += level_h * (logical_z_offset_px / max_layers_horiz); 202101e04c3fSmrg 202201e04c3fSmrg *x_offset_sa = x; 202301e04c3fSmrg *y_offset_sa = y; 202401e04c3fSmrg} 202501e04c3fSmrg 202601e04c3fSmrgstatic void 202701e04c3fSmrgget_image_offset_sa_gen6_stencil_hiz(const struct isl_surf *surf, 202801e04c3fSmrg uint32_t level, 202901e04c3fSmrg uint32_t logical_array_layer, 203001e04c3fSmrg uint32_t *x_offset_sa, 203101e04c3fSmrg uint32_t *y_offset_sa) 203201e04c3fSmrg{ 203301e04c3fSmrg assert(level < surf->levels); 203401e04c3fSmrg assert(surf->logical_level0_px.depth == 1); 203501e04c3fSmrg assert(logical_array_layer < surf->logical_level0_px.array_len); 203601e04c3fSmrg 203701e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); 203801e04c3fSmrg 203901e04c3fSmrg const struct isl_extent3d image_align_sa = 204001e04c3fSmrg isl_surf_get_image_alignment_sa(surf); 204101e04c3fSmrg 204201e04c3fSmrg struct isl_tile_info tile_info; 204301e04c3fSmrg isl_tiling_get_info(surf->tiling, fmtl->bpb, &tile_info); 204401e04c3fSmrg const struct isl_extent2d tile_extent_sa = { 204501e04c3fSmrg .w = tile_info.logical_extent_el.w * fmtl->bw, 204601e04c3fSmrg .h = tile_info.logical_extent_el.h * fmtl->bh, 204701e04c3fSmrg }; 204801e04c3fSmrg /* Tile size is a multiple of image alignment */ 204901e04c3fSmrg assert(tile_extent_sa.w % image_align_sa.w == 0); 205001e04c3fSmrg assert(tile_extent_sa.h % image_align_sa.h == 0); 205101e04c3fSmrg 205201e04c3fSmrg const uint32_t W0 = surf->phys_level0_sa.w; 205301e04c3fSmrg const uint32_t H0 = surf->phys_level0_sa.h; 205401e04c3fSmrg 205501e04c3fSmrg /* Each image has the same height as LOD0 because the hardware thinks 205601e04c3fSmrg * everything is LOD0 205701e04c3fSmrg */ 205801e04c3fSmrg const uint32_t H = isl_align(H0, image_align_sa.h); 205901e04c3fSmrg 206001e04c3fSmrg /* Quick sanity check for consistency */ 206101e04c3fSmrg if (surf->phys_level0_sa.array_len > 1) 206201e04c3fSmrg assert(surf->array_pitch_el_rows == isl_assert_div(H, fmtl->bh)); 206301e04c3fSmrg 206401e04c3fSmrg uint32_t x = 0, y = 0; 206501e04c3fSmrg for (uint32_t l = 0; l < level; ++l) { 206601e04c3fSmrg const uint32_t W = isl_minify(W0, l); 206701e04c3fSmrg 206801e04c3fSmrg const uint32_t w = isl_align(W, tile_extent_sa.w); 206901e04c3fSmrg const uint32_t h = isl_align(H * surf->phys_level0_sa.a, 207001e04c3fSmrg tile_extent_sa.h); 207101e04c3fSmrg 207201e04c3fSmrg if (l == 0) { 207301e04c3fSmrg y += h; 207401e04c3fSmrg } else { 207501e04c3fSmrg x += w; 207601e04c3fSmrg } 207701e04c3fSmrg } 207801e04c3fSmrg 207901e04c3fSmrg y += H * logical_array_layer; 208001e04c3fSmrg 208101e04c3fSmrg *x_offset_sa = x; 208201e04c3fSmrg *y_offset_sa = y; 208301e04c3fSmrg} 208401e04c3fSmrg 208501e04c3fSmrg/** 208601e04c3fSmrg * A variant of isl_surf_get_image_offset_sa() specific to 208701e04c3fSmrg * ISL_DIM_LAYOUT_GEN9_1D. 208801e04c3fSmrg */ 208901e04c3fSmrgstatic void 209001e04c3fSmrgget_image_offset_sa_gen9_1d(const struct isl_surf *surf, 209101e04c3fSmrg uint32_t level, uint32_t layer, 209201e04c3fSmrg uint32_t *x_offset_sa, 209301e04c3fSmrg uint32_t *y_offset_sa) 209401e04c3fSmrg{ 209501e04c3fSmrg assert(level < surf->levels); 209601e04c3fSmrg assert(layer < surf->phys_level0_sa.array_len); 209701e04c3fSmrg assert(surf->phys_level0_sa.height == 1); 209801e04c3fSmrg assert(surf->phys_level0_sa.depth == 1); 209901e04c3fSmrg assert(surf->samples == 1); 210001e04c3fSmrg 210101e04c3fSmrg const uint32_t W0 = surf->phys_level0_sa.width; 210201e04c3fSmrg const struct isl_extent3d image_align_sa = 210301e04c3fSmrg isl_surf_get_image_alignment_sa(surf); 210401e04c3fSmrg 210501e04c3fSmrg uint32_t x = 0; 210601e04c3fSmrg 210701e04c3fSmrg for (uint32_t l = 0; l < level; ++l) { 210801e04c3fSmrg uint32_t W = isl_minify(W0, l); 210901e04c3fSmrg uint32_t w = isl_align_npot(W, image_align_sa.w); 211001e04c3fSmrg 211101e04c3fSmrg x += w; 211201e04c3fSmrg } 211301e04c3fSmrg 211401e04c3fSmrg *x_offset_sa = x; 211501e04c3fSmrg *y_offset_sa = layer * isl_surf_get_array_pitch_sa_rows(surf); 211601e04c3fSmrg} 211701e04c3fSmrg 211801e04c3fSmrg/** 211901e04c3fSmrg * Calculate the offset, in units of surface samples, to a subimage in the 212001e04c3fSmrg * surface. 212101e04c3fSmrg * 212201e04c3fSmrg * @invariant level < surface levels 212301e04c3fSmrg * @invariant logical_array_layer < logical array length of surface 212401e04c3fSmrg * @invariant logical_z_offset_px < logical depth of surface at level 212501e04c3fSmrg */ 212601e04c3fSmrgvoid 212701e04c3fSmrgisl_surf_get_image_offset_sa(const struct isl_surf *surf, 212801e04c3fSmrg uint32_t level, 212901e04c3fSmrg uint32_t logical_array_layer, 213001e04c3fSmrg uint32_t logical_z_offset_px, 213101e04c3fSmrg uint32_t *x_offset_sa, 213201e04c3fSmrg uint32_t *y_offset_sa) 213301e04c3fSmrg{ 213401e04c3fSmrg assert(level < surf->levels); 213501e04c3fSmrg assert(logical_array_layer < surf->logical_level0_px.array_len); 213601e04c3fSmrg assert(logical_z_offset_px 213701e04c3fSmrg < isl_minify(surf->logical_level0_px.depth, level)); 213801e04c3fSmrg 213901e04c3fSmrg switch (surf->dim_layout) { 214001e04c3fSmrg case ISL_DIM_LAYOUT_GEN9_1D: 214101e04c3fSmrg get_image_offset_sa_gen9_1d(surf, level, logical_array_layer, 214201e04c3fSmrg x_offset_sa, y_offset_sa); 214301e04c3fSmrg break; 214401e04c3fSmrg case ISL_DIM_LAYOUT_GEN4_2D: 214501e04c3fSmrg get_image_offset_sa_gen4_2d(surf, level, logical_array_layer 214601e04c3fSmrg + logical_z_offset_px, 214701e04c3fSmrg x_offset_sa, y_offset_sa); 214801e04c3fSmrg break; 214901e04c3fSmrg case ISL_DIM_LAYOUT_GEN4_3D: 215001e04c3fSmrg get_image_offset_sa_gen4_3d(surf, level, logical_array_layer + 215101e04c3fSmrg logical_z_offset_px, 215201e04c3fSmrg x_offset_sa, y_offset_sa); 215301e04c3fSmrg break; 215401e04c3fSmrg case ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ: 215501e04c3fSmrg get_image_offset_sa_gen6_stencil_hiz(surf, level, logical_array_layer + 215601e04c3fSmrg logical_z_offset_px, 215701e04c3fSmrg x_offset_sa, y_offset_sa); 215801e04c3fSmrg break; 215901e04c3fSmrg 216001e04c3fSmrg default: 216101e04c3fSmrg unreachable("not reached"); 216201e04c3fSmrg } 216301e04c3fSmrg} 216401e04c3fSmrg 216501e04c3fSmrgvoid 216601e04c3fSmrgisl_surf_get_image_offset_el(const struct isl_surf *surf, 216701e04c3fSmrg uint32_t level, 216801e04c3fSmrg uint32_t logical_array_layer, 216901e04c3fSmrg uint32_t logical_z_offset_px, 217001e04c3fSmrg uint32_t *x_offset_el, 217101e04c3fSmrg uint32_t *y_offset_el) 217201e04c3fSmrg{ 217301e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); 217401e04c3fSmrg 217501e04c3fSmrg assert(level < surf->levels); 217601e04c3fSmrg assert(logical_array_layer < surf->logical_level0_px.array_len); 217701e04c3fSmrg assert(logical_z_offset_px 217801e04c3fSmrg < isl_minify(surf->logical_level0_px.depth, level)); 217901e04c3fSmrg 218001e04c3fSmrg uint32_t x_offset_sa, y_offset_sa; 218101e04c3fSmrg isl_surf_get_image_offset_sa(surf, level, 218201e04c3fSmrg logical_array_layer, 218301e04c3fSmrg logical_z_offset_px, 218401e04c3fSmrg &x_offset_sa, 218501e04c3fSmrg &y_offset_sa); 218601e04c3fSmrg 218701e04c3fSmrg *x_offset_el = x_offset_sa / fmtl->bw; 218801e04c3fSmrg *y_offset_el = y_offset_sa / fmtl->bh; 218901e04c3fSmrg} 219001e04c3fSmrg 219101e04c3fSmrgvoid 219201e04c3fSmrgisl_surf_get_image_offset_B_tile_sa(const struct isl_surf *surf, 219301e04c3fSmrg uint32_t level, 219401e04c3fSmrg uint32_t logical_array_layer, 219501e04c3fSmrg uint32_t logical_z_offset_px, 219601e04c3fSmrg uint32_t *offset_B, 219701e04c3fSmrg uint32_t *x_offset_sa, 219801e04c3fSmrg uint32_t *y_offset_sa) 219901e04c3fSmrg{ 220001e04c3fSmrg const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); 220101e04c3fSmrg 220201e04c3fSmrg uint32_t total_x_offset_el, total_y_offset_el; 220301e04c3fSmrg isl_surf_get_image_offset_el(surf, level, logical_array_layer, 220401e04c3fSmrg logical_z_offset_px, 220501e04c3fSmrg &total_x_offset_el, 220601e04c3fSmrg &total_y_offset_el); 220701e04c3fSmrg 220801e04c3fSmrg uint32_t x_offset_el, y_offset_el; 220901e04c3fSmrg isl_tiling_get_intratile_offset_el(surf->tiling, fmtl->bpb, 221001e04c3fSmrg surf->row_pitch_B, 221101e04c3fSmrg total_x_offset_el, 221201e04c3fSmrg total_y_offset_el, 221301e04c3fSmrg offset_B, 221401e04c3fSmrg &x_offset_el, 221501e04c3fSmrg &y_offset_el); 221601e04c3fSmrg 221701e04c3fSmrg if (x_offset_sa) { 221801e04c3fSmrg *x_offset_sa = x_offset_el * fmtl->bw; 221901e04c3fSmrg } else { 222001e04c3fSmrg assert(x_offset_el == 0); 222101e04c3fSmrg } 222201e04c3fSmrg 222301e04c3fSmrg if (y_offset_sa) { 222401e04c3fSmrg *y_offset_sa = y_offset_el * fmtl->bh; 222501e04c3fSmrg } else { 222601e04c3fSmrg assert(y_offset_el == 0); 222701e04c3fSmrg } 222801e04c3fSmrg} 222901e04c3fSmrg 223001e04c3fSmrgvoid 223101e04c3fSmrgisl_surf_get_image_surf(const struct isl_device *dev, 223201e04c3fSmrg const struct isl_surf *surf, 223301e04c3fSmrg uint32_t level, 223401e04c3fSmrg uint32_t logical_array_layer, 223501e04c3fSmrg uint32_t logical_z_offset_px, 223601e04c3fSmrg struct isl_surf *image_surf, 223701e04c3fSmrg uint32_t *offset_B, 223801e04c3fSmrg uint32_t *x_offset_sa, 223901e04c3fSmrg uint32_t *y_offset_sa) 224001e04c3fSmrg{ 224101e04c3fSmrg isl_surf_get_image_offset_B_tile_sa(surf, 224201e04c3fSmrg level, 224301e04c3fSmrg logical_array_layer, 224401e04c3fSmrg logical_z_offset_px, 224501e04c3fSmrg offset_B, 224601e04c3fSmrg x_offset_sa, 224701e04c3fSmrg y_offset_sa); 224801e04c3fSmrg 224901e04c3fSmrg /* Even for cube maps there will be only single face, therefore drop the 225001e04c3fSmrg * corresponding flag if present. 225101e04c3fSmrg */ 225201e04c3fSmrg const isl_surf_usage_flags_t usage = 225301e04c3fSmrg surf->usage & (~ISL_SURF_USAGE_CUBE_BIT); 225401e04c3fSmrg 225501e04c3fSmrg bool ok UNUSED; 225601e04c3fSmrg ok = isl_surf_init(dev, image_surf, 225701e04c3fSmrg .dim = ISL_SURF_DIM_2D, 225801e04c3fSmrg .format = surf->format, 225901e04c3fSmrg .width = isl_minify(surf->logical_level0_px.w, level), 226001e04c3fSmrg .height = isl_minify(surf->logical_level0_px.h, level), 226101e04c3fSmrg .depth = 1, 226201e04c3fSmrg .levels = 1, 226301e04c3fSmrg .array_len = 1, 226401e04c3fSmrg .samples = surf->samples, 226501e04c3fSmrg .row_pitch_B = surf->row_pitch_B, 226601e04c3fSmrg .usage = usage, 226701e04c3fSmrg .tiling_flags = (1 << surf->tiling)); 226801e04c3fSmrg assert(ok); 226901e04c3fSmrg} 227001e04c3fSmrg 227101e04c3fSmrgvoid 227201e04c3fSmrgisl_tiling_get_intratile_offset_el(enum isl_tiling tiling, 227301e04c3fSmrg uint32_t bpb, 227401e04c3fSmrg uint32_t row_pitch_B, 227501e04c3fSmrg uint32_t total_x_offset_el, 227601e04c3fSmrg uint32_t total_y_offset_el, 227701e04c3fSmrg uint32_t *base_address_offset, 227801e04c3fSmrg uint32_t *x_offset_el, 227901e04c3fSmrg uint32_t *y_offset_el) 228001e04c3fSmrg{ 228101e04c3fSmrg if (tiling == ISL_TILING_LINEAR) { 228201e04c3fSmrg assert(bpb % 8 == 0); 228301e04c3fSmrg *base_address_offset = total_y_offset_el * row_pitch_B + 228401e04c3fSmrg total_x_offset_el * (bpb / 8); 228501e04c3fSmrg *x_offset_el = 0; 228601e04c3fSmrg *y_offset_el = 0; 228701e04c3fSmrg return; 228801e04c3fSmrg } 228901e04c3fSmrg 229001e04c3fSmrg struct isl_tile_info tile_info; 229101e04c3fSmrg isl_tiling_get_info(tiling, bpb, &tile_info); 229201e04c3fSmrg 229301e04c3fSmrg assert(row_pitch_B % tile_info.phys_extent_B.width == 0); 229401e04c3fSmrg 229501e04c3fSmrg /* For non-power-of-two formats, we need the address to be both tile and 229601e04c3fSmrg * element-aligned. The easiest way to achieve this is to work with a tile 229701e04c3fSmrg * that is three times as wide as the regular tile. 229801e04c3fSmrg * 229901e04c3fSmrg * The tile info returned by get_tile_info has a logical size that is an 230001e04c3fSmrg * integer number of tile_info.format_bpb size elements. To scale the 230101e04c3fSmrg * tile, we scale up the physical width and then treat the logical tile 230201e04c3fSmrg * size as if it has bpb size elements. 230301e04c3fSmrg */ 230401e04c3fSmrg const uint32_t tile_el_scale = bpb / tile_info.format_bpb; 230501e04c3fSmrg tile_info.phys_extent_B.width *= tile_el_scale; 230601e04c3fSmrg 230701e04c3fSmrg /* Compute the offset into the tile */ 230801e04c3fSmrg *x_offset_el = total_x_offset_el % tile_info.logical_extent_el.w; 230901e04c3fSmrg *y_offset_el = total_y_offset_el % tile_info.logical_extent_el.h; 231001e04c3fSmrg 231101e04c3fSmrg /* Compute the offset of the tile in units of whole tiles */ 231201e04c3fSmrg uint32_t x_offset_tl = total_x_offset_el / tile_info.logical_extent_el.w; 231301e04c3fSmrg uint32_t y_offset_tl = total_y_offset_el / tile_info.logical_extent_el.h; 231401e04c3fSmrg 231501e04c3fSmrg *base_address_offset = 231601e04c3fSmrg y_offset_tl * tile_info.phys_extent_B.h * row_pitch_B + 231701e04c3fSmrg x_offset_tl * tile_info.phys_extent_B.h * tile_info.phys_extent_B.w; 231801e04c3fSmrg} 231901e04c3fSmrg 232001e04c3fSmrguint32_t 232101e04c3fSmrgisl_surf_get_depth_format(const struct isl_device *dev, 232201e04c3fSmrg const struct isl_surf *surf) 232301e04c3fSmrg{ 232401e04c3fSmrg /* Support for separate stencil buffers began in gen5. Support for 232501e04c3fSmrg * interleaved depthstencil buffers ceased in gen7. The intermediate gens, 232601e04c3fSmrg * those that supported separate and interleaved stencil, were gen5 and 232701e04c3fSmrg * gen6. 232801e04c3fSmrg * 232901e04c3fSmrg * For a list of all available formats, see the Sandybridge PRM >> Volume 233001e04c3fSmrg * 2 Part 1: 3D/Media - 3D Pipeline >> 3DSTATE_DEPTH_BUFFER >> Surface 233101e04c3fSmrg * Format (p321). 233201e04c3fSmrg */ 233301e04c3fSmrg 233401e04c3fSmrg bool has_stencil = surf->usage & ISL_SURF_USAGE_STENCIL_BIT; 233501e04c3fSmrg 233601e04c3fSmrg assert(surf->usage & ISL_SURF_USAGE_DEPTH_BIT); 233701e04c3fSmrg 233801e04c3fSmrg if (has_stencil) 233901e04c3fSmrg assert(ISL_DEV_GEN(dev) < 7); 234001e04c3fSmrg 234101e04c3fSmrg switch (surf->format) { 234201e04c3fSmrg default: 234301e04c3fSmrg unreachable("bad isl depth format"); 234401e04c3fSmrg case ISL_FORMAT_R32_FLOAT_X8X24_TYPELESS: 234501e04c3fSmrg assert(ISL_DEV_GEN(dev) < 7); 234601e04c3fSmrg return 0; /* D32_FLOAT_S8X24_UINT */ 234701e04c3fSmrg case ISL_FORMAT_R32_FLOAT: 234801e04c3fSmrg assert(!has_stencil); 234901e04c3fSmrg return 1; /* D32_FLOAT */ 235001e04c3fSmrg case ISL_FORMAT_R24_UNORM_X8_TYPELESS: 235101e04c3fSmrg if (has_stencil) { 235201e04c3fSmrg assert(ISL_DEV_GEN(dev) < 7); 235301e04c3fSmrg return 2; /* D24_UNORM_S8_UINT */ 235401e04c3fSmrg } else { 235501e04c3fSmrg assert(ISL_DEV_GEN(dev) >= 5); 235601e04c3fSmrg return 3; /* D24_UNORM_X8_UINT */ 235701e04c3fSmrg } 235801e04c3fSmrg case ISL_FORMAT_R16_UNORM: 235901e04c3fSmrg assert(!has_stencil); 236001e04c3fSmrg return 5; /* D16_UNORM */ 236101e04c3fSmrg } 236201e04c3fSmrg} 236301e04c3fSmrg 236401e04c3fSmrgbool 236501e04c3fSmrgisl_swizzle_supports_rendering(const struct gen_device_info *devinfo, 236601e04c3fSmrg struct isl_swizzle swizzle) 236701e04c3fSmrg{ 236801e04c3fSmrg if (devinfo->is_haswell) { 236901e04c3fSmrg /* From the Haswell PRM, 237001e04c3fSmrg * RENDER_SURFACE_STATE::Shader Channel Select Red 237101e04c3fSmrg * 237201e04c3fSmrg * "The Shader channel selects also define which shader channels are 237301e04c3fSmrg * written to which surface channel. If the Shader channel select is 237401e04c3fSmrg * SCS_ZERO or SCS_ONE then it is not written to the surface. If the 237501e04c3fSmrg * shader channel select is SCS_RED it is written to the surface red 237601e04c3fSmrg * channel and so on. If more than one shader channel select is set 237701e04c3fSmrg * to the same surface channel only the first shader channel in RGBA 237801e04c3fSmrg * order will be written." 237901e04c3fSmrg */ 238001e04c3fSmrg return true; 238101e04c3fSmrg } else if (devinfo->gen <= 7) { 238201e04c3fSmrg /* Ivy Bridge and early doesn't have any swizzling */ 238301e04c3fSmrg return isl_swizzle_is_identity(swizzle); 238401e04c3fSmrg } else { 238501e04c3fSmrg /* From the Sky Lake PRM Vol. 2d, 238601e04c3fSmrg * RENDER_SURFACE_STATE::Shader Channel Select Red 238701e04c3fSmrg * 238801e04c3fSmrg * "For Render Target, Red, Green and Blue Shader Channel Selects 238901e04c3fSmrg * MUST be such that only valid components can be swapped i.e. only 239001e04c3fSmrg * change the order of components in the pixel. Any other values for 239101e04c3fSmrg * these Shader Channel Select fields are not valid for Render 239201e04c3fSmrg * Targets. This also means that there MUST not be multiple shader 239301e04c3fSmrg * channels mapped to the same RT channel." 239401e04c3fSmrg * 239501e04c3fSmrg * From the Sky Lake PRM Vol. 2d, 239601e04c3fSmrg * RENDER_SURFACE_STATE::Shader Channel Select Alpha 239701e04c3fSmrg * 239801e04c3fSmrg * "For Render Target, this field MUST be programmed to 239901e04c3fSmrg * value = SCS_ALPHA." 240001e04c3fSmrg */ 240101e04c3fSmrg return (swizzle.r == ISL_CHANNEL_SELECT_RED || 240201e04c3fSmrg swizzle.r == ISL_CHANNEL_SELECT_GREEN || 240301e04c3fSmrg swizzle.r == ISL_CHANNEL_SELECT_BLUE) && 240401e04c3fSmrg (swizzle.g == ISL_CHANNEL_SELECT_RED || 240501e04c3fSmrg swizzle.g == ISL_CHANNEL_SELECT_GREEN || 240601e04c3fSmrg swizzle.g == ISL_CHANNEL_SELECT_BLUE) && 240701e04c3fSmrg (swizzle.b == ISL_CHANNEL_SELECT_RED || 240801e04c3fSmrg swizzle.b == ISL_CHANNEL_SELECT_GREEN || 240901e04c3fSmrg swizzle.b == ISL_CHANNEL_SELECT_BLUE) && 241001e04c3fSmrg swizzle.r != swizzle.g && 241101e04c3fSmrg swizzle.r != swizzle.b && 241201e04c3fSmrg swizzle.g != swizzle.b && 241301e04c3fSmrg swizzle.a == ISL_CHANNEL_SELECT_ALPHA; 241401e04c3fSmrg } 241501e04c3fSmrg} 241601e04c3fSmrg 241701e04c3fSmrgstatic enum isl_channel_select 241801e04c3fSmrgswizzle_select(enum isl_channel_select chan, struct isl_swizzle swizzle) 241901e04c3fSmrg{ 242001e04c3fSmrg switch (chan) { 242101e04c3fSmrg case ISL_CHANNEL_SELECT_ZERO: 242201e04c3fSmrg case ISL_CHANNEL_SELECT_ONE: 242301e04c3fSmrg return chan; 242401e04c3fSmrg case ISL_CHANNEL_SELECT_RED: 242501e04c3fSmrg return swizzle.r; 242601e04c3fSmrg case ISL_CHANNEL_SELECT_GREEN: 242701e04c3fSmrg return swizzle.g; 242801e04c3fSmrg case ISL_CHANNEL_SELECT_BLUE: 242901e04c3fSmrg return swizzle.b; 243001e04c3fSmrg case ISL_CHANNEL_SELECT_ALPHA: 243101e04c3fSmrg return swizzle.a; 243201e04c3fSmrg default: 243301e04c3fSmrg unreachable("Invalid swizzle component"); 243401e04c3fSmrg } 243501e04c3fSmrg} 243601e04c3fSmrg 243701e04c3fSmrg/** 243801e04c3fSmrg * Returns the single swizzle that is equivalent to applying the two given 243901e04c3fSmrg * swizzles in sequence. 244001e04c3fSmrg */ 244101e04c3fSmrgstruct isl_swizzle 244201e04c3fSmrgisl_swizzle_compose(struct isl_swizzle first, struct isl_swizzle second) 244301e04c3fSmrg{ 244401e04c3fSmrg return (struct isl_swizzle) { 244501e04c3fSmrg .r = swizzle_select(first.r, second), 244601e04c3fSmrg .g = swizzle_select(first.g, second), 244701e04c3fSmrg .b = swizzle_select(first.b, second), 244801e04c3fSmrg .a = swizzle_select(first.a, second), 244901e04c3fSmrg }; 245001e04c3fSmrg} 245101e04c3fSmrg 245201e04c3fSmrg/** 245301e04c3fSmrg * Returns a swizzle that is the pseudo-inverse of this swizzle. 245401e04c3fSmrg */ 245501e04c3fSmrgstruct isl_swizzle 245601e04c3fSmrgisl_swizzle_invert(struct isl_swizzle swizzle) 245701e04c3fSmrg{ 245801e04c3fSmrg /* Default to zero for channels which do not show up in the swizzle */ 245901e04c3fSmrg enum isl_channel_select chans[4] = { 246001e04c3fSmrg ISL_CHANNEL_SELECT_ZERO, 246101e04c3fSmrg ISL_CHANNEL_SELECT_ZERO, 246201e04c3fSmrg ISL_CHANNEL_SELECT_ZERO, 246301e04c3fSmrg ISL_CHANNEL_SELECT_ZERO, 246401e04c3fSmrg }; 246501e04c3fSmrg 246601e04c3fSmrg /* We go in ABGR order so that, if there are any duplicates, the first one 246701e04c3fSmrg * is taken if you look at it in RGBA order. This is what Haswell hardware 246801e04c3fSmrg * does for render target swizzles. 246901e04c3fSmrg */ 247001e04c3fSmrg if ((unsigned)(swizzle.a - ISL_CHANNEL_SELECT_RED) < 4) 247101e04c3fSmrg chans[swizzle.a - ISL_CHANNEL_SELECT_RED] = ISL_CHANNEL_SELECT_ALPHA; 247201e04c3fSmrg if ((unsigned)(swizzle.b - ISL_CHANNEL_SELECT_RED) < 4) 247301e04c3fSmrg chans[swizzle.b - ISL_CHANNEL_SELECT_RED] = ISL_CHANNEL_SELECT_BLUE; 247401e04c3fSmrg if ((unsigned)(swizzle.g - ISL_CHANNEL_SELECT_RED) < 4) 247501e04c3fSmrg chans[swizzle.g - ISL_CHANNEL_SELECT_RED] = ISL_CHANNEL_SELECT_GREEN; 247601e04c3fSmrg if ((unsigned)(swizzle.r - ISL_CHANNEL_SELECT_RED) < 4) 247701e04c3fSmrg chans[swizzle.r - ISL_CHANNEL_SELECT_RED] = ISL_CHANNEL_SELECT_RED; 247801e04c3fSmrg 247901e04c3fSmrg return (struct isl_swizzle) { chans[0], chans[1], chans[2], chans[3] }; 248001e04c3fSmrg} 2481