ShaderLoader.cpp 4.3 KB

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