From a20d4773459b01e86acceac45240a2b4e88f67e3 Mon Sep 17 00:00:00 2001 From: sandeepchundru Date: Thu, 11 May 2017 15:10:50 +0530 Subject: [PATCH] Create AGALMiniAssembler.as Upload a new version of AGALMiniAssembler.as file to support Vertex Texture Fetch Support --- src/com/adobe/utils/v4/AGALMiniAssembler.as | 819 ++++++++++++++++++++ 1 file changed, 819 insertions(+) create mode 100644 src/com/adobe/utils/v4/AGALMiniAssembler.as diff --git a/src/com/adobe/utils/v4/AGALMiniAssembler.as b/src/com/adobe/utils/v4/AGALMiniAssembler.as new file mode 100644 index 0000000..a5871b0 --- /dev/null +++ b/src/com/adobe/utils/v4/AGALMiniAssembler.as @@ -0,0 +1,819 @@ +/* +Copyright (c) 2015, Adobe Systems Incorporated +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +* Neither the name of Adobe Systems Incorporated nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package com.adobe.utils +{ + // =========================================================================== + // Imports + // --------------------------------------------------------------------------- + import flash.display3D.*; + import flash.utils.*; + + // =========================================================================== + // Class + // --------------------------------------------------------------------------- + public class AGALMiniAssembler + { // ====================================================================== + // Constants + // ---------------------------------------------------------------------- + protected static const REGEXP_OUTER_SPACES:RegExp = /^\s+|\s+$/g; + + // ====================================================================== + // Properties + // ---------------------------------------------------------------------- + // AGAL bytes and error buffer + private var _agalcode:ByteArray = null; + private var _error:String = ""; + + private var debugEnabled:Boolean = false; + + private static var initialized:Boolean = false; + public var verbose:Boolean = false; + + // ====================================================================== + // Getters + // ---------------------------------------------------------------------- + public function get error():String { return _error; } + public function get agalcode():ByteArray { return _agalcode; } + + // ====================================================================== + // Constructor + // ---------------------------------------------------------------------- + public function AGALMiniAssembler( debugging:Boolean = false ):void + { + debugEnabled = debugging; + if ( !initialized ) + init(); + } + // ====================================================================== + // Methods + // ---------------------------------------------------------------------- + + public function assemble2( ctx3d : Context3D, version:uint, vertexsrc:String, fragmentsrc:String ) : Program3D + { + var agalvertex : ByteArray = assemble ( VERTEX, vertexsrc, version ); + var agalfragment : ByteArray = assemble ( FRAGMENT, fragmentsrc, version ); + var prog : Program3D = ctx3d.createProgram(); + prog.upload(agalvertex,agalfragment); + return prog; + } + + public function assemble( mode:String, source:String, version:uint=1, ignorelimits:Boolean=false ):ByteArray + { + var start:uint = getTimer(); + + _agalcode = new ByteArray(); + _error = ""; + + var isFrag:Boolean = false; + + if ( mode == FRAGMENT ) + isFrag = true; + else if ( mode != VERTEX ) + _error = 'ERROR: mode needs to be "' + FRAGMENT + '" or "' + VERTEX + '" but is "' + mode + '".'; + + agalcode.endian = Endian.LITTLE_ENDIAN; + agalcode.writeByte( 0xa0 ); // tag version + agalcode.writeUnsignedInt( version ); // AGAL version, big endian, bit pattern will be 0x01000000 + agalcode.writeByte( 0xa1 ); // tag program id + agalcode.writeByte( isFrag ? 1 : 0 ); // vertex or fragment + + initregmap(version, ignorelimits); + + var lines:Array = source.replace( /[\f\n\r\v]+/g, "\n" ).split( "\n" ); + var nest:int = 0; + var nops:int = 0; + var i:int; + var lng:int = lines.length; + + for ( i = 0; i < lng && _error == ""; i++ ) + { + var line:String = new String( lines[i] ); + line = line.replace( REGEXP_OUTER_SPACES, "" ); + + // remove comments + var startcomment:int = line.search( "//" ); + if ( startcomment != -1 ) + line = line.slice( 0, startcomment ); + + // grab options + var optsi:int = line.search( /<.*>/g ); + var opts:Array; + if ( optsi != -1 ) + { + opts = line.slice( optsi ).match( /([\w\.\-\+]+)/gi ); + line = line.slice( 0, optsi ); + } + + // find opcode + var opCode:Array = line.match( /^\w{3}/ig ); + if ( !opCode ) + { + if ( line.length >= 3 ) + trace( "warning: bad line "+i+": "+lines[i] ); + continue; + } + var opFound:OpCode = OPMAP[ opCode[0] ]; + + // if debug is enabled, output the opcodes + if ( debugEnabled ) + trace( opFound ); + + if ( opFound == null ) + { + if ( line.length >= 3 ) + trace( "warning: bad line "+i+": "+lines[i] ); + continue; + } + + line = line.slice( line.search( opFound.name ) + opFound.name.length ); + + if ( ( opFound.flags & OP_VERSION2 ) && version<2 ) + { + _error = "error: opcode requires version 2."; + break; + } + + if ( ( opFound.flags & OP_VERT_ONLY ) && isFrag ) + { + _error = "error: opcode is only allowed in vertex programs."; + break; + } + + if ( ( opFound.flags & OP_FRAG_ONLY ) && !isFrag ) + { + _error = "error: opcode is only allowed in fragment programs."; + break; + } + if ( verbose ) + trace( "emit opcode=" + opFound ); + + agalcode.writeUnsignedInt( opFound.emitCode ); + nops++; + + if ( nops > MAX_OPCODES ) + { + _error = "error: too many opcodes. maximum is "+MAX_OPCODES+"."; + break; + } + + // get operands, use regexp + var regs:Array; + + // will match both syntax + regs = line.match( /vc\[([vofi][acostdip]?[d]?)(\d*)?((\.[xyzw])?(\+\d{1,3})?)?\](\.[xyzw]{1,4})?|([vofi][acostdip]?[d]?)(\d*)?(\.[xyzw]{1,4})?/gi ); + + if ( !regs || regs.length != opFound.numRegister ) + { + _error = "error: wrong number of operands. found "+regs.length+" but expected "+opFound.numRegister+"."; + break; + } + + var badreg:Boolean = false; + var pad:uint = 64 + 64 + 32; + var regLength:uint = regs.length; + + for ( var j:int = 0; j < regLength; j++ ) + { + var isRelative:Boolean = false; + var relreg:Array = regs[ j ].match( /\[.*\]/ig ); + if ( relreg && relreg.length > 0 ) + { + regs[ j ] = regs[ j ].replace( relreg[ 0 ], "0" ); + + if ( verbose ) + trace( "IS REL" ); + isRelative = true; + } + + var res:Array = regs[j].match( /^\b[A-Za-z]{1,3}/ig ); + if ( !res ) + { + _error = "error: could not parse operand "+j+" ("+regs[j]+")."; + badreg = true; + break; + } + var regFound:Register = REGMAP[ res[ 0 ] ]; + + // if debug is enabled, output the registers + if ( debugEnabled ) + trace( regFound ); + + if ( regFound == null ) + { + _error = "error: could not find register name for operand "+j+" ("+regs[j]+")."; + badreg = true; + break; + } + + if ( isFrag ) + { + if ( !( regFound.flags & REG_FRAG ) ) + { + _error = "error: register operand "+j+" ("+regs[j]+") only allowed in vertex programs."; + badreg = true; + break; + } + if ( isRelative ) + { + _error = "error: register operand "+j+" ("+regs[j]+") relative adressing not allowed in fragment programs."; + badreg = true; + break; + } + } + else + { + if ( !( regFound.flags & REG_VERT ) ) + { + _error = "error: register operand "+j+" ("+regs[j]+") only allowed in fragment programs."; + badreg = true; + break; + } + } + + regs[j] = regs[j].slice( regs[j].search( regFound.name ) + regFound.name.length ); + //trace( "REGNUM: " +regs[j] ); + var idxmatch:Array = isRelative ? relreg[0].match( /\d+/ ) : regs[j].match( /\d+/ ); + var regidx:uint = 0; + + if ( idxmatch ) + regidx = uint( idxmatch[0] ); + + if ( regFound.range < regidx ) + { + _error = "error: register operand "+j+" ("+regs[j]+") index exceeds limit of "+(regFound.range+1)+"."; + badreg = true; + break; + } + + var regmask:uint = 0; + var maskmatch:Array = regs[j].match( /(\.[xyzw]{1,4})/ ); + var isDest:Boolean = ( j == 0 && !( opFound.flags & OP_NO_DEST ) ); + var isSampler:Boolean = ( j == 2 && ( opFound.flags & OP_SPECIAL_TEX ) ); + var reltype:uint = 0; + var relsel:uint = 0; + var reloffset:int = 0; + + if ( isDest && isRelative ) + { + _error = "error: relative can not be destination"; + badreg = true; + break; + } + + if ( maskmatch ) + { + regmask = 0; + var cv:uint; + var maskLength:uint = maskmatch[0].length; + for ( var k:int = 1; k < maskLength; k++ ) + { + cv = maskmatch[0].charCodeAt(k) - "x".charCodeAt(0); + if ( cv > 2 ) + cv = 3; + if ( isDest ) + regmask |= 1 << cv; + else + regmask |= cv << ( ( k - 1 ) << 1 ); + } + if ( !isDest ) + for ( ; k <= 4; k++ ) + regmask |= cv << ( ( k - 1 ) << 1 ); // repeat last + } + else + { + regmask = isDest ? 0xf : 0xe4; // id swizzle or mask + } + + if ( isRelative ) + { + var relname:Array = relreg[0].match( /[A-Za-z]{1,3}/ig ); + var regFoundRel:Register = REGMAP[ relname[0]]; + if ( regFoundRel == null ) + { + _error = "error: bad index register"; + badreg = true; + break; + } + reltype = regFoundRel.emitCode; + var selmatch:Array = relreg[0].match( /(\.[xyzw]{1,1})/ ); + if ( selmatch.length==0 ) + { + _error = "error: bad index register select"; + badreg = true; + break; + } + relsel = selmatch[0].charCodeAt(1) - "x".charCodeAt(0); + if ( relsel > 2 ) + relsel = 3; + var relofs:Array = relreg[0].match( /\+\d{1,3}/ig ); + if ( relofs.length > 0 ) + reloffset = relofs[0]; + if ( reloffset < 0 || reloffset > 255 ) + { + _error = "error: index offset "+reloffset+" out of bounds. [0..255]"; + badreg = true; + break; + } + if ( verbose ) + trace( "RELATIVE: type="+reltype+"=="+relname[0]+" sel="+relsel+"=="+selmatch[0]+" idx="+regidx+" offset="+reloffset ); + } + + if ( verbose ) + trace( " emit argcode="+regFound+"["+regidx+"]["+regmask+"]" ); + if ( isDest ) + { + agalcode.writeShort( regidx ); + agalcode.writeByte( regmask ); + agalcode.writeByte( regFound.emitCode ); + pad -= 32; + } else + { + if ( isSampler ) + { + if ( verbose ) + trace( " emit sampler" ); + var samplerbits:uint = 5; // type 5 + var optsLength:uint = opts == null ? 0 : opts.length; + var bias:Number = 0; + for ( k = 0; k