1c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry/* 2c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * Copyright © 2011 Intel Corporation 3c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * 4c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * Permission is hereby granted, free of charge, to any person obtaining a 5c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * copy of this software and associated documentation files (the "Software"), 6c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * to deal in the Software without restriction, including without limitation 7c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * and/or sell copies of the Software, and to permit persons to whom the 9c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * Software is furnished to do so, subject to the following conditions: 10c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * 11c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * The above copyright notice and this permission notice (including the next 12c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * paragraph) shall be included in all copies or substantial portions of the 13c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * Software. 14c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * 15c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * DEALINGS IN THE SOFTWARE. 22c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 23c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 24c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry/** 25dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie * \file lower_distance.cpp 26c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * 27c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * This pass accounts for the difference between the way 287a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * gl_ClipDistance is declared in standard GLSL (as an array of 297a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * floats), and the way it is frequently implemented in hardware (as 307a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * a pair of vec4s, with four clip distances packed into each). 31c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * 327a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * The declaration of gl_ClipDistance is replaced with a declaration 337a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * of gl_ClipDistanceMESA, and any references to gl_ClipDistance are 347a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * translated to refer to gl_ClipDistanceMESA with the appropriate 357a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * swizzling of array indices. For instance: 36c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * 37c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * gl_ClipDistance[i] 38c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * 39c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * is translated into: 40c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * 41c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * gl_ClipDistanceMESA[i>>2][i&3] 42c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * 437a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * Since some hardware may not internally represent gl_ClipDistance as a pair 447a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * of vec4's, this lowering pass is optional. To enable it, set the 457a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * LowerCombinedClipCullDistance flag in gl_shader_compiler_options to true. 46c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 47c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 48a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie#include "main/macros.h" 4918392443d448e083187d085965375e7de910b18aPaul Berry#include "glsl_symbol_table.h" 50065da16508731f6b6a98865f392509be4f9ce07fIan Romanick#include "ir_rvalue_visitor.h" 51c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry#include "ir.h" 52c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick#include "program/prog_instruction.h" /* For WRITEMASK_* */ 53c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 54a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie#define GLSL_CLIP_VAR_NAME "gl_ClipDistanceMESA" 55a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 5610ef949424809d51c627008bb2feab5a067f8e08Eric Anholtnamespace { 5710ef949424809d51c627008bb2feab5a067f8e08Eric Anholt 58dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlieclass lower_distance_visitor : public ir_rvalue_visitor { 59c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berrypublic: 60a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie explicit lower_distance_visitor(gl_shader_stage shader_stage, 61a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie const char *in_name, int total_size, 62a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie int offset) 63dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie : progress(false), old_distance_out_var(NULL), 64dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie old_distance_in_var(NULL), new_distance_out_var(NULL), 65a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new_distance_in_var(NULL), shader_stage(shader_stage), 66a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie in_name(in_name), total_size(total_size), offset(offset) 67a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie { 68a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie } 69a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 70a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie explicit lower_distance_visitor(gl_shader_stage shader_stage, 71a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie const char *in_name, 72a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie const lower_distance_visitor *orig, 73a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie int offset) 74a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie : progress(false), 75a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie old_distance_out_var(NULL), 76a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie old_distance_in_var(NULL), 77a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new_distance_out_var(orig->new_distance_out_var), 78a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new_distance_in_var(orig->new_distance_in_var), 79a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie shader_stage(shader_stage), 80a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie in_name(in_name), 81a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie total_size(orig->total_size), 82a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie offset(offset) 83c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry { 84c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } 85c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 86c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry virtual ir_visitor_status visit(ir_variable *); 87c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry void create_indices(ir_rvalue*, ir_rvalue *&, ir_rvalue *&); 88dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie bool is_distance_vec8(ir_rvalue *ir); 89dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie ir_rvalue *lower_distance_vec8(ir_rvalue *ir); 90c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry virtual ir_visitor_status visit_leave(ir_assignment *); 91c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry void visit_new_assignment(ir_assignment *ir); 92c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry virtual ir_visitor_status visit_leave(ir_call *); 93c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 94065da16508731f6b6a98865f392509be4f9ce07fIan Romanick virtual void handle_rvalue(ir_rvalue **rvalue); 95065da16508731f6b6a98865f392509be4f9ce07fIan Romanick 96c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick void fix_lhs(ir_assignment *); 97c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick 98c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry bool progress; 99c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 100c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry /** 1017a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * Pointer to the declaration of gl_ClipDistance, if found. 1028f758b0b92f6105c9615740096fa1206befe343bBryan Cain * 1038f758b0b92f6105c9615740096fa1206befe343bBryan Cain * Note: 1048f758b0b92f6105c9615740096fa1206befe343bBryan Cain * 10554f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler * - the in_var is for geometry and both tessellation shader inputs only. 1068f758b0b92f6105c9615740096fa1206befe343bBryan Cain * 10754f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler * - since gl_ClipDistance is available in tessellation control, 10854f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler * tessellation evaluation and geometry shaders as both an input 109dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie * and an output, it's possible for both old_distance_out_var 110dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie * and old_distance_in_var to be non-null. 111c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 112dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie ir_variable *old_distance_out_var; 113dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie ir_variable *old_distance_in_var; 114c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 115c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry /** 1167a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * Pointer to the newly-created gl_ClipDistanceMESA variable. 117c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 118dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie ir_variable *new_distance_out_var; 119dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie ir_variable *new_distance_in_var; 1208f758b0b92f6105c9615740096fa1206befe343bBryan Cain 1218f758b0b92f6105c9615740096fa1206befe343bBryan Cain /** 1222adb9fea77140fccb7bd3f7a547f026c050333bdPaul Berry * Type of shader we are compiling (e.g. MESA_SHADER_VERTEX) 1238f758b0b92f6105c9615740096fa1206befe343bBryan Cain */ 1242adb9fea77140fccb7bd3f7a547f026c050333bdPaul Berry const gl_shader_stage shader_stage; 125a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie const char *in_name; 126a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie int total_size; 127a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie int offset; 128c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry}; 129c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 13010ef949424809d51c627008bb2feab5a067f8e08Eric Anholt} /* anonymous namespace */ 131c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 132c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry/** 133a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie * Replace any declaration of 'in_name' as an array of floats with a 1347a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * declaration of gl_ClipDistanceMESA as an array of vec4's. 135c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 136c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berryir_visitor_status 137dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlielower_distance_visitor::visit(ir_variable *ir) 138c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry{ 13954f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler ir_variable **old_var; 14054f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler ir_variable **new_var; 14154f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler 142a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (!ir->name || strcmp(ir->name, in_name) != 0) 143c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry return visit_continue; 1448f758b0b92f6105c9615740096fa1206befe343bBryan Cain assert (ir->type->is_array()); 1458f758b0b92f6105c9615740096fa1206befe343bBryan Cain 14654f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler if (ir->data.mode == ir_var_shader_out) { 147dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (this->old_distance_out_var) 14854f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler return visit_continue; 149dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie old_var = &old_distance_out_var; 150dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie new_var = &new_distance_out_var; 15154f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler } else if (ir->data.mode == ir_var_shader_in) { 152dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (this->old_distance_in_var) 1538f758b0b92f6105c9615740096fa1206befe343bBryan Cain return visit_continue; 154dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie old_var = &old_distance_in_var; 155dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie new_var = &new_distance_in_var; 15654f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler } else { 15754f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler unreachable("not reached"); 15854f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler } 159c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 16054f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler this->progress = true; 16154f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler 162a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie *old_var = ir; 16354f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler 164a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (!(*new_var)) { 165a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie unsigned new_size = (total_size + 3) / 4; 1667a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie 1677a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie /* Clone the old var so that we inherit all of its properties */ 1687a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie *new_var = ir->clone(ralloc_parent(ir), NULL); 169a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie (*new_var)->name = ralloc_strdup(*new_var, GLSL_CLIP_VAR_NAME); 170a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie (*new_var)->data.max_array_access = new_size - 1; 1718d4f4adfbd5b2f23cb2a6a1f77f79a23d3f2b035Dave Airlie (*new_var)->data.location = VARYING_SLOT_CLIP_DIST0; 1727a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie 173a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (!ir->type->fields.array->is_array()) { 174a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie /* gl_ClipDistance (used for vertex, tessellation evaluation and 175a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie * geometry output, and fragment input). 176a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie */ 177a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie assert((ir->data.mode == ir_var_shader_in && 178a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie this->shader_stage == MESA_SHADER_FRAGMENT) || 179a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie (ir->data.mode == ir_var_shader_out && 180a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie (this->shader_stage == MESA_SHADER_VERTEX || 181a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie this->shader_stage == MESA_SHADER_TESS_EVAL || 182a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie this->shader_stage == MESA_SHADER_GEOMETRY))); 183a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 184a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie assert (ir->type->fields.array == glsl_type::float_type); 185a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 186a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie /* And change the properties that we need to change */ 187a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie (*new_var)->type = glsl_type::get_array_instance(glsl_type::vec4_type, 188a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new_size); 189a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie } else { 190a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie /* 2D gl_ClipDistance (used for tessellation control, tessellation 191a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie * evaluation and geometry input, and tessellation control output). 192a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie */ 193a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie assert((ir->data.mode == ir_var_shader_in && 194a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie (this->shader_stage == MESA_SHADER_GEOMETRY || 195a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie this->shader_stage == MESA_SHADER_TESS_EVAL)) || 196a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie this->shader_stage == MESA_SHADER_TESS_CTRL); 197a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 198a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie assert (ir->type->fields.array->fields.array == glsl_type::float_type); 199a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 200a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie /* And change the properties that we need to change */ 201a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie (*new_var)->type = glsl_type::get_array_instance( 202a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie glsl_type::get_array_instance(glsl_type::vec4_type, 203a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new_size), 204a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie ir->type->array_size()); 205a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie } 2067a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie ir->replace_with(*new_var); 2078f758b0b92f6105c9615740096fa1206befe343bBryan Cain } else { 208a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie ir->remove(); 209c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } 21054f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler 211c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry return visit_continue; 212c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry} 213c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 214c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 215c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry/** 2167a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * Create the necessary GLSL rvalues to index into gl_ClipDistanceMESA based 217c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * on the rvalue previously used to index into gl_ClipDistance. 218c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * 2197a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * \param array_index Selects one of the vec4's in gl_ClipDistanceMESA 220c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * \param swizzle_index Selects a component within the vec4 selected by 221c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * array_index. 222c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 223c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berryvoid 224dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlielower_distance_visitor::create_indices(ir_rvalue *old_index, 225c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_rvalue *&array_index, 226c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_rvalue *&swizzle_index) 227c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry{ 228c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry void *ctx = ralloc_parent(old_index); 229c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 230c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry /* Make sure old_index is a signed int so that the bitwise "shift" and 231c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * "and" operations below type check properly. 232c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 233c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry if (old_index->type != glsl_type::int_type) { 234c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry assert (old_index->type == glsl_type::uint_type); 235c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry old_index = new(ctx) ir_expression(ir_unop_u2i, old_index); 236c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } 237c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 238c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_constant *old_index_constant = old_index->constant_expression_value(); 239c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry if (old_index_constant) { 2407a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie /* gl_ClipDistance is being accessed via a constant index. Don't bother 2417a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * creating expressions to calculate the lowered indices. Just create 2427a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * constants. 243c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 244a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie int const_val = old_index_constant->get_int_component(0) + offset; 2457a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie array_index = new(ctx) ir_constant(const_val / 4); 2467a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie swizzle_index = new(ctx) ir_constant(const_val % 4); 247c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } else { 248c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry /* Create a variable to hold the value of old_index (so that we 249c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * don't compute it twice). 250c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 251c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_variable *old_index_var = new(ctx) ir_variable( 252dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie glsl_type::int_type, "distance_index", ir_var_temporary); 253c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry this->base_ir->insert_before(old_index_var); 254c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry this->base_ir->insert_before(new(ctx) ir_assignment( 255c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry new(ctx) ir_dereference_variable(old_index_var), old_index)); 256c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 2577a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie /* Create the expression distance_index / 4. Do this as a bit 2587a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * shift because that's likely to be more efficient. 259c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 260c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry array_index = new(ctx) ir_expression( 261a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie ir_binop_rshift, 262a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new(ctx) ir_expression(ir_binop_add, 263a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new(ctx) ir_dereference_variable(old_index_var), 264a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new(ctx) ir_constant(offset)), 265c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry new(ctx) ir_constant(2)); 266c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 2677a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie /* Create the expression distance_index % 4. Do this as a bitwise 2687a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * AND because that's likely to be more efficient. 269c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 270c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry swizzle_index = new(ctx) ir_expression( 271a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie ir_binop_bit_and, 272a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new(ctx) ir_expression(ir_binop_add, 273a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new(ctx) ir_dereference_variable(old_index_var), 274a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new(ctx) ir_constant(offset)), 275c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry new(ctx) ir_constant(3)); 276c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } 277c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry} 278c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 279c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 2808f758b0b92f6105c9615740096fa1206befe343bBryan Cain/** 2818f758b0b92f6105c9615740096fa1206befe343bBryan Cain * Determine whether the given rvalue describes an array of 8 floats that 2828f758b0b92f6105c9615740096fa1206befe343bBryan Cain * needs to be lowered to an array of 2 vec4's; that is, determine whether it 2838f758b0b92f6105c9615740096fa1206befe343bBryan Cain * matches one of the following patterns: 2848f758b0b92f6105c9615740096fa1206befe343bBryan Cain * 2858f758b0b92f6105c9615740096fa1206befe343bBryan Cain * - gl_ClipDistance (if gl_ClipDistance is 1D) 2868f758b0b92f6105c9615740096fa1206befe343bBryan Cain * - gl_ClipDistance[i] (if gl_ClipDistance is 2D) 2878f758b0b92f6105c9615740096fa1206befe343bBryan Cain */ 2888f758b0b92f6105c9615740096fa1206befe343bBryan Cainbool 289dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlielower_distance_visitor::is_distance_vec8(ir_rvalue *ir) 2908f758b0b92f6105c9615740096fa1206befe343bBryan Cain{ 2917a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie /* Note that geometry shaders contain gl_ClipDistance both as an input 2927a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * (which is a 2D array) and an output (which is a 1D array), so it's 2937a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * possible for both this->old_distance_out_var and 294dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie * this->old_distance_in_var to be non-NULL in the same shader. 2958f758b0b92f6105c9615740096fa1206befe343bBryan Cain */ 2968f758b0b92f6105c9615740096fa1206befe343bBryan Cain 29754f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler if (!ir->type->is_array()) 29854f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler return false; 29954f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler if (ir->type->fields.array != glsl_type::float_type) 30054f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler return false; 30154f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler 302dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (this->old_distance_out_var) { 303dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (ir->variable_referenced() == this->old_distance_out_var) 3048f758b0b92f6105c9615740096fa1206befe343bBryan Cain return true; 3058f758b0b92f6105c9615740096fa1206befe343bBryan Cain } 306dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (this->old_distance_in_var) { 30754f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler assert(this->shader_stage == MESA_SHADER_TESS_CTRL || 30854f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler this->shader_stage == MESA_SHADER_TESS_EVAL || 30954f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler this->shader_stage == MESA_SHADER_GEOMETRY || 31054f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler this->shader_stage == MESA_SHADER_FRAGMENT); 3118f758b0b92f6105c9615740096fa1206befe343bBryan Cain 312dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (ir->variable_referenced() == this->old_distance_in_var) 31354f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler return true; 3148f758b0b92f6105c9615740096fa1206befe343bBryan Cain } 3158f758b0b92f6105c9615740096fa1206befe343bBryan Cain return false; 3168f758b0b92f6105c9615740096fa1206befe343bBryan Cain} 3178f758b0b92f6105c9615740096fa1206befe343bBryan Cain 3188f758b0b92f6105c9615740096fa1206befe343bBryan Cain 3198f758b0b92f6105c9615740096fa1206befe343bBryan Cain/** 320dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie * If the given ir satisfies is_distance_vec8(), return new ir 3218f758b0b92f6105c9615740096fa1206befe343bBryan Cain * representing its lowered equivalent. That is, map: 3228f758b0b92f6105c9615740096fa1206befe343bBryan Cain * 3238f758b0b92f6105c9615740096fa1206befe343bBryan Cain * - gl_ClipDistance => gl_ClipDistanceMESA (if gl_ClipDistance is 1D) 3248f758b0b92f6105c9615740096fa1206befe343bBryan Cain * - gl_ClipDistance[i] => gl_ClipDistanceMESA[i] (if gl_ClipDistance is 2D) 3258f758b0b92f6105c9615740096fa1206befe343bBryan Cain * 3268f758b0b92f6105c9615740096fa1206befe343bBryan Cain * Otherwise return NULL. 3278f758b0b92f6105c9615740096fa1206befe343bBryan Cain */ 3288f758b0b92f6105c9615740096fa1206befe343bBryan Cainir_rvalue * 329dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlielower_distance_visitor::lower_distance_vec8(ir_rvalue *ir) 3308f758b0b92f6105c9615740096fa1206befe343bBryan Cain{ 33154f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler if (!ir->type->is_array()) 33254f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler return NULL; 33354f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler if (ir->type->fields.array != glsl_type::float_type) 33454f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler return NULL; 33554f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler 33654f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler ir_variable **new_var = NULL; 337dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (this->old_distance_out_var) { 338dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (ir->variable_referenced() == this->old_distance_out_var) 339dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie new_var = &this->new_distance_out_var; 34054f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler } 341dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (this->old_distance_in_var) { 342dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (ir->variable_referenced() == this->old_distance_in_var) 343dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie new_var = &this->new_distance_in_var; 3448f758b0b92f6105c9615740096fa1206befe343bBryan Cain } 34554f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler if (new_var == NULL) 34654f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler return NULL; 3478f758b0b92f6105c9615740096fa1206befe343bBryan Cain 34854f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler if (ir->as_dereference_variable()) { 34954f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler return new(ralloc_parent(ir)) ir_dereference_variable(*new_var); 35054f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler } else { 3518f758b0b92f6105c9615740096fa1206befe343bBryan Cain ir_dereference_array *array_ref = ir->as_dereference_array(); 35254f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler assert(array_ref); 35354f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler assert(array_ref->array->as_dereference_variable()); 35454f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler 35554f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler return new(ralloc_parent(ir)) 35654f29502972cdd33302e69e029c8d07fb31b7bdfFabian Bieler ir_dereference_array(*new_var, array_ref->array_index); 3578f758b0b92f6105c9615740096fa1206befe343bBryan Cain } 3588f758b0b92f6105c9615740096fa1206befe343bBryan Cain} 3598f758b0b92f6105c9615740096fa1206befe343bBryan Cain 3608f758b0b92f6105c9615740096fa1206befe343bBryan Cain 361065da16508731f6b6a98865f392509be4f9ce07fIan Romanickvoid 362dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlielower_distance_visitor::handle_rvalue(ir_rvalue **rv) 363c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry{ 3648f758b0b92f6105c9615740096fa1206befe343bBryan Cain if (*rv == NULL) 365065da16508731f6b6a98865f392509be4f9ce07fIan Romanick return; 366c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 367065da16508731f6b6a98865f392509be4f9ce07fIan Romanick ir_dereference_array *const array_deref = (*rv)->as_dereference_array(); 368065da16508731f6b6a98865f392509be4f9ce07fIan Romanick if (array_deref == NULL) 369065da16508731f6b6a98865f392509be4f9ce07fIan Romanick return; 370065da16508731f6b6a98865f392509be4f9ce07fIan Romanick 3717a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie /* Replace any expression that indexes one of the floats in gl_ClipDistance 3727a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * with an expression that indexes into one of the vec4's in 3737a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * gl_ClipDistanceMESA and accesses the appropriate component. 374065da16508731f6b6a98865f392509be4f9ce07fIan Romanick */ 3758f758b0b92f6105c9615740096fa1206befe343bBryan Cain ir_rvalue *lowered_vec8 = 376dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie this->lower_distance_vec8(array_deref->array); 3778f758b0b92f6105c9615740096fa1206befe343bBryan Cain if (lowered_vec8 != NULL) { 378c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry this->progress = true; 379c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_rvalue *array_index; 380c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_rvalue *swizzle_index; 381065da16508731f6b6a98865f392509be4f9ce07fIan Romanick this->create_indices(array_deref->array_index, array_index, swizzle_index); 382065da16508731f6b6a98865f392509be4f9ce07fIan Romanick void *mem_ctx = ralloc_parent(array_deref); 383c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick 3848f758b0b92f6105c9615740096fa1206befe343bBryan Cain ir_dereference_array *const new_array_deref = 3858f758b0b92f6105c9615740096fa1206befe343bBryan Cain new(mem_ctx) ir_dereference_array(lowered_vec8, array_index); 386c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick 387c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick ir_expression *const expr = 388c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick new(mem_ctx) ir_expression(ir_binop_vector_extract, 3898f758b0b92f6105c9615740096fa1206befe343bBryan Cain new_array_deref, 390c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick swizzle_index); 391c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick 392c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick *rv = expr; 393c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } 394c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry} 395c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 396c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanickvoid 397dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlielower_distance_visitor::fix_lhs(ir_assignment *ir) 398c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick{ 399c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick if (ir->lhs->ir_type == ir_type_expression) { 400c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick void *mem_ctx = ralloc_parent(ir); 401c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick ir_expression *const expr = (ir_expression *) ir->lhs; 402c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick 403c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick /* The expression must be of the form: 404c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * 405c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * (vector_extract gl_ClipDistanceMESA[i], j). 406c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick */ 407c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick assert(expr->operation == ir_binop_vector_extract); 408c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick assert(expr->operands[0]->ir_type == ir_type_dereference_array); 409c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick assert(expr->operands[0]->type == glsl_type::vec4_type); 410c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick 411c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick ir_dereference *const new_lhs = (ir_dereference *) expr->operands[0]; 412c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick ir->rhs = new(mem_ctx) ir_expression(ir_triop_vector_insert, 413a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie glsl_type::vec4_type, 414a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie new_lhs->clone(mem_ctx, NULL), 415a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie ir->rhs, 416a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie expr->operands[1]); 417c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick ir->set_lhs(new_lhs); 418c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick ir->write_mask = WRITEMASK_XYZW; 419c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick } 420c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick} 421c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 422c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry/** 4237a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * Replace any assignment having the 1D gl_ClipDistance (undereferenced) as 4248f758b0b92f6105c9615740096fa1206befe343bBryan Cain * its LHS or RHS with a sequence of assignments, one for each component of 4258f758b0b92f6105c9615740096fa1206befe343bBryan Cain * the array. Each of these assignments is lowered to refer to 4267a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * gl_ClipDistanceMESA as appropriate. 4278f758b0b92f6105c9615740096fa1206befe343bBryan Cain * 4287a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * We need to do a similar replacement for 2D gl_ClipDistance, however since 4298f758b0b92f6105c9615740096fa1206befe343bBryan Cain * it's an input, the only case we need to address is where a 1D slice of it 4308f758b0b92f6105c9615740096fa1206befe343bBryan Cain * is the entire RHS of an assignment, e.g.: 4318f758b0b92f6105c9615740096fa1206befe343bBryan Cain * 4328f758b0b92f6105c9615740096fa1206befe343bBryan Cain * foo = gl_in[i].gl_ClipDistance 433c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 434c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berryir_visitor_status 435dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlielower_distance_visitor::visit_leave(ir_assignment *ir) 436c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry{ 4379dfcb05fa649ee7a573eab3d16851ebd4cb96010Paul Berry /* First invoke the base class visitor. This causes handle_rvalue() to be 4389dfcb05fa649ee7a573eab3d16851ebd4cb96010Paul Berry * called on ir->rhs and ir->condition. 4399dfcb05fa649ee7a573eab3d16851ebd4cb96010Paul Berry */ 4409dfcb05fa649ee7a573eab3d16851ebd4cb96010Paul Berry ir_rvalue_visitor::visit_leave(ir); 4419dfcb05fa649ee7a573eab3d16851ebd4cb96010Paul Berry 442dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (this->is_distance_vec8(ir->lhs) || 443dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie this->is_distance_vec8(ir->rhs)) { 4447a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie /* LHS or RHS of the assignment is the entire 1D gl_ClipDistance array 4457a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * (or a 1D slice of a 2D gl_ClipDistance input array). Since we are 4467a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * reshaping gl_ClipDistance from an array of floats to an array of 4478f758b0b92f6105c9615740096fa1206befe343bBryan Cain * vec4's, this isn't going to work as a bulk assignment anymore, so 4488f758b0b92f6105c9615740096fa1206befe343bBryan Cain * unroll it to element-by-element assignments and lower each of them. 449c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * 450c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * Note: to unroll into element-by-element assignments, we need to make 451d13fbeea9634b5e3cae0213cc61706ffc316b64fIan Romanick * clones of the LHS and RHS. This is safe because expressions and 452d13fbeea9634b5e3cae0213cc61706ffc316b64fIan Romanick * l-values are side-effect free. 453c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 454c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry void *ctx = ralloc_parent(ir); 4558f758b0b92f6105c9615740096fa1206befe343bBryan Cain int array_size = ir->lhs->type->array_size(); 456c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry for (int i = 0; i < array_size; ++i) { 457c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_dereference_array *new_lhs = new(ctx) ir_dereference_array( 458c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir->lhs->clone(ctx, NULL), new(ctx) ir_constant(i)); 459c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_dereference_array *new_rhs = new(ctx) ir_dereference_array( 460c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir->rhs->clone(ctx, NULL), new(ctx) ir_constant(i)); 461065da16508731f6b6a98865f392509be4f9ce07fIan Romanick this->handle_rvalue((ir_rvalue **) &new_rhs); 462c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick 463c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick /* Handle the LHS after creating the new assignment. This must 464c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * happen in this order because handle_rvalue may replace the old LHS 465c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * with an ir_expression of ir_binop_vector_extract. Since this is 466c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * not a valide l-value, this will cause an assertion in the 467c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * ir_assignment constructor to fail. 468c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * 469c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * If this occurs, replace the mangled LHS with a dereference of the 470c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * vector, and replace the RHS with an ir_triop_vector_insert. 471c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick */ 472c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick ir_assignment *const assign = new(ctx) ir_assignment(new_lhs, new_rhs); 473c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick this->handle_rvalue((ir_rvalue **) &assign->lhs); 474c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick this->fix_lhs(assign); 475c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick 476c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick this->base_ir->insert_before(assign); 477c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } 478c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir->remove(); 479065da16508731f6b6a98865f392509be4f9ce07fIan Romanick 480065da16508731f6b6a98865f392509be4f9ce07fIan Romanick return visit_continue; 481c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } 482c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 483065da16508731f6b6a98865f392509be4f9ce07fIan Romanick /* Handle the LHS as if it were an r-value. Normally 484065da16508731f6b6a98865f392509be4f9ce07fIan Romanick * rvalue_visit(ir_assignment *) only visits the RHS, but we need to lower 485065da16508731f6b6a98865f392509be4f9ce07fIan Romanick * expressions in the LHS as well. 486c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * 487c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * This may cause the LHS to get replaced with an ir_expression of 488c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * ir_binop_vector_extract. If this occurs, replace it with a dereference 489c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick * of the vector, and replace the RHS with an ir_triop_vector_insert. 490065da16508731f6b6a98865f392509be4f9ce07fIan Romanick */ 491065da16508731f6b6a98865f392509be4f9ce07fIan Romanick handle_rvalue((ir_rvalue **)&ir->lhs); 492c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick this->fix_lhs(ir); 493c3bb07f875075b08a0b13f47be95e0c49edb6555Ian Romanick 494065da16508731f6b6a98865f392509be4f9ce07fIan Romanick return rvalue_visit(ir); 495c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry} 496c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 497c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 498c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry/** 499c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * Set up base_ir properly and call visit_leave() on a newly created 500c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * ir_assignment node. This is used in cases where we have to insert an 501c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * ir_assignment in a place where we know the hierarchical visitor won't see 502c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * it. 503c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 504c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berryvoid 505dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlielower_distance_visitor::visit_new_assignment(ir_assignment *ir) 506c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry{ 507c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_instruction *old_base_ir = this->base_ir; 508c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry this->base_ir = ir; 509c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir->accept(this); 510c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry this->base_ir = old_base_ir; 511c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry} 512c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 513c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 514c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry/** 5157a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * If a 1D gl_ClipDistance variable appears as an argument in an ir_call 5168f758b0b92f6105c9615740096fa1206befe343bBryan Cain * expression, replace it with a temporary variable, and make sure the ir_call 5178f758b0b92f6105c9615740096fa1206befe343bBryan Cain * is preceded and/or followed by assignments that copy the contents of the 5187a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * temporary variable to and/or from gl_ClipDistance. Each of these 5197a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * assignments is then lowered to refer to gl_ClipDistanceMESA. 5208f758b0b92f6105c9615740096fa1206befe343bBryan Cain * 5217a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * We need to do a similar replacement for 2D gl_ClipDistance, however since 5228f758b0b92f6105c9615740096fa1206befe343bBryan Cain * it's an input, the only case we need to address is where a 1D slice of it 5238f758b0b92f6105c9615740096fa1206befe343bBryan Cain * is passed as an "in" parameter to an ir_call, e.g.: 5248f758b0b92f6105c9615740096fa1206befe343bBryan Cain * 5258f758b0b92f6105c9615740096fa1206befe343bBryan Cain * foo(gl_in[i].gl_ClipDistance) 526c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 527c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berryir_visitor_status 528dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlielower_distance_visitor::visit_leave(ir_call *ir) 529c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry{ 530c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry void *ctx = ralloc_parent(ir); 531c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 532d1f6f656973a2e18641441e3c97b30799a82de52Matt Turner const exec_node *formal_param_node = ir->callee->parameters.get_head_raw(); 533d1f6f656973a2e18641441e3c97b30799a82de52Matt Turner const exec_node *actual_param_node = ir->actual_parameters.get_head_raw(); 534c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry while (!actual_param_node->is_tail_sentinel()) { 535c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_variable *formal_param = (ir_variable *) formal_param_node; 536c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_rvalue *actual_param = (ir_rvalue *) actual_param_node; 537c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 538c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry /* Advance formal_param_node and actual_param_node now so that we can 539c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * safely replace actual_param with another node, if necessary, below. 540c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 541c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry formal_param_node = formal_param_node->next; 542c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry actual_param_node = actual_param_node->next; 543c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 544dd3390e12fa8c8fa127013a9fc7c83069747aad2Dave Airlie if (this->is_distance_vec8(actual_param)) { 5457a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie /* User is trying to pass the whole 1D gl_ClipDistance array (or a 1D 5467a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * slice of a 2D gl_ClipDistance array) to a function call. Since we 5477a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie * are reshaping gl_ClipDistance from an array of floats to an array 5488f758b0b92f6105c9615740096fa1206befe343bBryan Cain * of vec4's, this isn't going to work anymore, so use a temporary 5498f758b0b92f6105c9615740096fa1206befe343bBryan Cain * array instead. 550c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 5517a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie ir_variable *temp_clip_distance = new(ctx) ir_variable( 5527a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie actual_param->type, "temp_clip_distance", ir_var_temporary); 5537a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie this->base_ir->insert_before(temp_clip_distance); 554c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry actual_param->replace_with( 5557a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie new(ctx) ir_dereference_variable(temp_clip_distance)); 55633ee2c67c0a4e8f2fefbf37dacabd14918060af5Tapani Pälli if (formal_param->data.mode == ir_var_function_in 55733ee2c67c0a4e8f2fefbf37dacabd14918060af5Tapani Pälli || formal_param->data.mode == ir_var_function_inout) { 5587a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie /* Copy from gl_ClipDistance to the temporary before the call. 559c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * Since we are going to insert this copy before the current 560c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * instruction, we need to visit it afterwards to make sure it 561c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * gets lowered. 562c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 563c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_assignment *new_assignment = new(ctx) ir_assignment( 5647a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie new(ctx) ir_dereference_variable(temp_clip_distance), 5658f758b0b92f6105c9615740096fa1206befe343bBryan Cain actual_param->clone(ctx, NULL)); 566c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry this->base_ir->insert_before(new_assignment); 567c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry this->visit_new_assignment(new_assignment); 568c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } 56933ee2c67c0a4e8f2fefbf37dacabd14918060af5Tapani Pälli if (formal_param->data.mode == ir_var_function_out 57033ee2c67c0a4e8f2fefbf37dacabd14918060af5Tapani Pälli || formal_param->data.mode == ir_var_function_inout) { 5717a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie /* Copy from the temporary to gl_ClipDistance after the call. 572c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * Since visit_list_elements() has already decided which 573c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * instruction it's going to visit next, we need to visit 574c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry * afterwards to make sure it gets lowered. 575c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry */ 576c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry ir_assignment *new_assignment = new(ctx) ir_assignment( 5778f758b0b92f6105c9615740096fa1206befe343bBryan Cain actual_param->clone(ctx, NULL), 5787a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie new(ctx) ir_dereference_variable(temp_clip_distance)); 579c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry this->base_ir->insert_after(new_assignment); 580c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry this->visit_new_assignment(new_assignment); 581c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } 582c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } 583c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry } 584c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 585065da16508731f6b6a98865f392509be4f9ce07fIan Romanick return rvalue_visit(ir); 586c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry} 587c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 588a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlienamespace { 589a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlieclass lower_distance_visitor_counter : public ir_rvalue_visitor { 590a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airliepublic: 591a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie explicit lower_distance_visitor_counter(void) 592a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie : in_clip_size(0), in_cull_size(0), 593a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie out_clip_size(0), out_cull_size(0) 594a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie { 595a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie } 596a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 597a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie virtual ir_visitor_status visit(ir_variable *); 598a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie virtual void handle_rvalue(ir_rvalue **rvalue); 599a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 600a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie int in_clip_size; 601a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie int in_cull_size; 602a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie int out_clip_size; 603a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie int out_cull_size; 604a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie}; 605a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 606a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie} 607a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie/** 608a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie * Count gl_ClipDistance and gl_CullDistance sizes. 609a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie */ 610a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlieir_visitor_status 611a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlielower_distance_visitor_counter::visit(ir_variable *ir) 612a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie{ 613a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie int *clip_size, *cull_size; 614a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 615a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (!ir->name) 616a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie return visit_continue; 617a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 618a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (ir->data.mode == ir_var_shader_out) { 619a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie clip_size = &out_clip_size; 620a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie cull_size = &out_cull_size; 621a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie } else if (ir->data.mode == ir_var_shader_in) { 622a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie clip_size = &in_clip_size; 623a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie cull_size = &in_cull_size; 624a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie } else 625a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie return visit_continue; 626a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 627a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (ir->type->is_unsized_array()) 628a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie return visit_continue; 629a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 630a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (*clip_size == 0) { 631a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (!strcmp(ir->name, "gl_ClipDistance")) { 632a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (!ir->type->fields.array->is_array()) 633a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie *clip_size = ir->type->array_size(); 634a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie else 635a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie *clip_size = ir->type->fields.array->array_size(); 636a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie } 637a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie } 638a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 639a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (*cull_size == 0) { 640a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (!strcmp(ir->name, "gl_CullDistance")) { 641a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (!ir->type->fields.array->is_array()) 642a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie *cull_size = ir->type->array_size(); 643a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie else 644a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie *cull_size = ir->type->fields.array->array_size(); 645a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie } 646a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie } 647a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie return visit_continue; 648a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie} 649a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 650a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlievoid 651a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlielower_distance_visitor_counter::handle_rvalue(ir_rvalue **rv) 652a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie{ 653a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie return; 654a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie} 655c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 656c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berrybool 6571fb8c6df884c2a17cf980c4ea32db4c214903b55Timothy Arcerilower_clip_cull_distance(struct gl_shader_program *prog, 6581fb8c6df884c2a17cf980c4ea32db4c214903b55Timothy Arceri struct gl_linked_shader *shader) 659c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry{ 660a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie int clip_size, cull_size; 661a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 662a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie lower_distance_visitor_counter count; 663a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie visit_list_elements(&count, shader->ir); 664a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 665a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie clip_size = MAX2(count.in_clip_size, count.out_clip_size); 666a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie cull_size = MAX2(count.in_cull_size, count.out_cull_size); 667c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 668a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (clip_size == 0 && cull_size == 0) 669a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie return false; 670a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 671a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie lower_distance_visitor v(shader->Stage, "gl_ClipDistance", clip_size + cull_size, 0); 6727a6d55826e94e6c18471c671736f706bddfdb582Dave Airlie visit_list_elements(&v, shader->ir); 67318392443d448e083187d085965375e7de910b18aPaul Berry 674a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie lower_distance_visitor v2(shader->Stage, "gl_CullDistance", &v, clip_size); 675a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie visit_list_elements(&v2, shader->ir); 676a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie 677a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (v2.new_distance_out_var) 678a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie shader->symbols->add_variable(v2.new_distance_out_var); 679a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie if (v2.new_distance_in_var) 680a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie shader->symbols->add_variable(v2.new_distance_in_var); 681c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry 682a08c4ebbe841e22076c6d3929248876c60b3dfcdDave Airlie return v2.progress; 683c06e32596735074536b0e613cbddb1c5fd7b367aPaul Berry} 684