1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2017 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 12bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci/** 24bf215546Sopenharmony_ci * @file iris_formats.c 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci * Converts Gallium formats (PIPE_FORMAT_*) to hardware ones (ISL_FORMAT_*). 27bf215546Sopenharmony_ci * Provides information about which formats support what features. 28bf215546Sopenharmony_ci */ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "util/bitscan.h" 31bf215546Sopenharmony_ci#include "util/macros.h" 32bf215546Sopenharmony_ci#include "util/format/u_format.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "iris_resource.h" 35bf215546Sopenharmony_ci#include "iris_screen.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cistruct iris_format_info 38bf215546Sopenharmony_ciiris_format_for_usage(const struct intel_device_info *devinfo, 39bf215546Sopenharmony_ci enum pipe_format pformat, 40bf215546Sopenharmony_ci isl_surf_usage_flags_t usage) 41bf215546Sopenharmony_ci{ 42bf215546Sopenharmony_ci enum isl_format format = isl_format_for_pipe_format(pformat); 43bf215546Sopenharmony_ci struct isl_swizzle swizzle = ISL_SWIZZLE_IDENTITY; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci if (format == ISL_FORMAT_UNSUPPORTED) 46bf215546Sopenharmony_ci return (struct iris_format_info) { .fmt = format, .swizzle = swizzle }; 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci const struct isl_format_layout *fmtl = isl_format_get_layout(format); 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci if (!util_format_is_srgb(pformat)) { 51bf215546Sopenharmony_ci if (util_format_is_intensity(pformat)) { 52bf215546Sopenharmony_ci swizzle = ISL_SWIZZLE(RED, RED, RED, RED); 53bf215546Sopenharmony_ci } else if (util_format_is_luminance(pformat)) { 54bf215546Sopenharmony_ci swizzle = ISL_SWIZZLE(RED, RED, RED, ONE); 55bf215546Sopenharmony_ci } else if (util_format_is_luminance_alpha(pformat)) { 56bf215546Sopenharmony_ci swizzle = ISL_SWIZZLE(RED, RED, RED, GREEN); 57bf215546Sopenharmony_ci } else if (util_format_is_alpha(pformat)) { 58bf215546Sopenharmony_ci swizzle = ISL_SWIZZLE(ZERO, ZERO, ZERO, RED); 59bf215546Sopenharmony_ci } 60bf215546Sopenharmony_ci } 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci /* When faking RGBX pipe formats with RGBA ISL formats, override alpha. */ 63bf215546Sopenharmony_ci if (!util_format_has_alpha(pformat) && fmtl->channels.a.type != ISL_VOID) { 64bf215546Sopenharmony_ci swizzle = ISL_SWIZZLE(RED, GREEN, BLUE, ONE); 65bf215546Sopenharmony_ci } 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci if ((usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) && 68bf215546Sopenharmony_ci pformat == PIPE_FORMAT_A8_UNORM) { 69bf215546Sopenharmony_ci /* Most of the hardware A/LA formats are not renderable, except 70bf215546Sopenharmony_ci * for A8_UNORM. SURFACE_STATE's shader channel select fields 71bf215546Sopenharmony_ci * cannot be used to swap RGB and A channels when rendering (as 72bf215546Sopenharmony_ci * it could impact alpha blending), so we have to use the actual 73bf215546Sopenharmony_ci * A8_UNORM format when rendering. 74bf215546Sopenharmony_ci */ 75bf215546Sopenharmony_ci format = ISL_FORMAT_A8_UNORM; 76bf215546Sopenharmony_ci swizzle = ISL_SWIZZLE_IDENTITY; 77bf215546Sopenharmony_ci } 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci /* We choose RGBA over RGBX for rendering the hardware doesn't support 80bf215546Sopenharmony_ci * rendering to RGBX. However, when this internal override is used on Gfx9+, 81bf215546Sopenharmony_ci * fast clears don't work correctly. 82bf215546Sopenharmony_ci * 83bf215546Sopenharmony_ci * i965 fixes this by pretending to not support RGBX formats, and the higher 84bf215546Sopenharmony_ci * layers of Mesa pick the RGBA format instead. Gallium doesn't work that 85bf215546Sopenharmony_ci * way, and might choose a different format, like BGRX instead of RGBX, 86bf215546Sopenharmony_ci * which will also cause problems when sampling from a surface fast cleared 87bf215546Sopenharmony_ci * as RGBX. So we always choose RGBA instead of RGBX explicitly 88bf215546Sopenharmony_ci * here. 89bf215546Sopenharmony_ci */ 90bf215546Sopenharmony_ci if (isl_format_is_rgbx(format) && 91bf215546Sopenharmony_ci !isl_format_supports_rendering(devinfo, format)) { 92bf215546Sopenharmony_ci format = isl_format_rgbx_to_rgba(format); 93bf215546Sopenharmony_ci swizzle = ISL_SWIZZLE(RED, GREEN, BLUE, ONE); 94bf215546Sopenharmony_ci } 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci return (struct iris_format_info) { .fmt = format, .swizzle = swizzle }; 97bf215546Sopenharmony_ci} 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci/** 100bf215546Sopenharmony_ci * The pscreen->is_format_supported() driver hook. 101bf215546Sopenharmony_ci * 102bf215546Sopenharmony_ci * Returns true if the given format is supported for the given usage 103bf215546Sopenharmony_ci * (PIPE_BIND_*) and sample count. 104bf215546Sopenharmony_ci */ 105bf215546Sopenharmony_cibool 106bf215546Sopenharmony_ciiris_is_format_supported(struct pipe_screen *pscreen, 107bf215546Sopenharmony_ci enum pipe_format pformat, 108bf215546Sopenharmony_ci enum pipe_texture_target target, 109bf215546Sopenharmony_ci unsigned sample_count, 110bf215546Sopenharmony_ci unsigned storage_sample_count, 111bf215546Sopenharmony_ci unsigned usage) 112bf215546Sopenharmony_ci{ 113bf215546Sopenharmony_ci struct iris_screen *screen = (struct iris_screen *) pscreen; 114bf215546Sopenharmony_ci const struct intel_device_info *devinfo = &screen->devinfo; 115bf215546Sopenharmony_ci uint32_t max_samples = devinfo->ver == 8 ? 8 : 16; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (sample_count > max_samples || 118bf215546Sopenharmony_ci !util_is_power_of_two_or_zero(sample_count)) 119bf215546Sopenharmony_ci return false; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci if (pformat == PIPE_FORMAT_NONE) 122bf215546Sopenharmony_ci return true; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci /* Rely on gallium fallbacks for better YUV format support. */ 125bf215546Sopenharmony_ci if (util_format_is_yuv(pformat)) 126bf215546Sopenharmony_ci return false; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci enum isl_format format = isl_format_for_pipe_format(pformat); 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci if (format == ISL_FORMAT_UNSUPPORTED) 131bf215546Sopenharmony_ci return false; 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci const struct isl_format_layout *fmtl = isl_format_get_layout(format); 134bf215546Sopenharmony_ci const bool is_integer = isl_format_has_int_channel(format); 135bf215546Sopenharmony_ci bool supported = true; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci if (sample_count > 1) 138bf215546Sopenharmony_ci supported &= isl_format_supports_multisampling(devinfo, format); 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci if (usage & PIPE_BIND_DEPTH_STENCIL) { 141bf215546Sopenharmony_ci supported &= format == ISL_FORMAT_R32_FLOAT_X8X24_TYPELESS || 142bf215546Sopenharmony_ci format == ISL_FORMAT_R32_FLOAT || 143bf215546Sopenharmony_ci format == ISL_FORMAT_R24_UNORM_X8_TYPELESS || 144bf215546Sopenharmony_ci format == ISL_FORMAT_R16_UNORM || 145bf215546Sopenharmony_ci format == ISL_FORMAT_R8_UINT; 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci if (usage & PIPE_BIND_RENDER_TARGET) { 149bf215546Sopenharmony_ci /* Alpha and luminance-alpha formats other than A8_UNORM are not 150bf215546Sopenharmony_ci * renderable. For texturing, we can use R or RG formats with 151bf215546Sopenharmony_ci * shader channel selects (SCS) to swizzle the data into the correct 152bf215546Sopenharmony_ci * channels. But for render targets, the hardware prohibits using 153bf215546Sopenharmony_ci * SCS to move shader outputs between the RGB and A channels, as it 154bf215546Sopenharmony_ci * would alter what data is used for alpha blending. 155bf215546Sopenharmony_ci * 156bf215546Sopenharmony_ci * For BLORP, we can apply the swizzle in the shader. But for 157bf215546Sopenharmony_ci * general rendering, this would mean recompiling the shader, which 158bf215546Sopenharmony_ci * we'd like to avoid doing. So we mark these formats non-renderable. 159bf215546Sopenharmony_ci * 160bf215546Sopenharmony_ci * We do support A8_UNORM as it's required and is renderable. 161bf215546Sopenharmony_ci */ 162bf215546Sopenharmony_ci if (pformat != PIPE_FORMAT_A8_UNORM && 163bf215546Sopenharmony_ci (util_format_is_alpha(pformat) || 164bf215546Sopenharmony_ci util_format_is_luminance_alpha(pformat))) 165bf215546Sopenharmony_ci supported = false; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci enum isl_format rt_format = format; 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci if (isl_format_is_rgbx(format) && 170bf215546Sopenharmony_ci !isl_format_supports_rendering(devinfo, format)) 171bf215546Sopenharmony_ci rt_format = isl_format_rgbx_to_rgba(format); 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci supported &= isl_format_supports_rendering(devinfo, rt_format); 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci if (!is_integer) 176bf215546Sopenharmony_ci supported &= isl_format_supports_alpha_blending(devinfo, rt_format); 177bf215546Sopenharmony_ci } 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci if (usage & PIPE_BIND_SHADER_IMAGE) { 180bf215546Sopenharmony_ci /* Dataport doesn't support compression, and we can't resolve an MCS 181bf215546Sopenharmony_ci * compressed surface. (Buffer images may have sample count of 0.) 182bf215546Sopenharmony_ci */ 183bf215546Sopenharmony_ci supported &= sample_count == 0; 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci supported &= isl_format_supports_typed_writes(devinfo, format); 186bf215546Sopenharmony_ci supported &= isl_has_matching_typed_storage_image_format(devinfo, format); 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci if (usage & PIPE_BIND_SAMPLER_VIEW) { 190bf215546Sopenharmony_ci supported &= isl_format_supports_sampling(devinfo, format); 191bf215546Sopenharmony_ci if (!is_integer) 192bf215546Sopenharmony_ci supported &= isl_format_supports_filtering(devinfo, format); 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci /* Don't advertise 3-component RGB formats for non-buffer textures. 195bf215546Sopenharmony_ci * This ensures that they are renderable from an API perspective since 196bf215546Sopenharmony_ci * gallium frontends will fall back to RGBA or RGBX, which are 197bf215546Sopenharmony_ci * renderable. We want to render internally for copies and blits, 198bf215546Sopenharmony_ci * even if the application doesn't. 199bf215546Sopenharmony_ci * 200bf215546Sopenharmony_ci * Buffer textures don't need to be renderable, so we support real RGB. 201bf215546Sopenharmony_ci * This is useful for PBO upload, and 32-bit RGB support is mandatory. 202bf215546Sopenharmony_ci */ 203bf215546Sopenharmony_ci if (target != PIPE_BUFFER) 204bf215546Sopenharmony_ci supported &= fmtl->bpb != 24 && fmtl->bpb != 48 && fmtl->bpb != 96; 205bf215546Sopenharmony_ci } 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci if (usage & PIPE_BIND_VERTEX_BUFFER) 208bf215546Sopenharmony_ci supported &= isl_format_supports_vertex_fetch(devinfo, format); 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci if (usage & PIPE_BIND_INDEX_BUFFER) { 211bf215546Sopenharmony_ci supported &= format == ISL_FORMAT_R8_UINT || 212bf215546Sopenharmony_ci format == ISL_FORMAT_R16_UINT || 213bf215546Sopenharmony_ci format == ISL_FORMAT_R32_UINT; 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci /* TODO: Support ASTC 5x5 on Gfx9 properly. This means implementing 217bf215546Sopenharmony_ci * a complex sampler workaround (see i965's gfx9_apply_astc5x5_wa_flush). 218bf215546Sopenharmony_ci * Without it, st/mesa will emulate ASTC 5x5 via uncompressed textures. 219bf215546Sopenharmony_ci */ 220bf215546Sopenharmony_ci if (devinfo->ver == 9 && (format == ISL_FORMAT_ASTC_LDR_2D_5X5_FLT16 || 221bf215546Sopenharmony_ci format == ISL_FORMAT_ASTC_LDR_2D_5X5_U8SRGB)) 222bf215546Sopenharmony_ci return false; 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci return supported; 225bf215546Sopenharmony_ci} 226bf215546Sopenharmony_ci 227