gfxShader.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "gfx/gfxShader.h"
  24. #include "shaderGen/conditionerFeature.h"
  25. #include "core/volume.h"
  26. #include "console/engineAPI.h"
  27. Vector<GFXShaderMacro> GFXShader::smGlobalMacros;
  28. bool GFXShader::smLogErrors = true;
  29. bool GFXShader::smLogWarnings = true;
  30. GFXShader::GFXShader()
  31. : mPixVersion( 0.0f ),
  32. mReloadKey( 0 ),
  33. mInstancingFormat( NULL )
  34. {
  35. }
  36. GFXShader::~GFXShader()
  37. {
  38. Torque::FS::RemoveChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged );
  39. Torque::FS::RemoveChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged );
  40. SAFE_DELETE(mInstancingFormat);
  41. }
  42. #ifndef TORQUE_OPENGL
  43. bool GFXShader::init( const Torque::Path &vertFile,
  44. const Torque::Path &pixFile,
  45. F32 pixVersion,
  46. const Vector<GFXShaderMacro> &macros )
  47. {
  48. Vector<String> samplerNames;
  49. return init( vertFile, pixFile, pixVersion, macros, samplerNames );
  50. }
  51. #endif
  52. bool GFXShader::init( F32 pixVersion,
  53. const Vector<GFXShaderMacro> &macros,
  54. const Vector<String> &samplerNames,
  55. GFXVertexFormat *instanceFormat)
  56. {
  57. // early out.
  58. if (mVertexFile.isEmpty() && mPixelFile.isEmpty() && mGeometryFile.isEmpty())
  59. {
  60. Con::errorf("Shader files empty, please call setShaderStageFile from shaderData");
  61. return false;
  62. }
  63. // Take care of instancing
  64. if (instanceFormat)
  65. {
  66. mInstancingFormat = new GFXVertexFormat;
  67. mInstancingFormat->copy(*instanceFormat);
  68. }
  69. // Store the inputs for use in reloading.
  70. mPixVersion = pixVersion;
  71. mMacros = macros;
  72. mSamplerNamesOrdered = samplerNames;
  73. // Before we compile the shader make sure the
  74. // conditioner features have been updated.
  75. ConditionerFeature::updateConditioners();
  76. // Now do the real initialization.
  77. if ( !_init() )
  78. return false;
  79. _updateDesc();
  80. // Add file change notifications for reloads.
  81. if(!mVertexFile.isEmpty())
  82. Torque::FS::AddChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged );
  83. if(!mPixelFile.isEmpty())
  84. Torque::FS::AddChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged );
  85. if(!mGeometryFile.isEmpty())
  86. Torque::FS::AddChangeNotification( mGeometryFile, this, &GFXShader::_onFileChanged);
  87. return true;
  88. }
  89. bool GFXShader::reload()
  90. {
  91. // Before we compile the shader make sure the
  92. // conditioner features have been updated.
  93. ConditionerFeature::updateConditioners();
  94. mReloadKey++;
  95. // Init does the work.
  96. bool success = _init();
  97. if ( success )
  98. _updateDesc();
  99. // Let anything that cares know that
  100. // this shader has reloaded
  101. mReloadSignal.trigger();
  102. return success;
  103. }
  104. void GFXShader::_updateDesc()
  105. {
  106. mDescription = String::ToString( "Files: %s, %s Pix Version: %0.2f\nMacros: ",
  107. mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), mPixVersion );
  108. GFXShaderMacro::stringize( smGlobalMacros, &mDescription );
  109. GFXShaderMacro::stringize( mMacros, &mDescription );
  110. }
  111. void GFXShader::addGlobalMacro( const String &name, const String &value )
  112. {
  113. // Check to see if we already have this macro.
  114. Vector<GFXShaderMacro>::iterator iter = smGlobalMacros.begin();
  115. for ( ; iter != smGlobalMacros.end(); iter++ )
  116. {
  117. if ( iter->name == name )
  118. {
  119. if ( iter->value != value )
  120. iter->value = value;
  121. return;
  122. }
  123. }
  124. // Add a new macro.
  125. smGlobalMacros.increment();
  126. smGlobalMacros.last().name = name;
  127. smGlobalMacros.last().value = value;
  128. }
  129. bool GFXShader::removeGlobalMacro( const String &name )
  130. {
  131. Vector<GFXShaderMacro>::iterator iter = smGlobalMacros.begin();
  132. for ( ; iter != smGlobalMacros.end(); iter++ )
  133. {
  134. if ( iter->name == name )
  135. {
  136. smGlobalMacros.erase( iter );
  137. return true;
  138. }
  139. }
  140. return false;
  141. }
  142. void GFXShader::setShaderStageFile(const GFXShaderStage stage, const Torque::Path& filePath)
  143. {
  144. switch (stage)
  145. {
  146. case GFXShaderStage::VERTEX_SHADER:
  147. mVertexFile = filePath;
  148. break;
  149. case GFXShaderStage::PIXEL_SHADER:
  150. mPixelFile = filePath;
  151. break;
  152. case GFXShaderStage::GEOMETRY_SHADER:
  153. mGeometryFile = filePath;
  154. break;
  155. default:
  156. break;
  157. }
  158. }
  159. void GFXShader::_unlinkBuffer( GFXShaderConstBuffer *buf )
  160. {
  161. Vector<GFXShaderConstBuffer*>::iterator iter = mActiveBuffers.begin();
  162. for ( ; iter != mActiveBuffers.end(); iter++ )
  163. {
  164. if ( *iter == buf )
  165. {
  166. mActiveBuffers.erase_fast( iter );
  167. return;
  168. }
  169. }
  170. AssertFatal( false, "GFXShader::_unlinkBuffer - buffer was not found?" );
  171. }
  172. DefineEngineFunction( addGlobalShaderMacro, void,
  173. ( const char *name, const char *value ), ( nullAsType<const char*>() ),
  174. "Adds a global shader macro which will be merged with the script defined "
  175. "macros on every shader. The macro will replace the value of an existing "
  176. "macro of the same name. For the new macro to take effect all the shaders "
  177. "in the system need to be reloaded.\n"
  178. "@see resetLightManager, removeGlobalShaderMacro\n"
  179. "@ingroup Rendering\n" )
  180. {
  181. GFXShader::addGlobalMacro( name, value );
  182. }
  183. DefineEngineFunction( removeGlobalShaderMacro, void, ( const char *name ),,
  184. "Removes an existing global macro by name.\n"
  185. "@see addGlobalShaderMacro\n"
  186. "@ingroup Rendering\n" )
  187. {
  188. GFXShader::removeGlobalMacro( name );
  189. }