1 /*
2  * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
3  * Copyright (C) 2008  VMware, Inc.   All Rights Reserved.
4  * Copyright © 2010 Intel Corporation
5  * Copyright © 2011 Bryan Cain
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  */
26 
27 #include "compiler/glsl/glsl_parser_extras.h"
28 #include "compiler/glsl/ir_optimization.h"
29 #include "compiler/glsl/program.h"
30 
31 #include "st_nir.h"
32 #include "st_shader_cache.h"
33 #include "st_glsl_to_tgsi.h"
34 
35 #include "tgsi/tgsi_from_mesa.h"
36 
37 extern "C" {
38 
39 /**
40  * Link a shader.
41  * Called via ctx->Driver.LinkShader()
42  * This is a shared function that branches off to either GLSL IR -> TGSI or
43  * GLSL IR -> NIR
44  */
45 GLboolean
st_link_shader(struct gl_context * ctx,struct gl_shader_program * prog)46 st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
47 {
48    struct pipe_screen *pscreen = st_context(ctx)->screen;
49 
50    enum pipe_shader_ir preferred_ir = (enum pipe_shader_ir)
51       pscreen->get_shader_param(pscreen, PIPE_SHADER_VERTEX,
52                                 PIPE_SHADER_CAP_PREFERRED_IR);
53    bool use_nir = preferred_ir == PIPE_SHADER_IR_NIR;
54 
55    /* Return early if we are loading the shader from on-disk cache */
56    if (st_load_ir_from_disk_cache(ctx, prog, use_nir)) {
57       return GL_TRUE;
58    }
59 
60    assert(prog->data->LinkStatus);
61 
62    /* Skip the GLSL steps when using SPIR-V. */
63    if (prog->data->spirv) {
64       assert(use_nir);
65       return st_link_nir(ctx, prog);
66    }
67 
68    for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
69       if (prog->_LinkedShaders[i] == NULL)
70          continue;
71 
72       struct gl_linked_shader *shader = prog->_LinkedShaders[i];
73       exec_list *ir = shader->ir;
74       gl_shader_stage stage = shader->Stage;
75       const struct gl_shader_compiler_options *options =
76             &ctx->Const.ShaderCompilerOptions[stage];
77 
78       /* If there are forms of indirect addressing that the driver
79        * cannot handle, perform the lowering pass.
80        */
81       if (options->EmitNoIndirectInput || options->EmitNoIndirectOutput ||
82           options->EmitNoIndirectTemp || options->EmitNoIndirectUniform) {
83          lower_variable_index_to_cond_assign(stage, ir,
84                                              options->EmitNoIndirectInput,
85                                              options->EmitNoIndirectOutput,
86                                              options->EmitNoIndirectTemp,
87                                              options->EmitNoIndirectUniform);
88       }
89 
90       enum pipe_shader_type ptarget = pipe_shader_type_from_mesa(stage);
91       bool have_dround = pscreen->get_shader_param(pscreen, ptarget,
92                                                    PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED);
93       bool have_dfrexp = pscreen->get_shader_param(pscreen, ptarget,
94                                                    PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED);
95       bool have_ldexp = pscreen->get_shader_param(pscreen, ptarget,
96                                                   PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED);
97 
98       if (!pscreen->get_param(pscreen, PIPE_CAP_INT64_DIVMOD))
99          lower_64bit_integer_instructions(ir, DIV64 | MOD64);
100 
101       if (ctx->Extensions.ARB_shading_language_packing) {
102          unsigned lower_inst = LOWER_PACK_SNORM_2x16 |
103                                LOWER_UNPACK_SNORM_2x16 |
104                                LOWER_PACK_UNORM_2x16 |
105                                LOWER_UNPACK_UNORM_2x16 |
106                                LOWER_PACK_SNORM_4x8 |
107                                LOWER_UNPACK_SNORM_4x8 |
108                                LOWER_UNPACK_UNORM_4x8 |
109                                LOWER_PACK_UNORM_4x8;
110 
111          if (ctx->Extensions.ARB_gpu_shader5)
112             lower_inst |= LOWER_PACK_USE_BFI |
113                           LOWER_PACK_USE_BFE;
114          if (!ctx->st->has_half_float_packing)
115             lower_inst |= LOWER_PACK_HALF_2x16 |
116                           LOWER_UNPACK_HALF_2x16;
117 
118          lower_packing_builtins(ir, lower_inst);
119       }
120 
121       if (!pscreen->get_param(pscreen, PIPE_CAP_TEXTURE_GATHER_OFFSETS))
122          lower_offset_arrays(ir);
123       do_mat_op_to_vec(ir);
124 
125       if (stage == MESA_SHADER_FRAGMENT && pscreen->get_param(pscreen, PIPE_CAP_FBFETCH))
126          lower_blend_equation_advanced(
127             shader, ctx->Extensions.KHR_blend_equation_advanced_coherent);
128 
129       lower_instructions(ir,
130                          (use_nir ? 0 : MOD_TO_FLOOR) |
131                          FDIV_TO_MUL_RCP |
132                          EXP_TO_EXP2 |
133                          LOG_TO_LOG2 |
134                          MUL64_TO_MUL_AND_MUL_HIGH |
135                          (have_ldexp ? 0 : LDEXP_TO_ARITH) |
136                          (have_dfrexp ? 0 : DFREXP_DLDEXP_TO_ARITH) |
137                          CARRY_TO_ARITH |
138                          BORROW_TO_ARITH |
139                          (have_dround ? 0 : DOPS_TO_DFRAC) |
140                          (options->EmitNoPow ? POW_TO_EXP2 : 0) |
141                          (!ctx->Const.NativeIntegers ? INT_DIV_TO_MUL_RCP : 0) |
142                          (options->EmitNoSat ? SAT_TO_CLAMP : 0) |
143                          (ctx->Const.ForceGLSLAbsSqrt ? SQRT_TO_ABS_SQRT : 0) |
144                          /* Assume that if ARB_gpu_shader5 is not supported
145                           * then all of the extended integer functions need
146                           * lowering.  It may be necessary to add some caps
147                           * for individual instructions.
148                           */
149                          (!ctx->Extensions.ARB_gpu_shader5
150                           ? BIT_COUNT_TO_MATH |
151                             EXTRACT_TO_SHIFTS |
152                             INSERT_TO_SHIFTS |
153                             REVERSE_TO_SHIFTS |
154                             FIND_LSB_TO_FLOAT_CAST |
155                             FIND_MSB_TO_FLOAT_CAST |
156                             IMUL_HIGH_TO_MUL
157                           : 0));
158 
159       do_vec_index_to_cond_assign(ir);
160       lower_vector_insert(ir, true);
161       lower_quadop_vector(ir, false);
162       if (options->MaxIfDepth == 0) {
163          lower_discard(ir);
164       }
165 
166       validate_ir_tree(ir);
167    }
168 
169    build_program_resource_list(ctx, prog, use_nir);
170 
171    if (use_nir)
172       return st_link_nir(ctx, prog);
173    else
174       return st_link_tgsi(ctx, prog);
175 }
176 
177 } /* extern "C" */
178