conditionerFeature.cpp
Engine/source/shaderGen/conditionerFeature.cpp
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "shaderGen/conditionerFeature.h" 26 27#include "shaderGen/shaderOp.h" 28#include "shaderGen/featureMgr.h" 29#include "gfx/gfxDevice.h" 30#include "gfx/gfxStringEnumTranslate.h" 31#include "core/stream/fileStream.h" 32#include "materials/shaderData.h" 33#include "core/util/safeDelete.h" 34 35const String ConditionerFeature::ConditionerIncludeFileName = "autogenConditioners.h"; 36 37bool ConditionerFeature::smDirtyConditioners = true; 38 39Vector<ConditionerFeature*> ConditionerFeature::smConditioners; 40 41 42ConditionerFeature::ConditionerFeature( const GFXFormat bufferFormat ) 43 : mBufferFormat(bufferFormat) 44{ 45 dMemset( mMethodDependency, 0, sizeof( mMethodDependency ) ); 46 47 smConditioners.push_back( this ); 48 smDirtyConditioners = true; 49} 50 51ConditionerFeature::~ConditionerFeature() 52{ 53 for( U32 i = 0; i < NumMethodTypes; i++ ) 54 SAFE_DELETE( mMethodDependency[i] ); 55 56 smConditioners.remove( this ); 57 smDirtyConditioners = true; 58} 59 60LangElement *ConditionerFeature::assignOutput( Var *unconditionedOutput, ShaderFeature::OutputTarget outputTarget /* = ShaderFeature::DefaultTarget*/ ) 61{ 62 LangElement *assign; 63 MultiLine *meta = new MultiLine; 64 65 meta->addStatement( new GenOp( avar( "\r\n\r\n // output buffer format: %s\r\n", GFXStringTextureFormat[getBufferFormat()] ) ) ); 66 67 // condition the output 68 Var *conditionedOutput = _conditionOutput( unconditionedOutput, meta ); 69 70 // search for color var 71 Var *color = (Var*) LangElement::find( getOutputTargetVarName(outputTarget) ); 72 73 if ( !color ) 74 { 75 // create color var 76 color = new Var; 77 78 if(GFX->getAdapterType() == OpenGL) 79 { 80 color->setName( getOutputTargetVarName(outputTarget) ); 81 color->setType( "vec4" ); 82 color->setStructName( "OUT" ); 83 84 assign = new GenOp( "@ = vec4(@)", color, conditionedOutput ); 85 } 86 else 87 { 88 color->setType( "fragout" ); 89 color->setName( getOutputTargetVarName(outputTarget) ); 90 color->setStructName( "OUT" ); 91 92 assign = new GenOp( "@ = @", color, conditionedOutput ); 93 } 94 } 95 else 96 { 97 if (GFX->getAdapterType() == OpenGL) 98 assign = new GenOp( "@ = vec4(@)", color, conditionedOutput); 99 else 100 assign = new GenOp( "@ = @", color, conditionedOutput ); 101 } 102 103 meta->addStatement( new GenOp( " @;\r\n", assign ) ); 104 105 return meta; 106} 107 108Var *ConditionerFeature::_conditionOutput( Var *unconditionedOutput, MultiLine *meta ) 109{ 110 meta->addStatement( new GenOp( " // generic conditioner: no conditioning performed\r\n" ) ); 111 return unconditionedOutput; 112} 113 114Var *ConditionerFeature::_unconditionInput( Var *conditionedInput, MultiLine *meta ) 115{ 116 meta->addStatement( new GenOp( " // generic conditioner: no conditioning performed\r\n" ) ); 117 return conditionedInput; 118} 119 120const String &ConditionerFeature::getShaderMethodName( MethodType methodType ) 121{ 122 if ( mConditionMethodName.isEmpty() ) 123 { 124 const U32 hash = getName().getHashCaseInsensitive(); 125 mUnconditionMethodName = avar("autogen%s_%08x", "Uncondition", hash ); 126 mConditionMethodName = avar("autogen%s_%08x", "Condition", hash ); 127 } 128 129 return methodType == UnconditionMethod ? mUnconditionMethodName : mConditionMethodName; 130} 131 132ConditionerMethodDependency* ConditionerFeature::getConditionerMethodDependency( MethodType methodType ) 133{ 134 if ( mMethodDependency[methodType] == NULL ) 135 mMethodDependency[methodType] = new ConditionerMethodDependency( this, methodType ); 136 137 return mMethodDependency[methodType]; 138} 139 140void ConditionerFeature::_print( Stream *stream ) 141{ 142 _printMethod( ConditionMethod, getShaderMethodName( ConditionMethod ), *stream ); 143 LangElement::deleteElements(); 144 145 _printMethod( UnconditionMethod, getShaderMethodName( UnconditionMethod ), *stream ); 146 LangElement::deleteElements(); 147} 148 149void ConditionerFeature::_updateConditioners() 150{ 151 smDirtyConditioners = false; 152 153 String includePath = "shadergen:/" + ConditionerIncludeFileName; 154 155 FileStream stream; 156 if ( !stream.open( includePath, Torque::FS::File::Write ) ) 157 return; 158 159 for ( U32 i=0; i < smConditioners.size(); i++ ) 160 smConditioners[i]->_print( &stream ); 161} 162 163Var *ConditionerFeature::printMethodHeader( MethodType methodType, const String &methodName, Stream &stream, MultiLine *meta ) 164{ 165 Var *methodVar = new Var; 166 methodVar->setName(methodName); 167 DecOp *methodDecl = new DecOp(methodVar); 168 169 const bool isCondition = (methodType == ConditionerFeature::ConditionMethod); 170 171 Var *paramVar = new Var; 172 paramVar->setName(avar("%sconditioned%sput", isCondition ? "un" : "", isCondition ? "Out" : "In")); 173 DecOp *paramDecl = new DecOp(paramVar); 174 175 if(GFX->getAdapterType() == OpenGL) 176 { 177 methodVar->setType("vec4"); 178 paramVar->setType("vec4"); 179 } 180 else 181 { 182 methodVar->setType("inline float4"); 183 paramVar->setType("in float4"); 184 } 185 186 // Method header and opening bracket 187 meta->addStatement( new GenOp( "@(@)\r\n", methodDecl, paramDecl ) ); 188 meta->addStatement( new GenOp( "{\r\n" ) ); 189 190 return paramVar; 191} 192 193void ConditionerFeature::printMethodFooter( MethodType methodType, Var *retVar, Stream &stream, MultiLine *meta ) 194{ 195 // Return and closing bracket 196 meta->addStatement( new GenOp( "\r\n return @;\r\n", retVar ) ); 197 meta->addStatement( new GenOp( "}\r\n" ) ); 198} 199 200void ConditionerFeature::_printMethod( MethodType methodType, const String &methodName, Stream &stream ) 201{ 202 MultiLine *meta = new MultiLine; 203 204 printHeaderComment( methodType, methodName, stream, meta ); 205 Var *paramVar = printMethodHeader( methodType, methodName, stream, meta ); 206 Var *unconditionedInput = NULL; 207 if( methodType == UnconditionMethod ) 208 unconditionedInput = _unconditionInput( paramVar, meta ); 209 else 210 unconditionedInput = _conditionOutput( paramVar, meta ); 211 212 printMethodFooter( methodType, unconditionedInput, stream, meta ); 213 printFooterComment( methodType, methodName, stream, meta ); 214 215 meta->print(stream); 216} 217 218void ConditionerFeature::printHeaderComment( MethodType methodType, const String &methodName, Stream &stream, MultiLine *meta ) 219{ 220 meta->addStatement( new GenOp( "//------------------------------------------------------------------------------\r\n" ) ); 221 meta->addStatement( new GenOp( avar( "// Autogenerated '%s' %s Method\r\n", getName().c_str(), 222 methodType == ConditionMethod ? "Condition" : "Uncondition" ) ) ); 223 meta->addStatement( new GenOp( "//------------------------------------------------------------------------------\r\n" ) ); 224} 225 226void ConditionerFeature::printFooterComment( MethodType methodType, const String &methodName, Stream &stream, MultiLine *meta ) 227{ 228 meta->addStatement( new GenOp( "\r\n\r\n" ) ); 229} 230 231void ConditionerMethodDependency::print( Stream &s ) const 232{ 233 mConditioner->_printMethod(mMethodType, mConditioner->getShaderMethodName(mMethodType), s); 234} 235 236void ConditionerMethodDependency::createMethodMacro( const String &methodName, Vector<GFXShaderMacro> ¯os ) 237{ 238 GFXShaderMacro conditionerMethodMacro; 239 conditionerMethodMacro.name = methodName; 240 conditionerMethodMacro.value = mConditioner->getShaderMethodName(mMethodType); 241 macros.push_back(conditionerMethodMacro); 242} 243