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 #include "panfrost-quirks.h"
34
35 #include "compiler/nir/nir.h"
36 #include "nir/tgsi_to_nir.h"
37 #include "util/u_dynarray.h"
38 #include "util/u_upload_mgr.h"
39
40 #include "tgsi/tgsi_dump.h"
41
42 void
panfrost_shader_compile(struct pipe_screen * pscreen,struct panfrost_pool * shader_pool,struct panfrost_pool * desc_pool,enum pipe_shader_ir ir_type,const void * ir,gl_shader_stage stage,struct panfrost_shader_state * state)43 panfrost_shader_compile(struct pipe_screen *pscreen,
44 struct panfrost_pool *shader_pool,
45 struct panfrost_pool *desc_pool,
46 enum pipe_shader_ir ir_type,
47 const void *ir,
48 gl_shader_stage stage,
49 struct panfrost_shader_state *state)
50 {
51 struct panfrost_screen *screen = pan_screen(pscreen);
52 struct panfrost_device *dev = pan_device(pscreen);
53
54 nir_shader *s;
55
56 if (ir_type == PIPE_SHADER_IR_NIR) {
57 s = nir_shader_clone(NULL, ir);
58 } else {
59 assert (ir_type == PIPE_SHADER_IR_TGSI);
60 s = tgsi_to_nir(ir, pscreen, false);
61 }
62
63 /* Lower this early so the backends don't have to worry about it */
64 if (stage == MESA_SHADER_FRAGMENT)
65 NIR_PASS_V(s, nir_lower_fragcolor, state->nr_cbufs);
66
67 s->info.stage = stage;
68
69 /* Call out to Midgard compiler given the above NIR */
70 struct panfrost_compile_inputs inputs = {
71 .gpu_id = dev->gpu_id,
72 .shaderdb = !!(dev->debug & PAN_DBG_PRECOMPILE),
73 };
74
75 memcpy(inputs.rt_formats, state->rt_formats, sizeof(inputs.rt_formats));
76
77 struct util_dynarray binary;
78
79 util_dynarray_init(&binary, NULL);
80 screen->vtbl.compile_shader(s, &inputs, &binary, &state->info);
81
82 if (binary.size) {
83 state->bin = panfrost_pool_take_ref(shader_pool,
84 pan_pool_upload_aligned(&shader_pool->base,
85 binary.data, binary.size, 128));
86 }
87
88
89 /* Don't upload RSD for fragment shaders since they need draw-time
90 * merging for e.g. depth/stencil/alpha */
91 bool upload = stage != MESA_SHADER_FRAGMENT;
92 screen->vtbl.prepare_rsd(state, desc_pool, upload);
93
94 panfrost_analyze_sysvals(state);
95
96 util_dynarray_fini(&binary);
97
98 /* In both clone and tgsi_to_nir paths, the shader is ralloc'd against
99 * a NULL context */
100 ralloc_free(s);
101 }
102