1/* 2 * © Copyright 2018 Alyssa Rosenzweig 3 * Copyright (C) 2019-2020 Collabora, Ltd. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 */ 25 26#include <stdio.h> 27#include <stdlib.h> 28#include <string.h> 29#include "pan_bo.h" 30#include "pan_context.h" 31#include "pan_shader.h" 32#include "pan_util.h" 33 34#include "compiler/nir/nir.h" 35#include "util/u_dynarray.h" 36#include "util/u_upload_mgr.h" 37 38void 39panfrost_shader_compile(struct pipe_screen *pscreen, 40 struct panfrost_pool *shader_pool, 41 struct panfrost_pool *desc_pool, 42 const nir_shader *ir, 43 struct panfrost_shader_state *state) 44{ 45 struct panfrost_screen *screen = pan_screen(pscreen); 46 struct panfrost_device *dev = pan_device(pscreen); 47 48 nir_shader *s = nir_shader_clone(NULL, ir); 49 50 if (s->xfb_info && !s->info.internal) { 51 /* Create compute shader doing transform feedback */ 52 nir_shader *xfb = nir_shader_clone(NULL, s); 53 xfb->info.name = ralloc_asprintf(xfb, "%s@xfb", xfb->info.name); 54 xfb->info.internal = true; 55 56 state->xfb = calloc(1, sizeof(struct panfrost_shader_state)); 57 panfrost_shader_compile(pscreen, shader_pool, desc_pool, xfb, state->xfb); 58 59 /* Main shader no longer uses XFB */ 60 s->info.has_transform_feedback_varyings = false; 61 } 62 63 /* Lower this early so the backends don't have to worry about it */ 64 if (s->info.stage == MESA_SHADER_FRAGMENT) { 65 NIR_PASS_V(s, nir_lower_fragcolor, state->key.fs.nr_cbufs); 66 67 if (state->key.fs.sprite_coord_enable) { 68 NIR_PASS_V(s, nir_lower_texcoord_replace, 69 state->key.fs.sprite_coord_enable, 70 true /* point coord is sysval */, 71 false /* Y-invert */); 72 } 73 74 if (state->key.fs.clip_plane_enable) { 75 NIR_PASS_V(s, nir_lower_clip_fs, 76 state->key.fs.clip_plane_enable, 77 false); 78 } 79 } 80 81 /* Call out to Midgard compiler given the above NIR */ 82 struct panfrost_compile_inputs inputs = { 83 .gpu_id = dev->gpu_id, 84 .shaderdb = !!(dev->debug & PAN_DBG_PRECOMPILE), 85 .fixed_sysval_ubo = -1, 86 .fixed_varying_mask = state->key.fixed_varying_mask 87 }; 88 89 /* No IDVS for internal XFB shaders */ 90 if (s->info.stage == MESA_SHADER_VERTEX && s->info.has_transform_feedback_varyings) 91 inputs.no_idvs = true; 92 93 memcpy(inputs.rt_formats, state->key.fs.rt_formats, sizeof(inputs.rt_formats)); 94 95 struct util_dynarray binary; 96 97 util_dynarray_init(&binary, NULL); 98 screen->vtbl.compile_shader(s, &inputs, &binary, &state->info); 99 100 if (binary.size) { 101 state->bin = panfrost_pool_take_ref(shader_pool, 102 pan_pool_upload_aligned(&shader_pool->base, 103 binary.data, binary.size, 128)); 104 } 105 106 107 /* Don't upload RSD for fragment shaders since they need draw-time 108 * merging for e.g. depth/stencil/alpha. RSDs are replaced by simpler 109 * shader program descriptors on Valhall, which can be preuploaded even 110 * for fragment shaders. */ 111 bool upload = !(s->info.stage == MESA_SHADER_FRAGMENT && dev->arch <= 7); 112 screen->vtbl.prepare_shader(state, desc_pool, upload); 113 114 panfrost_analyze_sysvals(state); 115 116 util_dynarray_fini(&binary); 117 118 /* In both clone and tgsi_to_nir paths, the shader is ralloc'd against 119 * a NULL context */ 120 ralloc_free(s); 121} 122