ir_to_mesa.cpp revision bd3b835e7c32e093f91f636330fd93b3dedd8362
1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville/* 2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. 3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Copyright (C) 2008 VMware, Inc. All Rights Reserved. 4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Copyright © 2010 Intel Corporation 5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Permission is hereby granted, free of charge, to any person obtaining a 7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * copy of this software and associated documentation files (the "Software"), 8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * to deal in the Software without restriction, including without limitation 9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * and/or sell copies of the Software, and to permit persons to whom the 11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Software is furnished to do so, subject to the following conditions: 12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * The above copyright notice and this permission notice (including the next 14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * paragraph) shall be included in all copies or substantial portions of the 15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Software. 16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * DEALINGS IN THE SOFTWARE. 24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville/** 27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * \file ir_to_mesa.cpp 28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * Translates the IR to ARB_fragment_program text if possible, 30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * printing the result 31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <stdio.h> 34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "ir.h" 35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "ir_visitor.h" 36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "ir_print_visitor.h" 37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "ir_expression_flattening.h" 38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "glsl_types.h" 39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "glsl_parser_extras.h" 40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "../glsl/program.h" 41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "ir_optimization.h" 42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "ast.h" 43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleextern "C" { 45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "main/mtypes.h" 46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "shader/prog_instruction.h" 47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "shader/prog_print.h" 48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "shader/program.h" 49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "shader/prog_uniform.h" 50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "shader/prog_parameter.h" 51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "shader/shader_api.h" 52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville/** 55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * This struct is a corresponding struct to Mesa prog_src_register, with 56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * wider fields. 57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilletypedef struct ir_to_mesa_src_reg { 59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int file; /**< PROGRAM_* from Mesa */ 60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */ 61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */ 62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int negate; /**< NEGATE_XYZW mask from mesa */ 63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville bool reladdr; /**< Register index should be offset by address reg. */ 64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} ir_to_mesa_src_reg; 65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilletypedef struct ir_to_mesa_dst_reg { 67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int file; /**< PROGRAM_* from Mesa */ 68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */ 69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int writemask; /**< Bitfield of WRITEMASK_[XYZW] */ 70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} ir_to_mesa_dst_reg; 71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleextern ir_to_mesa_src_reg ir_to_mesa_undef; 73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass ir_to_mesa_instruction : public exec_node { 75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillepublic: 76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enum prog_opcode op; 77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_dst_reg dst_reg; 78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_src_reg src_reg[3]; 79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** Pointer to the ir source this tree came from for debugging */ 80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_instruction *ir; 81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass temp_entry : public exec_node { 84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillepublic: 85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville temp_entry(ir_variable *var, int file, int index) 86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville : file(file), index(index), var(var) 87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville { 88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /* empty */ 89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int file; 92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int index; 93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_variable *var; /* variable that maps to this, if any */ 94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass ir_to_mesa_visitor : public ir_visitor { 97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillepublic: 98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_visitor(); 99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GLcontext *ctx; 101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville struct gl_program *prog; 102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int next_temp; 104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville temp_entry *find_variable_storage(ir_variable *var); 106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_src_reg get_temp(const glsl_type *type); 108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville struct ir_to_mesa_src_reg src_reg_for_float(float val); 110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** 112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * \name Visit methods 113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * 114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * As typical for the visitor pattern, there must be one \c visit method for 115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * each concrete subclass of \c ir_instruction. Virtual base classes within 116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * the hierarchy should not have \c visit methods. 117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */ 118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /*@{*/ 119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville virtual void visit(ir_variable *); 120d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_loop *); 121d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_loop_jump *); 122d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_function_signature *); 123d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_function *); 124d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_expression *); 125d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_swizzle *); 126d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_dereference_variable *); 127d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_dereference_array *); 128d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_dereference_record *); 129d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_assignment *); 130d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_constant *); 131d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_call *); 132d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_return *); 133d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_texture *); 134d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void visit(ir_if *); 135d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville /*@}*/ 136d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 137d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville struct ir_to_mesa_src_reg result; 138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** List of temp_entry */ 140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville exec_list variable_storage; 141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /** List of ir_to_mesa_instruction */ 143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville exec_list instructions; 144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_instruction *ir_to_mesa_emit_op1(ir_instruction *ir, 146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enum prog_opcode op, 147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_dst_reg dst, 148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_src_reg src0); 149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_instruction *ir_to_mesa_emit_op2(ir_instruction *ir, 151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enum prog_opcode op, 152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_dst_reg dst, 153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_src_reg src0, 154d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ir_to_mesa_src_reg src1); 155d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 156d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ir_to_mesa_instruction *ir_to_mesa_emit_op3(ir_instruction *ir, 157d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville enum prog_opcode op, 158d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ir_to_mesa_dst_reg dst, 159d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ir_to_mesa_src_reg src0, 160d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ir_to_mesa_src_reg src1, 161d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ir_to_mesa_src_reg src2); 162d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 163d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville void ir_to_mesa_emit_scalar_op1(ir_instruction *ir, 164d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville enum prog_opcode op, 165d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ir_to_mesa_dst_reg dst, 166d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ir_to_mesa_src_reg src0); 167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void *mem_ctx; 169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleir_to_mesa_src_reg ir_to_mesa_undef = { 172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, NEGATE_NONE, false, 173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleir_to_mesa_dst_reg ir_to_mesa_undef_dst = { 176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP 177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleir_to_mesa_dst_reg ir_to_mesa_address_reg = { 180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville PROGRAM_ADDRESS, 0, WRITEMASK_X 181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestatic int swizzle_for_size(int size) 184d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville{ 185d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int size_swizzles[4] = { 186d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X), 187d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y), 188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z), 189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W), 190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville }; 191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return size_swizzles[size - 1]; 193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville/* This list should match up with builtin_variables.h */ 196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestatic const struct { 197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const char *name; 198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int file; 199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int index; 200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} builtin_var_to_mesa_reg[] = { 201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /* core_vs */ 202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_Position", PROGRAM_OUTPUT, VERT_RESULT_HPOS}, 203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_PointSize", PROGRAM_OUTPUT, VERT_RESULT_PSIZ}, 204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /* core_fs */ 206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_FragCoord", PROGRAM_INPUT, FRAG_ATTRIB_WPOS}, 207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_FrontFacing", PROGRAM_INPUT, FRAG_ATTRIB_FACE}, 208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_FragColor", PROGRAM_OUTPUT, FRAG_ATTRIB_COL0}, 209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_FragDepth", PROGRAM_UNDEFINED, FRAG_ATTRIB_WPOS}, /* FINISHME: WPOS.z */ 210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /* 110_deprecated_fs */ 212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_Color", PROGRAM_INPUT, FRAG_ATTRIB_COL0}, 213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_SecondaryColor", PROGRAM_INPUT, FRAG_ATTRIB_COL1}, 214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_FogFragCoord", PROGRAM_INPUT, FRAG_ATTRIB_FOGC}, 215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_TexCoord", PROGRAM_INPUT, FRAG_ATTRIB_TEX0}, /* array */ 216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /* 110_deprecated_vs */ 218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_Vertex", PROGRAM_INPUT, VERT_ATTRIB_POS}, 219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_Normal", PROGRAM_INPUT, VERT_ATTRIB_NORMAL}, 220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_Color", PROGRAM_INPUT, VERT_ATTRIB_COLOR0}, 221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_SecondaryColor", PROGRAM_INPUT, VERT_ATTRIB_COLOR1}, 222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_MultiTexCoord0", PROGRAM_INPUT, VERT_ATTRIB_TEX0}, 223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_MultiTexCoord1", PROGRAM_INPUT, VERT_ATTRIB_TEX1}, 224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_MultiTexCoord2", PROGRAM_INPUT, VERT_ATTRIB_TEX2}, 225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_MultiTexCoord3", PROGRAM_INPUT, VERT_ATTRIB_TEX3}, 226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_MultiTexCoord4", PROGRAM_INPUT, VERT_ATTRIB_TEX4}, 227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_MultiTexCoord5", PROGRAM_INPUT, VERT_ATTRIB_TEX5}, 228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_MultiTexCoord6", PROGRAM_INPUT, VERT_ATTRIB_TEX6}, 229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_MultiTexCoord7", PROGRAM_INPUT, VERT_ATTRIB_TEX7}, 230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_TexCoord", PROGRAM_OUTPUT, VERT_RESULT_TEX0}, /* array */ 231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_FogCoord", PROGRAM_INPUT, VERT_RESULT_FOGC}, 232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /*{"gl_ClipVertex", PROGRAM_OUTPUT, VERT_ATTRIB_FOGC},*/ /* FINISHME */ 233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_FrontColor", PROGRAM_OUTPUT, VERT_RESULT_COL0}, 234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_BackColor", PROGRAM_OUTPUT, VERT_RESULT_BFC0}, 235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_FrontSecondaryColor", PROGRAM_OUTPUT, VERT_RESULT_COL1}, 236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_BackSecondaryColor", PROGRAM_OUTPUT, VERT_RESULT_BFC1}, 237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_FogFragCoord", PROGRAM_OUTPUT, VERT_RESULT_FOGC}, 238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /* 130_vs */ 240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville /*{"gl_VertexID", PROGRAM_INPUT, VERT_ATTRIB_FOGC},*/ /* FINISHME */ 241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville {"gl_FragData", PROGRAM_OUTPUT, FRAG_RESULT_DATA0}, /* array */ 243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleir_to_mesa_instruction * 246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir, 247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville enum prog_opcode op, 248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_dst_reg dst, 249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_src_reg src0, 250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_src_reg src1, 251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_src_reg src2) 252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville{ 253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ir_to_mesa_instruction *inst = new(mem_ctx) ir_to_mesa_instruction(); 254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville inst->op = op; 256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville inst->dst_reg = dst; 257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville inst->src_reg[0] = src0; 258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville inst->src_reg[1] = src1; 259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville inst->src_reg[2] = src2; 260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville inst->ir = ir; 261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville this->instructions.push_tail(inst); 263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return inst; 265} 266 267 268ir_to_mesa_instruction * 269ir_to_mesa_visitor::ir_to_mesa_emit_op2(ir_instruction *ir, 270 enum prog_opcode op, 271 ir_to_mesa_dst_reg dst, 272 ir_to_mesa_src_reg src0, 273 ir_to_mesa_src_reg src1) 274{ 275 return ir_to_mesa_emit_op3(ir, op, dst, src0, src1, ir_to_mesa_undef); 276} 277 278ir_to_mesa_instruction * 279ir_to_mesa_visitor::ir_to_mesa_emit_op1(ir_instruction *ir, 280 enum prog_opcode op, 281 ir_to_mesa_dst_reg dst, 282 ir_to_mesa_src_reg src0) 283{ 284 return ir_to_mesa_emit_op3(ir, op, dst, 285 src0, ir_to_mesa_undef, ir_to_mesa_undef); 286} 287 288inline ir_to_mesa_dst_reg 289ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg) 290{ 291 ir_to_mesa_dst_reg dst_reg; 292 293 dst_reg.file = reg.file; 294 dst_reg.index = reg.index; 295 dst_reg.writemask = WRITEMASK_XYZW; 296 297 return dst_reg; 298} 299 300/** 301 * Emits Mesa scalar opcodes to produce unique answers across channels. 302 * 303 * Some Mesa opcodes are scalar-only, like ARB_fp/vp. The src X 304 * channel determines the result across all channels. So to do a vec4 305 * of this operation, we want to emit a scalar per source channel used 306 * to produce dest channels. 307 */ 308void 309ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op1(ir_instruction *ir, 310 enum prog_opcode op, 311 ir_to_mesa_dst_reg dst, 312 ir_to_mesa_src_reg src0) 313{ 314 int i, j; 315 int done_mask = ~dst.writemask; 316 317 /* Mesa RCP is a scalar operation splatting results to all channels, 318 * like ARB_fp/vp. So emit as many RCPs as necessary to cover our 319 * dst channels. 320 */ 321 for (i = 0; i < 4; i++) { 322 GLuint this_mask = (1 << i); 323 ir_to_mesa_instruction *inst; 324 ir_to_mesa_src_reg src = src0; 325 326 if (done_mask & this_mask) 327 continue; 328 329 GLuint src_swiz = GET_SWZ(src.swizzle, i); 330 for (j = i + 1; j < 4; j++) { 331 if (!(done_mask & (1 << j)) && GET_SWZ(src.swizzle, j) == src_swiz) { 332 this_mask |= (1 << j); 333 } 334 } 335 src.swizzle = MAKE_SWIZZLE4(src_swiz, src_swiz, 336 src_swiz, src_swiz); 337 338 inst = ir_to_mesa_emit_op1(ir, op, 339 dst, 340 src); 341 inst->dst_reg.writemask = this_mask; 342 done_mask |= this_mask; 343 } 344} 345 346struct ir_to_mesa_src_reg 347ir_to_mesa_visitor::src_reg_for_float(float val) 348{ 349 ir_to_mesa_src_reg src_reg; 350 351 src_reg.file = PROGRAM_CONSTANT; 352 src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters, 353 &val, 1, &src_reg.swizzle); 354 355 return src_reg; 356} 357 358/** 359 * In the initial pass of codegen, we assign temporary numbers to 360 * intermediate results. (not SSA -- variable assignments will reuse 361 * storage). Actual register allocation for the Mesa VM occurs in a 362 * pass over the Mesa IR later. 363 */ 364ir_to_mesa_src_reg 365ir_to_mesa_visitor::get_temp(const glsl_type *type) 366{ 367 ir_to_mesa_src_reg src_reg; 368 int swizzle[4]; 369 int i; 370 371 assert(!type->is_array()); 372 373 src_reg.file = PROGRAM_TEMPORARY; 374 src_reg.index = type->matrix_columns; 375 src_reg.reladdr = false; 376 377 for (i = 0; i < type->vector_elements; i++) 378 swizzle[i] = i; 379 for (; i < 4; i++) 380 swizzle[i] = type->vector_elements - 1; 381 src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], 382 swizzle[2], swizzle[3]); 383 384 return src_reg; 385} 386 387static int 388type_size(const struct glsl_type *type) 389{ 390 unsigned int i; 391 int size; 392 393 switch (type->base_type) { 394 case GLSL_TYPE_UINT: 395 case GLSL_TYPE_INT: 396 case GLSL_TYPE_FLOAT: 397 case GLSL_TYPE_BOOL: 398 if (type->is_matrix()) { 399 return 4; /* FINISHME: Not all matrices are 4x4. */ 400 } else { 401 /* Regardless of size of vector, it gets a vec4. This is bad 402 * packing for things like floats, but otherwise arrays become a 403 * mess. Hopefully a later pass over the code can pack scalars 404 * down if appropriate. 405 */ 406 return 1; 407 } 408 case GLSL_TYPE_ARRAY: 409 return type_size(type->fields.array) * type->length; 410 case GLSL_TYPE_STRUCT: 411 size = 0; 412 for (i = 0; i < type->length; i++) { 413 size += type_size(type->fields.structure[i].type); 414 } 415 return size; 416 default: 417 assert(0); 418 } 419} 420 421temp_entry * 422ir_to_mesa_visitor::find_variable_storage(ir_variable *var) 423{ 424 425 temp_entry *entry; 426 427 foreach_iter(exec_list_iterator, iter, this->variable_storage) { 428 entry = (temp_entry *)iter.get(); 429 430 if (entry->var == var) 431 return entry; 432 } 433 434 return NULL; 435} 436 437void 438ir_to_mesa_visitor::visit(ir_variable *ir) 439{ 440 (void)ir; 441} 442 443void 444ir_to_mesa_visitor::visit(ir_loop *ir) 445{ 446 assert(!ir->from); 447 assert(!ir->to); 448 assert(!ir->increment); 449 assert(!ir->counter); 450 451 ir_to_mesa_emit_op1(NULL, OPCODE_BGNLOOP, 452 ir_to_mesa_undef_dst, ir_to_mesa_undef); 453 454 visit_exec_list(&ir->body_instructions, this); 455 456 ir_to_mesa_emit_op1(NULL, OPCODE_ENDLOOP, 457 ir_to_mesa_undef_dst, ir_to_mesa_undef); 458} 459 460void 461ir_to_mesa_visitor::visit(ir_loop_jump *ir) 462{ 463 switch (ir->mode) { 464 case ir_loop_jump::jump_break: 465 ir_to_mesa_emit_op1(NULL, OPCODE_BRK, 466 ir_to_mesa_undef_dst, ir_to_mesa_undef); 467 break; 468 case ir_loop_jump::jump_continue: 469 ir_to_mesa_emit_op1(NULL, OPCODE_CONT, 470 ir_to_mesa_undef_dst, ir_to_mesa_undef); 471 break; 472 } 473} 474 475 476void 477ir_to_mesa_visitor::visit(ir_function_signature *ir) 478{ 479 assert(0); 480 (void)ir; 481} 482 483void 484ir_to_mesa_visitor::visit(ir_function *ir) 485{ 486 /* Ignore function bodies other than main() -- we shouldn't see calls to 487 * them since they should all be inlined before we get to ir_to_mesa. 488 */ 489 if (strcmp(ir->name, "main") == 0) { 490 const ir_function_signature *sig; 491 exec_list empty; 492 493 sig = ir->matching_signature(&empty); 494 495 assert(sig); 496 497 foreach_iter(exec_list_iterator, iter, sig->body) { 498 ir_instruction *ir = (ir_instruction *)iter.get(); 499 500 ir->accept(this); 501 } 502 } 503} 504 505void 506ir_to_mesa_visitor::visit(ir_expression *ir) 507{ 508 unsigned int operand; 509 struct ir_to_mesa_src_reg op[2]; 510 struct ir_to_mesa_src_reg result_src; 511 struct ir_to_mesa_dst_reg result_dst; 512 const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1); 513 const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1); 514 const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1); 515 516 for (operand = 0; operand < ir->get_num_operands(); operand++) { 517 this->result.file = PROGRAM_UNDEFINED; 518 ir->operands[operand]->accept(this); 519 if (this->result.file == PROGRAM_UNDEFINED) { 520 ir_print_visitor v; 521 printf("Failed to get tree for expression operand:\n"); 522 ir->operands[operand]->accept(&v); 523 exit(1); 524 } 525 op[operand] = this->result; 526 527 /* Only expression implemented for matrices yet */ 528 assert(!ir->operands[operand]->type->is_matrix() || 529 ir->operation == ir_binop_mul); 530 } 531 532 this->result.file = PROGRAM_UNDEFINED; 533 534 /* Storage for our result. Ideally for an assignment we'd be using 535 * the actual storage for the result here, instead. 536 */ 537 result_src = get_temp(ir->type); 538 /* convenience for the emit functions below. */ 539 result_dst = ir_to_mesa_dst_reg_from_src(result_src); 540 /* Limit writes to the channels that will be used by result_src later. 541 * This does limit this temp's use as a temporary for multi-instruction 542 * sequences. 543 */ 544 result_dst.writemask = (1 << ir->type->vector_elements) - 1; 545 546 switch (ir->operation) { 547 case ir_unop_logic_not: 548 ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, 549 op[0], src_reg_for_float(0.0)); 550 break; 551 case ir_unop_neg: 552 op[0].negate = ~op[0].negate; 553 result_src = op[0]; 554 break; 555 case ir_unop_exp: 556 ir_to_mesa_emit_scalar_op1(ir, OPCODE_EXP, result_dst, op[0]); 557 break; 558 case ir_unop_exp2: 559 ir_to_mesa_emit_scalar_op1(ir, OPCODE_EX2, result_dst, op[0]); 560 break; 561 case ir_unop_log: 562 ir_to_mesa_emit_scalar_op1(ir, OPCODE_LOG, result_dst, op[0]); 563 break; 564 case ir_unop_log2: 565 ir_to_mesa_emit_scalar_op1(ir, OPCODE_LG2, result_dst, op[0]); 566 break; 567 case ir_unop_sin: 568 ir_to_mesa_emit_scalar_op1(ir, OPCODE_SIN, result_dst, op[0]); 569 break; 570 case ir_unop_cos: 571 ir_to_mesa_emit_scalar_op1(ir, OPCODE_COS, result_dst, op[0]); 572 break; 573 case ir_binop_add: 574 ir_to_mesa_emit_op2(ir, OPCODE_ADD, result_dst, op[0], op[1]); 575 break; 576 case ir_binop_sub: 577 ir_to_mesa_emit_op2(ir, OPCODE_SUB, result_dst, op[0], op[1]); 578 break; 579 case ir_binop_mul: 580 if (ir->operands[0]->type->is_matrix() && 581 !ir->operands[1]->type->is_matrix()) { 582 if (ir->operands[0]->type->is_scalar()) { 583 ir_to_mesa_dst_reg dst_column = result_dst; 584 ir_to_mesa_src_reg src_column = op[0]; 585 for (int i = 0; i < ir->operands[0]->type->matrix_columns; i++) { 586 ir_to_mesa_emit_op2(ir, OPCODE_MUL, 587 dst_column, src_column, op[1]); 588 dst_column.index++; 589 src_column.index++; 590 } 591 } else { 592 ir_to_mesa_dst_reg dst_chan = result_dst; 593 ir_to_mesa_src_reg src_column = op[0]; 594 ir_to_mesa_src_reg src_chan = op[1]; 595 for (int i = 0; i < ir->operands[0]->type->matrix_columns; i++) { 596 dst_chan.writemask = (1 << i); 597 src_chan.swizzle = MAKE_SWIZZLE4(i, i, i, i); 598 ir_to_mesa_emit_op2(ir, OPCODE_MUL, 599 dst_chan, src_column, src_chan); 600 src_column.index++; 601 } 602 } 603 } else { 604 assert(!ir->operands[0]->type->is_matrix()); 605 assert(!ir->operands[1]->type->is_matrix()); 606 ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], op[1]); 607 } 608 break; 609 case ir_binop_div: 610 ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, op[1]); 611 ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], result_src); 612 break; 613 614 case ir_binop_less: 615 ir_to_mesa_emit_op2(ir, OPCODE_SLT, result_dst, op[0], op[1]); 616 break; 617 case ir_binop_greater: 618 ir_to_mesa_emit_op2(ir, OPCODE_SGT, result_dst, op[0], op[1]); 619 break; 620 case ir_binop_lequal: 621 ir_to_mesa_emit_op2(ir, OPCODE_SLE, result_dst, op[0], op[1]); 622 break; 623 case ir_binop_gequal: 624 ir_to_mesa_emit_op2(ir, OPCODE_SGE, result_dst, op[0], op[1]); 625 break; 626 case ir_binop_equal: 627 ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]); 628 break; 629 case ir_binop_logic_xor: 630 case ir_binop_nequal: 631 ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]); 632 break; 633 634 case ir_binop_logic_or: 635 /* This could be a saturated add and skip the SNE. */ 636 ir_to_mesa_emit_op2(ir, OPCODE_ADD, 637 result_dst, 638 op[0], op[1]); 639 640 ir_to_mesa_emit_op2(ir, OPCODE_SNE, 641 result_dst, 642 result_src, src_reg_for_float(0.0)); 643 break; 644 645 case ir_binop_logic_and: 646 /* the bool args are stored as float 0.0 or 1.0, so "mul" gives us "and". */ 647 ir_to_mesa_emit_op2(ir, OPCODE_MUL, 648 result_dst, 649 op[0], op[1]); 650 break; 651 652 case ir_binop_dot: 653 if (ir->operands[0]->type == vec4_type) { 654 assert(ir->operands[1]->type == vec4_type); 655 ir_to_mesa_emit_op2(ir, OPCODE_DP4, 656 result_dst, 657 op[0], op[1]); 658 } else if (ir->operands[0]->type == vec3_type) { 659 assert(ir->operands[1]->type == vec3_type); 660 ir_to_mesa_emit_op2(ir, OPCODE_DP3, 661 result_dst, 662 op[0], op[1]); 663 } else if (ir->operands[0]->type == vec2_type) { 664 assert(ir->operands[1]->type == vec2_type); 665 ir_to_mesa_emit_op2(ir, OPCODE_DP2, 666 result_dst, 667 op[0], op[1]); 668 } 669 break; 670 case ir_unop_sqrt: 671 ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]); 672 ir_to_mesa_emit_op1(ir, OPCODE_RCP, result_dst, result_src); 673 break; 674 case ir_unop_rsq: 675 ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]); 676 break; 677 case ir_unop_i2f: 678 /* Mesa IR lacks types, ints are stored as truncated floats. */ 679 result_src = op[0]; 680 break; 681 case ir_unop_f2i: 682 ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]); 683 break; 684 case ir_unop_f2b: 685 ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, 686 result_src, src_reg_for_float(0.0)); 687 break; 688 case ir_unop_trunc: 689 ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]); 690 break; 691 case ir_unop_ceil: 692 op[0].negate = ~op[0].negate; 693 ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]); 694 result_src.negate = ~result_src.negate; 695 break; 696 case ir_unop_floor: 697 ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]); 698 break; 699 case ir_binop_min: 700 ir_to_mesa_emit_op2(ir, OPCODE_MIN, result_dst, op[0], op[1]); 701 break; 702 case ir_binop_max: 703 ir_to_mesa_emit_op2(ir, OPCODE_MAX, result_dst, op[0], op[1]); 704 break; 705 default: 706 ir_print_visitor v; 707 printf("Failed to get tree for expression:\n"); 708 ir->accept(&v); 709 exit(1); 710 break; 711 } 712 713 this->result = result_src; 714} 715 716 717void 718ir_to_mesa_visitor::visit(ir_swizzle *ir) 719{ 720 ir_to_mesa_src_reg src_reg; 721 int i; 722 int swizzle[4]; 723 724 /* Note that this is only swizzles in expressions, not those on the left 725 * hand side of an assignment, which do write masking. See ir_assignment 726 * for that. 727 */ 728 729 ir->val->accept(this); 730 src_reg = this->result; 731 assert(src_reg.file != PROGRAM_UNDEFINED); 732 733 for (i = 0; i < 4; i++) { 734 if (i < ir->type->vector_elements) { 735 switch (i) { 736 case 0: 737 swizzle[i] = ir->mask.x; 738 break; 739 case 1: 740 swizzle[i] = ir->mask.y; 741 break; 742 case 2: 743 swizzle[i] = ir->mask.z; 744 break; 745 case 3: 746 swizzle[i] = ir->mask.w; 747 break; 748 } 749 } else { 750 /* If the type is smaller than a vec4, replicate the last 751 * channel out. 752 */ 753 swizzle[i] = ir->type->vector_elements - 1; 754 } 755 } 756 757 src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], 758 swizzle[1], 759 swizzle[2], 760 swizzle[3]); 761 762 this->result = src_reg; 763} 764 765static temp_entry * 766get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var) 767{ 768 /* 769 * NOTE: The ARB_vertex_program extension specified that matrices get 770 * loaded in registers in row-major order. With GLSL, we want column- 771 * major order. So, we need to transpose all matrices here... 772 */ 773 static const struct { 774 const char *name; 775 int matrix; 776 int modifier; 777 } matrices[] = { 778 { "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE }, 779 { "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS }, 780 { "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 }, 781 { "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE }, 782 783 { "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE }, 784 { "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS }, 785 { "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 }, 786 { "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE }, 787 788 { "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE }, 789 { "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS }, 790 { "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 }, 791 { "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE }, 792 793 { "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE }, 794 { "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS }, 795 { "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 }, 796 { "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE }, 797 798 { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE }, 799 800 }; 801 unsigned int i; 802 temp_entry *entry; 803 804 /* C++ gets angry when we try to use an int as a gl_state_index, so we use 805 * ints for gl_state_index. Make sure they're compatible. 806 */ 807 assert(sizeof(gl_state_index) == sizeof(int)); 808 809 for (i = 0; i < Elements(matrices); i++) { 810 if (strcmp(var->name, matrices[i].name) == 0) { 811 int j; 812 int last_pos = -1, base_pos = -1; 813 int tokens[STATE_LENGTH]; 814 815 tokens[0] = matrices[i].matrix; 816 tokens[1] = 0; /* array index! */ 817 tokens[4] = matrices[i].modifier; 818 819 /* Add a ref for each column. It looks like the reason we do 820 * it this way is that _mesa_add_state_reference doesn't work 821 * for things that aren't vec4s, so the tokens[2]/tokens[3] 822 * range has to be equal. 823 */ 824 for (j = 0; j < 4; j++) { 825 tokens[2] = j; 826 tokens[3] = j; 827 int pos = _mesa_add_state_reference(prog->Parameters, 828 (gl_state_index *)tokens); 829 assert(last_pos == -1 || last_pos == base_pos + j); 830 if (base_pos == -1) 831 base_pos = pos; 832 } 833 834 entry = new(mem_ctx) temp_entry(var, 835 PROGRAM_STATE_VAR, 836 base_pos); 837 838 return entry; 839 } 840 } 841 842 return NULL; 843} 844 845void 846ir_to_mesa_visitor::visit(ir_dereference_variable *ir) 847{ 848 ir_to_mesa_src_reg src_reg; 849 temp_entry *entry = find_variable_storage(ir->var); 850 unsigned int i, loc; 851 bool var_in; 852 853 if (!entry) { 854 switch (ir->var->mode) { 855 case ir_var_uniform: 856 entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, ir->var); 857 if (entry) 858 break; 859 860 /* FINISHME: Fix up uniform name for arrays and things */ 861 assert(ir->var->type->gl_type != 0 && 862 ir->var->type->gl_type != GL_INVALID_ENUM); 863 loc = _mesa_add_uniform(this->prog->Parameters, 864 ir->var->name, 865 type_size(ir->var->type) * 4, 866 ir->var->type->gl_type, 867 NULL); 868 /* Always mark the uniform used at this point. If it isn't 869 * used, dead code elimination should have nuked the decl already. 870 */ 871 this->prog->Parameters->Parameters[loc].Used = GL_TRUE; 872 873 entry = new(mem_ctx) temp_entry(ir->var, PROGRAM_UNIFORM, loc); 874 this->variable_storage.push_tail(entry); 875 break; 876 case ir_var_in: 877 case ir_var_out: 878 case ir_var_inout: 879 var_in = (ir->var->mode == ir_var_in || 880 ir->var->mode == ir_var_inout); 881 882 for (i = 0; i < ARRAY_SIZE(builtin_var_to_mesa_reg); i++) { 883 bool in = builtin_var_to_mesa_reg[i].file == PROGRAM_INPUT; 884 885 if (strcmp(ir->var->name, builtin_var_to_mesa_reg[i].name) == 0 && 886 !(var_in ^ in)) 887 break; 888 } 889 if (i == ARRAY_SIZE(builtin_var_to_mesa_reg)) { 890 printf("Failed to find builtin for %s variable %s\n", 891 var_in ? "in" : "out", 892 ir->var->name); 893 abort(); 894 } 895 entry = new(mem_ctx) temp_entry(ir->var, 896 builtin_var_to_mesa_reg[i].file, 897 builtin_var_to_mesa_reg[i].index); 898 break; 899 case ir_var_auto: 900 entry = new(mem_ctx) temp_entry(ir->var, PROGRAM_TEMPORARY, 901 this->next_temp); 902 this->variable_storage.push_tail(entry); 903 904 next_temp += type_size(ir->var->type); 905 break; 906 } 907 908 if (!entry) { 909 printf("Failed to make storage for %s\n", ir->var->name); 910 exit(1); 911 } 912 } 913 914 src_reg.file = entry->file; 915 src_reg.index = entry->index; 916 /* If the type is smaller than a vec4, replicate the last channel out. */ 917 src_reg.swizzle = swizzle_for_size(ir->var->type->vector_elements); 918 src_reg.reladdr = false; 919 src_reg.negate = 0; 920 921 this->result = src_reg; 922} 923 924void 925ir_to_mesa_visitor::visit(ir_dereference_array *ir) 926{ 927 ir_constant *index; 928 ir_to_mesa_src_reg src_reg; 929 930 index = ir->array_index->constant_expression_value(); 931 932 /* By the time we make it to this stage, matrices should be broken down 933 * to vectors. 934 */ 935 assert(!ir->type->is_matrix()); 936 937 ir->array->accept(this); 938 src_reg = this->result; 939 940 if (src_reg.file == PROGRAM_INPUT || 941 src_reg.file == PROGRAM_OUTPUT) { 942 assert(index); /* FINISHME: Handle variable indexing of builtins. */ 943 944 src_reg.index += index->value.i[0]; 945 } else { 946 if (index) { 947 src_reg.index += index->value.i[0]; 948 } else { 949 ir_to_mesa_src_reg array_base = this->result; 950 /* Variable index array dereference. It eats the "vec4" of the 951 * base of the array and an index that offsets the Mesa register 952 * index. 953 */ 954 ir->array_index->accept(this); 955 956 /* FINISHME: This doesn't work when we're trying to do the LHS 957 * of an assignment. 958 */ 959 src_reg.reladdr = true; 960 ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg, 961 this->result); 962 963 this->result = get_temp(ir->type); 964 ir_to_mesa_emit_op1(ir, OPCODE_MOV, 965 ir_to_mesa_dst_reg_from_src(this->result), 966 src_reg); 967 } 968 } 969 970 /* If the type is smaller than a vec4, replicate the last channel out. */ 971 src_reg.swizzle = swizzle_for_size(ir->type->vector_elements); 972 973 this->result = src_reg; 974} 975 976void 977ir_to_mesa_visitor::visit(ir_dereference_record *ir) 978{ 979 unsigned int i; 980 const glsl_type *struct_type = ir->record->type; 981 int offset = 0; 982 983 ir->record->accept(this); 984 985 for (i = 0; i < struct_type->length; i++) { 986 if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0) 987 break; 988 offset += type_size(struct_type->fields.structure[i].type); 989 } 990 this->result.index += offset; 991} 992 993/** 994 * We want to be careful in assignment setup to hit the actual storage 995 * instead of potentially using a temporary like we might with the 996 * ir_dereference handler. 997 * 998 * Thanks to ir_swizzle_swizzle, and ir_vec_index_to_swizzle, we 999 * should only see potentially one variable array index of a vector, 1000 * and one swizzle, before getting to actual vec4 storage. So handle 1001 * those, then go use ir_dereference to handle the rest. 1002 */ 1003static struct ir_to_mesa_dst_reg 1004get_assignment_lhs(ir_instruction *ir, ir_to_mesa_visitor *v) 1005{ 1006 struct ir_to_mesa_dst_reg dst_reg; 1007 ir_dereference *deref; 1008 ir_swizzle *swiz; 1009 1010 /* Use the rvalue deref handler for the most part. We'll ignore 1011 * swizzles in it and write swizzles using writemask, though. 1012 */ 1013 ir->accept(v); 1014 dst_reg = ir_to_mesa_dst_reg_from_src(v->result); 1015 1016 if ((deref = ir->as_dereference())) { 1017 ir_dereference_array *deref_array = ir->as_dereference_array(); 1018 assert(!deref_array || deref_array->array->type->is_array()); 1019 1020 ir->accept(v); 1021 } else if ((swiz = ir->as_swizzle())) { 1022 dst_reg.writemask = 0; 1023 if (swiz->mask.num_components >= 1) 1024 dst_reg.writemask |= (1 << swiz->mask.x); 1025 if (swiz->mask.num_components >= 2) 1026 dst_reg.writemask |= (1 << swiz->mask.y); 1027 if (swiz->mask.num_components >= 3) 1028 dst_reg.writemask |= (1 << swiz->mask.z); 1029 if (swiz->mask.num_components >= 4) 1030 dst_reg.writemask |= (1 << swiz->mask.w); 1031 } 1032 1033 return dst_reg; 1034} 1035 1036void 1037ir_to_mesa_visitor::visit(ir_assignment *ir) 1038{ 1039 struct ir_to_mesa_dst_reg l; 1040 struct ir_to_mesa_src_reg r; 1041 1042 assert(!ir->lhs->type->is_matrix()); 1043 assert(!ir->lhs->type->is_array()); 1044 assert(ir->lhs->type->base_type != GLSL_TYPE_STRUCT); 1045 1046 l = get_assignment_lhs(ir->lhs, this); 1047 1048 ir->rhs->accept(this); 1049 r = this->result; 1050 assert(l.file != PROGRAM_UNDEFINED); 1051 assert(r.file != PROGRAM_UNDEFINED); 1052 1053 if (ir->condition) { 1054 ir_constant *condition_constant; 1055 1056 condition_constant = ir->condition->constant_expression_value(); 1057 1058 assert(condition_constant && condition_constant->value.b[0]); 1059 } 1060 1061 ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r); 1062} 1063 1064 1065void 1066ir_to_mesa_visitor::visit(ir_constant *ir) 1067{ 1068 ir_to_mesa_src_reg src_reg; 1069 GLfloat stack_vals[4]; 1070 GLfloat *values = stack_vals; 1071 unsigned int i; 1072 1073 if (ir->type->is_matrix() || ir->type->is_array()) { 1074 assert(!"FINISHME: array/matrix constants"); 1075 } 1076 1077 src_reg.file = PROGRAM_CONSTANT; 1078 switch (ir->type->base_type) { 1079 case GLSL_TYPE_FLOAT: 1080 values = &ir->value.f[0]; 1081 break; 1082 case GLSL_TYPE_UINT: 1083 for (i = 0; i < ir->type->vector_elements; i++) { 1084 values[i] = ir->value.u[i]; 1085 } 1086 break; 1087 case GLSL_TYPE_INT: 1088 for (i = 0; i < ir->type->vector_elements; i++) { 1089 values[i] = ir->value.i[i]; 1090 } 1091 break; 1092 case GLSL_TYPE_BOOL: 1093 for (i = 0; i < ir->type->vector_elements; i++) { 1094 values[i] = ir->value.b[i]; 1095 } 1096 break; 1097 default: 1098 assert(!"Non-float/uint/int/bool constant"); 1099 } 1100 1101 src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters, 1102 values, ir->type->vector_elements, 1103 &src_reg.swizzle); 1104 src_reg.reladdr = false; 1105 src_reg.negate = 0; 1106 1107 this->result = src_reg; 1108} 1109 1110 1111void 1112ir_to_mesa_visitor::visit(ir_call *ir) 1113{ 1114 printf("Can't support call to %s\n", ir->callee_name()); 1115 exit(1); 1116} 1117 1118 1119void 1120ir_to_mesa_visitor::visit(ir_texture *ir) 1121{ 1122 assert(0); 1123 1124 ir->coordinate->accept(this); 1125} 1126 1127void 1128ir_to_mesa_visitor::visit(ir_return *ir) 1129{ 1130 assert(0); 1131 1132 ir->get_value()->accept(this); 1133} 1134 1135 1136void 1137ir_to_mesa_visitor::visit(ir_if *ir) 1138{ 1139 ir_to_mesa_instruction *if_inst, *else_inst = NULL; 1140 1141 ir->condition->accept(this); 1142 assert(this->result.file != PROGRAM_UNDEFINED); 1143 1144 if_inst = ir_to_mesa_emit_op1(ir->condition, 1145 OPCODE_IF, ir_to_mesa_undef_dst, 1146 this->result); 1147 1148 this->instructions.push_tail(if_inst); 1149 1150 visit_exec_list(&ir->then_instructions, this); 1151 1152 if (!ir->else_instructions.is_empty()) { 1153 else_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_ELSE, 1154 ir_to_mesa_undef_dst, 1155 ir_to_mesa_undef); 1156 visit_exec_list(&ir->then_instructions, this); 1157 } 1158 1159 if_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_ENDIF, 1160 ir_to_mesa_undef_dst, ir_to_mesa_undef); 1161} 1162 1163ir_to_mesa_visitor::ir_to_mesa_visitor() 1164{ 1165 result.file = PROGRAM_UNDEFINED; 1166 next_temp = 1; 1167} 1168 1169static struct prog_src_register 1170mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg) 1171{ 1172 struct prog_src_register mesa_reg; 1173 1174 mesa_reg.File = reg.file; 1175 assert(reg.index < (1 << INST_INDEX_BITS) - 1); 1176 mesa_reg.Index = reg.index; 1177 mesa_reg.Swizzle = reg.swizzle; 1178 mesa_reg.RelAddr = reg.reladdr; 1179 1180 return mesa_reg; 1181} 1182 1183static void 1184set_branchtargets(struct prog_instruction *mesa_instructions, 1185 int num_instructions) 1186{ 1187 int if_count = 0, loop_count; 1188 int *if_stack, *loop_stack; 1189 int if_stack_pos = 0, loop_stack_pos = 0; 1190 int i, j; 1191 1192 for (i = 0; i < num_instructions; i++) { 1193 switch (mesa_instructions[i].Opcode) { 1194 case OPCODE_IF: 1195 if_count++; 1196 break; 1197 case OPCODE_BGNLOOP: 1198 loop_count++; 1199 break; 1200 case OPCODE_BRK: 1201 case OPCODE_CONT: 1202 mesa_instructions[i].BranchTarget = -1; 1203 break; 1204 default: 1205 break; 1206 } 1207 } 1208 1209 if_stack = (int *)calloc(if_count, sizeof(*if_stack)); 1210 loop_stack = (int *)calloc(loop_count, sizeof(*loop_stack)); 1211 1212 for (i = 0; i < num_instructions; i++) { 1213 switch (mesa_instructions[i].Opcode) { 1214 case OPCODE_IF: 1215 if_stack[if_stack_pos] = i; 1216 if_stack_pos++; 1217 break; 1218 case OPCODE_ELSE: 1219 mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i; 1220 if_stack[if_stack_pos - 1] = i; 1221 break; 1222 case OPCODE_ENDIF: 1223 mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i; 1224 if_stack_pos--; 1225 break; 1226 case OPCODE_BGNLOOP: 1227 loop_stack[loop_stack_pos] = i; 1228 loop_stack_pos++; 1229 break; 1230 case OPCODE_ENDLOOP: 1231 loop_stack_pos--; 1232 /* Rewrite any breaks/conts at this nesting level (haven't 1233 * already had a BranchTarget assigned) to point to the end 1234 * of the loop. 1235 */ 1236 for (j = loop_stack[loop_stack_pos]; j < i; j++) { 1237 if (mesa_instructions[j].Opcode == OPCODE_BRK || 1238 mesa_instructions[j].Opcode == OPCODE_CONT) { 1239 if (mesa_instructions[j].BranchTarget == -1) { 1240 mesa_instructions[j].BranchTarget = i; 1241 } 1242 } 1243 } 1244 /* The loop ends point at each other. */ 1245 mesa_instructions[i].BranchTarget = loop_stack[loop_stack_pos]; 1246 mesa_instructions[loop_stack[loop_stack_pos]].BranchTarget = i; 1247 default: 1248 break; 1249 } 1250 } 1251 1252 free(if_stack); 1253} 1254 1255static void 1256print_program(struct prog_instruction *mesa_instructions, 1257 ir_instruction **mesa_instruction_annotation, 1258 int num_instructions) 1259{ 1260 ir_instruction *last_ir = NULL; 1261 int i; 1262 1263 for (i = 0; i < num_instructions; i++) { 1264 struct prog_instruction *mesa_inst = mesa_instructions + i; 1265 ir_instruction *ir = mesa_instruction_annotation[i]; 1266 1267 if (last_ir != ir && ir) { 1268 ir_print_visitor print; 1269 ir->accept(&print); 1270 printf("\n"); 1271 last_ir = ir; 1272 } 1273 1274 _mesa_print_instruction(mesa_inst); 1275 } 1276} 1277 1278static void 1279count_resources(struct gl_program *prog) 1280{ 1281 prog->InputsRead = 0; 1282 prog->OutputsWritten = 0; 1283 unsigned int i; 1284 1285 for (i = 0; i < prog->NumInstructions; i++) { 1286 struct prog_instruction *inst = &prog->Instructions[i]; 1287 unsigned int reg; 1288 1289 switch (inst->DstReg.File) { 1290 case PROGRAM_OUTPUT: 1291 prog->OutputsWritten |= BITFIELD64_BIT(inst->DstReg.Index); 1292 break; 1293 case PROGRAM_INPUT: 1294 prog->InputsRead |= BITFIELD64_BIT(inst->DstReg.Index); 1295 break; 1296 default: 1297 break; 1298 } 1299 1300 for (reg = 0; reg < _mesa_num_inst_src_regs(inst->Opcode); reg++) { 1301 switch (inst->SrcReg[reg].File) { 1302 case PROGRAM_OUTPUT: 1303 prog->OutputsWritten |= BITFIELD64_BIT(inst->SrcReg[reg].Index); 1304 break; 1305 case PROGRAM_INPUT: 1306 prog->InputsRead |= BITFIELD64_BIT(inst->SrcReg[reg].Index); 1307 break; 1308 default: 1309 break; 1310 } 1311 } 1312 } 1313} 1314 1315/* Each stage has some uniforms in its Parameters list. The Uniforms 1316 * list for the linked shader program has a pointer to these uniforms 1317 * in each of the stage's Parameters list, so that their values can be 1318 * updated when a uniform is set. 1319 */ 1320static void 1321link_uniforms_to_shared_uniform_list(struct gl_uniform_list *uniforms, 1322 struct gl_program *prog) 1323{ 1324 unsigned int i; 1325 1326 for (i = 0; i < prog->Parameters->NumParameters; i++) { 1327 const struct gl_program_parameter *p = prog->Parameters->Parameters + i; 1328 1329 if (p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER) { 1330 struct gl_uniform *uniform = 1331 _mesa_append_uniform(uniforms, p->Name, prog->Target, i); 1332 if (uniform) 1333 uniform->Initialized = p->Initialized; 1334 } 1335 } 1336} 1337 1338struct gl_program * 1339get_mesa_program(GLcontext *ctx, void *mem_ctx, struct glsl_shader *shader) 1340{ 1341 ir_to_mesa_visitor v; 1342 struct prog_instruction *mesa_instructions, *mesa_inst; 1343 ir_instruction **mesa_instruction_annotation; 1344 int i; 1345 exec_list *instructions = &shader->ir; 1346 struct gl_program *prog; 1347 GLenum target; 1348 1349 switch (shader->Type) { 1350 case GL_VERTEX_SHADER: target = GL_VERTEX_PROGRAM_ARB; break; 1351 case GL_FRAGMENT_SHADER: target = GL_FRAGMENT_PROGRAM_ARB; break; 1352 default: assert(!"should not be reached"); break; 1353 } 1354 1355 prog = ctx->Driver.NewProgram(ctx, target, 1); 1356 if (!prog) 1357 return NULL; 1358 prog->Parameters = _mesa_new_parameter_list(); 1359 prog->Varying = _mesa_new_parameter_list(); 1360 prog->Attributes = _mesa_new_parameter_list(); 1361 v.ctx = ctx; 1362 v.prog = prog; 1363 1364 v.mem_ctx = talloc_new(NULL); 1365 visit_exec_list(instructions, &v); 1366 v.ir_to_mesa_emit_op1(NULL, OPCODE_END, 1367 ir_to_mesa_undef_dst, ir_to_mesa_undef); 1368 1369 prog->NumTemporaries = v.next_temp; 1370 1371 int num_instructions = 0; 1372 foreach_iter(exec_list_iterator, iter, v.instructions) { 1373 num_instructions++; 1374 } 1375 1376 mesa_instructions = 1377 (struct prog_instruction *)calloc(num_instructions, 1378 sizeof(*mesa_instructions)); 1379 mesa_instruction_annotation = talloc_array(mem_ctx, ir_instruction *, 1380 num_instructions); 1381 1382 mesa_inst = mesa_instructions; 1383 i = 0; 1384 foreach_iter(exec_list_iterator, iter, v.instructions) { 1385 ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get(); 1386 1387 mesa_inst->Opcode = inst->op; 1388 mesa_inst->DstReg.File = inst->dst_reg.file; 1389 mesa_inst->DstReg.Index = inst->dst_reg.index; 1390 mesa_inst->DstReg.CondMask = COND_TR; 1391 mesa_inst->DstReg.WriteMask = inst->dst_reg.writemask; 1392 mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src_reg[0]); 1393 mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src_reg[1]); 1394 mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src_reg[2]); 1395 mesa_instruction_annotation[i] = inst->ir; 1396 1397 mesa_inst++; 1398 i++; 1399 } 1400 1401 set_branchtargets(mesa_instructions, num_instructions); 1402 if (0) { 1403 print_program(mesa_instructions, mesa_instruction_annotation, 1404 num_instructions); 1405 } 1406 1407 prog->Instructions = mesa_instructions; 1408 prog->NumInstructions = num_instructions; 1409 1410 _mesa_reference_program(ctx, &shader->mesa_shader->Program, prog); 1411 1412 return prog; 1413} 1414 1415/* Takes a Mesa gl shader structure and compiles it, returning our Mesa-like 1416 * structure with the IR and such attached. 1417 */ 1418static struct glsl_shader * 1419_mesa_get_glsl_shader(GLcontext *ctx, void *mem_ctx, struct gl_shader *sh) 1420{ 1421 struct glsl_shader *shader = talloc_zero(mem_ctx, struct glsl_shader); 1422 struct _mesa_glsl_parse_state *state; 1423 1424 shader->Type = sh->Type; 1425 shader->Name = sh->Name; 1426 shader->RefCount = 1; 1427 shader->Source = sh->Source; 1428 shader->SourceLen = strlen(sh->Source); 1429 shader->mesa_shader = sh; 1430 1431 state = talloc_zero(shader, struct _mesa_glsl_parse_state); 1432 switch (shader->Type) { 1433 case GL_VERTEX_SHADER: state->target = vertex_shader; break; 1434 case GL_FRAGMENT_SHADER: state->target = fragment_shader; break; 1435 case GL_GEOMETRY_SHADER: state->target = geometry_shader; break; 1436 } 1437 1438 state->scanner = NULL; 1439 state->translation_unit.make_empty(); 1440 state->symbols = new(mem_ctx) glsl_symbol_table; 1441 state->info_log = talloc_strdup(shader, ""); 1442 state->error = false; 1443 state->temp_index = 0; 1444 state->loop_or_switch_nesting = NULL; 1445 state->ARB_texture_rectangle_enable = true; 1446 1447 _mesa_glsl_lexer_ctor(state, shader->Source); 1448 _mesa_glsl_parse(state); 1449 _mesa_glsl_lexer_dtor(state); 1450 1451 shader->ir.make_empty(); 1452 if (!state->error && !state->translation_unit.is_empty()) 1453 _mesa_ast_to_hir(&shader->ir, state); 1454 1455 /* Optimization passes */ 1456 if (!state->error && !shader->ir.is_empty()) { 1457 bool progress; 1458 do { 1459 progress = false; 1460 1461 progress = do_function_inlining(&shader->ir) || progress; 1462 progress = do_if_simplification(&shader->ir) || progress; 1463 progress = do_copy_propagation(&shader->ir) || progress; 1464 progress = do_dead_code_local(&shader->ir) || progress; 1465 progress = do_dead_code_unlinked(state, &shader->ir) || progress; 1466 progress = do_constant_variable_unlinked(&shader->ir) || progress; 1467 progress = do_constant_folding(&shader->ir) || progress; 1468 progress = do_vec_index_to_swizzle(&shader->ir) || progress; 1469 progress = do_swizzle_swizzle(&shader->ir) || progress; 1470 } while (progress); 1471 } 1472 1473 shader->symbols = state->symbols; 1474 1475 shader->CompileStatus = !state->error; 1476 shader->InfoLog = state->info_log; 1477 1478 talloc_free(state); 1479 1480 return shader; 1481} 1482 1483extern "C" { 1484 1485void 1486_mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *sh) 1487{ 1488 struct glsl_shader *shader; 1489 TALLOC_CTX *mem_ctx = talloc_new(NULL); 1490 1491 shader = _mesa_get_glsl_shader(ctx, mem_ctx, sh); 1492 1493 sh->CompileStatus = shader->CompileStatus; 1494 sh->InfoLog = strdup(shader->InfoLog); 1495 talloc_free(mem_ctx); 1496 } 1497 1498void 1499_mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) 1500{ 1501 struct glsl_program *whole_program; 1502 unsigned int i; 1503 1504 _mesa_clear_shader_program_data(ctx, prog); 1505 1506 whole_program = talloc_zero(NULL, struct glsl_program); 1507 whole_program->LinkStatus = GL_TRUE; 1508 whole_program->NumShaders = prog->NumShaders; 1509 whole_program->Shaders = talloc_array(whole_program, struct glsl_shader *, 1510 prog->NumShaders); 1511 1512 for (i = 0; i < prog->NumShaders; i++) { 1513 whole_program->Shaders[i] = _mesa_get_glsl_shader(ctx, whole_program, 1514 prog->Shaders[i]); 1515 if (!whole_program->Shaders[i]->CompileStatus) { 1516 whole_program->InfoLog = 1517 talloc_asprintf_append(whole_program->InfoLog, 1518 "linking with uncompiled shader"); 1519 whole_program->LinkStatus = GL_FALSE; 1520 } 1521 } 1522 1523 prog->Uniforms = _mesa_new_uniform_list(); 1524 prog->Varying = _mesa_new_parameter_list(); 1525 _mesa_reference_vertprog(ctx, &prog->VertexProgram, NULL); 1526 _mesa_reference_fragprog(ctx, &prog->FragmentProgram, NULL); 1527 1528 if (whole_program->LinkStatus) 1529 link_shaders(whole_program); 1530 1531 prog->LinkStatus = whole_program->LinkStatus; 1532 1533 /* FINISHME: This should use the linker-generated code */ 1534 if (prog->LinkStatus) { 1535 for (i = 0; i < prog->NumShaders; i++) { 1536 struct gl_program *linked_prog; 1537 1538 linked_prog = get_mesa_program(ctx, whole_program, 1539 whole_program->Shaders[i]); 1540 count_resources(linked_prog); 1541 1542 link_uniforms_to_shared_uniform_list(prog->Uniforms, linked_prog); 1543 1544 switch (whole_program->Shaders[i]->Type) { 1545 case GL_VERTEX_SHADER: 1546 _mesa_reference_vertprog(ctx, &prog->VertexProgram, 1547 (struct gl_vertex_program *)linked_prog); 1548 break; 1549 case GL_FRAGMENT_SHADER: 1550 _mesa_reference_fragprog(ctx, &prog->FragmentProgram, 1551 (struct gl_fragment_program *)linked_prog); 1552 break; 1553 } 1554 } 1555 } 1556 1557 talloc_free(whole_program); 1558} 1559 1560} /* extern "C" */ 1561