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