shaderCompHLSL.cpp
Engine/source/shaderGen/HLSL/shaderCompHLSL.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/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