ShaderLoader.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include "Config.h"
  2. #include "ErrorHandlerLocator.h"
  3. #include "ShaderLoader.h"
  4. #include "ShaderUniformUpdater.h"
  5. #include "Utilities.h"
  6. unsigned int ShaderLoader::ShaderProgram::m_defaultProgramHandle = 0;
  7. ShaderLoader::ShaderLoader()
  8. {
  9. // Assign shader types, so they could be resolved from array type
  10. //m_shaderTypes[ArrayFragment] = ShaderFragment;
  11. //m_shaderTypes[ArrayGeometry] = ShaderGeometry;
  12. //m_shaderTypes[ArrayVertex] = ShaderVertex;
  13. //m_shaderTypes[ArrayTessControl] = ShaderTessControl;
  14. //m_shaderTypes[ArrayTessEvaluation] = ShaderTessEvaluation;
  15. }
  16. ShaderLoader::~ShaderLoader()
  17. {
  18. }
  19. ErrorCode ShaderLoader::init()
  20. {
  21. // Initialize default shader program
  22. m_defaultProgram.loadToMemory();
  23. // Reserve space in the program pool, to speed up push_backs
  24. m_shaderPrograms.reserve(Config::rendererVar().shader_pool_size);
  25. ShaderProgram::m_defaultProgramHandle = m_defaultProgram.m_programHandle;
  26. return ErrorCode::Success;
  27. }
  28. ShaderLoader::ShaderProgram *ShaderLoader::load(const PropertySet &p_properties)
  29. {
  30. if(p_properties)
  31. {
  32. // Create shader filename array
  33. std::string shaderFilename[ShaderType_NumOfTypes];
  34. std::string programName;
  35. int numberOfShaders = 0;
  36. // Iterate over all passed properties
  37. for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
  38. {
  39. switch(p_properties[i].getPropertyID())
  40. {
  41. case Properties::Name:
  42. programName = p_properties[i].getString();
  43. break;
  44. case Properties::FragmentShader:
  45. shaderFilename[ShaderType_Fragment] = p_properties[i].getString();
  46. numberOfShaders++;
  47. break;
  48. case Properties::VertexShader:
  49. shaderFilename[ShaderType_Vertex] = p_properties[i].getString();
  50. numberOfShaders++;
  51. break;
  52. case Properties::GeometryShader:
  53. shaderFilename[ShaderType_Geometry] = p_properties[i].getString();
  54. numberOfShaders++;
  55. break;
  56. case Properties::TessControlShader:
  57. shaderFilename[ShaderType_TessControl] = p_properties[i].getString();
  58. numberOfShaders++;
  59. break;
  60. case Properties::TessEvaluationShader:
  61. shaderFilename[ShaderType_TessEvaluation] = p_properties[i].getString();
  62. numberOfShaders++;
  63. break;
  64. }
  65. }
  66. if(numberOfShaders > 0)
  67. {
  68. // If program name was not specified, combine all shader names into one program name
  69. if(programName.empty())
  70. {
  71. // For every shader filename, if it's not empty, add it to the program name
  72. for(unsigned int shaderType = 0; shaderType < ShaderType_NumOfTypes; shaderType++)
  73. if(!shaderFilename[shaderType].empty())
  74. programName += shaderFilename[shaderType] + ", ";
  75. // Remove the last 2 characters from the filename (comma and space)
  76. if(!programName.empty())
  77. {
  78. programName.pop_back();
  79. programName.pop_back();
  80. }
  81. }
  82. // Generate hash key from program's name
  83. unsigned int programHashkey = Utilities::getHashKey(programName);
  84. // Make sure calls from other threads are locked, while current call is in progress
  85. // This is needed to as the object that is being requested might be currently loading /
  86. // being added to the pool. Mutex prevents duplicates being loaded, and same data being changed.
  87. SpinWait::Lock lock(m_mutex);
  88. // Iterate over all shader programs and match hash key and name; if match is found, return it
  89. for(decltype(m_shaderPrograms.size()) i = 0, size = m_shaderPrograms.size(); i < size; i++)
  90. if(m_shaderPrograms[i].m_filenameHash == programHashkey)
  91. if(m_shaderPrograms[i].m_combinedFilename == programName)
  92. return &m_shaderPrograms[i];
  93. // Add the new program to the array
  94. m_shaderPrograms.push_back(ShaderProgram(programName, programHashkey));
  95. ShaderProgram *newProgram = &m_shaderPrograms[m_shaderPrograms.size() - 1];
  96. // Iterate over shader types
  97. for(unsigned int shaderType = 0; shaderType < ShaderType_NumOfTypes; shaderType++)
  98. // If shader filename is valid
  99. if(!shaderFilename[shaderType].empty())
  100. newProgram->addShader(static_cast<ShaderType>(shaderType), shaderFilename[shaderType]);
  101. // Create a uniform updater for the new shader
  102. newProgram->m_uniformUpdater = new ShaderUniformUpdater(*newProgram);
  103. return newProgram;
  104. }
  105. }
  106. return &m_defaultProgram;
  107. }