ShaderProgramResource.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Resource/ResourceObject.h>
  7. #include <AnKi/ShaderCompiler/ShaderCompiler.h>
  8. #include <AnKi/Gr/BackendCommon/Functions.h>
  9. #include <AnKi/Gr/ShaderProgram.h>
  10. #include <AnKi/Util/BitSet.h>
  11. #include <AnKi/Util/String.h>
  12. #include <AnKi/Util/HashMap.h>
  13. #include <AnKi/Util/WeakArray.h>
  14. #include <AnKi/Math.h>
  15. namespace anki {
  16. // Forward
  17. class ShaderProgramResourceVariantInitInfo;
  18. /// @addtogroup resource
  19. /// @{
  20. /// Shader program resource variant.
  21. class ShaderProgramResourceVariant
  22. {
  23. friend class ShaderProgramResource;
  24. public:
  25. ShaderProgramResourceVariant();
  26. ~ShaderProgramResourceVariant();
  27. /// @note On ray tracing program resources it points to the actual ray tracing program that contains everything.
  28. ShaderProgram& getProgram() const
  29. {
  30. return *m_prog;
  31. }
  32. /// Only for hit ray tracing programs.
  33. U32 getShaderGroupHandleIndex() const
  34. {
  35. ANKI_ASSERT(m_shaderGroupHandleIndex < kMaxU32);
  36. return m_shaderGroupHandleIndex;
  37. }
  38. private:
  39. ShaderProgramPtr m_prog;
  40. U32 m_shaderGroupHandleIndex = kMaxU32; ///< Cache the index of the handle here.
  41. };
  42. class ShaderProgramResourceVariantInitInfo
  43. {
  44. friend class ShaderProgramResource;
  45. public:
  46. ShaderProgramResourceVariantInitInfo()
  47. {
  48. }
  49. ShaderProgramResourceVariantInitInfo(const ShaderProgramResourcePtr& ptr)
  50. : m_ptr(ptr)
  51. {
  52. }
  53. ~ShaderProgramResourceVariantInitInfo()
  54. {
  55. }
  56. ShaderProgramResourceVariantInitInfo& addMutation(CString name, MutatorValue t);
  57. /// Request a non default technique and specific shaders.
  58. void requestTechniqueAndTypes(ShaderTypeBit types, CString technique = "Unnamed")
  59. {
  60. ANKI_ASSERT(types != ShaderTypeBit::kNone);
  61. ANKI_ASSERT(!(m_shaderTypes & types) && "Shader types already requested. Possibly programmer's error");
  62. m_shaderTypes |= types;
  63. const U32 len = technique.getLength();
  64. ANKI_ASSERT(len > 0 && len <= kMaxTechniqueNameLength);
  65. for(ShaderType type : EnumBitsIterable<ShaderType, ShaderTypeBit>(types))
  66. {
  67. memcpy(m_techniqueNames[type].getBegin(), technique.cstr(), len + 1);
  68. }
  69. }
  70. private:
  71. static constexpr U32 kMaxMutators = 32;
  72. static constexpr U32 kMaxTechniqueNameLength = 32;
  73. ShaderProgramResourcePtr m_ptr;
  74. Array<MutatorValue, kMaxMutators> m_mutation; ///< The order of storing the values is important. It will be hashed.
  75. BitSet<kMaxMutators> m_setMutators = {false};
  76. Array<Array<Char, kMaxTechniqueNameLength + 1>, U32(ShaderType::kCount)> m_techniqueNames = {};
  77. ShaderTypeBit m_shaderTypes = ShaderTypeBit::kNone;
  78. };
  79. /// Shader program resource. It loads special AnKi programs.
  80. class ShaderProgramResource : public ResourceObject
  81. {
  82. public:
  83. ShaderProgramResource(CString fname, U32 uuid)
  84. : ResourceObject(fname, uuid)
  85. {
  86. }
  87. ~ShaderProgramResource();
  88. /// Load the resource.
  89. Error load(const ResourceFilename& filename, Bool async);
  90. /// Try to find a mutator.
  91. const ShaderBinaryMutator* tryFindMutator(CString name) const
  92. {
  93. for(const ShaderBinaryMutator& m : m_binary->m_mutators)
  94. {
  95. if(m.m_name.getBegin() == name)
  96. {
  97. return &m;
  98. }
  99. }
  100. return nullptr;
  101. }
  102. const ShaderBinary& getBinary() const
  103. {
  104. return *m_binary;
  105. }
  106. /// Get or create a graphics shader program variant. If returned variant is nullptr then it means that the mutation is skipped and thus incorrect.
  107. /// @note It's thread-safe.
  108. void getOrCreateVariant(const ShaderProgramResourceVariantInitInfo& info, const ShaderProgramResourceVariant*& variant) const;
  109. private:
  110. ShaderBinary* m_binary = nullptr;
  111. mutable ResourceHashMap<U64, ShaderProgramResourceVariant*> m_variants;
  112. mutable RWMutex m_mtx;
  113. ShaderProgramResourceVariant* createNewVariant(const ShaderProgramResourceVariantInitInfo& info) const;
  114. U32 findTechnique(CString name) const;
  115. };
  116. inline ShaderProgramResourceVariantInitInfo& ShaderProgramResourceVariantInitInfo::addMutation(CString name, MutatorValue t)
  117. {
  118. const ShaderBinaryMutator* m = m_ptr->tryFindMutator(name);
  119. ANKI_ASSERT(m);
  120. [[maybe_unused]] Bool valueExits = false;
  121. for(auto v : m->m_values)
  122. {
  123. if(v == t)
  124. {
  125. valueExits = true;
  126. break;
  127. }
  128. }
  129. ANKI_ASSERT(valueExits);
  130. const PtrSize mutatorIdx = m - m_ptr->getBinary().m_mutators.getBegin();
  131. m_mutation[mutatorIdx] = t;
  132. m_setMutators.set(mutatorIdx);
  133. return *this;
  134. }
  135. /// @}
  136. } // end namespace anki