• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
38 void
panfrost_shader_compile(struct pipe_screen * pscreen,struct panfrost_pool * shader_pool,struct panfrost_pool * desc_pool,const nir_shader * ir,struct panfrost_shader_state * state)39 panfrost_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