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