ShaderPrecache.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "../Precompiled.h"
  4. #include "../Graphics/Graphics.h"
  5. #include "../GraphicsAPI/GraphicsImpl.h"
  6. #include "../GraphicsAPI/ShaderPrecache.h"
  7. #include "../GraphicsAPI/ShaderVariation.h"
  8. #include "../IO/File.h"
  9. #include "../IO/FileSystem.h"
  10. #include "../IO/Log.h"
  11. #include "../DebugNew.h"
  12. namespace Urho3D
  13. {
  14. ShaderPrecache::ShaderPrecache(Context* context, const String& fileName) :
  15. Object(context),
  16. fileName_(fileName),
  17. xmlFile_(context)
  18. {
  19. if (GetSubsystem<FileSystem>()->FileExists(fileName))
  20. {
  21. // If file exists, read the already listed combinations
  22. File source(context_, fileName);
  23. xmlFile_.Load(source);
  24. XMLElement shader = xmlFile_.GetRoot().GetChild("shader");
  25. while (shader)
  26. {
  27. String oldCombination = shader.GetAttribute("vs") + " " + shader.GetAttribute("vsdefines") + " " +
  28. shader.GetAttribute("ps") + " " + shader.GetAttribute("psdefines");
  29. usedCombinations_.Insert(oldCombination);
  30. shader = shader.GetNext("shader");
  31. }
  32. }
  33. // If no file yet or loading failed, create the root element now
  34. if (!xmlFile_.GetRoot())
  35. xmlFile_.CreateRoot("shaders");
  36. URHO3D_LOGINFO("Begin dumping shaders to " + fileName_);
  37. }
  38. ShaderPrecache::~ShaderPrecache()
  39. {
  40. URHO3D_LOGINFO("End dumping shaders");
  41. if (usedCombinations_.Empty())
  42. return;
  43. File dest(context_, fileName_, FILE_WRITE);
  44. xmlFile_.Save(dest);
  45. }
  46. void ShaderPrecache::StoreShaders(ShaderVariation* vs, ShaderVariation* ps)
  47. {
  48. if (!vs || !ps)
  49. return;
  50. // Check for duplicate using pointers first (fast)
  51. Pair<ShaderVariation*, ShaderVariation*> shaderPair = MakePair(vs, ps);
  52. if (usedPtrCombinations_.Contains(shaderPair))
  53. return;
  54. usedPtrCombinations_.Insert(shaderPair);
  55. String vsName = vs->GetName();
  56. String psName = ps->GetName();
  57. const String& vsDefines = vs->GetDefines();
  58. const String& psDefines = ps->GetDefines();
  59. // Check for duplicate using strings (needed for combinations loaded from existing file)
  60. String newCombination = vsName + " " + vsDefines + " " + psName + " " + psDefines;
  61. if (usedCombinations_.Contains(newCombination))
  62. return;
  63. usedCombinations_.Insert(newCombination);
  64. XMLElement shaderElem = xmlFile_.GetRoot().CreateChild("shader");
  65. shaderElem.SetAttribute("vs", vsName);
  66. shaderElem.SetAttribute("vsdefines", vsDefines);
  67. shaderElem.SetAttribute("ps", psName);
  68. shaderElem.SetAttribute("psdefines", psDefines);
  69. }
  70. void ShaderPrecache::LoadShaders(Graphics* graphics, Deserializer& source)
  71. {
  72. URHO3D_LOGDEBUG("Begin precaching shaders");
  73. XMLFile xmlFile(graphics->GetContext());
  74. xmlFile.Load(source);
  75. XMLElement shader = xmlFile.GetRoot().GetChild("shader");
  76. while (shader)
  77. {
  78. String vsDefines = shader.GetAttribute("vsdefines");
  79. String psDefines = shader.GetAttribute("psdefines");
  80. // Check for illegal variations on OpenGL ES and skip them
  81. #if defined(GL_ES_VERSION_2_0) && !defined(GL_ES_VERSION_3_0)
  82. if (
  83. #ifndef __EMSCRIPTEN__
  84. vsDefines.Contains("INSTANCED") ||
  85. #endif
  86. (psDefines.Contains("POINTLIGHT") && psDefines.Contains("SHADOW")))
  87. {
  88. shader = shader.GetNext("shader");
  89. continue;
  90. }
  91. #endif
  92. ShaderVariation* vs = graphics->GetShader(VS, shader.GetAttribute("vs"), vsDefines);
  93. ShaderVariation* ps = graphics->GetShader(PS, shader.GetAttribute("ps"), psDefines);
  94. // Set the shaders active to actually compile them
  95. graphics->SetShaders(vs, ps);
  96. shader = shader.GetNext("shader");
  97. }
  98. URHO3D_LOGDEBUG("End precaching shaders");
  99. }
  100. }