1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright © 2010 Intel Corporation 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"), 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions: 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the next 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * paragraph) shall be included in all copies or substantial portions of the 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software. 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DEALINGS IN THE SOFTWARE. 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \file linker.cpp 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * GLSL linker implementation 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Given a set of shaders that are to be linked to generate a final program, 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * there are three distinct stages. 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * In the first stage shaders are partitioned into groups based on the shader 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * type. All shaders of a particular type (e.g., vertex shaders) are linked 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * together. 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Undefined references in each shader are resolve to definitions in 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * another shader. 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Types and qualifiers of uniforms, outputs, and global variables defined 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * in multiple shaders with the same name are verified to be the same. 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Initializers for uniforms and global variables defined 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * in multiple shaders with the same name are verified to be the same. 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The result, in the terminology of the GLSL spec, is a set of shader 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * executables for each processing unit. 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * After the first stage is complete, a series of semantic checks are performed 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * on each of the shader executables. 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Each shader executable must define a \c main function. 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Each vertex shader executable must write to \c gl_Position. 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Each fragment shader executable must write to either \c gl_FragData or 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \c gl_FragColor. 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * In the final stage individual shader executables are linked to create a 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * complete exectuable. 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Types of uniforms defined in multiple shader stages with the same name 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * are verified to be the same. 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Initializers for uniforms defined in multiple shader stages with the 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * same name are verified to be the same. 60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Types and qualifiers of outputs defined in one stage are verified to 61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * be the same as the types and qualifiers of inputs defined with the same 62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * name in a later stage. 63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \author Ian Romanick <ian.d.romanick@intel.com> 65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/core.h" 68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "glsl_symbol_table.h" 69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir.h" 70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "program.h" 71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "program/hash_table.h" 72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "linker.h" 73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_optimization.h" 74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgextern "C" { 76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/shaderobj.h" 77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Visitor that determines whether or not a variable is ever written. 81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass find_assignment_visitor : public ir_hierarchical_visitor { 83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic: 84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find_assignment_visitor(const char *name) 85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org : name(name), found(false) 86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* empty */ 88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit_enter(ir_assignment *ir) 91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const var = ir->lhs->variable_referenced(); 93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(name, var->name) == 0) { 95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org found = true; 96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_stop; 97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue_with_parent; 100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit_enter(ir_call *ir) 103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exec_list_iterator sig_iter = ir->callee->parameters.iterator(); 105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_iter(exec_list_iterator, iter, *ir) { 106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_rvalue *param_rval = (ir_rvalue *)iter.get(); 107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *sig_param = (ir_variable *)sig_iter.get(); 108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (sig_param->mode == ir_var_out || 110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sig_param->mode == ir_var_inout) { 111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var = param_rval->variable_referenced(); 112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var && strcmp(name, var->name) == 0) { 113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org found = true; 114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_stop; 115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sig_iter.next(); 118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ir->return_deref != NULL) { 121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const var = ir->return_deref->variable_referenced(); 122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(name, var->name) == 0) { 124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org found = true; 125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_stop; 126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue_with_parent; 130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool variable_found() 133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return found; 135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgprivate: 138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *name; /**< Find writes to a variable with this name. */ 139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool found; /**< Was a write to the variable found? */ 140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Visitor that determines whether or not a variable is ever read. 145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass find_deref_visitor : public ir_hierarchical_visitor { 147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic: 148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find_deref_visitor(const char *name) 149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org : name(name), found(false) 150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* empty */ 152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit(ir_dereference_variable *ir) 155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(this->name, ir->var->name) == 0) { 157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->found = true; 158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_stop; 159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool variable_found() const 165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return this->found; 167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgprivate: 170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *name; /**< Find writes to a variable with this name. */ 171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool found; /**< Was a write to the variable found? */ 172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglinker_error(gl_shader_program *prog, const char *fmt, ...) 177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_list ap; 179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_strcat(&prog->InfoLog, "error: "); 181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_start(ap, fmt); 182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_vasprintf_append(&prog->InfoLog, fmt, ap); 183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_end(ap); 184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->LinkStatus = false; 186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglinker_warning(gl_shader_program *prog, const char *fmt, ...) 191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_list ap; 193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_strcat(&prog->InfoLog, "error: "); 195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_start(ap, fmt); 196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_vasprintf_append(&prog->InfoLog, fmt, ap); 197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_end(ap); 198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglink_invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode, 204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int generic_base) 205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, sh->ir) { 207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const var = ((ir_instruction *) node)->as_variable(); 208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((var == NULL) || (var->mode != (unsigned) mode)) 210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Only assign locations for generic attributes / varyings / etc. 213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((var->location >= generic_base) && !var->explicit_location) 215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->location = -1; 216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Determine the number of attribute slots required for a particular type 222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This code is here because it implements the language rules of a specific 224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * GLSL version. Since it's a property of the language and not a property of 225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * types in general, it doesn't really belong in glsl_type. 226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgunsigned 228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcount_attribute_slots(const glsl_type *t) 229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec: 231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "A scalar input counts the same amount against this limit as a vec4, 233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * so applications may want to consider packing groups of four 234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * unrelated float inputs together into a vector to better utilize the 235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * capabilities of the underlying hardware. A matrix input will use up 236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * multiple locations. The number of locations used will equal the 237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * number of columns in the matrix." 238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The spec does not explicitly say how arrays are counted. However, it 240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * should be safe to assume the total number of slots consumed by an array 241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is the number of entries in the array multiplied by the number of slots 242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * consumed by a single element of the array. 243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (t->is_array()) 246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return t->array_size() * count_attribute_slots(t->element_type()); 247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (t->is_matrix()) 249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return t->matrix_columns; 250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return 1; 252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Verify that a vertex shader executable meets all semantic requirements. 257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Also sets prog->Vert.UsesClipDistance and prog->Vert.ClipDistanceArraySize 259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * as a side effect. 260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param shader Vertex shader executable to be verified 262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvalidate_vertex_shader_executable(struct gl_shader_program *prog, 265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader *shader) 266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (shader == NULL) 268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* From the GLSL 1.10 spec, page 48: 271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "The variable gl_Position is available only in the vertex 273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * language and is intended for writing the homogeneous vertex 274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * position. All executions of a well-formed vertex shader 275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * executable must write a value into this variable. [...] The 276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * variable gl_Position is available only in the vertex 277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * language and is intended for writing the homogeneous vertex 278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * position. All executions of a well-formed vertex shader 279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * executable must write a value into this variable." 280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * while in GLSL 1.40 this text is changed to: 282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "The variable gl_Position is available only in the vertex 284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * language and is intended for writing the homogeneous vertex 285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * position. It can be written at any time during shader 286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * execution. It may also be read back by a vertex shader 287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * after being written. This value will be used by primitive 288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * assembly, clipping, culling, and other fixed functionality 289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * operations, if present, that operate on primitives after 290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vertex processing has occurred. Its value is undefined if 291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the vertex shader executable does not write gl_Position." 292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->Version < 140) { 294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find_assignment_visitor find("gl_Position"); 295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find.run(shader->ir); 296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!find.variable_found()) { 297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "vertex shader does not write to `gl_Position'\n"); 298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->Vert.ClipDistanceArraySize = 0; 303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->Version >= 130) { 305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* From section 7.1 (Vertex Shader Special Variables) of the 306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * GLSL 1.30 spec: 307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "It is an error for a shader to statically write both 309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * gl_ClipVertex and gl_ClipDistance." 310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find_assignment_visitor clip_vertex("gl_ClipVertex"); 312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find_assignment_visitor clip_distance("gl_ClipDistance"); 313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clip_vertex.run(shader->ir); 315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clip_distance.run(shader->ir); 316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (clip_vertex.variable_found() && clip_distance.variable_found()) { 317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "vertex shader writes to both `gl_ClipVertex' " 318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "and `gl_ClipDistance'\n"); 319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->Vert.UsesClipDistance = clip_distance.variable_found(); 322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *clip_distance_var = 323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org shader->symbols->get_variable("gl_ClipDistance"); 324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (clip_distance_var) 325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->Vert.ClipDistanceArraySize = clip_distance_var->type->length; 326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Verify that a fragment shader executable meets all semantic requirements 334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param shader Fragment shader executable to be verified 336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvalidate_fragment_shader_executable(struct gl_shader_program *prog, 339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader *shader) 340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (shader == NULL) 342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find_assignment_visitor frag_color("gl_FragColor"); 345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find_assignment_visitor frag_data("gl_FragData"); 346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org frag_color.run(shader->ir); 348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org frag_data.run(shader->ir); 349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (frag_color.variable_found() && frag_data.variable_found()) { 351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "fragment shader writes to both " 352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "`gl_FragColor' and `gl_FragData'\n"); 353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Generate a string describing the mode of a variable 362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char * 364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmode_string(const ir_variable *var) 365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (var->mode) { 367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_var_auto: 368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return (var->read_only) ? "global constant" : "global variable"; 369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_var_uniform: return "uniform"; 371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_var_in: return "shader input"; 372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_var_out: return "shader output"; 373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_var_inout: return "shader inout"; 374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_var_const_in: 376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_var_temporary: 377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org default: 378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(!"Should not get here."); 379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return "invalid variable"; 380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Perform validation of global variables used across multiple shaders 386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcross_validate_globals(struct gl_shader_program *prog, 389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader **shader_list, 390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_shaders, 391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool uniforms_only) 392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Examine all of the uniforms in all of the shaders and cross validate 394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * them. 395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org glsl_symbol_table variables; 397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_shaders; i++) { 398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (shader_list[i] == NULL) 399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, shader_list[i]->ir) { 402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const var = ((ir_instruction *) node)->as_variable(); 403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var == NULL) 405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (uniforms_only && (var->mode != ir_var_uniform)) 408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Don't cross validate temporaries that are at global scope. These 411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * will eventually get pulled into the shaders 'main'. 412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->mode == ir_var_temporary) 414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If a global with this name has already been seen, verify that the 417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * new instance has the same type. In addition, if the globals have 418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * initializers, the values of the initializers must be the same. 419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const existing = variables.get_variable(var->name); 421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (existing != NULL) { 422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->type != existing->type) { 423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Consider the types to be "the same" if both types are arrays 424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of the same type and one of the arrays is implicitly sized. 425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * In addition, set the type of the linked variable to the 426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * explicitly sized array. 427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->type->is_array() 429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org && existing->type->is_array() 430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org && (var->type->fields.array == existing->type->fields.array) 431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org && ((var->type->length == 0) 432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || (existing->type->length == 0))) { 433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->type->length != 0) { 434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org existing->type = var->type; 435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "%s `%s' declared as type " 438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "`%s' and type `%s'\n", 439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org mode_string(var), 440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->name, var->type->name, 441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org existing->type->name); 442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->explicit_location) { 447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (existing->explicit_location 448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org && (var->location != existing->location)) { 449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "explicit locations for %s " 450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "`%s' have differing values\n", 451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org mode_string(var), var->name); 452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org existing->location = var->location; 456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org existing->explicit_location = true; 457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Validate layout qualifiers for gl_FragDepth. 460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * From the AMD/ARB_conservative_depth specs: 462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "If gl_FragDepth is redeclared in any fragment shader in a 464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * program, it must be redeclared in all fragment shaders in 465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * that program that have static assignments to 466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * gl_FragDepth. All redeclarations of gl_FragDepth in all 467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * fragment shaders in a single program must have the same set 468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of qualifiers." 469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(var->name, "gl_FragDepth") == 0) { 471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool layout_declared = var->depth_layout != ir_depth_layout_none; 472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool layout_differs = 473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->depth_layout != existing->depth_layout; 474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (layout_declared && layout_differs) { 476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, 477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "All redeclarations of gl_FragDepth in all " 478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "fragment shaders in a single program must have " 479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "the same set of qualifiers."); 480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->used && layout_differs) { 483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, 484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "If gl_FragDepth is redeclared with a layout " 485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "qualifier in any fragment shader, it must be " 486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "redeclared with the same layout qualifier in " 487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "all fragment shaders that have assignments to " 488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "gl_FragDepth"); 489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Page 35 (page 41 of the PDF) of the GLSL 4.20 spec says: 493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "If a shared global has multiple initializers, the 495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * initializers must all be constant expressions, and they 496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * must all have the same value. Otherwise, a link error will 497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * result. (A shared global having only one initializer does 498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * not require that initializer to be a constant expression.)" 499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Previous to 4.20 the GLSL spec simply said that initializers 501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * must have the same value. In this case of non-constant 502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * initializers, this was impossible to determine. As a result, 503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * no vendor actually implemented that behavior. The 4.20 504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * behavior matches the implemented behavior of at least one other 505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vendor, so we'll implement that for all GLSL versions. 506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->constant_initializer != NULL) { 508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (existing->constant_initializer != NULL) { 509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!var->constant_initializer->has_value(existing->constant_initializer)) { 510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "initializers for %s " 511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "`%s' have differing values\n", 512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org mode_string(var), var->name); 513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If the first-seen instance of a particular uniform did not 517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * have an initializer but a later instance does, copy the 518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * initializer to the version stored in the symbol table. 519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* FINISHME: This is wrong. The constant_value field should 521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: not be modified! Imagine a case where a shader 522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: without an initializer is linked in two different 523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: programs with shaders that have differing 524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: initializers. Linking with the first will 525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: modify the shader, and linking with the second 526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: will fail. 527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org existing->constant_initializer = 529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->constant_initializer->clone(ralloc_parent(existing), 530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org NULL); 531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->has_initializer) { 535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (existing->has_initializer 536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org && (var->constant_initializer == NULL 537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || existing->constant_initializer == NULL)) { 538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, 539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "shared global variable `%s' has multiple " 540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "non-constant initializers.\n", 541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->name); 542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Some instance had an initializer, so keep track of that. In 546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * this location, all sorts of initializers (constant or 547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * otherwise) will propagate the existence to the variable 548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * stored in the symbol table. 549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org existing->has_initializer = true; 551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (existing->invariant != var->invariant) { 554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "declarations for %s `%s' have " 555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "mismatching invariant qualifiers\n", 556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org mode_string(var), var->name); 557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (existing->centroid != var->centroid) { 560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "declarations for %s `%s' have " 561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "mismatching centroid qualifiers\n", 562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org mode_string(var), var->name); 563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else 566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variables.add_variable(var); 567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Perform validation of uniforms used across multiple shader stages 576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcross_validate_uniforms(struct gl_shader_program *prog) 579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return cross_validate_globals(prog, prog->_LinkedShaders, 581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org MESA_SHADER_TYPES, true); 582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Accumulates the array of prog->UniformBlocks and checks that all 586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * definitons of blocks agree on their contents. 587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool 589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orginterstage_cross_validate_uniform_blocks(struct gl_shader_program *prog) 590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned max_num_uniform_blocks = 0; 592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { 593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[i]) 594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org max_num_uniform_blocks += prog->_LinkedShaders[i]->NumUniformBlocks; 595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { 598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader *sh = prog->_LinkedShaders[i]; 599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->UniformBlockStageIndex[i] = ralloc_array(prog, int, 601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org max_num_uniform_blocks); 602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned int j = 0; j < max_num_uniform_blocks; j++) 603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->UniformBlockStageIndex[i][j] = -1; 604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (sh == NULL) 606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned int j = 0; j < sh->NumUniformBlocks; j++) { 609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int index = link_cross_validate_uniform_block(prog, 610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org &prog->UniformBlocks, 611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org &prog->NumUniformBlocks, 612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org &sh->UniformBlocks[j]); 613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (index == -1) { 615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "uniform block `%s' has mismatching definitions", 616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sh->UniformBlocks[j].Name); 617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->UniformBlockStageIndex[i][index] = j; 621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Validate that outputs from one stage match inputs of another 629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcross_validate_outputs_to_inputs(struct gl_shader_program *prog, 632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gl_shader *producer, gl_shader *consumer) 633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org glsl_symbol_table parameters; 635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* FINISHME: Figure these out dynamically. */ 636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *const producer_stage = "vertex"; 637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *const consumer_stage = "fragment"; 638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Find all shader outputs in the "producer" stage. 640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, producer->ir) { 642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const var = ((ir_instruction *) node)->as_variable(); 643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* FINISHME: For geometry shaders, this should also look for inout 645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: variables. 646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((var == NULL) || (var->mode != ir_var_out)) 648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org parameters.add_variable(var); 651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Find all shader inputs in the "consumer" stage. Any variables that have 655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * matching outputs already in the symbol table must have the same type and 656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * qualifiers. 657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, consumer->ir) { 659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const input = ((ir_instruction *) node)->as_variable(); 660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* FINISHME: For geometry shaders, this should also look for inout 662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: variables. 663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((input == NULL) || (input->mode != ir_var_in)) 665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const output = parameters.get_variable(input->name); 668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (output != NULL) { 669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Check that the types match between stages. 670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (input->type != output->type) { 672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* There is a bit of a special case for gl_TexCoord. This 673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * built-in is unsized by default. Applications that variable 674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * access it must redeclare it with a size. There is some 675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * language in the GLSL spec that implies the fragment shader 676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and vertex shader do not have to agree on this size. Other 677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * driver behave this way, and one or two applications seem to 678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * rely on it. 679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Neither declaration needs to be modified here because the array 681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * sizes are fixed later when update_array_sizes is called. 682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * From page 48 (page 54 of the PDF) of the GLSL 1.10 spec: 684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "Unlike user-defined varying variables, the built-in 686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * varying variables don't have a strict one-to-one 687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * correspondence between the vertex language and the 688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * fragment language." 689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!output->type->is_array() 691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || (strncmp("gl_", output->name, 3) != 0)) { 692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, 693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s shader output `%s' declared as type `%s', " 694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "but %s shader input declared as type `%s'\n", 695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org producer_stage, output->name, 696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org output->type->name, 697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org consumer_stage, input->type->name); 698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Check that all of the qualifiers match between stages. 703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (input->centroid != output->centroid) { 705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, 706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s shader output `%s' %s centroid qualifier, " 707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "but %s shader input %s centroid qualifier\n", 708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org producer_stage, 709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org output->name, 710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (output->centroid) ? "has" : "lacks", 711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org consumer_stage, 712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (input->centroid) ? "has" : "lacks"); 713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (input->invariant != output->invariant) { 717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, 718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s shader output `%s' %s invariant qualifier, " 719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "but %s shader input %s invariant qualifier\n", 720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org producer_stage, 721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org output->name, 722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (output->invariant) ? "has" : "lacks", 723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org consumer_stage, 724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (input->invariant) ? "has" : "lacks"); 725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (input->interpolation != output->interpolation) { 729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, 730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s shader output `%s' specifies %s " 731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "interpolation qualifier, " 732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "but %s shader input specifies %s " 733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "interpolation qualifier\n", 734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org producer_stage, 735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org output->name, 736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org output->interpolation_string(), 737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org consumer_stage, 738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org input->interpolation_string()); 739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Populates a shaders symbol table with all global declarations 750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void 752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpopulate_symbol_table(gl_shader *sh) 753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sh->symbols = new(sh) glsl_symbol_table; 755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, sh->ir) { 757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_instruction *const inst = (ir_instruction *) node; 758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var; 759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_function *func; 760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((func = inst->as_function()) != NULL) { 762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sh->symbols->add_function(func); 763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if ((var = inst->as_variable()) != NULL) { 764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sh->symbols->add_variable(var); 765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Remap variables referenced in an instruction tree 772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This is used when instruction trees are cloned from one shader and placed in 774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * another. These trees will contain references to \c ir_variable nodes that 775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * do not exist in the target shader. This function finds these \c ir_variable 776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * references and replaces the references with matching variables in the target 777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * shader. 778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If there is no matching variable in the target shader, a clone of the 780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \c ir_variable is made and added to the target shader. The new variable is 781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * added to \b both the instruction stream and the symbol table. 782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param inst IR tree that is to be processed. 784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param symbols Symbol table containing global scope symbols in the 785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * linked shader. 786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param instructions Instruction stream where new variable declarations 787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * should be added. 788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgremap_variables(ir_instruction *inst, struct gl_shader *target, 791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hash_table *temps) 792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org class remap_visitor : public ir_hierarchical_visitor { 794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public: 795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org remap_visitor(struct gl_shader *target, 796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hash_table *temps) 797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->target = target; 799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->symbols = target->symbols; 800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->instructions = target->ir; 801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->temps = temps; 802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit(ir_dereference_variable *ir) 805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ir->var->mode == ir_var_temporary) { 807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var = (ir_variable *) hash_table_find(temps, ir->var); 808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(var != NULL); 810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir->var = var; 811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const existing = 815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->symbols->get_variable(ir->var->name); 816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (existing != NULL) 817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir->var = existing; 818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else { 819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *copy = ir->var->clone(this->target, NULL); 820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->symbols->add_variable(copy); 822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->instructions->push_head(copy); 823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir->var = copy; 824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org private: 830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader *target; 831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org glsl_symbol_table *symbols; 832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exec_list *instructions; 833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hash_table *temps; 834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org }; 835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org remap_visitor v(target, temps); 837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org inst->accept(&v); 839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Move non-declarations from one instruction stream to another 844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The intended usage pattern of this function is to pass the pointer to the 846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * head sentinel of a list (i.e., a pointer to the list cast to an \c exec_node 847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * pointer) for \c last and \c false for \c make_copies on the first 848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * call. Successive calls pass the return value of the previous call for 849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \c last and \c true for \c make_copies. 850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param instructions Source instruction stream 852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param last Instruction after which new instructions should be 853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * inserted in the target instruction stream 854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param make_copies Flag selecting whether instructions in \c instructions 855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * should be copied (via \c ir_instruction::clone) into the 856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * target list or moved. 857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \return 859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The new "last" instruction in the target instruction stream. This pointer 860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is suitable for use as the \c last parameter of a later call to this 861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * function. 862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgexec_node * 864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmove_non_declarations(exec_list *instructions, exec_node *last, 865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool make_copies, gl_shader *target) 866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hash_table *temps = NULL; 868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (make_copies) 870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org temps = hash_table_ctor(0, hash_table_pointer_hash, 871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hash_table_pointer_compare); 872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list_safe(node, instructions) { 874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_instruction *inst = (ir_instruction *) node; 875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (inst->as_function()) 877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var = inst->as_variable(); 880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((var != NULL) && (var->mode != ir_var_temporary)) 881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(inst->as_assignment() 884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || inst->as_call() 885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || inst->as_if() /* for initializers with the ?: operator */ 886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || ((var != NULL) && (var->mode == ir_var_temporary))); 887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (make_copies) { 889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org inst = inst->clone(target, NULL); 890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var != NULL) 892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hash_table_insert(temps, inst, var); 893f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 894f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org remap_variables(inst, target, temps); 895f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 896f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org inst->remove(); 897f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 898f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 899f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org last->insert_after(inst); 900f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org last = inst; 901f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 902f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 903f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (make_copies) 904f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hash_table_dtor(temps); 905f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 906f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return last; 907f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 908f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 909f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 910f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Get the function signature for main from a shader 911f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 912f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic ir_function_signature * 913f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgget_main_function_signature(gl_shader *sh) 914f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 915f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_function *const f = sh->symbols->get_function("main"); 916f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (f != NULL) { 917f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exec_list void_parameters; 918f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 919f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Look for the 'void main()' signature and ensure that it's defined. 920f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This keeps the linker from accidentally pick a shader that just 921f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * contains a prototype for main. 922f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 923f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * We don't have to check for multiple definitions of main (in multiple 924f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * shaders) because that would have already been caught above. 925f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 926f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_function_signature *sig = f->matching_signature(&void_parameters); 927f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((sig != NULL) && sig->is_defined) { 928f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return sig; 929f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 930f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 931f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 932f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 933f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 934f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 935f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 936f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 937f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This class is only used in link_intrastage_shaders() below but declaring 938f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * it inside that function leads to compiler warnings with some versions of 939f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * gcc. 940f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 941f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass array_sizing_visitor : public ir_hierarchical_visitor { 942f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic: 943f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit(ir_variable *var) 944f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 945f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->type->is_array() && (var->type->length == 0)) { 946f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const glsl_type *type = 947f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org glsl_type::get_array_instance(var->type->fields.array, 948f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->max_array_access + 1); 949f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(type != NULL); 950f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->type = type; 951f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 952f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 953f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 954f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 955f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 956f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 957f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Combine a group of shaders for a single stage to generate a linked shader 958f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 959f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \note 960f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If this function is supplied a single shader, it is cloned, and the new 961f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * shader is returned. 962f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 963f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct gl_shader * 964f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglink_intrastage_shaders(void *mem_ctx, 965f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_context *ctx, 966f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader_program *prog, 967f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader **shader_list, 968f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_shaders) 969f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 970f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_uniform_block *uniform_blocks = NULL; 971f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_uniform_blocks = 0; 972f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 973f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Check that global variables defined in multiple shaders are consistent. 974f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 975f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!cross_validate_globals(prog, shader_list, num_shaders, false)) 976f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 977f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 978f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Check that uniform blocks between shaders for a stage agree. */ 979f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_shaders; i++) { 980f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader *sh = shader_list[i]; 981f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 982f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned j = 0; j < shader_list[i]->NumUniformBlocks; j++) { 983f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org link_assign_uniform_block_offsets(shader_list[i]); 984f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 985f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int index = link_cross_validate_uniform_block(mem_ctx, 986f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org &uniform_blocks, 987f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org &num_uniform_blocks, 988f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org &sh->UniformBlocks[j]); 989f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (index == -1) { 990f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "uniform block `%s' has mismatching definitions", 991f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sh->UniformBlocks[j].Name); 992f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 993f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 994f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 995f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 996f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 997f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Check that there is only a single definition of each function signature 998f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * across all shaders. 999f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1000f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < (num_shaders - 1); i++) { 1001f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, shader_list[i]->ir) { 1002f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_function *const f = ((ir_instruction *) node)->as_function(); 1003f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1004f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (f == NULL) 1005f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1006f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1007f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned j = i + 1; j < num_shaders; j++) { 1008f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_function *const other = 1009f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org shader_list[j]->symbols->get_function(f->name); 1010f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1011f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If the other shader has no function (and therefore no function 1012f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * signatures) with the same name, skip to the next shader. 1013f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1014f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (other == NULL) 1015f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1016f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1017f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_iter (exec_list_iterator, iter, *f) { 1018f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_function_signature *sig = 1019f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (ir_function_signature *) iter.get(); 1020f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1021f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!sig->is_defined || sig->is_builtin) 1022f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1023f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1024f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_function_signature *other_sig = 1025f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org other->exact_matching_signature(& sig->parameters); 1026f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1027f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((other_sig != NULL) && other_sig->is_defined 1028f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org && !other_sig->is_builtin) { 1029f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "function `%s' is multiply defined", 1030f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org f->name); 1031f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1032f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1033f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1034f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1035f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1036f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1037f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1038f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Find the shader that defines main, and make a clone of it. 1039f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1040f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Starting with the clone, search for undefined references. If one is 1041f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * found, find the shader that defines it. Clone the reference and add 1042f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * it to the shader. Repeat until there are no undefined references or 1043f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * until a reference cannot be resolved. 1044f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1045f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gl_shader *main = NULL; 1046f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_shaders; i++) { 1047f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (get_main_function_signature(shader_list[i]) != NULL) { 1048f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org main = shader_list[i]; 1049f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 1050f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1051f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1052f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1053f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (main == NULL) { 1054f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "%s shader lacks `main'\n", 1055f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (shader_list[0]->Type == GL_VERTEX_SHADER) 1056f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ? "vertex" : "fragment"); 1057f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1058f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1059f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1060f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gl_shader *linked = ctx->Driver.NewShader(NULL, 0, main->Type); 1061f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linked->ir = new(linked) exec_list; 1062f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clone_ir_list(mem_ctx, linked->ir, main->ir); 1063f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1064f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linked->UniformBlocks = uniform_blocks; 1065f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linked->NumUniformBlocks = num_uniform_blocks; 1066f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_steal(linked, linked->UniformBlocks); 1067f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1068f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org populate_symbol_table(linked); 1069f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1070f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* The a pointer to the main function in the final linked shader (i.e., the 1071f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of the original shader that contained the main function). 1072f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1073f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_function_signature *const main_sig = get_main_function_signature(linked); 1074f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1075f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Move any instructions other than variable declarations or function 1076f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * declarations into main. 1077f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1078f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exec_node *insertion_point = 1079f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org move_non_declarations(linked->ir, (exec_node *) &main_sig->body, false, 1080f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linked); 1081f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1082f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_shaders; i++) { 1083f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (shader_list[i] == main) 1084f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1085f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1086f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org insertion_point = move_non_declarations(shader_list[i]->ir, 1087f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org insertion_point, true, linked); 1088f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1089f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1090f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Resolve initializers for global variables in the linked shader. 1091f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1092f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_linking_shaders = num_shaders; 1093f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_shaders; i++) 1094f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_linking_shaders += shader_list[i]->num_builtins_to_link; 1095f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1096f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gl_shader **linking_shaders = 1097f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (gl_shader **) calloc(num_linking_shaders, sizeof(gl_shader *)); 1098f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1099f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(linking_shaders, shader_list, 1100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sizeof(linking_shaders[0]) * num_shaders); 1101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned idx = num_shaders; 1103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_shaders; i++) { 1104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(&linking_shaders[idx], shader_list[i]->builtins_to_link, 1105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sizeof(linking_shaders[0]) * shader_list[i]->num_builtins_to_link); 1106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org idx += shader_list[i]->num_builtins_to_link; 1107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(idx == num_linking_shaders); 1110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!link_function_calls(prog, linked, linking_shaders, 1112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_linking_shaders)) { 1113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Driver.DeleteShader(ctx, linked); 1114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linked = NULL; 1115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free(linking_shaders); 1118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef DEBUG 1120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* At this point linked should contain all of the linked IR, so 1121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * validate it to make sure nothing went wrong. 1122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (linked) 1124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org validate_ir_tree(linked->ir); 1125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 1126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Make a pass over all variable declarations to ensure that arrays with 1128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * unspecified sizes have a size specified. The size is inferred from the 1129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * max_array_access field. 1130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (linked != NULL) { 1132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org array_sizing_visitor v; 1133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org v.run(linked->ir); 1135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return linked; 1138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Update the sizes of linked shader uniform arrays to the maximum 1142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * array index used. 1143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * From page 81 (page 95 of the PDF) of the OpenGL 2.1 spec: 1145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If one or more elements of an array are active, 1147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * GetActiveUniform will return the name of the array in name, 1148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * subject to the restrictions listed above. The type of the array 1149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is returned in type. The size parameter contains the highest 1150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * array element index used, plus one. The compiler or linker 1151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * determines the highest index used. There will be only one 1152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * active uniform reported by the GL per uniform array. 1153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void 1156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgupdate_array_sizes(struct gl_shader_program *prog) 1157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { 1159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[i] == NULL) 1160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, prog->_LinkedShaders[i]->ir) { 1163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const var = ((ir_instruction *) node)->as_variable(); 1164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((var == NULL) || (var->mode != ir_var_uniform && 1166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->mode != ir_var_in && 1167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->mode != ir_var_out) || 1168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org !var->type->is_array()) 1169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* GL_ARB_uniform_buffer_object says that std140 uniforms 1172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * will not be eliminated. Since we always do std140, just 1173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * don't resize arrays in UBOs. 1174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->uniform_block != -1) 1176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int size = var->max_array_access; 1179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) { 1180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[j] == NULL) 1181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node2, prog->_LinkedShaders[j]->ir) { 1184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *other_var = ((ir_instruction *) node2)->as_variable(); 1185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!other_var) 1186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(var->name, other_var->name) == 0 && 1189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org other_var->max_array_access > size) { 1190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org size = other_var->max_array_access; 1191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (size + 1 != var->type->fields.array->length) { 1196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If this is a built-in uniform (i.e., it's backed by some 1197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * fixed-function state), adjust the number of state slots to 1198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * match the new array size. The number of slots per array entry 1199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is not known. It seems safe to assume that the total number of 1200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * slots is an integer multiple of the number of array elements. 1201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Determine the number of slots per array element by dividing by 1202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the old (total) size. 1203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->num_state_slots > 0) { 1205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->num_state_slots = (size + 1) 1206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * (var->num_state_slots / var->type->length); 1207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->type = glsl_type::get_array_instance(var->type->fields.array, 1210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org size + 1); 1211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* FINISHME: We should update the types of array 1212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * dereferences of this variable now. 1213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Find a contiguous set of available bits in a bitmask. 1221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param used_mask Bits representing used (1) and unused (0) locations 1223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param needed_count Number of contiguous bits needed. 1224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \return 1226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Base location of the available bits on success or -1 on failure. 1227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint 1229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgfind_available_slots(unsigned used_mask, unsigned needed_count) 1230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned needed_mask = (1 << needed_count) - 1; 1232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const int max_bit_to_test = (8 * sizeof(used_mask)) - needed_count; 1233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* The comparison to 32 is redundant, but without it GCC emits "warning: 1235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * cannot optimize possibly infinite loops" for the loop below. 1236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((needed_count == 0) || (max_bit_to_test < 0) || (max_bit_to_test > 32)) 1238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return -1; 1239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (int i = 0; i <= max_bit_to_test; i++) { 1241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((needed_mask & ~used_mask) == needed_mask) 1242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return i; 1243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org needed_mask <<= 1; 1245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return -1; 1248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Assign locations for either VS inputs for FS outputs 1253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param prog Shader program whose variables need locations assigned 1255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param target_index Selector for the program target to receive location 1256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * assignmnets. Must be either \c MESA_SHADER_VERTEX or 1257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \c MESA_SHADER_FRAGMENT. 1258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param max_index Maximum number of generic locations. This corresponds 1259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to either the maximum number of draw buffers or the 1260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * maximum number of generic attributes. 1261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \return 1263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If locations are successfully assigned, true is returned. Otherwise an 1264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * error is emitted to the shader link log and false is returned. 1265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 1267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgassign_attribute_or_color_locations(gl_shader_program *prog, 1268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned target_index, 1269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned max_index) 1270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Mark invalid locations as being used. 1272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned used_locations = (max_index >= 32) 1274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ? ~0 : ~((1 << max_index) - 1); 1275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert((target_index == MESA_SHADER_VERTEX) 1277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || (target_index == MESA_SHADER_FRAGMENT)); 1278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gl_shader *const sh = prog->_LinkedShaders[target_index]; 1280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (sh == NULL) 1281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Operate in a total of four passes. 1284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1. Invalidate the location assignments for all vertex shader inputs. 1286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2. Assign locations for inputs that have user-defined (via 1288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * glBindVertexAttribLocation) locations and outputs that have 1289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * user-defined locations (via glBindFragDataLocation). 1290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 3. Sort the attributes without assigned locations by number of slots 1292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * required in decreasing order. Fragmentation caused by attribute 1293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * locations assigned by the application may prevent large attributes 1294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * from having enough contiguous space. 1295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 4. Assign locations to any inputs without assigned locations. 1297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const int generic_base = (target_index == MESA_SHADER_VERTEX) 1300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ? (int) VERT_ATTRIB_GENERIC0 : (int) FRAG_RESULT_DATA0; 1301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const enum ir_variable_mode direction = 1303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (target_index == MESA_SHADER_VERTEX) ? ir_var_in : ir_var_out; 1304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org link_invalidate_variable_locations(sh, direction, generic_base); 1307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Temporary storage for the set of attributes that need locations assigned. 1309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct temp_attr { 1311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned slots; 1312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var; 1313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Used below in the call to qsort. */ 1315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static int compare(const void *a, const void *b) 1316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 1317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const temp_attr *const l = (const temp_attr *) a; 1318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const temp_attr *const r = (const temp_attr *) b; 1319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Reversed because we want a descending order sort below. */ 1321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return r->slots - l->slots; 1322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } to_assign[16]; 1324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_attr = 0; 1326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, sh->ir) { 1328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const var = ((ir_instruction *) node)->as_variable(); 1329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((var == NULL) || (var->mode != (unsigned) direction)) 1331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->explicit_location) { 1334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((var->location >= (int)(max_index + generic_base)) 1335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || (var->location < 0)) { 1336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, 1337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "invalid explicit location %d specified for `%s'\n", 1338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (var->location < 0) 1339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ? var->location : var->location - generic_base, 1340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->name); 1341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (target_index == MESA_SHADER_VERTEX) { 1344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned binding; 1345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->AttributeBindings->get(binding, var->name)) { 1347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(binding >= VERT_ATTRIB_GENERIC0); 1348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->location = binding; 1349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (target_index == MESA_SHADER_FRAGMENT) { 1351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned binding; 1352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned index; 1353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->FragDataBindings->get(binding, var->name)) { 1355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(binding >= FRAG_RESULT_DATA0); 1356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->location = binding; 1357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->FragDataIndexBindings->get(index, var->name)) { 1359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->index = index; 1360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If the variable is not a built-in and has a location statically 1365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * assigned in the shader (presumably via a layout qualifier), make sure 1366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * that it doesn't collide with other assigned locations. Otherwise, 1367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * add it to the list of variables that need linker-assigned locations. 1368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned slots = count_attribute_slots(var->type); 1370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->location != -1) { 1371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->location >= generic_base && var->index < 1) { 1372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* From page 61 of the OpenGL 4.0 spec: 1373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "LinkProgram will fail if the attribute bindings assigned 1375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * by BindAttribLocation do not leave not enough space to 1376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * assign a location for an active matrix attribute or an 1377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * active attribute array, both of which require multiple 1378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * contiguous generic attributes." 1379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Previous versions of the spec contain similar language but omit 1381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the bit about attribute arrays. 1382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Page 61 of the OpenGL 4.0 spec also says: 1384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "It is possible for an application to bind more than one 1386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * attribute name to the same location. This is referred to as 1387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * aliasing. This will only work if only one of the aliased 1388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * attributes is active in the executable program, or if no 1389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * path through the shader consumes more than one attribute of 1390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * a set of attributes aliased to the same location. A link 1391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * error can occur if the linker determines that every path 1392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * through the shader consumes multiple aliased attributes, 1393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * but implementations are not required to generate an error 1394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * in this case." 1395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * These two paragraphs are either somewhat contradictory, or I 1397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * don't fully understand one or both of them. 1398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* FINISHME: The code as currently written does not support 1400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: attribute location aliasing (see comment above). 1401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Mask representing the contiguous slots that will be used by 1403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * this attribute. 1404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned attr = var->location - generic_base; 1406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned use_mask = (1 << slots) - 1; 1407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Generate a link error if the set of bits requested for this 1409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * attribute overlaps any previously allocated bits. 1410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((~(use_mask << attr) & used_locations) != used_locations) { 1412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *const string = (target_index == MESA_SHADER_VERTEX) 1413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ? "vertex shader input" : "fragment shader output"; 1414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, 1415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "insufficient contiguous locations " 1416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "available for %s `%s' %d %d %d", string, 1417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->name, used_locations, use_mask, attr); 1418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org used_locations |= (use_mask << attr); 1422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org to_assign[num_attr].slots = slots; 1428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org to_assign[num_attr].var = var; 1429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_attr++; 1430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If all of the attributes were assigned locations by the application (or 1433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * are built-in attributes with fixed locations), return early. This should 1434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * be the common case. 1435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (num_attr == 0) 1437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org qsort(to_assign, num_attr, sizeof(to_assign[0]), temp_attr::compare); 1440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (target_index == MESA_SHADER_VERTEX) { 1442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* VERT_ATTRIB_GENERIC0 is a pseudo-alias for VERT_ATTRIB_POS. It can 1443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * only be explicitly assigned by via glBindAttribLocation. Mark it as 1444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * reserved to prevent it from being automatically allocated below. 1445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find_deref_visitor find("gl_Vertex"); 1447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find.run(sh->ir); 1448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (find.variable_found()) 1449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org used_locations |= (1 << 0); 1450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_attr; i++) { 1453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Mask representing the contiguous slots that will be used by this 1454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * attribute. 1455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned use_mask = (1 << to_assign[i].slots) - 1; 1457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int location = find_available_slots(used_locations, to_assign[i].slots); 1459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (location < 0) { 1461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *const string = (target_index == MESA_SHADER_VERTEX) 1462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ? "vertex shader input" : "fragment shader output"; 1463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, 1465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "insufficient contiguous locations " 1466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "available for %s `%s'", 1467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org string, to_assign[i].var->name); 1468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org to_assign[i].var->location = generic_base + location; 1472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org used_locations |= (use_mask << location); 1473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Demote shader inputs and outputs that are not used in other stages 1481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 1483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdemote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode) 1484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, sh->ir) { 1486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const var = ((ir_instruction *) node)->as_variable(); 1487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((var == NULL) || (var->mode != int(mode))) 1489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* A shader 'in' or 'out' variable is only really an input or output if 1492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * its value is used by other shader stages. This will cause the variable 1493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to have a location assigned. 1494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->location == -1) { 1496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->mode = ir_var_auto; 1497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Data structure tracking information about a transform feedback declaration 1504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * during linking. 1505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass tfeedback_decl 1507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic: 1509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool init(struct gl_context *ctx, struct gl_shader_program *prog, 1510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const void *mem_ctx, const char *input); 1511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y); 1512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool assign_location(struct gl_context *ctx, struct gl_shader_program *prog, 1513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *output_var); 1514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool accumulate_num_outputs(struct gl_shader_program *prog, unsigned *count); 1515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool store(struct gl_context *ctx, struct gl_shader_program *prog, 1516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_transform_feedback_info *info, unsigned buffer, 1517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned max_outputs) const; 1518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * True if assign_location() has been called for this object. 1521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool is_assigned() const 1523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 1524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return this->location != -1; 1525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool is_next_buffer_separator() const 1528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 1529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return this->next_buffer_separator; 1530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool is_varying() const 1533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 1534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return !this->next_buffer_separator && !this->skip_components; 1535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Determine whether this object refers to the variable var. 1539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool matches_var(ir_variable *var) const 1541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 1542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->is_clip_distance_mesa) 1543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return strcmp(var->name, "gl_ClipDistanceMESA") == 0; 1544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 1545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return strcmp(var->name, this->var_name) == 0; 1546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The total number of varying components taken up by this variable. Only 1550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * valid if is_assigned() is true. 1551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_components() const 1553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 1554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->is_clip_distance_mesa) 1555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return this->size; 1556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 1557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return this->vector_elements * this->matrix_columns * this->size; 1558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgprivate: 1561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The name that was supplied to glTransformFeedbackVaryings. Used for 1563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * error reporting and glGetTransformFeedbackVarying(). 1564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *orig_name; 1566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The name of the variable, parsed from orig_name. 1569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *var_name; 1571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * True if the declaration in orig_name represents an array. 1574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool is_subscripted; 1576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If is_subscripted is true, the subscript that was specified in orig_name. 1579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned array_subscript; 1581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * True if the variable is gl_ClipDistance and the driver lowers 1584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * gl_ClipDistance to gl_ClipDistanceMESA. 1585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool is_clip_distance_mesa; 1587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The vertex shader output location that the linker assigned for this 1590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * variable. -1 if a location hasn't been assigned yet. 1591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int location; 1593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If location != -1, the number of vector elements in this variable, or 1 1596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * if this variable is a scalar. 1597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned vector_elements; 1599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If location != -1, the number of matrix columns in this variable, or 1 1602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * if this variable is not a matrix. 1603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned matrix_columns; 1605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** Type of the varying returned by glGetTransformFeedbackVarying() */ 1607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GLenum type; 1608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If location != -1, the size that should be returned by 1611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * glGetTransformFeedbackVarying(). 1612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned size; 1614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * How many components to skip. If non-zero, this is 1617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * gl_SkipComponents{1,2,3,4} from ARB_transform_feedback3. 1618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned skip_components; 1620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** 1622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Whether this is gl_NextBuffer from ARB_transform_feedback3. 1623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool next_buffer_separator; 1625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 1626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Initialize this object based on a string that was passed to 1630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * glTransformFeedbackVaryings. If there is a parse error, the error is 1631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * reported using linker_error(), and false is returned. 1632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 1634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog, 1635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const void *mem_ctx, const char *input) 1636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* We don't have to be pedantic about what is a valid GLSL variable name, 1638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * because any variable with an invalid name can't exist in the IR anyway. 1639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->location = -1; 1642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->orig_name = input; 1643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->is_clip_distance_mesa = false; 1644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->skip_components = 0; 1645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->next_buffer_separator = false; 1646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ctx->Extensions.ARB_transform_feedback3) { 1648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Parse gl_NextBuffer. */ 1649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(input, "gl_NextBuffer") == 0) { 1650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->next_buffer_separator = true; 1651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Parse gl_SkipComponents. */ 1655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(input, "gl_SkipComponents1") == 0) 1656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->skip_components = 1; 1657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else if (strcmp(input, "gl_SkipComponents2") == 0) 1658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->skip_components = 2; 1659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else if (strcmp(input, "gl_SkipComponents3") == 0) 1660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->skip_components = 3; 1661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else if (strcmp(input, "gl_SkipComponents4") == 0) 1662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->skip_components = 4; 1663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->skip_components) 1665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Parse a declaration. */ 1669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *bracket = strrchr(input, '['); 1670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (bracket) { 1672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->var_name = ralloc_strndup(mem_ctx, input, bracket - input); 1673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (sscanf(bracket, "[%u]", &this->array_subscript) != 1) { 1674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "Cannot parse transform feedback varying %s", input); 1675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->is_subscripted = true; 1678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 1679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->var_name = ralloc_strdup(mem_ctx, input); 1680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->is_subscripted = false; 1681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* For drivers that lower gl_ClipDistance to gl_ClipDistanceMESA, this 1684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * class must behave specially to account for the fact that gl_ClipDistance 1685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is converted from a float[8] to a vec4[2]. 1686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance && 1688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strcmp(this->var_name, "gl_ClipDistance") == 0) { 1689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->is_clip_distance_mesa = true; 1690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Determine whether two tfeedback_decl objects refer to the same variable and 1698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * array index (if applicable). 1699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 1701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y) 1702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(x.is_varying() && y.is_varying()); 1704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(x.var_name, y.var_name) != 0) 1706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (x.is_subscripted != y.is_subscripted) 1708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (x.is_subscripted && x.array_subscript != y.array_subscript) 1710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Assign a location for this tfeedback_decl object based on the location 1717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * assignment in output_var. 1718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If an error occurs, the error is reported through linker_error() and false 1720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is returned. 1721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 1723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtfeedback_decl::assign_location(struct gl_context *ctx, 1724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader_program *prog, 1725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *output_var) 1726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(this->is_varying()); 1728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (output_var->type->is_array()) { 1730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Array variable */ 1731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned matrix_cols = 1732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org output_var->type->fields.array->matrix_columns; 1733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned actual_array_size = this->is_clip_distance_mesa ? 1734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->Vert.ClipDistanceArraySize : output_var->type->array_size(); 1735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->is_subscripted) { 1737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Check array bounds. */ 1738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->array_subscript >= actual_array_size) { 1739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "Transform feedback varying %s has index " 1740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%i, but the array size is %u.", 1741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->orig_name, this->array_subscript, 1742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org actual_array_size); 1743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->is_clip_distance_mesa) { 1746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->location = 1747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org output_var->location + this->array_subscript / 4; 1748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 1749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->location = 1750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org output_var->location + this->array_subscript * matrix_cols; 1751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->size = 1; 1753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 1754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->location = output_var->location; 1755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->size = actual_array_size; 1756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->vector_elements = output_var->type->fields.array->vector_elements; 1758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->matrix_columns = matrix_cols; 1759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->is_clip_distance_mesa) 1760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->type = GL_FLOAT; 1761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 1762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->type = output_var->type->fields.array->gl_type; 1763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 1764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Regular variable (scalar, vector, or matrix) */ 1765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->is_subscripted) { 1766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "Transform feedback varying %s requested, " 1767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "but %s is not an array.", 1768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->orig_name, this->var_name); 1769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->location = output_var->location; 1772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->size = 1; 1773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->vector_elements = output_var->type->vector_elements; 1774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->matrix_columns = output_var->type->matrix_columns; 1775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->type = output_var->type->gl_type; 1776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* From GL_EXT_transform_feedback: 1779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * A program will fail to link if: 1780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * * the total number of components to capture in any varying 1782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * variable in <varyings> is greater than the constant 1783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT and the 1784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * buffer mode is SEPARATE_ATTRIBS_EXT; 1785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS && 1787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->num_components() > 1788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Const.MaxTransformFeedbackSeparateComponents) { 1789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "Transform feedback varying %s exceeds " 1790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS.", 1791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->orig_name); 1792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 1800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtfeedback_decl::accumulate_num_outputs(struct gl_shader_program *prog, 1801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned *count) 1802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!this->is_varying()) { 1804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!this->is_assigned()) { 1808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* From GL_EXT_transform_feedback: 1809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * A program will fail to link if: 1810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * * any variable name specified in the <varyings> array is not 1812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * declared as an output in the geometry shader (if present) or 1813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the vertex shader (if no geometry shader is present); 1814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "Transform feedback varying %s undeclared.", 1816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->orig_name); 1817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned translated_size = this->size; 1821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->is_clip_distance_mesa) 1822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org translated_size = (translated_size + 3) / 4; 1823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *count += translated_size * this->matrix_columns; 1825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Update gl_transform_feedback_info to reflect this tfeedback_decl. 1832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If an error occurs, the error is reported through linker_error() and false 1834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is returned. 1835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 1837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, 1838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_transform_feedback_info *info, 1839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned buffer, const unsigned max_outputs) const 1840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(!this->next_buffer_separator); 1842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Handle gl_SkipComponents. */ 1844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->skip_components) { 1845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->BufferStride[buffer] += this->skip_components; 1846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* From GL_EXT_transform_feedback: 1850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * A program will fail to link if: 1851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * * the total number of components to capture is greater than 1853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 1854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and the buffer mode is INTERLEAVED_ATTRIBS_EXT. 1855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS && 1857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->BufferStride[buffer] + this->num_components() > 1858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Const.MaxTransformFeedbackInterleavedComponents) { 1859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS " 1860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "limit has been exceeded."); 1861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned translated_size = this->size; 1865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->is_clip_distance_mesa) 1866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org translated_size = (translated_size + 3) / 4; 1867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned components_so_far = 0; 1868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned index = 0; index < translated_size; ++index) { 1869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned v = 0; v < this->matrix_columns; ++v) { 1870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_components = this->vector_elements; 1871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(info->NumOutputs < max_outputs); 1872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->Outputs[info->NumOutputs].ComponentOffset = 0; 1873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->is_clip_distance_mesa) { 1874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (this->is_subscripted) { 1875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_components = 1; 1876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->Outputs[info->NumOutputs].ComponentOffset = 1877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->array_subscript % 4; 1878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 1879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_components = MIN2(4, this->size - components_so_far); 1880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->Outputs[info->NumOutputs].OutputRegister = 1883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->location + v + index * this->matrix_columns; 1884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->Outputs[info->NumOutputs].NumComponents = num_components; 1885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->Outputs[info->NumOutputs].OutputBuffer = buffer; 1886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer]; 1887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ++info->NumOutputs; 1888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->BufferStride[buffer] += num_components; 1889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org components_so_far += num_components; 1890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(components_so_far == this->num_components()); 1893f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1894f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->Varyings[info->NumVarying].Name = ralloc_strdup(prog, this->orig_name); 1895f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->Varyings[info->NumVarying].Type = this->type; 1896f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->Varyings[info->NumVarying].Size = this->size; 1897f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org info->NumVarying++; 1898f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1899f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1900f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1901f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1902f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1903f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1904f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Parse all the transform feedback declarations that were passed to 1905f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * glTransformFeedbackVaryings() and store them in tfeedback_decl objects. 1906f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1907f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If an error occurs, the error is reported through linker_error() and false 1908f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is returned. 1909f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1910f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool 1911f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgparse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog, 1912f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const void *mem_ctx, unsigned num_names, 1913f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char **varying_names, tfeedback_decl *decls) 1914f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1915f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_names; ++i) { 1916f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!decls[i].init(ctx, prog, mem_ctx, varying_names[i])) 1917f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1918f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1919f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!decls[i].is_varying()) 1920f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1921f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1922f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* From GL_EXT_transform_feedback: 1923f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * A program will fail to link if: 1924f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1925f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * * any two entries in the <varyings> array specify the same varying 1926f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * variable; 1927f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1928f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * We interpret this to mean "any two entries in the <varyings> array 1929f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * specify the same varying variable and array index", since transform 1930f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * feedback of arrays would be useless otherwise. 1931f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1932f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned j = 0; j < i; ++j) { 1933f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!decls[j].is_varying()) 1934f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 1935f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1936f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (tfeedback_decl::is_same(decls[i], decls[j])) { 1937f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "Transform feedback varying %s specified " 1938f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "more than once.", varying_names[i]); 1939f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1940f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1941f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1942f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1943f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1944f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1945f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1946f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1947f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1948f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Assign a location for a variable that is produced in one pipeline stage 1949f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * (the "producer") and consumed in the next stage (the "consumer"). 1950f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1951f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param input_var is the input variable declaration in the consumer. 1952f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1953f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param output_var is the output variable declaration in the producer. 1954f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1955f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param input_index is the counter that keeps track of assigned input 1956f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * locations in the consumer. 1957f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1958f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param output_index is the counter that keeps track of assigned output 1959f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * locations in the producer. 1960f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1961f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * It is permissible for \c input_var to be NULL (this happens if a variable 1962f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is output by the producer and consumed by transform feedback, but not 1963f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * consumed by the consumer). 1964f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1965f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If the variable has already been assigned a location, this function has no 1966f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * effect. 1967f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1968f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 1969f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgassign_varying_location(ir_variable *input_var, ir_variable *output_var, 1970f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned *input_index, unsigned *output_index) 1971f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1972f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (output_var->location != -1) { 1973f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Location already assigned. */ 1974f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 1975f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1976f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1977f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (input_var) { 1978f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(input_var->location == -1); 1979f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org input_var->location = *input_index; 1980f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1981f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1982f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org output_var->location = *output_index; 1983f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1984f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* FINISHME: Support for "varying" records in GLSL 1.50. */ 1985f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(!output_var->type->is_record()); 1986f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1987f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (output_var->type->is_array()) { 1988f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned slots = output_var->type->length 1989f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * output_var->type->fields.array->matrix_columns; 1990f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1991f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *output_index += slots; 1992f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *input_index += slots; 1993f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 1994f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned slots = output_var->type->matrix_columns; 1995f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1996f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *output_index += slots; 1997f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *input_index += slots; 1998f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1999f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 2000f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2001f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2002f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 2003f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Is the given variable a varying variable to be counted against the 2004f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * limit in ctx->Const.MaxVarying? 2005f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This includes variables such as texcoords, colors and generic 2006f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * varyings, but excludes variables such as gl_FrontFacing and gl_FragCoord. 2007f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2008f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool 2009f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgis_varying_var(GLenum shaderType, const ir_variable *var) 2010f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 2011f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Only fragment shaders will take a varying variable as an input */ 2012f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (shaderType == GL_FRAGMENT_SHADER && 2013f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->mode == ir_var_in && 2014f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->explicit_location) { 2015f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (var->location) { 2016f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case FRAG_ATTRIB_WPOS: 2017f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case FRAG_ATTRIB_FACE: 2018f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case FRAG_ATTRIB_PNTC: 2019f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 2020f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org default: 2021f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 2022f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2023f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2024f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 2025f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 2026f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2027f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2028f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 2029f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Assign locations for all variables that are produced in one pipeline stage 2030f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * (the "producer") and consumed in the next stage (the "consumer"). 2031f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2032f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Variables produced by the producer may also be consumed by transform 2033f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * feedback. 2034f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2035f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param num_tfeedback_decls is the number of declarations indicating 2036f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * variables that may be consumed by transform feedback. 2037f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2038f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param tfeedback_decls is a pointer to an array of tfeedback_decl objects 2039f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * representing the result of parsing the strings passed to 2040f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * glTransformFeedbackVaryings(). assign_location() will be called for 2041f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * each of these objects that matches one of the outputs of the 2042f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * producer. 2043f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2044f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * When num_tfeedback_decls is nonzero, it is permissible for the consumer to 2045f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * be NULL. In this case, varying locations are assigned solely based on the 2046f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * requirements of transform feedback. 2047f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2048f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 2049f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgassign_varying_locations(struct gl_context *ctx, 2050f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader_program *prog, 2051f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gl_shader *producer, gl_shader *consumer, 2052f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_tfeedback_decls, 2053f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org tfeedback_decl *tfeedback_decls) 2054f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 2055f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* FINISHME: Set dynamically when geometry shader support is added. */ 2056f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned output_index = VERT_RESULT_VAR0; 2057f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned input_index = FRAG_ATTRIB_VAR0; 2058f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2059f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Operate in a total of three passes. 2060f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2061f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1. Assign locations for any matching inputs and outputs. 2062f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2063f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2. Mark output variables in the producer that do not have locations as 2064f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * not being outputs. This lets the optimizer eliminate them. 2065f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2066f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 3. Mark input variables in the consumer that do not have locations as 2067f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * not being inputs. This lets the optimizer eliminate them. 2068f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2069f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2070f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org link_invalidate_variable_locations(producer, ir_var_out, VERT_RESULT_VAR0); 2071f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (consumer) 2072f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org link_invalidate_variable_locations(consumer, ir_var_in, FRAG_ATTRIB_VAR0); 2073f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2074f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, producer->ir) { 2075f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const output_var = ((ir_instruction *) node)->as_variable(); 2076f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2077f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((output_var == NULL) || (output_var->mode != ir_var_out)) 2078f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 2079f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2080f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *input_var = 2081f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org consumer ? consumer->symbols->get_variable(output_var->name) : NULL; 2082f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2083f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (input_var && input_var->mode != ir_var_in) 2084f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org input_var = NULL; 2085f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2086f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (input_var) { 2087f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assign_varying_location(input_var, output_var, &input_index, 2088f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org &output_index); 2089f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2090f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2091f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_tfeedback_decls; ++i) { 2092f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!tfeedback_decls[i].is_varying()) 2093f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 2094f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2095f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!tfeedback_decls[i].is_assigned() && 2096f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org tfeedback_decls[i].matches_var(output_var)) { 2097f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (output_var->location == -1) { 2098f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assign_varying_location(input_var, output_var, &input_index, 2099f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org &output_index); 2100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!tfeedback_decls[i].assign_location(ctx, prog, output_var)) 2102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 2103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned varying_vectors = 0; 2108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (consumer) { 2110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, consumer->ir) { 2111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const var = ((ir_instruction *) node)->as_variable(); 2112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((var == NULL) || (var->mode != ir_var_in)) 2114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 2115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->location == -1) { 2117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->Version <= 120) { 2118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec: 2119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Only those varying variables used (i.e. read) in 2121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the fragment shader executable must be written to 2122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * by the vertex shader executable; declaring 2123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * superfluous varying variables in a vertex shader is 2124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * permissible. 2125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * We interpret this text as meaning that the VS must 2127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * write the variable for the FS to read it. See 2128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "glsl1-varying read but not written" in piglit. 2129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "fragment shader varying %s not written " 2132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "by vertex shader\n.", var->name); 2133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* An 'in' variable is only really a shader input if its 2136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * value is written by the previous stage. 2137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->mode = ir_var_auto; 2139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (is_varying_var(consumer->Type, var)) { 2140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* The packing rules are used for vertex shader inputs are also 2141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * used for fragment shader inputs. 2142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org varying_vectors += count_attribute_slots(var->type); 2144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ctx->API == API_OPENGLES2 || prog->Version == 100) { 2149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (varying_vectors > ctx->Const.MaxVarying) { 2150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) { 2151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_warning(prog, "shader uses too many varying vectors " 2152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "(%u > %u), but the driver will try to optimize " 2153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "them out; this is non-portable out-of-spec " 2154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "behavior\n", 2155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org varying_vectors, ctx->Const.MaxVarying); 2156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 2157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "shader uses too many varying vectors " 2158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "(%u > %u)\n", 2159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org varying_vectors, ctx->Const.MaxVarying); 2160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 2161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 2164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned float_components = varying_vectors * 4; 2165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (float_components > ctx->Const.MaxVarying * 4) { 2166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) { 2167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_warning(prog, "shader uses too many varying components " 2168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "(%u > %u), but the driver will try to optimize " 2169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "them out; this is non-portable out-of-spec " 2170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "behavior\n", 2171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org float_components, ctx->Const.MaxVarying * 4); 2172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 2173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "shader uses too many varying components " 2174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "(%u > %u)\n", 2175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org float_components, ctx->Const.MaxVarying * 4); 2176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 2177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 2182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 2183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 2186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Store transform feedback location assignments into 2187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * prog->LinkedTransformFeedback based on the data stored in tfeedback_decls. 2188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If an error occurs, the error is reported through linker_error() and false 2190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is returned. 2191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool 2193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstore_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, 2194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_tfeedback_decls, 2195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org tfeedback_decl *tfeedback_decls) 2196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 2197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool separate_attribs_mode = 2198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS; 2199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_free(prog->LinkedTransformFeedback.Varyings); 2201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_free(prog->LinkedTransformFeedback.Outputs); 2202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(&prog->LinkedTransformFeedback, 0, 2204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sizeof(prog->LinkedTransformFeedback)); 2205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->LinkedTransformFeedback.Varyings = 2207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org rzalloc_array(prog, 2208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_transform_feedback_varying_info, 2209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_tfeedback_decls); 2210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_outputs = 0; 2212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_tfeedback_decls; ++i) 2213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!tfeedback_decls[i].accumulate_num_outputs(prog, &num_outputs)) 2214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 2215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->LinkedTransformFeedback.Outputs = 2217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org rzalloc_array(prog, 2218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_transform_feedback_output, 2219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_outputs); 2220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_buffers = 0; 2222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (separate_attribs_mode) { 2224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* GL_SEPARATE_ATTRIBS */ 2225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_tfeedback_decls; ++i) { 2226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback, 2227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_buffers, num_outputs)) 2228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 2229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_buffers++; 2231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else { 2234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* GL_INVERLEAVED_ATTRIBS */ 2235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < num_tfeedback_decls; ++i) { 2236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (tfeedback_decls[i].is_next_buffer_separator()) { 2237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_buffers++; 2238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 2239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!tfeedback_decls[i].store(ctx, prog, 2242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org &prog->LinkedTransformFeedback, 2243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_buffers, num_outputs)) 2244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 2245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_buffers++; 2247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(prog->LinkedTransformFeedback.NumOutputs == num_outputs); 2250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->LinkedTransformFeedback.NumBuffers = num_buffers; 2252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 2253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 2254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 2256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Store the gl_FragDepth layout in the gl_shader_program struct. 2257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void 2259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstore_fragdepth_layout(struct gl_shader_program *prog) 2260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 2261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) { 2262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 2263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct exec_list *ir = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir; 2266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* We don't look up the gl_FragDepth symbol directly because if 2268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * gl_FragDepth is not used in the shader, it's removed from the IR. 2269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * However, the symbol won't be removed from the symbol table. 2270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * We're only interested in the cases where the variable is NOT removed 2272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * from the IR. 2273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, ir) { 2275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *const var = ((ir_instruction *) node)->as_variable(); 2276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var == NULL || var->mode != ir_var_out) { 2278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 2279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(var->name, "gl_FragDepth") == 0) { 2282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (var->depth_layout) { 2283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_depth_layout_none: 2284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_NONE; 2285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 2286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_depth_layout_any: 2287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_ANY; 2288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 2289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_depth_layout_greater: 2290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_GREATER; 2291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 2292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_depth_layout_less: 2293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_LESS; 2294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 2295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case ir_depth_layout_unchanged: 2296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_UNCHANGED; 2297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 2298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org default: 2299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(0); 2300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 2301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 2305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 2307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Validate the resources used by a program versus the implementation limits 2308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool 2310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcheck_resources(struct gl_context *ctx, struct gl_shader_program *prog) 2311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 2312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static const char *const shader_names[MESA_SHADER_TYPES] = { 2313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "vertex", "fragment", "geometry" 2314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org }; 2315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned max_samplers[MESA_SHADER_TYPES] = { 2317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Const.MaxVertexTextureImageUnits, 2318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Const.MaxTextureImageUnits, 2319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Const.MaxGeometryTextureImageUnits 2320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org }; 2321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned max_uniform_components[MESA_SHADER_TYPES] = { 2323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Const.VertexProgram.MaxUniformComponents, 2324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Const.FragmentProgram.MaxUniformComponents, 2325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 0 /* FINISHME: Geometry shaders. */ 2326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org }; 2327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned max_uniform_blocks[MESA_SHADER_TYPES] = { 2329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Const.VertexProgram.MaxUniformBlocks, 2330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Const.FragmentProgram.MaxUniformBlocks, 2331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Const.GeometryProgram.MaxUniformBlocks, 2332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org }; 2333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { 2335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader *sh = prog->_LinkedShaders[i]; 2336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (sh == NULL) 2338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 2339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (sh->num_samplers > max_samplers[i]) { 2341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "Too many %s shader texture samplers", 2342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org shader_names[i]); 2343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (sh->num_uniform_components > max_uniform_components[i]) { 2346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ctx->Const.GLSLSkipStrictMaxUniformLimitCheck) { 2347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_warning(prog, "Too many %s shader uniform components, " 2348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "but the driver will try to optimize them out; " 2349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "this is non-portable out-of-spec behavior\n", 2350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org shader_names[i]); 2351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 2352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "Too many %s shader uniform components", 2353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org shader_names[i]); 2354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned blocks[MESA_SHADER_TYPES] = {0}; 2359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned total_uniform_blocks = 0; 2360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < prog->NumUniformBlocks; i++) { 2362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) { 2363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->UniformBlockStageIndex[j][i] != -1) { 2364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org blocks[j]++; 2365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org total_uniform_blocks++; 2366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (total_uniform_blocks > ctx->Const.MaxCombinedUniformBlocks) { 2370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "Too many combined uniform blocks (%d/%d)", 2371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->NumUniformBlocks, 2372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Const.MaxCombinedUniformBlocks); 2373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 2374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { 2375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (blocks[i] > max_uniform_blocks[i]) { 2376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "Too many %s uniform blocks (%d/%d)", 2377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org shader_names[i], 2378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org blocks[i], 2379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org max_uniform_blocks[i]); 2380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 2381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return prog->LinkStatus; 2387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 2388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 2390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglink_shaders(struct gl_context *ctx, struct gl_shader_program *prog) 2391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 2392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org tfeedback_decl *tfeedback_decls = NULL; 2393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_tfeedback_decls = prog->TransformFeedback.NumVarying; 2394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void *mem_ctx = ralloc_context(NULL); // temporary linker context 2396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->LinkStatus = false; 2398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->Validated = false; 2399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->_Used = false; 2400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_free(prog->InfoLog); 2402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->InfoLog = ralloc_strdup(NULL, ""); 2403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_free(prog->UniformBlocks); 2405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->UniformBlocks = NULL; 2406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->NumUniformBlocks = 0; 2407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (int i = 0; i < MESA_SHADER_TYPES; i++) { 2408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_free(prog->UniformBlockStageIndex[i]); 2409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->UniformBlockStageIndex[i] = NULL; 2410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Separate the shaders into groups based on their type. 2413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader **vert_shader_list; 2415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_vert_shaders = 0; 2416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader **frag_shader_list; 2417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned num_frag_shaders = 0; 2418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org vert_shader_list = (struct gl_shader **) 2420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org calloc(2 * prog->NumShaders, sizeof(struct gl_shader *)); 2421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org frag_shader_list = &vert_shader_list[prog->NumShaders]; 2422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned min_version = UINT_MAX; 2424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned max_version = 0; 2425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < prog->NumShaders; i++) { 2426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org min_version = MIN2(min_version, prog->Shaders[i]->Version); 2427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org max_version = MAX2(max_version, prog->Shaders[i]->Version); 2428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (prog->Shaders[i]->Type) { 2430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case GL_VERTEX_SHADER: 2431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org vert_shader_list[num_vert_shaders] = prog->Shaders[i]; 2432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_vert_shaders++; 2433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 2434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case GL_FRAGMENT_SHADER: 2435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org frag_shader_list[num_frag_shaders] = prog->Shaders[i]; 2436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_frag_shaders++; 2437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 2438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case GL_GEOMETRY_SHADER: 2439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* FINISHME: Support geometry shaders. */ 2440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(prog->Shaders[i]->Type != GL_GEOMETRY_SHADER); 2441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 2442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Previous to GLSL version 1.30, different compilation units could mix and 2446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * match shading language versions. With GLSL 1.30 and later, the versions 2447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of all shaders must match. 2448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(min_version >= 100); 2450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(max_version <= 140); 2451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((max_version >= 130 || min_version == 100) 2452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org && min_version != max_version) { 2453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "all shaders must use same shading " 2454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "language version\n"); 2455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->Version = max_version; 2459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) { 2461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[i] != NULL) 2462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]); 2463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->_LinkedShaders[i] = NULL; 2465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Link all shaders for a particular stage and validate the result. 2468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (num_vert_shaders > 0) { 2470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gl_shader *const sh = 2471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org link_intrastage_shaders(mem_ctx, ctx, prog, vert_shader_list, 2472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_vert_shaders); 2473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (sh == NULL) 2475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!validate_vertex_shader_executable(prog, sh)) 2478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_VERTEX], 2481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sh); 2482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (num_frag_shaders > 0) { 2485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gl_shader *const sh = 2486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org link_intrastage_shaders(mem_ctx, ctx, prog, frag_shader_list, 2487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org num_frag_shaders); 2488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (sh == NULL) 2490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!validate_fragment_shader_executable(prog, sh)) 2493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_FRAGMENT], 2496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sh); 2497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Here begins the inter-stage linking phase. Some initial validation is 2500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * performed, then locations are assigned for uniforms, attributes, and 2501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * varyings. 2502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (cross_validate_uniforms(prog)) { 2504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned prev; 2505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (prev = 0; prev < MESA_SHADER_TYPES; prev++) { 2507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[prev] != NULL) 2508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 2509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Validate the inputs of each stage with the output of the preceding 2512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * stage. 2513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) { 2515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[i] == NULL) 2516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 2517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!cross_validate_outputs_to_inputs(prog, 2519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->_LinkedShaders[prev], 2520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->_LinkedShaders[i])) 2521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prev = i; 2524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->LinkStatus = true; 2527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Implement the GLSL 1.30+ rule for discard vs infinite loops Do 2530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * it before optimization because we want most of the checks to get 2531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * dropped thanks to constant propagation. 2532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (max_version >= 130) { 2534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct gl_shader *sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; 2535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (sh) { 2536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org lower_discard_flow(sh->ir); 2537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!interstage_cross_validate_uniform_blocks(prog)) 2541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Do common optimization before assigning storage for attributes, 2544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * uniforms, and varyings. Later optimization could possibly make 2545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * some of that unused. 2546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { 2548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[i] == NULL) 2549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 2550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org detect_recursion_linked(prog, prog->_LinkedShaders[i]->ir); 2552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!prog->LinkStatus) 2553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ctx->ShaderCompilerOptions[i].LowerClipDistance) 2556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org lower_clip_distance(prog->_LinkedShaders[i]->ir); 2557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned max_unroll = ctx->ShaderCompilerOptions[i].MaxUnrollIterations; 2559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, max_unroll)) 2561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ; 2562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* FINISHME: The value of the max_attribute_index parameter is 2565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: implementation dependent based on the value of 2566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: GL_MAX_VERTEX_ATTRIBS. GL_MAX_VERTEX_ATTRIBS must be 2567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FINISHME: at least 16, so hardcode 16 for now. 2568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!assign_attribute_or_color_locations(prog, MESA_SHADER_VERTEX, 16)) { 2570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, MAX2(ctx->Const.MaxDrawBuffers, ctx->Const.MaxDualSourceDrawBuffers))) { 2574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned prev; 2578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (prev = 0; prev < MESA_SHADER_TYPES; prev++) { 2579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[prev] != NULL) 2580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 2581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (num_tfeedback_decls != 0) { 2584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* From GL_EXT_transform_feedback: 2585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * A program will fail to link if: 2586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * * the <count> specified by TransformFeedbackVaryingsEXT is 2588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * non-zero, but the program object has no vertex or geometry 2589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * shader; 2590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prev >= MESA_SHADER_FRAGMENT) { 2592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "Transform feedback varyings specified, but " 2593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "no vertex or geometry shader is present."); 2594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org tfeedback_decls = ralloc_array(mem_ctx, tfeedback_decl, 2598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->TransformFeedback.NumVarying); 2599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!parse_tfeedback_decls(ctx, prog, mem_ctx, num_tfeedback_decls, 2600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->TransformFeedback.VaryingNames, 2601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org tfeedback_decls)) 2602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) { 2606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[i] == NULL) 2607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 2608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!assign_varying_locations( 2610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx, prog, prog->_LinkedShaders[prev], prog->_LinkedShaders[i], 2611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org i == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, 2612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org tfeedback_decls)) 2613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prev = i; 2616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prev != MESA_SHADER_FRAGMENT && num_tfeedback_decls != 0) { 2619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* There was no fragment shader, but we still have to assign varying 2620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * locations for use by transform feedback. 2621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!assign_varying_locations( 2623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ctx, prog, prog->_LinkedShaders[prev], NULL, num_tfeedback_decls, 2624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org tfeedback_decls)) 2625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls)) 2629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) { 2632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org demote_shader_inputs_and_outputs(prog->_LinkedShaders[MESA_SHADER_VERTEX], 2633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_var_out); 2634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Eliminate code that is now dead due to unused vertex outputs being 2636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * demoted. 2637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_VERTEX]->ir, false)) 2639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ; 2640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) { 2643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_GEOMETRY]; 2644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org demote_shader_inputs_and_outputs(sh, ir_var_in); 2646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org demote_shader_inputs_and_outputs(sh, ir_var_inout); 2647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org demote_shader_inputs_and_outputs(sh, ir_var_out); 2648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Eliminate code that is now dead due to unused geometry outputs being 2650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * demoted. 2651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir, false)) 2653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ; 2654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) { 2657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; 2658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org demote_shader_inputs_and_outputs(sh, ir_var_in); 2660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Eliminate code that is now dead due to unused fragment inputs being 2662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * demoted. This shouldn't actually do anything other than remove 2663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * declarations of the (now unused) global variables. 2664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir, false)) 2666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ; 2667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org update_array_sizes(prog); 2670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org link_assign_uniform_locations(prog); 2671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org store_fragdepth_layout(prog); 2672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!check_resources(ctx, prog)) 2674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org goto done; 2675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* OpenGL ES requires that a vertex shader and a fragment shader both be 2677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * present in a linked program. By checking for use of shading language 2678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * version 1.00, we also catch the GL_ARB_ES2_compatibility case. 2679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!prog->InternalSeparateShader && 2681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (ctx->API == API_OPENGLES2 || prog->Version == 100)) { 2682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { 2683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "program lacks a vertex shader\n"); 2684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) { 2685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker_error(prog, "program lacks a fragment shader\n"); 2686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* FINISHME: Assign fragment shader output locations. */ 2690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdone: 2692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free(vert_shader_list); 2693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { 2695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (prog->_LinkedShaders[i] == NULL) 2696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 2697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Retain any live IR, but trash the rest. */ 2699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org reparent_ir(prog->_LinkedShaders[i]->ir, prog->_LinkedShaders[i]->ir); 2700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* The symbol table in the linked shaders may contain references to 2702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * variables that were removed (e.g., unused uniforms). Since it may 2703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * contain junk, there is no possible valid use. Delete it and set the 2704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * pointer to NULL. 2705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 2706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org delete prog->_LinkedShaders[i]->symbols; 2707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prog->_LinkedShaders[i]->symbols = NULL; 2708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 2709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_free(mem_ctx); 2711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 2712