diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources index 009659ff28a..6a400677529 100644 --- a/src/compiler/Makefile.sources +++ b/src/compiler/Makefile.sources @@ -271,6 +271,7 @@ NIR_FILES = \ nir/nir_lower_io_to_temporaries.c \ nir/nir_lower_io_to_scalar.c \ nir/nir_lower_io_to_vector.c \ + nir/nir_lower_mediump_outputs.c \ nir/nir_lower_non_uniform_access.c \ nir/nir_lower_packing.c \ nir/nir_lower_passthrough_edgeflags.c \ diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build index 7e720e5e925..fbe403d42a7 100644 --- a/src/compiler/nir/meson.build +++ b/src/compiler/nir/meson.build @@ -150,6 +150,7 @@ files_libnir = files( 'nir_lower_io_to_temporaries.c', 'nir_lower_io_to_scalar.c', 'nir_lower_io_to_vector.c', + 'nir_lower_mediump_outputs.c', 'nir_lower_non_uniform_access.c', 'nir_lower_packing.c', 'nir_lower_passthrough_edgeflags.c', diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 4f445b1b894..ce12410b79b 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -4278,6 +4278,8 @@ bool nir_lower_doubles(nir_shader *shader, const nir_shader *softfp64, nir_lower_doubles_options options); bool nir_lower_pack(nir_shader *shader); +void nir_lower_mediump_outputs(nir_shader *nir); + bool nir_lower_point_size(nir_shader *shader, float min, float max); typedef enum { diff --git a/src/compiler/nir/nir_lower_mediump_outputs.c b/src/compiler/nir/nir_lower_mediump_outputs.c new file mode 100644 index 00000000000..1b3b9ebc7ae --- /dev/null +++ b/src/compiler/nir/nir_lower_mediump_outputs.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 Google, Inc. + * + * 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. + */ + +#include "nir.h" +#include "nir_builder.h" + +/* Lower mediump FS outputs to fp16 */ + +static bool +lower_output_var(nir_shader *nir, int location) +{ + nir_foreach_variable (var, &nir->outputs) { + if (var->data.driver_location == location && + ((var->data.precision == GLSL_PRECISION_MEDIUM) || + (var->data.precision == GLSL_PRECISION_LOW))) { + if (glsl_get_base_type(var->type) == GLSL_TYPE_FLOAT) + var->type = glsl_float16_type(var->type); + + return glsl_get_base_type(var->type) == GLSL_TYPE_FLOAT16; + } + } + + return false; +} + +void +nir_lower_mediump_outputs(nir_shader *nir) +{ + nir_function_impl *impl = nir_shader_get_entrypoint(nir); + assert(impl); + + /* Get rid of old derefs before we change the types of the variables */ + nir_opt_dce(nir); + + nir_builder b; + nir_builder_init(&b, impl); + + nir_foreach_block_safe (block, impl) { + nir_foreach_instr_safe (instr, block) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + if (intr->intrinsic != nir_intrinsic_store_output) + continue; + + if (!lower_output_var(nir, nir_intrinsic_base(intr))) + continue; + + b.cursor = nir_before_instr(&intr->instr); + nir_instr_rewrite_src(&intr->instr, &intr->src[0], + nir_src_for_ssa(nir_f2f16(&b, intr->src[0].ssa))); + + nir_intrinsic_set_type(intr, nir_type_float16); + } + } +}