1/* 2 * Copyright © 2014 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 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24/** 25 * \file lower_const_arrays_to_uniforms.cpp 26 * 27 * Lower constant arrays to uniform arrays. 28 * 29 * Some driver backends (such as i965 and nouveau) don't handle constant arrays 30 * gracefully, instead treating them as ordinary writable temporary arrays. 31 * Since arrays can be large, this often means spilling them to scratch memory, 32 * which usually involves a large number of instructions. 33 * 34 * This must be called prior to link_set_uniform_initializers(); we need the 35 * linker to process our new uniform's constant initializer. 36 * 37 * This should be called after optimizations, since those can result in 38 * splitting and removing arrays that are indexed by constant expressions. 39 */ 40#include "ir.h" 41#include "ir_visitor.h" 42#include "ir_rvalue_visitor.h" 43#include "compiler/glsl_types.h" 44 45namespace { 46class lower_const_array_visitor : public ir_rvalue_visitor { 47public: 48 lower_const_array_visitor(exec_list *insts, unsigned s) 49 { 50 instructions = insts; 51 stage = s; 52 const_count = 0; 53 progress = false; 54 } 55 56 bool run() 57 { 58 visit_list_elements(this, instructions); 59 return progress; 60 } 61 62 ir_visitor_status visit_enter(ir_texture *); 63 void handle_rvalue(ir_rvalue **rvalue); 64 65private: 66 exec_list *instructions; 67 unsigned stage; 68 unsigned const_count; 69 bool progress; 70}; 71 72ir_visitor_status 73lower_const_array_visitor::visit_enter(ir_texture *) 74{ 75 return visit_continue_with_parent; 76} 77 78void 79lower_const_array_visitor::handle_rvalue(ir_rvalue **rvalue) 80{ 81 if (!*rvalue) 82 return; 83 84 ir_constant *con = (*rvalue)->as_constant(); 85 if (!con || !con->type->is_array()) 86 return; 87 88 void *mem_ctx = ralloc_parent(con); 89 90 /* In the very unlikely event of 4294967295 constant arrays in a single 91 * shader, don't promote this to a uniform. 92 */ 93 unsigned limit = ~0; 94 if (const_count == limit) 95 return; 96 97 char *uniform_name = ralloc_asprintf(mem_ctx, "constarray_%x_%u", 98 const_count, stage); 99 const_count++; 100 101 ir_variable *uni = 102 new(mem_ctx) ir_variable(con->type, uniform_name, ir_var_uniform); 103 uni->constant_initializer = con; 104 uni->constant_value = con; 105 uni->data.has_initializer = true; 106 uni->data.how_declared = ir_var_hidden; 107 uni->data.read_only = true; 108 /* Assume the whole thing is accessed. */ 109 uni->data.max_array_access = uni->type->length - 1; 110 instructions->push_head(uni); 111 112 *rvalue = new(mem_ctx) ir_dereference_variable(uni); 113 114 progress = true; 115} 116 117} /* anonymous namespace */ 118 119bool 120lower_const_arrays_to_uniforms(exec_list *instructions, unsigned stage) 121{ 122 lower_const_array_visitor v(instructions, stage); 123 return v.run(); 124} 125