gfxShader.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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. if (!mVertexFile.isEmpty())
  39. Torque::FS::RemoveChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged );
  40. if (!mPixelFile.isEmpty())
  41. Torque::FS::RemoveChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged );
  42. if (!mGeometryFile.isEmpty())
  43. Torque::FS::RemoveChangeNotification(mGeometryFile, this, &GFXShader::_onFileChanged);
  44. SAFE_DELETE(mInstancingFormat);
  45. }
  46. #ifndef TORQUE_OPENGL
  47. bool GFXShader::init( const Torque::Path &vertFile,
  48. const Torque::Path &pixFile,
  49. F32 pixVersion,
  50. const Vector<GFXShaderMacro> &macros )
  51. {
  52. Vector<String> samplerNames;
  53. return init( vertFile, pixFile, pixVersion, macros, samplerNames );
  54. }
  55. #endif
  56. bool GFXShader::init( F32 pixVersion,
  57. const Vector<GFXShaderMacro> &macros,
  58. const Vector<String> &samplerNames,
  59. GFXVertexFormat *instanceFormat)
  60. {
  61. // early out.
  62. if (mVertexFile.isEmpty() && mPixelFile.isEmpty() && mGeometryFile.isEmpty())
  63. {
  64. Con::errorf("Shader files empty, please call setShaderStageFile from shaderData");
  65. return false;
  66. }
  67. // Take care of instancing
  68. if (instanceFormat)
  69. {
  70. mInstancingFormat = new GFXVertexFormat;
  71. mInstancingFormat->copy(*instanceFormat);
  72. }
  73. // Store the inputs for use in reloading.
  74. mPixVersion = pixVersion;
  75. mMacros = macros;
  76. mSamplerNamesOrdered = samplerNames;
  77. // Before we compile the shader make sure the
  78. // conditioner features have been updated.
  79. ConditionerFeature::updateConditioners();
  80. // Now do the real initialization.
  81. if ( !_init() )
  82. return false;
  83. _updateDesc();
  84. // Add file change notifications for reloads.
  85. if(!mVertexFile.isEmpty())
  86. Torque::FS::AddChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged );
  87. if(!mPixelFile.isEmpty())
  88. Torque::FS::AddChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged );
  89. if(!mGeometryFile.isEmpty())
  90. Torque::FS::AddChangeNotification( mGeometryFile, this, &GFXShader::_onFileChanged);
  91. return true;
  92. }
  93. bool GFXShader::reload()
  94. {
  95. // Before we compile the shader make sure the
  96. // conditioner features have been updated.
  97. ConditionerFeature::updateConditioners();
  98. mReloadKey++;
  99. // Init does the work.
  100. bool success = _init();
  101. if ( success )
  102. _updateDesc();
  103. // Let anything that cares know that
  104. // this shader has reloaded
  105. mReloadSignal.trigger();
  106. return success;
  107. }
  108. void GFXShader::_updateDesc()
  109. {
  110. mDescription = String::ToString( "Files: %s, %s Pix Version: %0.2f\nMacros: ",
  111. mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), mPixVersion );
  112. GFXShaderMacro::stringize( smGlobalMacros, &mDescription );
  113. GFXShaderMacro::stringize( mMacros, &mDescription );
  114. }
  115. void GFXShader::addGlobalMacro( const String &name, const String &value )
  116. {
  117. // Check to see if we already have this macro.
  118. Vector<GFXShaderMacro>::iterator iter = smGlobalMacros.begin();
  119. for ( ; iter != smGlobalMacros.end(); iter++ )
  120. {
  121. if ( iter->name == name )
  122. {
  123. if ( iter->value != value )
  124. iter->value = value;
  125. return;
  126. }
  127. }
  128. // Add a new macro.
  129. smGlobalMacros.increment();
  130. smGlobalMacros.last().name = name;
  131. smGlobalMacros.last().value = value;
  132. }
  133. bool GFXShader::removeGlobalMacro( const String &name )
  134. {
  135. Vector<GFXShaderMacro>::iterator iter = smGlobalMacros.begin();
  136. for ( ; iter != smGlobalMacros.end(); iter++ )
  137. {
  138. if ( iter->name == name )
  139. {
  140. smGlobalMacros.erase( iter );
  141. return true;
  142. }
  143. }
  144. return false;
  145. }
  146. void GFXShader::setShaderStageFile(const GFXShaderStage stage, const Torque::Path& filePath)
  147. {
  148. switch (stage)
  149. {
  150. case GFXShaderStage::VERTEX_SHADER:
  151. mVertexFile = filePath;
  152. break;
  153. case GFXShaderStage::PIXEL_SHADER:
  154. mPixelFile = filePath;
  155. break;
  156. case GFXShaderStage::GEOMETRY_SHADER:
  157. mGeometryFile = filePath;
  158. break;
  159. default:
  160. break;
  161. }
  162. }
  163. void GFXShader::_unlinkBuffer( GFXShaderConstBuffer *buf )
  164. {
  165. Vector<GFXShaderConstBuffer*>::iterator iter = mActiveBuffers.begin();
  166. for ( ; iter != mActiveBuffers.end(); iter++ )
  167. {
  168. if ( *iter == buf )
  169. {
  170. mActiveBuffers.erase_fast( iter );
  171. return;
  172. }
  173. }
  174. AssertFatal( false, "GFXShader::_unlinkBuffer - buffer was not found?" );
  175. }
  176. DefineEngineFunction( addGlobalShaderMacro, void,
  177. ( const char *name, const char *value ), ( nullAsType<const char*>() ),
  178. "Adds a global shader macro which will be merged with the script defined "
  179. "macros on every shader. The macro will replace the value of an existing "
  180. "macro of the same name. For the new macro to take effect all the shaders "
  181. "in the system need to be reloaded.\n"
  182. "@see resetLightManager, removeGlobalShaderMacro\n"
  183. "@ingroup Rendering\n" )
  184. {
  185. GFXShader::addGlobalMacro( name, value );
  186. }
  187. DefineEngineFunction( removeGlobalShaderMacro, void, ( const char *name ),,
  188. "Removes an existing global macro by name.\n"
  189. "@see addGlobalShaderMacro\n"
  190. "@ingroup Rendering\n" )
  191. {
  192. GFXShader::removeGlobalMacro( name );
  193. }