brw_shader.cpp revision 2e5a1a254ed81b1d3efa6064f48183eefac784d0
1/*
2 * Copyright © 2010 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24extern "C" {
25#include "main/macros.h"
26#include "brw_context.h"
27#include "brw_vs.h"
28}
29#include "brw_fs.h"
30#include "glsl/ir_optimization.h"
31#include "glsl/ir_print_visitor.h"
32
33struct gl_shader *
34brw_new_shader(struct gl_context *ctx, GLuint name, GLuint type)
35{
36   struct brw_shader *shader;
37
38   shader = rzalloc(NULL, struct brw_shader);
39   if (shader) {
40      shader->base.Type = type;
41      shader->base.Name = name;
42      _mesa_init_shader(ctx, &shader->base);
43   }
44
45   return &shader->base;
46}
47
48struct gl_shader_program *
49brw_new_shader_program(struct gl_context *ctx, GLuint name)
50{
51   struct brw_shader_program *prog;
52   prog = rzalloc(NULL, struct brw_shader_program);
53   if (prog) {
54      prog->base.Name = name;
55      _mesa_init_shader_program(ctx, &prog->base);
56   }
57   return &prog->base;
58}
59
60/**
61 * Performs a compile of the shader stages even when we don't know
62 * what non-orthogonal state will be set, in the hope that it reflects
63 * the eventual NOS used, and thus allows us to produce link failures.
64 */
65bool
66brw_shader_precompile(struct gl_context *ctx, struct gl_shader_program *prog)
67{
68   if (!brw_fs_precompile(ctx, prog))
69      return false;
70
71   if (!brw_vs_precompile(ctx, prog))
72      return false;
73
74   return true;
75}
76
77GLboolean
78brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
79{
80   struct brw_context *brw = brw_context(ctx);
81   struct intel_context *intel = &brw->intel;
82   unsigned int stage;
83
84   for (stage = 0; stage < ARRAY_SIZE(prog->_LinkedShaders); stage++) {
85      struct brw_shader *shader =
86	 (struct brw_shader *)prog->_LinkedShaders[stage];
87
88      if (!shader)
89	 continue;
90
91      void *mem_ctx = ralloc_context(NULL);
92      bool progress;
93
94      if (shader->ir)
95	 ralloc_free(shader->ir);
96      shader->ir = new(shader) exec_list;
97      clone_ir_list(mem_ctx, shader->ir, shader->base.ir);
98
99      do_mat_op_to_vec(shader->ir);
100      lower_instructions(shader->ir,
101			 MOD_TO_FRACT |
102			 DIV_TO_MUL_RCP |
103			 SUB_TO_ADD_NEG |
104			 EXP_TO_EXP2 |
105			 LOG_TO_LOG2);
106
107      /* Pre-gen6 HW can only nest if-statements 16 deep.  Beyond this,
108       * if-statements need to be flattened.
109       */
110      if (intel->gen < 6)
111	 lower_if_to_cond_assign(shader->ir, 16);
112
113      do_lower_texture_projection(shader->ir);
114      do_vec_index_to_cond_assign(shader->ir);
115      brw_do_cubemap_normalize(shader->ir);
116      lower_noise(shader->ir);
117      lower_quadop_vector(shader->ir, false);
118
119      bool input = true;
120      bool output = stage == MESA_SHADER_FRAGMENT;
121      bool temp = stage == MESA_SHADER_FRAGMENT;
122      bool uniform = stage == MESA_SHADER_FRAGMENT;
123
124      lower_variable_index_to_cond_assign(shader->ir,
125					  input, output, temp, uniform);
126
127      do {
128	 progress = false;
129
130	 if (stage == MESA_SHADER_FRAGMENT) {
131	    brw_do_channel_expressions(shader->ir);
132	    brw_do_vector_splitting(shader->ir);
133	 }
134
135	 progress = do_lower_jumps(shader->ir, true, true,
136				   true, /* main return */
137				   false, /* continue */
138				   false /* loops */
139				   ) || progress;
140
141	 progress = do_common_optimization(shader->ir, true, 32) || progress;
142      } while (progress);
143
144      validate_ir_tree(shader->ir);
145
146      reparent_ir(shader->ir, shader->ir);
147      ralloc_free(mem_ctx);
148   }
149
150   if (!_mesa_ir_link_shader(ctx, prog))
151      return false;
152
153   if (!brw_shader_precompile(ctx, prog))
154      return false;
155
156   return true;
157}
158
159
160int
161brw_type_for_base_type(const struct glsl_type *type)
162{
163   switch (type->base_type) {
164   case GLSL_TYPE_FLOAT:
165      return BRW_REGISTER_TYPE_F;
166   case GLSL_TYPE_INT:
167   case GLSL_TYPE_BOOL:
168      return BRW_REGISTER_TYPE_D;
169   case GLSL_TYPE_UINT:
170      return BRW_REGISTER_TYPE_UD;
171   case GLSL_TYPE_ARRAY:
172   case GLSL_TYPE_STRUCT:
173   case GLSL_TYPE_SAMPLER:
174      /* These should be overridden with the type of the member when
175       * dereferenced into.  BRW_REGISTER_TYPE_UD seems like a likely
176       * way to trip up if we don't.
177       */
178      return BRW_REGISTER_TYPE_UD;
179   default:
180      assert(!"not reached");
181      return BRW_REGISTER_TYPE_F;
182   }
183}
184
185uint32_t
186brw_conditional_for_comparison(unsigned int op)
187{
188   switch (op) {
189   case ir_binop_less:
190      return BRW_CONDITIONAL_L;
191   case ir_binop_greater:
192      return BRW_CONDITIONAL_G;
193   case ir_binop_lequal:
194      return BRW_CONDITIONAL_LE;
195   case ir_binop_gequal:
196      return BRW_CONDITIONAL_GE;
197   case ir_binop_equal:
198   case ir_binop_all_equal: /* same as equal for scalars */
199      return BRW_CONDITIONAL_Z;
200   case ir_binop_nequal:
201   case ir_binop_any_nequal: /* same as nequal for scalars */
202      return BRW_CONDITIONAL_NZ;
203   default:
204      assert(!"not reached: bad operation for comparison");
205      return BRW_CONDITIONAL_NZ;
206   }
207}
208
209uint32_t
210brw_math_function(enum opcode op)
211{
212   switch (op) {
213   case SHADER_OPCODE_RCP:
214      return BRW_MATH_FUNCTION_INV;
215   case SHADER_OPCODE_RSQ:
216      return BRW_MATH_FUNCTION_RSQ;
217   case SHADER_OPCODE_SQRT:
218      return BRW_MATH_FUNCTION_SQRT;
219   case SHADER_OPCODE_EXP2:
220      return BRW_MATH_FUNCTION_EXP;
221   case SHADER_OPCODE_LOG2:
222      return BRW_MATH_FUNCTION_LOG;
223   case SHADER_OPCODE_POW:
224      return BRW_MATH_FUNCTION_POW;
225   case SHADER_OPCODE_SIN:
226      return BRW_MATH_FUNCTION_SIN;
227   case SHADER_OPCODE_COS:
228      return BRW_MATH_FUNCTION_COS;
229   case SHADER_OPCODE_INT_QUOTIENT:
230      return BRW_MATH_FUNCTION_INT_DIV_QUOTIENT;
231   case SHADER_OPCODE_INT_REMAINDER:
232      return BRW_MATH_FUNCTION_INT_DIV_REMAINDER;
233   default:
234      assert(!"not reached: unknown math function");
235      return 0;
236   }
237}
238