17ec681f3Smrg/*
27ec681f3Smrg * Copyright © 2021 Collabora Ltd.
37ec681f3Smrg *
47ec681f3Smrg * Derived from tu_shader.c which is:
57ec681f3Smrg * Copyright © 2019 Google LLC
67ec681f3Smrg *
77ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
87ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
97ec681f3Smrg * to deal in the Software without restriction, including without limitation
107ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
117ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
127ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
137ec681f3Smrg *
147ec681f3Smrg * The above copyright notice and this permission notice (including the next
157ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
167ec681f3Smrg * Software.
177ec681f3Smrg *
187ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
197ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
207ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
217ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
227ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
237ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
247ec681f3Smrg * DEALINGS IN THE SOFTWARE.
257ec681f3Smrg */
267ec681f3Smrg
277ec681f3Smrg#include "genxml/gen_macros.h"
287ec681f3Smrg
297ec681f3Smrg#include "panvk_private.h"
307ec681f3Smrg
317ec681f3Smrg#include "nir_builder.h"
327ec681f3Smrg#include "nir_lower_blend.h"
337ec681f3Smrg#include "nir_conversion_builder.h"
347ec681f3Smrg#include "spirv/nir_spirv.h"
357ec681f3Smrg#include "util/mesa-sha1.h"
367ec681f3Smrg
377ec681f3Smrg#include "panfrost-quirks.h"
387ec681f3Smrg#include "pan_shader.h"
397ec681f3Smrg#include "util/pan_lower_framebuffer.h"
407ec681f3Smrg
417ec681f3Smrg#include "vk_util.h"
427ec681f3Smrg
437ec681f3Smrgstatic nir_shader *
447ec681f3Smrgpanvk_spirv_to_nir(const void *code,
457ec681f3Smrg                   size_t codesize,
467ec681f3Smrg                   gl_shader_stage stage,
477ec681f3Smrg                   const char *entry_point_name,
487ec681f3Smrg                   const VkSpecializationInfo *spec_info,
497ec681f3Smrg                   const nir_shader_compiler_options *nir_options)
507ec681f3Smrg{
517ec681f3Smrg   /* TODO these are made-up */
527ec681f3Smrg   const struct spirv_to_nir_options spirv_options = {
537ec681f3Smrg      .caps = { false },
547ec681f3Smrg      .ubo_addr_format = nir_address_format_32bit_index_offset,
557ec681f3Smrg      .ssbo_addr_format = nir_address_format_32bit_index_offset,
567ec681f3Smrg   };
577ec681f3Smrg
587ec681f3Smrg   /* convert VkSpecializationInfo */
597ec681f3Smrg   uint32_t num_spec = 0;
607ec681f3Smrg   struct nir_spirv_specialization *spec =
617ec681f3Smrg      vk_spec_info_to_nir_spirv(spec_info, &num_spec);
627ec681f3Smrg
637ec681f3Smrg   nir_shader *nir = spirv_to_nir(code, codesize / sizeof(uint32_t), spec,
647ec681f3Smrg                                  num_spec, stage, entry_point_name,
657ec681f3Smrg                                  &spirv_options, nir_options);
667ec681f3Smrg
677ec681f3Smrg   free(spec);
687ec681f3Smrg
697ec681f3Smrg   assert(nir->info.stage == stage);
707ec681f3Smrg   nir_validate_shader(nir, "after spirv_to_nir");
717ec681f3Smrg
727ec681f3Smrg   const struct nir_lower_sysvals_to_varyings_options sysvals_to_varyings = {
737ec681f3Smrg      .frag_coord = PAN_ARCH <= 5,
747ec681f3Smrg      .point_coord = PAN_ARCH <= 5,
757ec681f3Smrg      .front_face = PAN_ARCH <= 5,
767ec681f3Smrg   };
777ec681f3Smrg   NIR_PASS_V(nir, nir_lower_sysvals_to_varyings, &sysvals_to_varyings);
787ec681f3Smrg
797ec681f3Smrg   return nir;
807ec681f3Smrg}
817ec681f3Smrg
827ec681f3Smrgstruct panvk_lower_misc_ctx {
837ec681f3Smrg   struct panvk_shader *shader;
847ec681f3Smrg   const struct panvk_pipeline_layout *layout;
857ec681f3Smrg};
867ec681f3Smrg
877ec681f3Smrgstatic unsigned
887ec681f3Smrgget_fixed_sampler_index(nir_deref_instr *deref,
897ec681f3Smrg                        const struct panvk_lower_misc_ctx *ctx)
907ec681f3Smrg{
917ec681f3Smrg   nir_variable *var = nir_deref_instr_get_variable(deref);
927ec681f3Smrg   unsigned set = var->data.descriptor_set;
937ec681f3Smrg   unsigned binding = var->data.binding;
947ec681f3Smrg   const struct panvk_descriptor_set_binding_layout *bind_layout =
957ec681f3Smrg      &ctx->layout->sets[set].layout->bindings[binding];
967ec681f3Smrg
977ec681f3Smrg   return bind_layout->sampler_idx + ctx->layout->sets[set].sampler_offset;
987ec681f3Smrg}
997ec681f3Smrg
1007ec681f3Smrgstatic unsigned
1017ec681f3Smrgget_fixed_texture_index(nir_deref_instr *deref,
1027ec681f3Smrg                        const struct panvk_lower_misc_ctx *ctx)
1037ec681f3Smrg{
1047ec681f3Smrg   nir_variable *var = nir_deref_instr_get_variable(deref);
1057ec681f3Smrg   unsigned set = var->data.descriptor_set;
1067ec681f3Smrg   unsigned binding = var->data.binding;
1077ec681f3Smrg   const struct panvk_descriptor_set_binding_layout *bind_layout =
1087ec681f3Smrg      &ctx->layout->sets[set].layout->bindings[binding];
1097ec681f3Smrg
1107ec681f3Smrg   return bind_layout->tex_idx + ctx->layout->sets[set].tex_offset;
1117ec681f3Smrg}
1127ec681f3Smrg
1137ec681f3Smrgstatic bool
1147ec681f3Smrglower_tex(nir_builder *b, nir_tex_instr *tex,
1157ec681f3Smrg          const struct panvk_lower_misc_ctx *ctx)
1167ec681f3Smrg{
1177ec681f3Smrg   bool progress = false;
1187ec681f3Smrg   int sampler_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref);
1197ec681f3Smrg
1207ec681f3Smrg   b->cursor = nir_before_instr(&tex->instr);
1217ec681f3Smrg
1227ec681f3Smrg   if (sampler_src_idx >= 0) {
1237ec681f3Smrg      nir_deref_instr *deref = nir_src_as_deref(tex->src[sampler_src_idx].src);
1247ec681f3Smrg      tex->sampler_index = get_fixed_sampler_index(deref, ctx);
1257ec681f3Smrg      nir_tex_instr_remove_src(tex, sampler_src_idx);
1267ec681f3Smrg      progress = true;
1277ec681f3Smrg   }
1287ec681f3Smrg
1297ec681f3Smrg   int tex_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_texture_deref);
1307ec681f3Smrg   if (tex_src_idx >= 0) {
1317ec681f3Smrg      nir_deref_instr *deref = nir_src_as_deref(tex->src[tex_src_idx].src);
1327ec681f3Smrg      tex->texture_index = get_fixed_texture_index(deref, ctx);
1337ec681f3Smrg      nir_tex_instr_remove_src(tex, tex_src_idx);
1347ec681f3Smrg      progress = true;
1357ec681f3Smrg   }
1367ec681f3Smrg
1377ec681f3Smrg   return progress;
1387ec681f3Smrg}
1397ec681f3Smrg
1407ec681f3Smrgstatic void
1417ec681f3Smrglower_vulkan_resource_index(nir_builder *b, nir_intrinsic_instr *intr,
1427ec681f3Smrg                            const struct panvk_lower_misc_ctx *ctx)
1437ec681f3Smrg{
1447ec681f3Smrg   nir_ssa_def *vulkan_idx = intr->src[0].ssa;
1457ec681f3Smrg
1467ec681f3Smrg   unsigned set = nir_intrinsic_desc_set(intr);
1477ec681f3Smrg   unsigned binding = nir_intrinsic_binding(intr);
1487ec681f3Smrg   struct panvk_descriptor_set_layout *set_layout = ctx->layout->sets[set].layout;
1497ec681f3Smrg   struct panvk_descriptor_set_binding_layout *binding_layout =
1507ec681f3Smrg      &set_layout->bindings[binding];
1517ec681f3Smrg   unsigned base;
1527ec681f3Smrg
1537ec681f3Smrg   switch (binding_layout->type) {
1547ec681f3Smrg   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1557ec681f3Smrg   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1567ec681f3Smrg      base = binding_layout->ubo_idx + ctx->layout->sets[set].ubo_offset;
1577ec681f3Smrg      break;
1587ec681f3Smrg   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1597ec681f3Smrg   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1607ec681f3Smrg      base = binding_layout->ssbo_idx + ctx->layout->sets[set].ssbo_offset;
1617ec681f3Smrg      break;
1627ec681f3Smrg   default:
1637ec681f3Smrg      unreachable("Invalid descriptor type");
1647ec681f3Smrg      break;
1657ec681f3Smrg   }
1667ec681f3Smrg
1677ec681f3Smrg   b->cursor = nir_before_instr(&intr->instr);
1687ec681f3Smrg   nir_ssa_def *idx = nir_iadd(b, nir_imm_int(b, base), vulkan_idx);
1697ec681f3Smrg   nir_ssa_def_rewrite_uses(&intr->dest.ssa, idx);
1707ec681f3Smrg   nir_instr_remove(&intr->instr);
1717ec681f3Smrg}
1727ec681f3Smrg
1737ec681f3Smrgstatic void
1747ec681f3Smrglower_load_vulkan_descriptor(nir_builder *b, nir_intrinsic_instr *intrin)
1757ec681f3Smrg{
1767ec681f3Smrg   /* Loading the descriptor happens as part of the load/store instruction so
1777ec681f3Smrg    * this is a no-op.
1787ec681f3Smrg    */
1797ec681f3Smrg   b->cursor = nir_before_instr(&intrin->instr);
1807ec681f3Smrg   nir_ssa_def *val = nir_vec2(b, intrin->src[0].ssa, nir_imm_int(b, 0));
1817ec681f3Smrg   nir_ssa_def_rewrite_uses(&intrin->dest.ssa, val);
1827ec681f3Smrg   nir_instr_remove(&intrin->instr);
1837ec681f3Smrg}
1847ec681f3Smrg
1857ec681f3Smrgstatic bool
1867ec681f3Smrglower_intrinsic(nir_builder *b, nir_intrinsic_instr *intr,
1877ec681f3Smrg                const struct panvk_lower_misc_ctx *ctx)
1887ec681f3Smrg{
1897ec681f3Smrg   switch (intr->intrinsic) {
1907ec681f3Smrg   case nir_intrinsic_vulkan_resource_index:
1917ec681f3Smrg      lower_vulkan_resource_index(b, intr, ctx);
1927ec681f3Smrg      return true;
1937ec681f3Smrg   case nir_intrinsic_load_vulkan_descriptor:
1947ec681f3Smrg      lower_load_vulkan_descriptor(b, intr);
1957ec681f3Smrg      return true;
1967ec681f3Smrg   default:
1977ec681f3Smrg      return false;
1987ec681f3Smrg   }
1997ec681f3Smrg
2007ec681f3Smrg}
2017ec681f3Smrg
2027ec681f3Smrgstatic bool
2037ec681f3Smrgpanvk_lower_misc_instr(nir_builder *b,
2047ec681f3Smrg                       nir_instr *instr,
2057ec681f3Smrg                       void *data)
2067ec681f3Smrg{
2077ec681f3Smrg   const struct panvk_lower_misc_ctx *ctx = data;
2087ec681f3Smrg
2097ec681f3Smrg   switch (instr->type) {
2107ec681f3Smrg   case nir_instr_type_tex:
2117ec681f3Smrg      return lower_tex(b, nir_instr_as_tex(instr), ctx);
2127ec681f3Smrg   case nir_instr_type_intrinsic:
2137ec681f3Smrg      return lower_intrinsic(b, nir_instr_as_intrinsic(instr), ctx);
2147ec681f3Smrg   default:
2157ec681f3Smrg      return false;
2167ec681f3Smrg   }
2177ec681f3Smrg}
2187ec681f3Smrg
2197ec681f3Smrgstatic bool
2207ec681f3Smrgpanvk_lower_misc(nir_shader *nir, const struct panvk_lower_misc_ctx *ctx)
2217ec681f3Smrg{
2227ec681f3Smrg   return nir_shader_instructions_pass(nir, panvk_lower_misc_instr,
2237ec681f3Smrg                                       nir_metadata_block_index |
2247ec681f3Smrg                                       nir_metadata_dominance,
2257ec681f3Smrg                                       (void *)ctx);
2267ec681f3Smrg}
2277ec681f3Smrg
2287ec681f3Smrgstatic bool
2297ec681f3Smrgpanvk_inline_blend_constants(nir_builder *b, nir_instr *instr, void *data)
2307ec681f3Smrg{
2317ec681f3Smrg   if (instr->type != nir_instr_type_intrinsic)
2327ec681f3Smrg      return false;
2337ec681f3Smrg
2347ec681f3Smrg   nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
2357ec681f3Smrg   if (intr->intrinsic != nir_intrinsic_load_blend_const_color_rgba)
2367ec681f3Smrg      return false;
2377ec681f3Smrg
2387ec681f3Smrg   const nir_const_value *constants = data;
2397ec681f3Smrg
2407ec681f3Smrg   b->cursor = nir_after_instr(instr);
2417ec681f3Smrg   nir_ssa_def *constant = nir_build_imm(b, 4, 32, constants);
2427ec681f3Smrg   nir_ssa_def_rewrite_uses(&intr->dest.ssa, constant);
2437ec681f3Smrg   nir_instr_remove(instr);
2447ec681f3Smrg   return true;
2457ec681f3Smrg}
2467ec681f3Smrg
2477ec681f3Smrg#if PAN_ARCH <= 5
2487ec681f3Smrgstruct panvk_lower_blend_type_conv {
2497ec681f3Smrg   nir_variable *var;
2507ec681f3Smrg   nir_alu_type newtype;
2517ec681f3Smrg   nir_alu_type oldtype;
2527ec681f3Smrg};
2537ec681f3Smrg
2547ec681f3Smrgstatic bool
2557ec681f3Smrgpanvk_adjust_rt_type(nir_builder *b, nir_instr *instr, void *data)
2567ec681f3Smrg{
2577ec681f3Smrg   if (instr->type != nir_instr_type_intrinsic)
2587ec681f3Smrg      return false;
2597ec681f3Smrg
2607ec681f3Smrg   nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
2617ec681f3Smrg   if (intr->intrinsic != nir_intrinsic_store_deref &&
2627ec681f3Smrg       intr->intrinsic != nir_intrinsic_load_deref)
2637ec681f3Smrg      return false;
2647ec681f3Smrg
2657ec681f3Smrg   nir_variable *var = nir_intrinsic_get_var(intr, 0);
2667ec681f3Smrg   if (var->data.mode != nir_var_shader_out ||
2677ec681f3Smrg       (var->data.location != FRAG_RESULT_COLOR &&
2687ec681f3Smrg        var->data.location < FRAG_RESULT_DATA0))
2697ec681f3Smrg      return false;
2707ec681f3Smrg
2717ec681f3Smrg   /* Determine render target for per-RT blending */
2727ec681f3Smrg   unsigned rt =
2737ec681f3Smrg      (var->data.location == FRAG_RESULT_COLOR) ? 0 :
2747ec681f3Smrg      (var->data.location - FRAG_RESULT_DATA0);
2757ec681f3Smrg
2767ec681f3Smrg   const struct panvk_lower_blend_type_conv *typeconv = data;
2777ec681f3Smrg   nir_alu_type newtype = typeconv[rt].newtype;
2787ec681f3Smrg   nir_alu_type oldtype = typeconv[rt].oldtype;
2797ec681f3Smrg
2807ec681f3Smrg   /* No conversion */
2817ec681f3Smrg   if (newtype == nir_type_invalid || newtype == oldtype)
2827ec681f3Smrg      return false;
2837ec681f3Smrg
2847ec681f3Smrg
2857ec681f3Smrg   b->cursor = nir_before_instr(instr);
2867ec681f3Smrg
2877ec681f3Smrg   nir_deref_instr *deref = nir_build_deref_var(b, typeconv[rt].var);
2887ec681f3Smrg   nir_instr_rewrite_src(&intr->instr, &intr->src[0],
2897ec681f3Smrg                         nir_src_for_ssa(&deref->dest.ssa));
2907ec681f3Smrg
2917ec681f3Smrg   if (intr->intrinsic == nir_intrinsic_store_deref) {
2927ec681f3Smrg      nir_ssa_def *val = nir_ssa_for_src(b, intr->src[1], 4);
2937ec681f3Smrg      bool clamp = nir_alu_type_get_base_type(newtype) != nir_type_float;
2947ec681f3Smrg      val = nir_convert_with_rounding(b, val, oldtype, newtype,
2957ec681f3Smrg                                      nir_rounding_mode_undef, clamp);
2967ec681f3Smrg      nir_store_var(b, typeconv[rt].var, val, nir_intrinsic_write_mask(intr));
2977ec681f3Smrg   } else {
2987ec681f3Smrg      bool clamp = nir_alu_type_get_base_type(oldtype) != nir_type_float;
2997ec681f3Smrg      nir_ssa_def *val = nir_load_var(b, typeconv[rt].var);
3007ec681f3Smrg      val = nir_convert_with_rounding(b, val, newtype, oldtype,
3017ec681f3Smrg                                      nir_rounding_mode_undef, clamp);
3027ec681f3Smrg      nir_ssa_def_rewrite_uses(&intr->dest.ssa, val);
3037ec681f3Smrg   }
3047ec681f3Smrg
3057ec681f3Smrg   nir_instr_remove(instr);
3067ec681f3Smrg
3077ec681f3Smrg   return true;
3087ec681f3Smrg}
3097ec681f3Smrg#endif
3107ec681f3Smrg
3117ec681f3Smrgstatic void
3127ec681f3Smrgpanvk_lower_blend(struct panfrost_device *pdev,
3137ec681f3Smrg                  nir_shader *nir,
3147ec681f3Smrg                  struct panfrost_compile_inputs *inputs,
3157ec681f3Smrg                  struct pan_blend_state *blend_state,
3167ec681f3Smrg                  bool static_blend_constants)
3177ec681f3Smrg{
3187ec681f3Smrg   nir_lower_blend_options options = {
3197ec681f3Smrg      .logicop_enable = blend_state->logicop_enable,
3207ec681f3Smrg      .logicop_func = blend_state->logicop_func,
3217ec681f3Smrg   };
3227ec681f3Smrg
3237ec681f3Smrg#if PAN_ARCH <= 5
3247ec681f3Smrg   struct panvk_lower_blend_type_conv typeconv[8] = { 0 };
3257ec681f3Smrg#endif
3267ec681f3Smrg   bool lower_blend = false;
3277ec681f3Smrg
3287ec681f3Smrg   for (unsigned rt = 0; rt < blend_state->rt_count; rt++) {
3297ec681f3Smrg      struct pan_blend_rt_state *rt_state = &blend_state->rts[rt];
3307ec681f3Smrg
3317ec681f3Smrg      if (!panvk_per_arch(blend_needs_lowering)(pdev, blend_state, rt))
3327ec681f3Smrg         continue;
3337ec681f3Smrg
3347ec681f3Smrg      enum pipe_format fmt = rt_state->format;
3357ec681f3Smrg
3367ec681f3Smrg      options.format[rt] = fmt;
3377ec681f3Smrg      options.rt[rt].colormask = rt_state->equation.color_mask;
3387ec681f3Smrg
3397ec681f3Smrg      if (!rt_state->equation.blend_enable) {
3407ec681f3Smrg         static const nir_lower_blend_channel replace = {
3417ec681f3Smrg            .func = BLEND_FUNC_ADD,
3427ec681f3Smrg            .src_factor = BLEND_FACTOR_ZERO,
3437ec681f3Smrg            .invert_src_factor = true,
3447ec681f3Smrg            .dst_factor = BLEND_FACTOR_ZERO,
3457ec681f3Smrg            .invert_dst_factor = false,
3467ec681f3Smrg         };
3477ec681f3Smrg
3487ec681f3Smrg         options.rt[rt].rgb = replace;
3497ec681f3Smrg         options.rt[rt].alpha = replace;
3507ec681f3Smrg      } else {
3517ec681f3Smrg         options.rt[rt].rgb.func = rt_state->equation.rgb_func;
3527ec681f3Smrg         options.rt[rt].rgb.src_factor = rt_state->equation.rgb_src_factor;
3537ec681f3Smrg         options.rt[rt].rgb.invert_src_factor = rt_state->equation.rgb_invert_src_factor;
3547ec681f3Smrg         options.rt[rt].rgb.dst_factor = rt_state->equation.rgb_dst_factor;
3557ec681f3Smrg         options.rt[rt].rgb.invert_dst_factor = rt_state->equation.rgb_invert_dst_factor;
3567ec681f3Smrg         options.rt[rt].alpha.func = rt_state->equation.alpha_func;
3577ec681f3Smrg         options.rt[rt].alpha.src_factor = rt_state->equation.alpha_src_factor;
3587ec681f3Smrg         options.rt[rt].alpha.invert_src_factor = rt_state->equation.alpha_invert_src_factor;
3597ec681f3Smrg         options.rt[rt].alpha.dst_factor = rt_state->equation.alpha_dst_factor;
3607ec681f3Smrg         options.rt[rt].alpha.invert_dst_factor = rt_state->equation.alpha_invert_dst_factor;
3617ec681f3Smrg      }
3627ec681f3Smrg
3637ec681f3Smrg      /* Update the equation to force a color replacement */
3647ec681f3Smrg      rt_state->equation.color_mask = 0xf;
3657ec681f3Smrg      rt_state->equation.rgb_func = BLEND_FUNC_ADD;
3667ec681f3Smrg      rt_state->equation.rgb_src_factor = BLEND_FACTOR_ZERO;
3677ec681f3Smrg      rt_state->equation.rgb_invert_src_factor = true;
3687ec681f3Smrg      rt_state->equation.rgb_dst_factor = BLEND_FACTOR_ZERO;
3697ec681f3Smrg      rt_state->equation.rgb_invert_dst_factor = false;
3707ec681f3Smrg      rt_state->equation.alpha_func = BLEND_FUNC_ADD;
3717ec681f3Smrg      rt_state->equation.alpha_src_factor = BLEND_FACTOR_ZERO;
3727ec681f3Smrg      rt_state->equation.alpha_invert_src_factor = true;
3737ec681f3Smrg      rt_state->equation.alpha_dst_factor = BLEND_FACTOR_ZERO;
3747ec681f3Smrg      rt_state->equation.alpha_invert_dst_factor = false;
3757ec681f3Smrg      lower_blend = true;
3767ec681f3Smrg
3777ec681f3Smrg#if PAN_ARCH >= 6
3787ec681f3Smrg      inputs->bifrost.static_rt_conv = true;
3797ec681f3Smrg      inputs->bifrost.rt_conv[rt] =
3807ec681f3Smrg         GENX(pan_blend_get_internal_desc)(pdev, fmt, rt, 32, false) >> 32;
3817ec681f3Smrg#else
3827ec681f3Smrg      if (!panfrost_blendable_formats_v6[fmt].internal) {
3837ec681f3Smrg         nir_variable *outvar =
3847ec681f3Smrg            nir_find_variable_with_location(nir, nir_var_shader_out, FRAG_RESULT_DATA0 + rt);
3857ec681f3Smrg         if (!outvar && !rt)
3867ec681f3Smrg            outvar = nir_find_variable_with_location(nir, nir_var_shader_out, FRAG_RESULT_COLOR);
3877ec681f3Smrg
3887ec681f3Smrg         assert(outvar);
3897ec681f3Smrg
3907ec681f3Smrg         const struct util_format_description *format_desc =
3917ec681f3Smrg            util_format_description(fmt);
3927ec681f3Smrg
3937ec681f3Smrg         typeconv[rt].newtype = pan_unpacked_type_for_format(format_desc);
3947ec681f3Smrg         typeconv[rt].oldtype = nir_get_nir_type_for_glsl_type(outvar->type);
3957ec681f3Smrg         typeconv[rt].var =
3967ec681f3Smrg            nir_variable_create(nir, nir_var_shader_out,
3977ec681f3Smrg                                glsl_vector_type(nir_get_glsl_base_type_for_nir_type(typeconv[rt].newtype),
3987ec681f3Smrg                                                 glsl_get_vector_elements(outvar->type)),
3997ec681f3Smrg                                outvar->name);
4007ec681f3Smrg         typeconv[rt].var->data.location = outvar->data.location;
4017ec681f3Smrg         inputs->blend.nr_samples = rt_state->nr_samples;
4027ec681f3Smrg         inputs->rt_formats[rt] = rt_state->format;
4037ec681f3Smrg      }
4047ec681f3Smrg#endif
4057ec681f3Smrg   }
4067ec681f3Smrg
4077ec681f3Smrg   if (lower_blend) {
4087ec681f3Smrg#if PAN_ARCH <= 5
4097ec681f3Smrg      NIR_PASS_V(nir, nir_shader_instructions_pass,
4107ec681f3Smrg                 panvk_adjust_rt_type,
4117ec681f3Smrg                 nir_metadata_block_index |
4127ec681f3Smrg                 nir_metadata_dominance,
4137ec681f3Smrg                 &typeconv);
4147ec681f3Smrg      nir_remove_dead_derefs(nir);
4157ec681f3Smrg      nir_remove_dead_variables(nir, nir_var_shader_out, NULL);
4167ec681f3Smrg#endif
4177ec681f3Smrg
4187ec681f3Smrg      NIR_PASS_V(nir, nir_lower_blend, options);
4197ec681f3Smrg
4207ec681f3Smrg      if (static_blend_constants) {
4217ec681f3Smrg         const nir_const_value constants[4] = {
4227ec681f3Smrg            { .f32 = CLAMP(blend_state->constants[0], 0.0f, 1.0f) },
4237ec681f3Smrg            { .f32 = CLAMP(blend_state->constants[1], 0.0f, 1.0f) },
4247ec681f3Smrg            { .f32 = CLAMP(blend_state->constants[2], 0.0f, 1.0f) },
4257ec681f3Smrg            { .f32 = CLAMP(blend_state->constants[3], 0.0f, 1.0f) },
4267ec681f3Smrg         };
4277ec681f3Smrg         NIR_PASS_V(nir, nir_shader_instructions_pass,
4287ec681f3Smrg                    panvk_inline_blend_constants,
4297ec681f3Smrg                    nir_metadata_block_index |
4307ec681f3Smrg                    nir_metadata_dominance,
4317ec681f3Smrg                    (void *)constants);
4327ec681f3Smrg      }
4337ec681f3Smrg   }
4347ec681f3Smrg}
4357ec681f3Smrg
4367ec681f3Smrgstruct panvk_shader *
4377ec681f3Smrgpanvk_per_arch(shader_create)(struct panvk_device *dev,
4387ec681f3Smrg                              gl_shader_stage stage,
4397ec681f3Smrg                              const VkPipelineShaderStageCreateInfo *stage_info,
4407ec681f3Smrg                              const struct panvk_pipeline_layout *layout,
4417ec681f3Smrg                              unsigned sysval_ubo,
4427ec681f3Smrg                              struct pan_blend_state *blend_state,
4437ec681f3Smrg                              bool static_blend_constants,
4447ec681f3Smrg                              const VkAllocationCallbacks *alloc)
4457ec681f3Smrg{
4467ec681f3Smrg   const struct panvk_shader_module *module = panvk_shader_module_from_handle(stage_info->module);
4477ec681f3Smrg   struct panfrost_device *pdev = &dev->physical_device->pdev;
4487ec681f3Smrg   struct panvk_shader *shader;
4497ec681f3Smrg
4507ec681f3Smrg   shader = vk_zalloc2(&dev->vk.alloc, alloc, sizeof(*shader), 8,
4517ec681f3Smrg                       VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
4527ec681f3Smrg   if (!shader)
4537ec681f3Smrg      return NULL;
4547ec681f3Smrg
4557ec681f3Smrg   util_dynarray_init(&shader->binary, NULL);
4567ec681f3Smrg
4577ec681f3Smrg   /* translate SPIR-V to NIR */
4587ec681f3Smrg   assert(module->code_size % 4 == 0);
4597ec681f3Smrg   nir_shader *nir = panvk_spirv_to_nir(module->code,
4607ec681f3Smrg                                        module->code_size,
4617ec681f3Smrg                                        stage, stage_info->pName,
4627ec681f3Smrg                                        stage_info->pSpecializationInfo,
4637ec681f3Smrg                                        GENX(pan_shader_get_compiler_options)());
4647ec681f3Smrg   if (!nir) {
4657ec681f3Smrg      vk_free2(&dev->vk.alloc, alloc, shader);
4667ec681f3Smrg      return NULL;
4677ec681f3Smrg   }
4687ec681f3Smrg
4697ec681f3Smrg   struct panfrost_compile_inputs inputs = {
4707ec681f3Smrg      .gpu_id = pdev->gpu_id,
4717ec681f3Smrg      .no_ubo_to_push = true,
4727ec681f3Smrg      .sysval_ubo = sysval_ubo,
4737ec681f3Smrg   };
4747ec681f3Smrg
4757ec681f3Smrg   /* multi step inlining procedure */
4767ec681f3Smrg   NIR_PASS_V(nir, nir_lower_variable_initializers, nir_var_function_temp);
4777ec681f3Smrg   NIR_PASS_V(nir, nir_lower_returns);
4787ec681f3Smrg   NIR_PASS_V(nir, nir_inline_functions);
4797ec681f3Smrg   NIR_PASS_V(nir, nir_copy_prop);
4807ec681f3Smrg   NIR_PASS_V(nir, nir_opt_deref);
4817ec681f3Smrg   foreach_list_typed_safe(nir_function, func, node, &nir->functions) {
4827ec681f3Smrg      if (!func->is_entrypoint)
4837ec681f3Smrg         exec_node_remove(&func->node);
4847ec681f3Smrg   }
4857ec681f3Smrg   assert(exec_list_length(&nir->functions) == 1);
4867ec681f3Smrg   NIR_PASS_V(nir, nir_lower_variable_initializers, ~nir_var_function_temp);
4877ec681f3Smrg
4887ec681f3Smrg   /* Split member structs.  We do this before lower_io_to_temporaries so that
4897ec681f3Smrg    * it doesn't lower system values to temporaries by accident.
4907ec681f3Smrg    */
4917ec681f3Smrg   NIR_PASS_V(nir, nir_split_var_copies);
4927ec681f3Smrg   NIR_PASS_V(nir, nir_split_per_member_structs);
4937ec681f3Smrg
4947ec681f3Smrg   NIR_PASS_V(nir, nir_remove_dead_variables,
4957ec681f3Smrg              nir_var_shader_in | nir_var_shader_out |
4967ec681f3Smrg              nir_var_system_value | nir_var_mem_shared,
4977ec681f3Smrg              NULL);
4987ec681f3Smrg
4997ec681f3Smrg   NIR_PASS_V(nir, nir_lower_io_to_temporaries,
5007ec681f3Smrg              nir_shader_get_entrypoint(nir), true, true);
5017ec681f3Smrg
5027ec681f3Smrg   NIR_PASS_V(nir, nir_lower_indirect_derefs,
5037ec681f3Smrg              nir_var_shader_in | nir_var_shader_out,
5047ec681f3Smrg              UINT32_MAX);
5057ec681f3Smrg
5067ec681f3Smrg   NIR_PASS_V(nir, nir_opt_copy_prop_vars);
5077ec681f3Smrg   NIR_PASS_V(nir, nir_opt_combine_stores, nir_var_all);
5087ec681f3Smrg
5097ec681f3Smrg   if (stage == MESA_SHADER_FRAGMENT)
5107ec681f3Smrg      panvk_lower_blend(pdev, nir, &inputs, blend_state, static_blend_constants);
5117ec681f3Smrg
5127ec681f3Smrg   NIR_PASS_V(nir, nir_lower_uniforms_to_ubo, true, false);
5137ec681f3Smrg   NIR_PASS_V(nir, nir_lower_explicit_io,
5147ec681f3Smrg              nir_var_mem_ubo | nir_var_mem_ssbo,
5157ec681f3Smrg              nir_address_format_32bit_index_offset);
5167ec681f3Smrg
5177ec681f3Smrg   nir_assign_io_var_locations(nir, nir_var_shader_in, &nir->num_inputs, stage);
5187ec681f3Smrg   nir_assign_io_var_locations(nir, nir_var_shader_out, &nir->num_outputs, stage);
5197ec681f3Smrg
5207ec681f3Smrg   NIR_PASS_V(nir, nir_lower_system_values);
5217ec681f3Smrg   NIR_PASS_V(nir, nir_lower_compute_system_values, NULL);
5227ec681f3Smrg
5237ec681f3Smrg   NIR_PASS_V(nir, nir_split_var_copies);
5247ec681f3Smrg   NIR_PASS_V(nir, nir_lower_var_copies);
5257ec681f3Smrg
5267ec681f3Smrg   struct panvk_lower_misc_ctx ctx = {
5277ec681f3Smrg      .shader = shader,
5287ec681f3Smrg      .layout = layout,
5297ec681f3Smrg   };
5307ec681f3Smrg   NIR_PASS_V(nir, panvk_lower_misc, &ctx);
5317ec681f3Smrg
5327ec681f3Smrg   nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
5337ec681f3Smrg   if (unlikely(dev->physical_device->instance->debug_flags & PANVK_DEBUG_NIR)) {
5347ec681f3Smrg      fprintf(stderr, "translated nir:\n");
5357ec681f3Smrg      nir_print_shader(nir, stderr);
5367ec681f3Smrg   }
5377ec681f3Smrg
5387ec681f3Smrg   GENX(pan_shader_compile)(nir, &inputs, &shader->binary, &shader->info);
5397ec681f3Smrg
5407ec681f3Smrg   /* Patch the descriptor count */
5417ec681f3Smrg   shader->info.ubo_count =
5427ec681f3Smrg      shader->info.sysvals.sysval_count ? sysval_ubo + 1 : layout->num_ubos;
5437ec681f3Smrg   shader->info.sampler_count = layout->num_samplers;
5447ec681f3Smrg   shader->info.texture_count = layout->num_textures;
5457ec681f3Smrg
5467ec681f3Smrg   shader->sysval_ubo = sysval_ubo;
5477ec681f3Smrg
5487ec681f3Smrg   ralloc_free(nir);
5497ec681f3Smrg
5507ec681f3Smrg   return shader;
5517ec681f3Smrg}
552