Torque3D Documentation / _generateds / shaderCompHLSL.cpp

shaderCompHLSL.cpp

Engine/source/shaderGen/HLSL/shaderCompHLSL.cpp

More...

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/HLSL/shaderCompHLSL.h"
 26
 27#include "shaderGen/shaderComp.h"
 28#include "shaderGen/langElement.h"
 29#include "gfx/gfxDevice.h"
 30
 31
 32Var * ShaderConnectorHLSL::getElement( RegisterType type, 
 33                                       U32 numElements, 
 34                                       U32 numRegisters )
 35{
 36   Var *ret = NULL;
 37   
 38   if ( type == RT_BLENDINDICES )
 39   {
 40      ret = getIndexedElement( mCurBlendIndicesElem, type, numElements, numRegisters );
 41   }
 42   else if ( type == RT_BLENDWEIGHT )
 43   {
 44      ret = getIndexedElement( mCurBlendWeightsElem, type, numElements, numRegisters );
 45   }
 46   else
 47   {
 48      ret = getIndexedElement( mCurTexElem, type, numElements, numRegisters );
 49   }
 50
 51   // Adjust texture offset if this is a texcoord type
 52   if( type == RT_TEXCOORD )
 53   {
 54      if ( numRegisters != -1 )
 55         mCurTexElem += numRegisters;
 56      else
 57         mCurTexElem += numElements;
 58   }
 59   else if ( type == RT_BLENDINDICES )
 60   {
 61      if ( numRegisters != -1 )
 62         mCurBlendIndicesElem += numRegisters;
 63      else
 64         mCurBlendIndicesElem += numElements;
 65   }
 66   else if ( type == RT_BLENDWEIGHT )
 67   {
 68      if ( numRegisters != -1 )
 69         mCurBlendWeightsElem += numRegisters;
 70      else
 71         mCurBlendWeightsElem += numElements;
 72   }
 73
 74   return ret;
 75}
 76
 77Var * ShaderConnectorHLSL::getIndexedElement( U32 index, RegisterType type, U32 numElements /*= 1*/, U32 numRegisters /*= -1 */ )
 78{
 79   switch( type )
 80   { 
 81   case RT_POSITION:
 82      {
 83         Var *newVar = new Var;
 84         mElementList.push_back( newVar );
 85         newVar->setConnectName( "POSITION" );
 86         newVar->rank = 0;
 87         return newVar;
 88      }
 89
 90   case RT_VPOS:
 91      {
 92         Var *newVar = new Var;
 93         mElementList.push_back(newVar);
 94         newVar->setConnectName("VPOS");
 95         newVar->rank = 0;
 96         return newVar;
 97      }
 98
 99   case RT_SVPOSITION:
100      {
101         Var *newVar = new Var;
102         mElementList.push_back(newVar);
103         newVar->setConnectName("SV_Position");
104         newVar->rank = 0;
105         return newVar;
106      }
107
108   case RT_NORMAL:
109      {
110         Var *newVar = new Var;
111         mElementList.push_back( newVar );
112         newVar->setConnectName( "NORMAL" );
113         newVar->rank = 1;
114         return newVar;
115      }
116
117   case RT_BINORMAL:
118      {
119         Var *newVar = new Var;
120         mElementList.push_back( newVar );
121         newVar->setConnectName( "BINORMAL" );
122         newVar->rank = 2;
123         return newVar;
124      }
125
126   case RT_TANGENT:
127      {
128         Var *newVar = new Var;
129         mElementList.push_back( newVar );
130         newVar->setConnectName( "TANGENT" );
131         newVar->rank = 3;
132         return newVar;
133      }
134
135   case RT_COLOR:
136      {
137         Var *newVar = new Var;
138         mElementList.push_back( newVar );
139         newVar->setConnectName( "COLOR" );
140         newVar->rank = 4;
141         return newVar;
142      }
143
144   case RT_TEXCOORD:
145      {
146         Var *newVar = new Var;
147         mElementList.push_back( newVar );
148
149         // This was needed for hardware instancing, but
150         // i don't really remember why right now.
151         if ( index > mCurTexElem )
152            mCurTexElem = index + 1;
153
154         char out[32];
155         dSprintf( (char*)out, sizeof(out), "TEXCOORD%d", index );
156         newVar->setConnectName( out );
157         newVar->constNum = index;
158         newVar->arraySize = numElements;
159         newVar->rank = 5 + index;
160
161         return newVar;
162      }
163
164   case RT_BLENDINDICES:
165      {
166         Var *newVar = new Var;
167         mElementList.push_back( newVar );
168
169         // This was needed for hardware instancing, but
170         // i don't really remember why right now.
171         if ( index > mCurBlendIndicesElem )
172            mCurBlendIndicesElem = index + 1;
173
174         char out[32];
175         dSprintf( (char*)out, sizeof(out), "BLENDINDICES%d", index );
176         newVar->setConnectName( out );
177         newVar->constNum = index;
178         newVar->arraySize = numElements;
179
180         return newVar;
181      }
182
183   case RT_BLENDWEIGHT:
184      {
185         Var *newVar = new Var;
186         mElementList.push_back( newVar );
187
188         // This was needed for hardware instancing, but
189         // i don't really remember why right now.
190         if ( index > mCurBlendWeightsElem )
191            mCurBlendWeightsElem = index + 1;
192
193         char out[32];
194         dSprintf( (char*)out, sizeof(out), "BLENDWEIGHT%d", index );
195         newVar->setConnectName( out );
196         newVar->constNum = index;
197         newVar->arraySize = numElements;
198
199         return newVar;
200      }
201
202
203
204   default:
205      break;
206   }
207
208   return NULL;
209}
210
211
212
213S32 QSORT_CALLBACK ShaderConnectorHLSL::_hlsl4VarSort(const void* e1, const void* e2)
214{
215   Var* a = *((Var **)e1);
216   Var* b = *((Var **)e2);
217
218   return a->rank - b->rank;
219}
220
221void ShaderConnectorHLSL::sortVars()
222{
223
224   // If shader model 4+ than we gotta sort the vars to make sure the order is consistent
225   if (GFX->getPixelShaderVersion() >= 4.f)
226   {
227      dQsort((void *)&mElementList[0], mElementList.size(), sizeof(Var *), _hlsl4VarSort);
228      return;
229   }
230
231   return;
232}
233
234void ShaderConnectorHLSL::setName( char *newName )
235{
236   dStrcpy( (char*)mName, newName, 32 );
237}
238
239void ShaderConnectorHLSL::reset()
240{
241   for( U32 i=0; i<mElementList.size(); i++ )
242   {
243      mElementList[i] = NULL;
244   }
245
246   mElementList.setSize( 0 );
247   mCurTexElem = 0;
248   mCurBlendIndicesElem = 0;
249   mCurBlendWeightsElem = 0;
250}
251
252void ShaderConnectorHLSL::print( Stream &stream, bool isVertexShader )
253{
254   const char * header = "struct ";
255   const char * header2 = "\r\n{\r\n";
256   const char * footer = "};\r\n\r\n\r\n";
257
258   stream.write( dStrlen(header), header );
259   stream.write( dStrlen((char*)mName), mName );
260   stream.write( dStrlen(header2), header2 );
261
262
263   // print out elements
264   for( U32 i=0; i<mElementList.size(); i++ )
265   {
266      U8 output[256];
267
268      Var *var = mElementList[i];
269      if (var->arraySize <= 1)
270         dSprintf( (char*)output, sizeof(output), "   %s %-15s : %s;\r\n", var->type, var->name, var->connectName );
271      else
272         dSprintf( (char*)output, sizeof(output), "   %s %s[%d] : %s;\r\n", var->type, var->name, var->arraySize, var->connectName );
273
274      stream.write( dStrlen((char*)output), output );
275   }
276
277   stream.write( dStrlen(footer), footer );
278}
279
280void ParamsDefHLSL::assignConstantNumbers()
281{
282
283   // Here we assign constant number to uniform vars, sorted 
284   // by their update frequency.
285
286   U32 mCurrConst = 0;
287   for (U32 bin = cspUninit+1; bin < csp_Count; bin++)
288   {   
289      // Find all the uniform variables that are part of this group and assign constant numbers
290      for( U32 i=0; i<LangElement::elementList.size(); i++)
291      {
292         Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
293         if( var )
294         {            
295            bool shaderConst = var->uniform && !var->sampler && !var->texture;
296            AssertFatal((!shaderConst) || var->constSortPos != cspUninit, "Const sort position has not been set, variable will not receive a constant number!!");
297            if( shaderConst && var->constSortPos == bin)
298            {
299               var->constNum = mCurrConst;
300               // Increment our constant number based on the variable type
301               if (String::compare((const char*)var->type, "float4x4") == 0)
302               {
303                  mCurrConst += (4 * var->arraySize);
304               }
305               else
306               {
307                  if (String::compare((const char*)var->type, "float3x3") == 0)
308                  {
309                     mCurrConst += (3 * var->arraySize);
310                  }
311                  else
312                  {
313                     if (String::compare((const char*)var->type, "float4x3") == 0)
314                     {
315                        mCurrConst += (3 * var->arraySize);
316                     }
317                     else
318                     {
319                        mCurrConst += var->arraySize;
320                     }
321                  }
322               }
323            }
324         }
325      }
326   }
327}
328
329void VertexParamsDefHLSL::print( Stream &stream, bool isVerterShader )
330{
331   assignConstantNumbers();
332
333   const char *opener = "ConnectData main( VertData IN";
334   stream.write( dStrlen(opener), opener );
335
336   // find all the uniform variables and print them out
337   for( U32 i=0; i<LangElement::elementList.size(); i++)
338   {
339      Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
340      if( var )
341      {
342         if( var->uniform )
343         {
344            const char* nextVar = ",\r\n                  ";
345            stream.write( dStrlen(nextVar), nextVar );            
346
347            U8 varNum[64];
348            dSprintf( (char*)varNum, sizeof(varNum), "register(C%d)", var->constNum );
349
350            U8 output[256];
351            if (var->arraySize <= 1)
352               dSprintf( (char*)output, sizeof(output), "uniform %-8s %-15s : %s", var->type, var->name, varNum );
353            else
354               dSprintf( (char*)output, sizeof(output), "uniform %-8s %s[%d] : %s", var->type, var->name, var->arraySize, varNum );
355
356            stream.write( dStrlen((char*)output), output );
357         }
358      }
359   }
360
361   const char *closer = "\r\n)\r\n{\r\n   ConnectData OUT;\r\n\r\n";
362   stream.write( dStrlen(closer), closer );
363}
364
365void PixelParamsDefHLSL::print( Stream &stream, bool isVerterShader )
366{
367   assignConstantNumbers();
368
369   const char * opener = "Fragout main( ConnectData IN";
370   stream.write( dStrlen(opener), opener );
371
372   // find all the sampler & uniform variables and print them out
373   for( U32 i=0; i<LangElement::elementList.size(); i++)
374   {
375      Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
376      if( var )
377      {
378         if( var->uniform )
379         {
380            WRITESTR( ",\r\n              " );
381
382            U8 varNum[32];
383
384            if( var->sampler )
385            {
386               dSprintf( (char*)varNum, sizeof(varNum), ": register(S%d)", var->constNum );
387            }
388            else if (var->texture)
389            {
390               dSprintf((char*)varNum, sizeof(varNum), ": register(T%d)", var->constNum);
391            }
392            else
393            {
394               dSprintf( (char*)varNum, sizeof(varNum), ": register(C%d)", var->constNum );
395            }
396
397            U8 output[256];
398            if (var->arraySize <= 1)
399               dSprintf( (char*)output, sizeof(output), "uniform %-9s %-15s %s", var->type, var->name, varNum );
400            else
401               dSprintf( (char*)output, sizeof(output), "uniform %-9s %s[%d] %s", var->type, var->name, var->arraySize, varNum );
402
403            WRITESTR( (char*) output );
404         }
405      }
406   }
407
408   const char *closer = "\r\n)\r\n{\r\n   Fragout OUT;\r\n\r\n";
409   stream.write( dStrlen(closer), closer );
410}
411