14c1403f667c6047a44ff494364725b3b7da82c68Brian/************************************************************************** 24c1403f667c6047a44ff494364725b3b7da82c68Brian * 34c1403f667c6047a44ff494364725b3b7da82c68Brian * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 44c1403f667c6047a44ff494364725b3b7da82c68Brian * All Rights Reserved. 54c1403f667c6047a44ff494364725b3b7da82c68Brian * 64c1403f667c6047a44ff494364725b3b7da82c68Brian * Permission is hereby granted, free of charge, to any person obtaining a 74c1403f667c6047a44ff494364725b3b7da82c68Brian * copy of this software and associated documentation files (the 84c1403f667c6047a44ff494364725b3b7da82c68Brian * "Software"), to deal in the Software without restriction, including 94c1403f667c6047a44ff494364725b3b7da82c68Brian * without limitation the rights to use, copy, modify, merge, publish, 104c1403f667c6047a44ff494364725b3b7da82c68Brian * distribute, sub license, and/or sell copies of the Software, and to 114c1403f667c6047a44ff494364725b3b7da82c68Brian * permit persons to whom the Software is furnished to do so, subject to 124c1403f667c6047a44ff494364725b3b7da82c68Brian * the following conditions: 134c1403f667c6047a44ff494364725b3b7da82c68Brian * 144c1403f667c6047a44ff494364725b3b7da82c68Brian * The above copyright notice and this permission notice (including the 154c1403f667c6047a44ff494364725b3b7da82c68Brian * next paragraph) shall be included in all copies or substantial portions 164c1403f667c6047a44ff494364725b3b7da82c68Brian * of the Software. 174c1403f667c6047a44ff494364725b3b7da82c68Brian * 184c1403f667c6047a44ff494364725b3b7da82c68Brian * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194c1403f667c6047a44ff494364725b3b7da82c68Brian * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 204c1403f667c6047a44ff494364725b3b7da82c68Brian * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 214c1403f667c6047a44ff494364725b3b7da82c68Brian * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 224c1403f667c6047a44ff494364725b3b7da82c68Brian * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 234c1403f667c6047a44ff494364725b3b7da82c68Brian * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 244c1403f667c6047a44ff494364725b3b7da82c68Brian * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 254c1403f667c6047a44ff494364725b3b7da82c68Brian * 264c1403f667c6047a44ff494364725b3b7da82c68Brian **************************************************************************/ 274c1403f667c6047a44ff494364725b3b7da82c68Brian 284c1403f667c6047a44ff494364725b3b7da82c68Brian/** 294c1403f667c6047a44ff494364725b3b7da82c68Brian * TGSI program transformation utility. 304c1403f667c6047a44ff494364725b3b7da82c68Brian * 314c1403f667c6047a44ff494364725b3b7da82c68Brian * Authors: Brian Paul 324c1403f667c6047a44ff494364725b3b7da82c68Brian */ 334c1403f667c6047a44ff494364725b3b7da82c68Brian 34ea4bf267e4b023b08043f91ac44592fed1736e7fJosé Fonseca#include "util/u_debug.h" 354c1403f667c6047a44ff494364725b3b7da82c68Brian 364c1403f667c6047a44ff494364725b3b7da82c68Brian#include "tgsi_transform.h" 374c1403f667c6047a44ff494364725b3b7da82c68Brian 384c1403f667c6047a44ff494364725b3b7da82c68Brian 394c1403f667c6047a44ff494364725b3b7da82c68Brian 404c1403f667c6047a44ff494364725b3b7da82c68Brianstatic void 414c1403f667c6047a44ff494364725b3b7da82c68Brianemit_instruction(struct tgsi_transform_context *ctx, 424c1403f667c6047a44ff494364725b3b7da82c68Brian const struct tgsi_full_instruction *inst) 434c1403f667c6047a44ff494364725b3b7da82c68Brian{ 444c1403f667c6047a44ff494364725b3b7da82c68Brian uint ti = ctx->ti; 454c1403f667c6047a44ff494364725b3b7da82c68Brian 464c1403f667c6047a44ff494364725b3b7da82c68Brian ti += tgsi_build_full_instruction(inst, 474c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->tokens_out + ti, 484c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->header, 494c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->max_tokens_out - ti); 504c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->ti = ti; 514c1403f667c6047a44ff494364725b3b7da82c68Brian} 524c1403f667c6047a44ff494364725b3b7da82c68Brian 534c1403f667c6047a44ff494364725b3b7da82c68Brian 544c1403f667c6047a44ff494364725b3b7da82c68Brianstatic void 554c1403f667c6047a44ff494364725b3b7da82c68Brianemit_declaration(struct tgsi_transform_context *ctx, 564c1403f667c6047a44ff494364725b3b7da82c68Brian const struct tgsi_full_declaration *decl) 574c1403f667c6047a44ff494364725b3b7da82c68Brian{ 584c1403f667c6047a44ff494364725b3b7da82c68Brian uint ti = ctx->ti; 594c1403f667c6047a44ff494364725b3b7da82c68Brian 604c1403f667c6047a44ff494364725b3b7da82c68Brian ti += tgsi_build_full_declaration(decl, 614c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->tokens_out + ti, 624c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->header, 634c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->max_tokens_out - ti); 644c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->ti = ti; 654c1403f667c6047a44ff494364725b3b7da82c68Brian} 664c1403f667c6047a44ff494364725b3b7da82c68Brian 674c1403f667c6047a44ff494364725b3b7da82c68Brian 684c1403f667c6047a44ff494364725b3b7da82c68Brianstatic void 694c1403f667c6047a44ff494364725b3b7da82c68Brianemit_immediate(struct tgsi_transform_context *ctx, 704c1403f667c6047a44ff494364725b3b7da82c68Brian const struct tgsi_full_immediate *imm) 714c1403f667c6047a44ff494364725b3b7da82c68Brian{ 724c1403f667c6047a44ff494364725b3b7da82c68Brian uint ti = ctx->ti; 734c1403f667c6047a44ff494364725b3b7da82c68Brian 744c1403f667c6047a44ff494364725b3b7da82c68Brian ti += tgsi_build_full_immediate(imm, 754c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->tokens_out + ti, 764c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->header, 774c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->max_tokens_out - ti); 784c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->ti = ti; 794c1403f667c6047a44ff494364725b3b7da82c68Brian} 804c1403f667c6047a44ff494364725b3b7da82c68Brian 814c1403f667c6047a44ff494364725b3b7da82c68Brian 823ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusinstatic void 833ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusinemit_property(struct tgsi_transform_context *ctx, 843ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin const struct tgsi_full_property *prop) 853ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin{ 863ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin uint ti = ctx->ti; 873ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin 883ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin ti += tgsi_build_full_property(prop, 893ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin ctx->tokens_out + ti, 903ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin ctx->header, 913ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin ctx->max_tokens_out - ti); 923ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin ctx->ti = ti; 933ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin} 943ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin 954c1403f667c6047a44ff494364725b3b7da82c68Brian 964c1403f667c6047a44ff494364725b3b7da82c68Brian/** 974c1403f667c6047a44ff494364725b3b7da82c68Brian * Apply user-defined transformations to the input shader to produce 984c1403f667c6047a44ff494364725b3b7da82c68Brian * the output shader. 994c1403f667c6047a44ff494364725b3b7da82c68Brian * For example, a register search-and-replace operation could be applied 1004c1403f667c6047a44ff494364725b3b7da82c68Brian * by defining a transform_instruction() callback that examined and changed 1014c1403f667c6047a44ff494364725b3b7da82c68Brian * the instruction src/dest regs. 1024c1403f667c6047a44ff494364725b3b7da82c68Brian * 1034c1403f667c6047a44ff494364725b3b7da82c68Brian * \return number of tokens emitted 1044c1403f667c6047a44ff494364725b3b7da82c68Brian */ 1054c1403f667c6047a44ff494364725b3b7da82c68Brianint 1064c1403f667c6047a44ff494364725b3b7da82c68Briantgsi_transform_shader(const struct tgsi_token *tokens_in, 1074c1403f667c6047a44ff494364725b3b7da82c68Brian struct tgsi_token *tokens_out, 1084c1403f667c6047a44ff494364725b3b7da82c68Brian uint max_tokens_out, 1094c1403f667c6047a44ff494364725b3b7da82c68Brian struct tgsi_transform_context *ctx) 1104c1403f667c6047a44ff494364725b3b7da82c68Brian{ 1114c1403f667c6047a44ff494364725b3b7da82c68Brian uint procType; 1124c1403f667c6047a44ff494364725b3b7da82c68Brian 1134c1403f667c6047a44ff494364725b3b7da82c68Brian /* input shader */ 1144c1403f667c6047a44ff494364725b3b7da82c68Brian struct tgsi_parse_context parse; 1154c1403f667c6047a44ff494364725b3b7da82c68Brian 1164c1403f667c6047a44ff494364725b3b7da82c68Brian /* output shader */ 1174c1403f667c6047a44ff494364725b3b7da82c68Brian struct tgsi_processor *processor; 1184c1403f667c6047a44ff494364725b3b7da82c68Brian 1194c1403f667c6047a44ff494364725b3b7da82c68Brian 1204c1403f667c6047a44ff494364725b3b7da82c68Brian /** 1214c1403f667c6047a44ff494364725b3b7da82c68Brian ** callback context init 1224c1403f667c6047a44ff494364725b3b7da82c68Brian **/ 1234c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->emit_instruction = emit_instruction; 1244c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->emit_declaration = emit_declaration; 1254c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->emit_immediate = emit_immediate; 1263ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin ctx->emit_property = emit_property; 1274c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->tokens_out = tokens_out; 1284c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->max_tokens_out = max_tokens_out; 1294c1403f667c6047a44ff494364725b3b7da82c68Brian 1304c1403f667c6047a44ff494364725b3b7da82c68Brian 1314c1403f667c6047a44ff494364725b3b7da82c68Brian /** 1324c1403f667c6047a44ff494364725b3b7da82c68Brian ** Setup to begin parsing input shader 1334c1403f667c6047a44ff494364725b3b7da82c68Brian **/ 1344c1403f667c6047a44ff494364725b3b7da82c68Brian if (tgsi_parse_init( &parse, tokens_in ) != TGSI_PARSE_OK) { 1354c1403f667c6047a44ff494364725b3b7da82c68Brian debug_printf("tgsi_parse_init() failed in tgsi_transform_shader()!\n"); 1364c1403f667c6047a44ff494364725b3b7da82c68Brian return -1; 1374c1403f667c6047a44ff494364725b3b7da82c68Brian } 1384c1403f667c6047a44ff494364725b3b7da82c68Brian procType = parse.FullHeader.Processor.Processor; 1394c1403f667c6047a44ff494364725b3b7da82c68Brian assert(procType == TGSI_PROCESSOR_FRAGMENT || 1404c1403f667c6047a44ff494364725b3b7da82c68Brian procType == TGSI_PROCESSOR_VERTEX || 1414c1403f667c6047a44ff494364725b3b7da82c68Brian procType == TGSI_PROCESSOR_GEOMETRY); 1424c1403f667c6047a44ff494364725b3b7da82c68Brian 1434c1403f667c6047a44ff494364725b3b7da82c68Brian 1444c1403f667c6047a44ff494364725b3b7da82c68Brian /** 1454c1403f667c6047a44ff494364725b3b7da82c68Brian ** Setup output shader 1464c1403f667c6047a44ff494364725b3b7da82c68Brian **/ 147e6133564bf2e65fc86f626a45d7977bdeaff8579Michal Krol ctx->header = (struct tgsi_header *)tokens_out; 1484c1403f667c6047a44ff494364725b3b7da82c68Brian *ctx->header = tgsi_build_header(); 1494c1403f667c6047a44ff494364725b3b7da82c68Brian 150e6133564bf2e65fc86f626a45d7977bdeaff8579Michal Krol processor = (struct tgsi_processor *) (tokens_out + 1); 1514c1403f667c6047a44ff494364725b3b7da82c68Brian *processor = tgsi_build_processor( procType, ctx->header ); 1524c1403f667c6047a44ff494364725b3b7da82c68Brian 153e6133564bf2e65fc86f626a45d7977bdeaff8579Michal Krol ctx->ti = 2; 1544c1403f667c6047a44ff494364725b3b7da82c68Brian 1554c1403f667c6047a44ff494364725b3b7da82c68Brian 1564c1403f667c6047a44ff494364725b3b7da82c68Brian /** 1574c1403f667c6047a44ff494364725b3b7da82c68Brian ** Loop over incoming program tokens/instructions 1584c1403f667c6047a44ff494364725b3b7da82c68Brian */ 1594c1403f667c6047a44ff494364725b3b7da82c68Brian while( !tgsi_parse_end_of_tokens( &parse ) ) { 1604c1403f667c6047a44ff494364725b3b7da82c68Brian 1614c1403f667c6047a44ff494364725b3b7da82c68Brian tgsi_parse_token( &parse ); 1624c1403f667c6047a44ff494364725b3b7da82c68Brian 1634c1403f667c6047a44ff494364725b3b7da82c68Brian switch( parse.FullToken.Token.Type ) { 1644c1403f667c6047a44ff494364725b3b7da82c68Brian case TGSI_TOKEN_TYPE_INSTRUCTION: 1654c1403f667c6047a44ff494364725b3b7da82c68Brian { 1664c1403f667c6047a44ff494364725b3b7da82c68Brian struct tgsi_full_instruction *fullinst 1674c1403f667c6047a44ff494364725b3b7da82c68Brian = &parse.FullToken.FullInstruction; 1684c1403f667c6047a44ff494364725b3b7da82c68Brian 1694c1403f667c6047a44ff494364725b3b7da82c68Brian if (ctx->transform_instruction) 1704c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->transform_instruction(ctx, fullinst); 1714c1403f667c6047a44ff494364725b3b7da82c68Brian else 1724c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->emit_instruction(ctx, fullinst); 1734c1403f667c6047a44ff494364725b3b7da82c68Brian } 1744c1403f667c6047a44ff494364725b3b7da82c68Brian break; 1754c1403f667c6047a44ff494364725b3b7da82c68Brian 1764c1403f667c6047a44ff494364725b3b7da82c68Brian case TGSI_TOKEN_TYPE_DECLARATION: 1774c1403f667c6047a44ff494364725b3b7da82c68Brian { 1784c1403f667c6047a44ff494364725b3b7da82c68Brian struct tgsi_full_declaration *fulldecl 1794c1403f667c6047a44ff494364725b3b7da82c68Brian = &parse.FullToken.FullDeclaration; 1804c1403f667c6047a44ff494364725b3b7da82c68Brian 1814c1403f667c6047a44ff494364725b3b7da82c68Brian if (ctx->transform_declaration) 1824c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->transform_declaration(ctx, fulldecl); 1834c1403f667c6047a44ff494364725b3b7da82c68Brian else 1844c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->emit_declaration(ctx, fulldecl); 1854c1403f667c6047a44ff494364725b3b7da82c68Brian } 1864c1403f667c6047a44ff494364725b3b7da82c68Brian break; 1874c1403f667c6047a44ff494364725b3b7da82c68Brian 1884c1403f667c6047a44ff494364725b3b7da82c68Brian case TGSI_TOKEN_TYPE_IMMEDIATE: 1894c1403f667c6047a44ff494364725b3b7da82c68Brian { 1904c1403f667c6047a44ff494364725b3b7da82c68Brian struct tgsi_full_immediate *fullimm 1914c1403f667c6047a44ff494364725b3b7da82c68Brian = &parse.FullToken.FullImmediate; 1924c1403f667c6047a44ff494364725b3b7da82c68Brian 1934c1403f667c6047a44ff494364725b3b7da82c68Brian if (ctx->transform_immediate) 1944c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->transform_immediate(ctx, fullimm); 1954c1403f667c6047a44ff494364725b3b7da82c68Brian else 1964c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->emit_immediate(ctx, fullimm); 1974c1403f667c6047a44ff494364725b3b7da82c68Brian } 1984c1403f667c6047a44ff494364725b3b7da82c68Brian break; 1993ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin case TGSI_TOKEN_TYPE_PROPERTY: 2003ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin { 2013ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin struct tgsi_full_property *fullprop 2023ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin = &parse.FullToken.FullProperty; 2033ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin 2043ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin if (ctx->transform_property) 2053ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin ctx->transform_property(ctx, fullprop); 2063ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin else 2073ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin ctx->emit_property(ctx, fullprop); 2083ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin } 2093ff688ea299581e60caf5d6e1a464f68c717fe83Zack Rusin break; 2104c1403f667c6047a44ff494364725b3b7da82c68Brian 2114c1403f667c6047a44ff494364725b3b7da82c68Brian default: 2124c1403f667c6047a44ff494364725b3b7da82c68Brian assert( 0 ); 2134c1403f667c6047a44ff494364725b3b7da82c68Brian } 2144c1403f667c6047a44ff494364725b3b7da82c68Brian } 2154c1403f667c6047a44ff494364725b3b7da82c68Brian 2164c1403f667c6047a44ff494364725b3b7da82c68Brian if (ctx->epilog) { 2174c1403f667c6047a44ff494364725b3b7da82c68Brian ctx->epilog(ctx); 2184c1403f667c6047a44ff494364725b3b7da82c68Brian } 2194c1403f667c6047a44ff494364725b3b7da82c68Brian 2204c1403f667c6047a44ff494364725b3b7da82c68Brian tgsi_parse_free (&parse); 2214c1403f667c6047a44ff494364725b3b7da82c68Brian 2224c1403f667c6047a44ff494364725b3b7da82c68Brian return ctx->ti; 2234c1403f667c6047a44ff494364725b3b7da82c68Brian} 224b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell 225b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell 226b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell#include "tgsi_text.h" 227b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell 228b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwellextern int tgsi_transform_foo( struct tgsi_token *tokens_out, 229b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell uint max_tokens_out ); 230b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell 231b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell/* This function exists only so that tgsi_text_translate() doesn't get 232b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell * magic-ed out of the libtgsi.a archive by the build system. Don't 233b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell * remove unless you know this has been fixed - check on mingw/scons 234b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell * builds as well. 235b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell */ 236b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwellint 237b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwelltgsi_transform_foo( struct tgsi_token *tokens_out, 238b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell uint max_tokens_out ) 239b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell{ 240b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell const char *text = 241e6133564bf2e65fc86f626a45d7977bdeaff8579Michal Krol "FRAG\n" 242b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell "DCL IN[0], COLOR, CONSTANT\n" 243b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell "DCL OUT[0], COLOR\n" 244b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell " 0: MOV OUT[0], IN[0]\n" 245b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell " 1: END"; 246b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell 247b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell return tgsi_text_translate( text, 248b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell tokens_out, 249b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell max_tokens_out ); 250b865501bda8f2f99bfa8ee365aa4a3da64291e6eKeith Whitwell} 251