Functions.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Gr/Utils/Functions.h>
  6. namespace anki
  7. {
  8. template<typename T>
  9. static void writeShaderBlockMemorySanityChecks(const ShaderVariableBlockInfo& varBlkInfo, const void* elements,
  10. U32 elementsCount, void* buffBegin, const void* buffEnd)
  11. {
  12. // Check args
  13. ANKI_ASSERT(elements != nullptr);
  14. ANKI_ASSERT(elementsCount > 0);
  15. ANKI_ASSERT(buffBegin != nullptr);
  16. ANKI_ASSERT(buffEnd != nullptr);
  17. ANKI_ASSERT(buffBegin < buffEnd);
  18. ANKI_ASSERT(isAligned(alignof(T), ptrToNumber(elements)) && "Breaking strict aliasing rules");
  19. ANKI_ASSERT(isAligned(alignof(T), ptrToNumber(static_cast<U8*>(buffBegin) + varBlkInfo.m_offset))
  20. && "Breaking strict aliasing rules");
  21. // Check varBlkInfo
  22. ANKI_ASSERT(varBlkInfo.m_offset != -1);
  23. ANKI_ASSERT(varBlkInfo.m_arraySize > 0);
  24. if(varBlkInfo.m_arraySize > 1)
  25. {
  26. ANKI_ASSERT(varBlkInfo.m_arrayStride > 0);
  27. }
  28. // Check array size
  29. ANKI_ASSERT(I16(elementsCount) <= varBlkInfo.m_arraySize);
  30. }
  31. template<typename T>
  32. static void writeShaderBlockMemorySimple(const ShaderVariableBlockInfo& varBlkInfo, const void* elements,
  33. U32 elementsCount, void* buffBegin, const void* buffEnd)
  34. {
  35. writeShaderBlockMemorySanityChecks<T>(varBlkInfo, elements, elementsCount, buffBegin, buffEnd);
  36. U8* buff = static_cast<U8*>(buffBegin) + varBlkInfo.m_offset;
  37. for(U i = 0; i < elementsCount; i++)
  38. {
  39. ANKI_ASSERT(buff + sizeof(T) <= static_cast<const U8*>(buffEnd));
  40. T* out = reinterpret_cast<T*>(buff);
  41. const T* in = reinterpret_cast<const T*>(elements) + i;
  42. *out = *in;
  43. buff += varBlkInfo.m_arrayStride;
  44. }
  45. }
  46. template<typename T, typename Vec>
  47. static void writeShaderBlockMemoryMatrix(const ShaderVariableBlockInfo& varBlkInfo, const void* elements,
  48. U32 elementsCount, void* buffBegin, const void* buffEnd)
  49. {
  50. writeShaderBlockMemorySanityChecks<T>(varBlkInfo, elements, elementsCount, buffBegin, buffEnd);
  51. ANKI_ASSERT(varBlkInfo.m_matrixStride > 0);
  52. ANKI_ASSERT(varBlkInfo.m_matrixStride >= static_cast<I16>(sizeof(Vec)));
  53. U8* buff = static_cast<U8*>(buffBegin) + varBlkInfo.m_offset;
  54. for(U i = 0; i < elementsCount; i++)
  55. {
  56. U8* subbuff = buff;
  57. const T& matrix = static_cast<const T*>(elements)[i];
  58. for(U j = 0; j < sizeof(T) / sizeof(Vec); j++)
  59. {
  60. ANKI_ASSERT((subbuff + sizeof(Vec)) <= static_cast<const U8*>(buffEnd));
  61. Vec* out = reinterpret_cast<Vec*>(subbuff);
  62. *out = matrix.getRow(j);
  63. subbuff += varBlkInfo.m_matrixStride;
  64. }
  65. buff += varBlkInfo.m_arrayStride;
  66. }
  67. }
  68. // This is some trickery to select calling between writeShaderBlockMemoryMatrix and writeShaderBlockMemorySimple
  69. namespace
  70. {
  71. template<typename T>
  72. class IsShaderVarDataTypeAMatrix
  73. {
  74. public:
  75. static constexpr Bool VALUE = false;
  76. };
  77. #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
  78. template<> \
  79. class IsShaderVarDataTypeAMatrix<type> \
  80. { \
  81. public: \
  82. static constexpr Bool VALUE = rowCount * columnCount > 4; \
  83. };
  84. #include <AnKi/Gr/ShaderVariableDataTypeDefs.h>
  85. #undef ANKI_SVDT_MACRO
  86. template<typename T, Bool isMatrix = IsShaderVarDataTypeAMatrix<T>::VALUE>
  87. class WriteShaderBlockMemory
  88. {
  89. public:
  90. void operator()(const ShaderVariableBlockInfo& varBlkInfo, const void* elements, U32 elementsCount, void* buffBegin,
  91. const void* buffEnd)
  92. {
  93. using RowVec = typename T::RowVec;
  94. writeShaderBlockMemoryMatrix<T, RowVec>(varBlkInfo, elements, elementsCount, buffBegin, buffEnd);
  95. }
  96. };
  97. template<typename T>
  98. class WriteShaderBlockMemory<T, false>
  99. {
  100. public:
  101. void operator()(const ShaderVariableBlockInfo& varBlkInfo, const void* elements, U32 elementsCount, void* buffBegin,
  102. const void* buffEnd)
  103. {
  104. writeShaderBlockMemorySimple<T>(varBlkInfo, elements, elementsCount, buffBegin, buffEnd);
  105. }
  106. };
  107. } // namespace
  108. void writeShaderBlockMemory(ShaderVariableDataType type, const ShaderVariableBlockInfo& varBlkInfo,
  109. const void* elements, U32 elementsCount, void* buffBegin, const void* buffEnd)
  110. {
  111. switch(type)
  112. {
  113. #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
  114. case ShaderVariableDataType::capital: \
  115. WriteShaderBlockMemory<type>()(varBlkInfo, elements, elementsCount, buffBegin, buffEnd); \
  116. break;
  117. #include <AnKi/Gr/ShaderVariableDataTypeDefs.h>
  118. #undef ANKI_SVDT_MACRO
  119. default:
  120. ANKI_ASSERT(0);
  121. }
  122. }
  123. const CString shaderVariableDataTypeToString(ShaderVariableDataType t)
  124. {
  125. switch(t)
  126. {
  127. case ShaderVariableDataType::NONE:
  128. return "NONE";
  129. #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
  130. case ShaderVariableDataType::capital: \
  131. return ANKI_STRINGIZE(type);
  132. #define ANKI_SVDT_MACRO_OPAQUE(capital, type) ANKI_SVDT_MACRO(capital, type, 0, 0, 0)
  133. #include <AnKi/Gr/ShaderVariableDataTypeDefs.h>
  134. #undef ANKI_SVDT_MACRO
  135. #undef ANKI_SVDT_MACRO_OPAQUE
  136. default:
  137. ANKI_ASSERT(0);
  138. }
  139. ANKI_ASSERT(0);
  140. return "";
  141. }
  142. } // end namespace anki