Functions.cpp 4.9 KB

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