/* * Copyright (c) 2021 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ /* * Lower the shading rate output from the bit field format described in the * SPIRV spec : * * bit | name | description * 0 | Vertical2Pixels | Fragment invocation covers 2 pixels vertically * 1 | Vertical4Pixels | Fragment invocation covers 4 pixels vertically * 2 | Horizontal2Pixels | Fragment invocation covers 2 pixels horizontally * 3 | Horizontal4Pixels | Fragment invocation covers 4 pixels horizontally * * into a single dword composed of 2 fp16 to be stored in the dword 0 of the * VUE header. * * When no horizontal/vertical bits are set, the size in pixel size in that * dimension is assumed to be 1. * * According to the specification, the shading rate output can be read & * written. A read after a write should report a different value if the * implementation decides on different primitive shading rate for some reason. * This is never the case in our implementation. */ #include "brw_nir.h" #include "compiler/nir/nir_builder.h" static bool lower_shading_rate_output_instr(nir_builder *b, nir_instr *instr, UNUSED void *_state) { if (instr->type != nir_instr_type_intrinsic) return false; nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); nir_intrinsic_op op = intrin->intrinsic; if (op != nir_intrinsic_load_output && op != nir_intrinsic_store_output && op != nir_intrinsic_load_per_primitive_output && op != nir_intrinsic_store_per_primitive_output) return false; struct nir_io_semantics io = nir_intrinsic_io_semantics(intrin); if (io.location != VARYING_SLOT_PRIMITIVE_SHADING_RATE) return false; bool is_store = op == nir_intrinsic_store_output || op == nir_intrinsic_store_per_primitive_output; b->cursor = is_store ? nir_before_instr(instr) : nir_after_instr(instr); if (is_store) { assert(intrin->src[0].is_ssa); nir_ssa_def *bit_field = intrin->src[0].ssa; nir_ssa_def *fp16_x = nir_i2f16(b, nir_ishl(b, nir_imm_int(b, 1), nir_ishr_imm(b, bit_field, 2))); nir_ssa_def *fp16_y = nir_i2f16(b, nir_ishl(b, nir_imm_int(b, 1), nir_iand_imm(b, bit_field, 0x3))); nir_ssa_def *packed_fp16_xy = nir_pack_32_2x16_split(b, fp16_x, fp16_y); nir_instr_rewrite_src(instr, &intrin->src[0], nir_src_for_ssa(packed_fp16_xy)); } else { nir_ssa_def *packed_fp16_xy = &intrin->dest.ssa; nir_ssa_def *u32_x = nir_i2i32(b, nir_unpack_32_2x16_split_x(b, packed_fp16_xy)); nir_ssa_def *u32_y = nir_i2i32(b, nir_unpack_32_2x16_split_y(b, packed_fp16_xy)); nir_ssa_def *bit_field = nir_ior(b, nir_ishl_imm(b, nir_ushr_imm(b, u32_x, 1), 2), nir_ushr_imm(b, u32_y, 1)); nir_ssa_def_rewrite_uses_after(packed_fp16_xy, bit_field, bit_field->parent_instr); } return true; } bool brw_nir_lower_shading_rate_output(nir_shader *nir) { return nir_shader_instructions_pass(nir, lower_shading_rate_output_instr, nir_metadata_block_index | nir_metadata_dominance, NULL); }