brw_shader.cpp revision ff8f272b0d02b41a0ce34ab6af7119b9e06f4961
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			 INT_DIV_TO_MUL_RCP |
104			 SUB_TO_ADD_NEG |
105			 EXP_TO_EXP2 |
106			 LOG_TO_LOG2);
107
108      /* Pre-gen6 HW can only nest if-statements 16 deep.  Beyond this,
109       * if-statements need to be flattened.
110       */
111      if (intel->gen < 6)
112	 lower_if_to_cond_assign(shader->ir, 16);
113
114      do_lower_texture_projection(shader->ir);
115      do_vec_index_to_cond_assign(shader->ir);
116      brw_do_cubemap_normalize(shader->ir);
117      lower_noise(shader->ir);
118      lower_quadop_vector(shader->ir, false);
119
120      bool input = true;
121      bool output = stage == MESA_SHADER_FRAGMENT;
122      bool temp = stage == MESA_SHADER_FRAGMENT;
123      bool uniform = stage == MESA_SHADER_FRAGMENT;
124
125      lower_variable_index_to_cond_assign(shader->ir,
126					  input, output, temp, uniform);
127
128      do {
129	 progress = false;
130
131	 if (stage == MESA_SHADER_FRAGMENT) {
132	    brw_do_channel_expressions(shader->ir);
133	    brw_do_vector_splitting(shader->ir);
134	 }
135
136	 progress = do_lower_jumps(shader->ir, true, true,
137				   true, /* main return */
138				   false, /* continue */
139				   false /* loops */
140				   ) || progress;
141
142	 progress = do_common_optimization(shader->ir, true, 32) || progress;
143      } while (progress);
144
145      validate_ir_tree(shader->ir);
146
147      reparent_ir(shader->ir, shader->ir);
148      ralloc_free(mem_ctx);
149   }
150
151   if (!_mesa_ir_link_shader(ctx, prog))
152      return GL_FALSE;
153
154   if (!brw_shader_precompile(ctx, prog))
155      return GL_FALSE;
156
157   return GL_TRUE;
158}
159
160
161int
162brw_type_for_base_type(const struct glsl_type *type)
163{
164   switch (type->base_type) {
165   case GLSL_TYPE_FLOAT:
166      return BRW_REGISTER_TYPE_F;
167   case GLSL_TYPE_INT:
168   case GLSL_TYPE_BOOL:
169      return BRW_REGISTER_TYPE_D;
170   case GLSL_TYPE_UINT:
171      return BRW_REGISTER_TYPE_UD;
172   case GLSL_TYPE_ARRAY:
173   case GLSL_TYPE_STRUCT:
174   case GLSL_TYPE_SAMPLER:
175      /* These should be overridden with the type of the member when
176       * dereferenced into.  BRW_REGISTER_TYPE_UD seems like a likely
177       * way to trip up if we don't.
178       */
179      return BRW_REGISTER_TYPE_UD;
180   default:
181      assert(!"not reached");
182      return BRW_REGISTER_TYPE_F;
183   }
184}
185
186uint32_t
187brw_conditional_for_comparison(unsigned int op)
188{
189   switch (op) {
190   case ir_binop_less:
191      return BRW_CONDITIONAL_L;
192   case ir_binop_greater:
193      return BRW_CONDITIONAL_G;
194   case ir_binop_lequal:
195      return BRW_CONDITIONAL_LE;
196   case ir_binop_gequal:
197      return BRW_CONDITIONAL_GE;
198   case ir_binop_equal:
199   case ir_binop_all_equal: /* same as equal for scalars */
200      return BRW_CONDITIONAL_Z;
201   case ir_binop_nequal:
202   case ir_binop_any_nequal: /* same as nequal for scalars */
203      return BRW_CONDITIONAL_NZ;
204   default:
205      assert(!"not reached: bad operation for comparison");
206      return BRW_CONDITIONAL_NZ;
207   }
208}
209
210uint32_t
211brw_math_function(enum opcode op)
212{
213   switch (op) {
214   case SHADER_OPCODE_RCP:
215      return BRW_MATH_FUNCTION_INV;
216   case SHADER_OPCODE_RSQ:
217      return BRW_MATH_FUNCTION_RSQ;
218   case SHADER_OPCODE_SQRT:
219      return BRW_MATH_FUNCTION_SQRT;
220   case SHADER_OPCODE_EXP2:
221      return BRW_MATH_FUNCTION_EXP;
222   case SHADER_OPCODE_LOG2:
223      return BRW_MATH_FUNCTION_LOG;
224   case SHADER_OPCODE_POW:
225      return BRW_MATH_FUNCTION_POW;
226   case SHADER_OPCODE_SIN:
227      return BRW_MATH_FUNCTION_SIN;
228   case SHADER_OPCODE_COS:
229      return BRW_MATH_FUNCTION_COS;
230   case SHADER_OPCODE_INT_QUOTIENT:
231      return BRW_MATH_FUNCTION_INT_DIV_QUOTIENT;
232   case SHADER_OPCODE_INT_REMAINDER:
233      return BRW_MATH_FUNCTION_INT_DIV_REMAINDER;
234   default:
235      assert(!"not reached: unknown math function");
236      return 0;
237   }
238}
239