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 (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "nir_builder.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "util/format_rgb9e5.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_cistatic inline nir_ssa_def * 29bf215546Sopenharmony_cinir_shift_imm(nir_builder *b, nir_ssa_def *value, int left_shift) 30bf215546Sopenharmony_ci{ 31bf215546Sopenharmony_ci if (left_shift > 0) 32bf215546Sopenharmony_ci return nir_ishl(b, value, nir_imm_int(b, left_shift)); 33bf215546Sopenharmony_ci else if (left_shift < 0) 34bf215546Sopenharmony_ci return nir_ushr(b, value, nir_imm_int(b, -left_shift)); 35bf215546Sopenharmony_ci else 36bf215546Sopenharmony_ci return value; 37bf215546Sopenharmony_ci} 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_cistatic inline nir_ssa_def * 40bf215546Sopenharmony_cinir_shift(nir_builder *b, nir_ssa_def *value, nir_ssa_def *left_shift) 41bf215546Sopenharmony_ci{ 42bf215546Sopenharmony_ci return nir_bcsel(b, 43bf215546Sopenharmony_ci nir_ige(b, left_shift, nir_imm_int(b, 0)), 44bf215546Sopenharmony_ci nir_ishl(b, value, left_shift), 45bf215546Sopenharmony_ci nir_ushr(b, value, nir_ineg(b, left_shift))); 46bf215546Sopenharmony_ci} 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistatic inline nir_ssa_def * 49bf215546Sopenharmony_cinir_mask_shift(struct nir_builder *b, nir_ssa_def *src, 50bf215546Sopenharmony_ci uint32_t mask, int left_shift) 51bf215546Sopenharmony_ci{ 52bf215546Sopenharmony_ci return nir_shift_imm(b, nir_iand(b, src, nir_imm_int(b, mask)), left_shift); 53bf215546Sopenharmony_ci} 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_cistatic inline nir_ssa_def * 56bf215546Sopenharmony_cinir_mask_shift_or(struct nir_builder *b, nir_ssa_def *dst, nir_ssa_def *src, 57bf215546Sopenharmony_ci uint32_t src_mask, int src_left_shift) 58bf215546Sopenharmony_ci{ 59bf215546Sopenharmony_ci return nir_ior(b, nir_mask_shift(b, src, src_mask, src_left_shift), dst); 60bf215546Sopenharmony_ci} 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_cistatic inline nir_ssa_def * 63bf215546Sopenharmony_cinir_format_mask_uvec(nir_builder *b, nir_ssa_def *src, const unsigned *bits) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci nir_const_value mask[NIR_MAX_VEC_COMPONENTS]; 66bf215546Sopenharmony_ci memset(mask, 0, sizeof(mask)); 67bf215546Sopenharmony_ci for (unsigned i = 0; i < src->num_components; i++) { 68bf215546Sopenharmony_ci assert(bits[i] < 32); 69bf215546Sopenharmony_ci mask[i].u32 = (1u << bits[i]) - 1; 70bf215546Sopenharmony_ci } 71bf215546Sopenharmony_ci return nir_iand(b, src, nir_build_imm(b, src->num_components, 32, mask)); 72bf215546Sopenharmony_ci} 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_cistatic inline nir_ssa_def * 75bf215546Sopenharmony_cinir_format_sign_extend_ivec(nir_builder *b, nir_ssa_def *src, 76bf215546Sopenharmony_ci const unsigned *bits) 77bf215546Sopenharmony_ci{ 78bf215546Sopenharmony_ci assert(src->num_components <= 4); 79bf215546Sopenharmony_ci nir_ssa_def *comps[4]; 80bf215546Sopenharmony_ci for (unsigned i = 0; i < src->num_components; i++) { 81bf215546Sopenharmony_ci nir_ssa_def *shift = nir_imm_int(b, src->bit_size - bits[i]); 82bf215546Sopenharmony_ci comps[i] = nir_ishr(b, nir_ishl(b, nir_channel(b, src, i), shift), shift); 83bf215546Sopenharmony_ci } 84bf215546Sopenharmony_ci return nir_vec(b, comps, src->num_components); 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_cistatic inline nir_ssa_def * 89bf215546Sopenharmony_cinir_format_unpack_int(nir_builder *b, nir_ssa_def *packed, 90bf215546Sopenharmony_ci const unsigned *bits, unsigned num_components, 91bf215546Sopenharmony_ci bool sign_extend) 92bf215546Sopenharmony_ci{ 93bf215546Sopenharmony_ci assert(num_components >= 1 && num_components <= 4); 94bf215546Sopenharmony_ci const unsigned bit_size = packed->bit_size; 95bf215546Sopenharmony_ci nir_ssa_def *comps[4]; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci if (bits[0] >= bit_size) { 98bf215546Sopenharmony_ci assert(bits[0] == bit_size); 99bf215546Sopenharmony_ci assert(num_components == 1); 100bf215546Sopenharmony_ci return packed; 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci unsigned next_chan = 0; 104bf215546Sopenharmony_ci unsigned offset = 0; 105bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 106bf215546Sopenharmony_ci assert(bits[i] < bit_size); 107bf215546Sopenharmony_ci assert(offset + bits[i] <= bit_size); 108bf215546Sopenharmony_ci nir_ssa_def *chan = nir_channel(b, packed, next_chan); 109bf215546Sopenharmony_ci nir_ssa_def *lshift = nir_imm_int(b, bit_size - (offset + bits[i])); 110bf215546Sopenharmony_ci nir_ssa_def *rshift = nir_imm_int(b, bit_size - bits[i]); 111bf215546Sopenharmony_ci if (sign_extend) 112bf215546Sopenharmony_ci comps[i] = nir_ishr(b, nir_ishl(b, chan, lshift), rshift); 113bf215546Sopenharmony_ci else 114bf215546Sopenharmony_ci comps[i] = nir_ushr(b, nir_ishl(b, chan, lshift), rshift); 115bf215546Sopenharmony_ci offset += bits[i]; 116bf215546Sopenharmony_ci if (offset >= bit_size) { 117bf215546Sopenharmony_ci next_chan++; 118bf215546Sopenharmony_ci offset -= bit_size; 119bf215546Sopenharmony_ci } 120bf215546Sopenharmony_ci } 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci return nir_vec(b, comps, num_components); 123bf215546Sopenharmony_ci} 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_cistatic inline nir_ssa_def * 126bf215546Sopenharmony_cinir_format_unpack_uint(nir_builder *b, nir_ssa_def *packed, 127bf215546Sopenharmony_ci const unsigned *bits, unsigned num_components) 128bf215546Sopenharmony_ci{ 129bf215546Sopenharmony_ci return nir_format_unpack_int(b, packed, bits, num_components, false); 130bf215546Sopenharmony_ci} 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_cistatic inline nir_ssa_def * 133bf215546Sopenharmony_cinir_format_unpack_sint(nir_builder *b, nir_ssa_def *packed, 134bf215546Sopenharmony_ci const unsigned *bits, unsigned num_components) 135bf215546Sopenharmony_ci{ 136bf215546Sopenharmony_ci return nir_format_unpack_int(b, packed, bits, num_components, true); 137bf215546Sopenharmony_ci} 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_cistatic inline nir_ssa_def * 140bf215546Sopenharmony_cinir_format_pack_uint_unmasked(nir_builder *b, nir_ssa_def *color, 141bf215546Sopenharmony_ci const unsigned *bits, unsigned num_components) 142bf215546Sopenharmony_ci{ 143bf215546Sopenharmony_ci assert(num_components >= 1 && num_components <= 4); 144bf215546Sopenharmony_ci nir_ssa_def *packed = nir_imm_int(b, 0); 145bf215546Sopenharmony_ci unsigned offset = 0; 146bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 147bf215546Sopenharmony_ci packed = nir_ior(b, packed, nir_shift_imm(b, nir_channel(b, color, i), 148bf215546Sopenharmony_ci offset)); 149bf215546Sopenharmony_ci offset += bits[i]; 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci assert(offset <= packed->bit_size); 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci return packed; 154bf215546Sopenharmony_ci} 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cistatic inline nir_ssa_def * 157bf215546Sopenharmony_cinir_format_pack_uint_unmasked_ssa(nir_builder *b, nir_ssa_def *color, 158bf215546Sopenharmony_ci nir_ssa_def *bits) 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci nir_ssa_def *packed = nir_imm_int(b, 0); 161bf215546Sopenharmony_ci nir_ssa_def *offset = nir_imm_int(b, 0); 162bf215546Sopenharmony_ci for (unsigned i = 0; i < bits->num_components; i++) { 163bf215546Sopenharmony_ci packed = nir_ior(b, packed, nir_ishl(b, nir_channel(b, color, i), offset)); 164bf215546Sopenharmony_ci offset = nir_iadd(b, offset, nir_channel(b, bits, i)); 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci return packed; 167bf215546Sopenharmony_ci} 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_cistatic inline nir_ssa_def * 170bf215546Sopenharmony_cinir_format_pack_uint(nir_builder *b, nir_ssa_def *color, 171bf215546Sopenharmony_ci const unsigned *bits, unsigned num_components) 172bf215546Sopenharmony_ci{ 173bf215546Sopenharmony_ci return nir_format_pack_uint_unmasked(b, nir_format_mask_uvec(b, color, bits), 174bf215546Sopenharmony_ci bits, num_components); 175bf215546Sopenharmony_ci} 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_cistatic inline nir_ssa_def * 178bf215546Sopenharmony_cinir_format_bitcast_uvec_unmasked(nir_builder *b, nir_ssa_def *src, 179bf215546Sopenharmony_ci unsigned src_bits, unsigned dst_bits) 180bf215546Sopenharmony_ci{ 181bf215546Sopenharmony_ci assert(src->bit_size >= src_bits && src->bit_size >= dst_bits); 182bf215546Sopenharmony_ci assert(src_bits == 8 || src_bits == 16 || src_bits == 32); 183bf215546Sopenharmony_ci assert(dst_bits == 8 || dst_bits == 16 || dst_bits == 32); 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci if (src_bits == dst_bits) 186bf215546Sopenharmony_ci return src; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci const unsigned dst_components = 189bf215546Sopenharmony_ci DIV_ROUND_UP(src->num_components * src_bits, dst_bits); 190bf215546Sopenharmony_ci assert(dst_components <= 4); 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci nir_ssa_def *dst_chan[4] = {0}; 193bf215546Sopenharmony_ci if (dst_bits > src_bits) { 194bf215546Sopenharmony_ci unsigned shift = 0; 195bf215546Sopenharmony_ci unsigned dst_idx = 0; 196bf215546Sopenharmony_ci for (unsigned i = 0; i < src->num_components; i++) { 197bf215546Sopenharmony_ci nir_ssa_def *shifted = nir_ishl(b, nir_channel(b, src, i), 198bf215546Sopenharmony_ci nir_imm_int(b, shift)); 199bf215546Sopenharmony_ci if (shift == 0) { 200bf215546Sopenharmony_ci dst_chan[dst_idx] = shifted; 201bf215546Sopenharmony_ci } else { 202bf215546Sopenharmony_ci dst_chan[dst_idx] = nir_ior(b, dst_chan[dst_idx], shifted); 203bf215546Sopenharmony_ci } 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci shift += src_bits; 206bf215546Sopenharmony_ci if (shift >= dst_bits) { 207bf215546Sopenharmony_ci dst_idx++; 208bf215546Sopenharmony_ci shift = 0; 209bf215546Sopenharmony_ci } 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci } else { 212bf215546Sopenharmony_ci nir_ssa_def *mask = nir_imm_int(b, ~0u >> (32 - dst_bits)); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci unsigned src_idx = 0; 215bf215546Sopenharmony_ci unsigned shift = 0; 216bf215546Sopenharmony_ci for (unsigned i = 0; i < dst_components; i++) { 217bf215546Sopenharmony_ci dst_chan[i] = nir_iand(b, nir_ushr_imm(b, nir_channel(b, src, src_idx), 218bf215546Sopenharmony_ci shift), 219bf215546Sopenharmony_ci mask); 220bf215546Sopenharmony_ci shift += dst_bits; 221bf215546Sopenharmony_ci if (shift >= src_bits) { 222bf215546Sopenharmony_ci src_idx++; 223bf215546Sopenharmony_ci shift = 0; 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci return nir_vec(b, dst_chan, dst_components); 229bf215546Sopenharmony_ci} 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_cistatic inline nir_ssa_def * 232bf215546Sopenharmony_ci_nir_format_norm_factor(nir_builder *b, const unsigned *bits, 233bf215546Sopenharmony_ci unsigned num_components, 234bf215546Sopenharmony_ci bool is_signed) 235bf215546Sopenharmony_ci{ 236bf215546Sopenharmony_ci nir_const_value factor[NIR_MAX_VEC_COMPONENTS]; 237bf215546Sopenharmony_ci memset(factor, 0, sizeof(factor)); 238bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 239bf215546Sopenharmony_ci assert(bits[i] <= 32); 240bf215546Sopenharmony_ci factor[i].f32 = (1ull << (bits[i] - is_signed)) - 1; 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci return nir_build_imm(b, num_components, 32, factor); 243bf215546Sopenharmony_ci} 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_cistatic inline nir_ssa_def * 246bf215546Sopenharmony_cinir_format_unorm_to_float(nir_builder *b, nir_ssa_def *u, const unsigned *bits) 247bf215546Sopenharmony_ci{ 248bf215546Sopenharmony_ci nir_ssa_def *factor = 249bf215546Sopenharmony_ci _nir_format_norm_factor(b, bits, u->num_components, false); 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci return nir_fdiv(b, nir_u2f32(b, u), factor); 252bf215546Sopenharmony_ci} 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_cistatic inline nir_ssa_def * 255bf215546Sopenharmony_cinir_format_snorm_to_float(nir_builder *b, nir_ssa_def *s, const unsigned *bits) 256bf215546Sopenharmony_ci{ 257bf215546Sopenharmony_ci nir_ssa_def *factor = 258bf215546Sopenharmony_ci _nir_format_norm_factor(b, bits, s->num_components, true); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci return nir_fmax(b, nir_fdiv(b, nir_i2f32(b, s), factor), 261bf215546Sopenharmony_ci nir_imm_float(b, -1.0f)); 262bf215546Sopenharmony_ci} 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_cistatic inline nir_ssa_def * 265bf215546Sopenharmony_cinir_format_float_to_unorm(nir_builder *b, nir_ssa_def *f, const unsigned *bits) 266bf215546Sopenharmony_ci{ 267bf215546Sopenharmony_ci nir_ssa_def *factor = 268bf215546Sopenharmony_ci _nir_format_norm_factor(b, bits, f->num_components, false); 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci /* Clamp to the range [0, 1] */ 271bf215546Sopenharmony_ci f = nir_fsat(b, f); 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci return nir_f2u32(b, nir_fround_even(b, nir_fmul(b, f, factor))); 274bf215546Sopenharmony_ci} 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_cistatic inline nir_ssa_def * 277bf215546Sopenharmony_cinir_format_float_to_snorm(nir_builder *b, nir_ssa_def *f, const unsigned *bits) 278bf215546Sopenharmony_ci{ 279bf215546Sopenharmony_ci nir_ssa_def *factor = 280bf215546Sopenharmony_ci _nir_format_norm_factor(b, bits, f->num_components, true); 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci /* Clamp to the range [-1, 1] */ 283bf215546Sopenharmony_ci f = nir_fmin(b, nir_fmax(b, f, nir_imm_float(b, -1)), nir_imm_float(b, 1)); 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci return nir_f2i32(b, nir_fround_even(b, nir_fmul(b, f, factor))); 286bf215546Sopenharmony_ci} 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci/* Converts a vector of floats to a vector of half-floats packed in the low 16 289bf215546Sopenharmony_ci * bits. 290bf215546Sopenharmony_ci */ 291bf215546Sopenharmony_cistatic inline nir_ssa_def * 292bf215546Sopenharmony_cinir_format_float_to_half(nir_builder *b, nir_ssa_def *f) 293bf215546Sopenharmony_ci{ 294bf215546Sopenharmony_ci nir_ssa_def *zero = nir_imm_float(b, 0); 295bf215546Sopenharmony_ci nir_ssa_def *f16comps[4]; 296bf215546Sopenharmony_ci for (unsigned i = 0; i < f->num_components; i++) 297bf215546Sopenharmony_ci f16comps[i] = nir_pack_half_2x16_split(b, nir_channel(b, f, i), zero); 298bf215546Sopenharmony_ci return nir_vec(b, f16comps, f->num_components); 299bf215546Sopenharmony_ci} 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_cistatic inline nir_ssa_def * 302bf215546Sopenharmony_cinir_format_linear_to_srgb(nir_builder *b, nir_ssa_def *c) 303bf215546Sopenharmony_ci{ 304bf215546Sopenharmony_ci nir_ssa_def *linear = nir_fmul(b, c, nir_imm_float(b, 12.92f)); 305bf215546Sopenharmony_ci nir_ssa_def *curved = 306bf215546Sopenharmony_ci nir_fsub(b, nir_fmul(b, nir_imm_float(b, 1.055f), 307bf215546Sopenharmony_ci nir_fpow(b, c, nir_imm_float(b, 1.0 / 2.4))), 308bf215546Sopenharmony_ci nir_imm_float(b, 0.055f)); 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci return nir_fsat(b, nir_bcsel(b, nir_flt(b, c, nir_imm_float(b, 0.0031308f)), 311bf215546Sopenharmony_ci linear, curved)); 312bf215546Sopenharmony_ci} 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_cistatic inline nir_ssa_def * 315bf215546Sopenharmony_cinir_format_srgb_to_linear(nir_builder *b, nir_ssa_def *c) 316bf215546Sopenharmony_ci{ 317bf215546Sopenharmony_ci nir_ssa_def *linear = nir_fdiv(b, c, nir_imm_float(b, 12.92f)); 318bf215546Sopenharmony_ci nir_ssa_def *curved = 319bf215546Sopenharmony_ci nir_fpow(b, nir_fdiv(b, nir_fadd(b, c, nir_imm_float(b, 0.055f)), 320bf215546Sopenharmony_ci nir_imm_float(b, 1.055f)), 321bf215546Sopenharmony_ci nir_imm_float(b, 2.4f)); 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci return nir_fsat(b, nir_bcsel(b, nir_fge(b, nir_imm_float(b, 0.04045f), c), 324bf215546Sopenharmony_ci linear, curved)); 325bf215546Sopenharmony_ci} 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci/* Clamps a vector of uints so they don't extend beyond the given number of 328bf215546Sopenharmony_ci * bits per channel. 329bf215546Sopenharmony_ci */ 330bf215546Sopenharmony_cistatic inline nir_ssa_def * 331bf215546Sopenharmony_cinir_format_clamp_uint(nir_builder *b, nir_ssa_def *f, const unsigned *bits) 332bf215546Sopenharmony_ci{ 333bf215546Sopenharmony_ci if (bits[0] == 32) 334bf215546Sopenharmony_ci return f; 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci nir_const_value max[NIR_MAX_VEC_COMPONENTS]; 337bf215546Sopenharmony_ci memset(max, 0, sizeof(max)); 338bf215546Sopenharmony_ci for (unsigned i = 0; i < f->num_components; i++) { 339bf215546Sopenharmony_ci assert(bits[i] < 32); 340bf215546Sopenharmony_ci max[i].u32 = (1 << bits[i]) - 1; 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci return nir_umin(b, f, nir_build_imm(b, f->num_components, 32, max)); 343bf215546Sopenharmony_ci} 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci/* Clamps a vector of sints so they don't extend beyond the given number of 346bf215546Sopenharmony_ci * bits per channel. 347bf215546Sopenharmony_ci */ 348bf215546Sopenharmony_cistatic inline nir_ssa_def * 349bf215546Sopenharmony_cinir_format_clamp_sint(nir_builder *b, nir_ssa_def *f, const unsigned *bits) 350bf215546Sopenharmony_ci{ 351bf215546Sopenharmony_ci if (bits[0] == 32) 352bf215546Sopenharmony_ci return f; 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci nir_const_value min[NIR_MAX_VEC_COMPONENTS], max[NIR_MAX_VEC_COMPONENTS]; 355bf215546Sopenharmony_ci memset(min, 0, sizeof(min)); 356bf215546Sopenharmony_ci memset(max, 0, sizeof(max)); 357bf215546Sopenharmony_ci for (unsigned i = 0; i < f->num_components; i++) { 358bf215546Sopenharmony_ci assert(bits[i] < 32); 359bf215546Sopenharmony_ci max[i].i32 = (1 << (bits[i] - 1)) - 1; 360bf215546Sopenharmony_ci min[i].i32 = -(1 << (bits[i] - 1)); 361bf215546Sopenharmony_ci } 362bf215546Sopenharmony_ci f = nir_imin(b, f, nir_build_imm(b, f->num_components, 32, max)); 363bf215546Sopenharmony_ci f = nir_imax(b, f, nir_build_imm(b, f->num_components, 32, min)); 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci return f; 366bf215546Sopenharmony_ci} 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_cistatic inline nir_ssa_def * 369bf215546Sopenharmony_cinir_format_unpack_11f11f10f(nir_builder *b, nir_ssa_def *packed) 370bf215546Sopenharmony_ci{ 371bf215546Sopenharmony_ci nir_ssa_def *chans[3]; 372bf215546Sopenharmony_ci chans[0] = nir_mask_shift(b, packed, 0x000007ff, 4); 373bf215546Sopenharmony_ci chans[1] = nir_mask_shift(b, packed, 0x003ff800, -7); 374bf215546Sopenharmony_ci chans[2] = nir_mask_shift(b, packed, 0xffc00000, -17); 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci for (unsigned i = 0; i < 3; i++) 377bf215546Sopenharmony_ci chans[i] = nir_unpack_half_2x16_split_x(b, chans[i]); 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci return nir_vec(b, chans, 3); 380bf215546Sopenharmony_ci} 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_cistatic inline nir_ssa_def * 383bf215546Sopenharmony_cinir_format_pack_11f11f10f(nir_builder *b, nir_ssa_def *color) 384bf215546Sopenharmony_ci{ 385bf215546Sopenharmony_ci /* 10 and 11-bit floats are unsigned. Clamp to non-negative */ 386bf215546Sopenharmony_ci nir_ssa_def *clamped = nir_fmax(b, color, nir_imm_float(b, 0)); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci nir_ssa_def *undef = nir_ssa_undef(b, 1, color->bit_size); 389bf215546Sopenharmony_ci nir_ssa_def *p1 = nir_pack_half_2x16_split(b, nir_channel(b, clamped, 0), 390bf215546Sopenharmony_ci nir_channel(b, clamped, 1)); 391bf215546Sopenharmony_ci nir_ssa_def *p2 = nir_pack_half_2x16_split(b, nir_channel(b, clamped, 2), 392bf215546Sopenharmony_ci undef); 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci /* A 10 or 11-bit float has the same exponent as a 16-bit float but with 395bf215546Sopenharmony_ci * fewer mantissa bits and no sign bit. All we have to do is throw away 396bf215546Sopenharmony_ci * the sign bit and the bottom mantissa bits and shift it into place. 397bf215546Sopenharmony_ci */ 398bf215546Sopenharmony_ci nir_ssa_def *packed = nir_imm_int(b, 0); 399bf215546Sopenharmony_ci packed = nir_mask_shift_or(b, packed, p1, 0x00007ff0, -4); 400bf215546Sopenharmony_ci packed = nir_mask_shift_or(b, packed, p1, 0x7ff00000, -9); 401bf215546Sopenharmony_ci packed = nir_mask_shift_or(b, packed, p2, 0x00007fe0, 17); 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci return packed; 404bf215546Sopenharmony_ci} 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_cistatic inline nir_ssa_def * 407bf215546Sopenharmony_cinir_format_pack_r9g9b9e5(nir_builder *b, nir_ssa_def *color) 408bf215546Sopenharmony_ci{ 409bf215546Sopenharmony_ci /* See also float3_to_rgb9e5 */ 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci /* First, we need to clamp it to range. */ 412bf215546Sopenharmony_ci nir_ssa_def *clamped = nir_fmin(b, color, nir_imm_float(b, MAX_RGB9E5)); 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci /* Get rid of negatives and NaN */ 415bf215546Sopenharmony_ci clamped = nir_bcsel(b, nir_ult(b, nir_imm_int(b, 0x7f800000), color), 416bf215546Sopenharmony_ci nir_imm_float(b, 0), clamped); 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ci /* maxrgb.u = MAX3(rc.u, gc.u, bc.u); */ 419bf215546Sopenharmony_ci nir_ssa_def *maxu = nir_umax(b, nir_channel(b, clamped, 0), 420bf215546Sopenharmony_ci nir_umax(b, nir_channel(b, clamped, 1), 421bf215546Sopenharmony_ci nir_channel(b, clamped, 2))); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci /* maxrgb.u += maxrgb.u & (1 << (23-9)); */ 424bf215546Sopenharmony_ci maxu = nir_iadd(b, maxu, nir_iand(b, maxu, nir_imm_int(b, 1 << 14))); 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci /* exp_shared = MAX2((maxrgb.u >> 23), -RGB9E5_EXP_BIAS - 1 + 127) + 427bf215546Sopenharmony_ci * 1 + RGB9E5_EXP_BIAS - 127; 428bf215546Sopenharmony_ci */ 429bf215546Sopenharmony_ci nir_ssa_def *exp_shared = 430bf215546Sopenharmony_ci nir_iadd(b, nir_umax(b, nir_ushr_imm(b, maxu, 23), 431bf215546Sopenharmony_ci nir_imm_int(b, -RGB9E5_EXP_BIAS - 1 + 127)), 432bf215546Sopenharmony_ci nir_imm_int(b, 1 + RGB9E5_EXP_BIAS - 127)); 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_ci /* revdenom_biasedexp = 127 - (exp_shared - RGB9E5_EXP_BIAS - 435bf215546Sopenharmony_ci * RGB9E5_MANTISSA_BITS) + 1; 436bf215546Sopenharmony_ci */ 437bf215546Sopenharmony_ci nir_ssa_def *revdenom_biasedexp = 438bf215546Sopenharmony_ci nir_isub(b, nir_imm_int(b, 127 + RGB9E5_EXP_BIAS + 439bf215546Sopenharmony_ci RGB9E5_MANTISSA_BITS + 1), 440bf215546Sopenharmony_ci exp_shared); 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci /* revdenom.u = revdenom_biasedexp << 23; */ 443bf215546Sopenharmony_ci nir_ssa_def *revdenom = 444bf215546Sopenharmony_ci nir_ishl(b, revdenom_biasedexp, nir_imm_int(b, 23)); 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci /* rm = (int) (rc.f * revdenom.f); 447bf215546Sopenharmony_ci * gm = (int) (gc.f * revdenom.f); 448bf215546Sopenharmony_ci * bm = (int) (bc.f * revdenom.f); 449bf215546Sopenharmony_ci */ 450bf215546Sopenharmony_ci nir_ssa_def *mantissa = 451bf215546Sopenharmony_ci nir_f2i32(b, nir_fmul(b, clamped, revdenom)); 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci /* rm = (rm & 1) + (rm >> 1); 454bf215546Sopenharmony_ci * gm = (gm & 1) + (gm >> 1); 455bf215546Sopenharmony_ci * bm = (bm & 1) + (bm >> 1); 456bf215546Sopenharmony_ci */ 457bf215546Sopenharmony_ci mantissa = nir_iadd(b, nir_iand_imm(b, mantissa, 1), 458bf215546Sopenharmony_ci nir_ushr_imm(b, mantissa, 1)); 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci nir_ssa_def *packed = nir_channel(b, mantissa, 0); 461bf215546Sopenharmony_ci packed = nir_mask_shift_or(b, packed, nir_channel(b, mantissa, 1), ~0, 9); 462bf215546Sopenharmony_ci packed = nir_mask_shift_or(b, packed, nir_channel(b, mantissa, 2), ~0, 18); 463bf215546Sopenharmony_ci packed = nir_mask_shift_or(b, packed, exp_shared, ~0, 27); 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci return packed; 466bf215546Sopenharmony_ci} 467