BsParamBlocks.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsCorePrerequisites.h"
  5. #include "BsGpuParamDesc.h"
  6. #include "BsGpuParams.h"
  7. #include "BsRenderAPI.h"
  8. #include "BsGpuParamBlockBuffer.h"
  9. namespace bs { namespace ct
  10. {
  11. /** @addtogroup Renderer-Internal
  12. * @{
  13. */
  14. /** Wrapper for a single parameter in a parameter block buffer. */
  15. template<class T>
  16. class BS_CORE_EXPORT ParamBlockParam
  17. {
  18. public:
  19. ParamBlockParam() { }
  20. ParamBlockParam(const GpuParamDataDesc& paramDesc);
  21. /**
  22. * Sets the parameter in the provided parameter block buffer. Caller is responsible for ensuring the param block
  23. * buffer contains this parameter.
  24. */
  25. void set(const SPtr<GpuParamBlockBuffer>& paramBlock, const T& value, UINT32 arrayIdx = 0) const;
  26. /**
  27. * Gets the parameter in the provided parameter block buffer. Caller is responsible for ensuring the param block
  28. * buffer contains this parameter.
  29. */
  30. T get(const SPtr<GpuParamBlockBuffer>& paramBlock, UINT32 arrayIdx = 0) const;
  31. protected:
  32. GpuParamDataDesc mParamDesc;
  33. };
  34. /** Base class for all parameter blocks. */
  35. struct BS_CORE_EXPORT ParamBlock
  36. {
  37. virtual ~ParamBlock();
  38. virtual void initialize() = 0;
  39. };
  40. /**
  41. * Takes care of initializing param block definitions in a delayed manner since they depend on engine systems yet
  42. * are usually used as global variables which are initialized before engine systems are ready.
  43. */
  44. class BS_CORE_EXPORT ParamBlockManager : public Module<ParamBlockManager>
  45. {
  46. public:
  47. ParamBlockManager();
  48. /** Registers a new param block, and initializes it when ready. */
  49. static void registerBlock(ParamBlock* paramBlock);
  50. /** Removes the param block from the initialization list. */
  51. static void unregisterBlock(ParamBlock* paramBlock);
  52. private:
  53. static Vector<ParamBlock*> sToInitialize;
  54. };
  55. /**
  56. * Starts a new custom parameter block. Custom parameter blocks allow you to create C++ structures that map directly
  57. * to GPU program buffers (for example uniform buffer in OpenGL or constant buffer in DX). Must be followed by
  58. * BS_PARAM_BLOCK_END.
  59. */
  60. #define BS_PARAM_BLOCK_BEGIN(Name) \
  61. struct Name : ParamBlock \
  62. { \
  63. Name() \
  64. { \
  65. ParamBlockManager::registerBlock(this); \
  66. } \
  67. \
  68. SPtr<GpuParamBlockBuffer> createBuffer() const { return GpuParamBlockBuffer::create(mBlockSize); } \
  69. \
  70. private: \
  71. friend class ParamBlockManager; \
  72. \
  73. void initialize() override \
  74. { \
  75. mParams = getEntries(); \
  76. RenderAPI& rapi = RenderAPI::instance(); \
  77. \
  78. GpuParamBlockDesc blockDesc = rapi.generateParamBlockDesc(#Name, mParams); \
  79. mBlockSize = blockDesc.blockSize * sizeof(UINT32); \
  80. \
  81. initEntries(); \
  82. } \
  83. \
  84. struct META_FirstEntry {}; \
  85. static void META_GetPrevEntries(Vector<GpuParamDataDesc>& params, META_FirstEntry id) { } \
  86. void META_InitPrevEntry(const Vector<GpuParamDataDesc>& params, UINT32 idx, META_FirstEntry id) { } \
  87. \
  88. typedef META_FirstEntry
  89. /**
  90. * Registers a new entry in a parameter block. Must be called in between BS_PARAM_BLOCK_BEGIN and BS_PARAM_BLOCK_END calls.
  91. */
  92. #define BS_PARAM_BLOCK_ENTRY_ARRAY(Type, Name, NumElements) \
  93. META_Entry_##Name; \
  94. \
  95. struct META_NextEntry_##Name {}; \
  96. static void META_GetPrevEntries(Vector<GpuParamDataDesc>& params, META_NextEntry_##Name id) \
  97. { \
  98. META_GetPrevEntries(params, META_Entry_##Name()); \
  99. \
  100. params.push_back(GpuParamDataDesc()); \
  101. GpuParamDataDesc& newEntry = params.back(); \
  102. newEntry.name = #Name; \
  103. newEntry.type = (GpuParamDataType)TGpuDataParamInfo<Type>::TypeId; \
  104. newEntry.arraySize = NumElements; \
  105. } \
  106. \
  107. void META_InitPrevEntry(const Vector<GpuParamDataDesc>& params, UINT32 idx, META_NextEntry_##Name id) \
  108. { \
  109. META_InitPrevEntry(params, idx - 1, META_Entry_##Name()); \
  110. Name = ParamBlockParam<Type>(params[idx]); \
  111. } \
  112. \
  113. public: \
  114. ParamBlockParam<Type> Name; \
  115. \
  116. private: \
  117. typedef META_NextEntry_##Name
  118. /**
  119. * Registers a new entry in a parameter block. Must be called in between BS_PARAM_BLOCK_BEGIN and BS_PARAM_BLOCK_END calls.
  120. */
  121. #define BS_PARAM_BLOCK_ENTRY(Type, Name) BS_PARAM_BLOCK_ENTRY_ARRAY(Type, Name, 1)
  122. /** Ends parameter block definition. See BS_PARAM_BLOCK_BEGIN. */
  123. #define BS_PARAM_BLOCK_END \
  124. META_LastEntry; \
  125. \
  126. static Vector<GpuParamDataDesc> getEntries() \
  127. { \
  128. Vector<GpuParamDataDesc> entries; \
  129. META_GetPrevEntries(entries, META_LastEntry()); \
  130. return entries; \
  131. } \
  132. \
  133. void initEntries() \
  134. { \
  135. META_InitPrevEntry(mParams, (UINT32)mParams.size() - 1, META_LastEntry()); \
  136. } \
  137. \
  138. Vector<GpuParamDataDesc> mParams; \
  139. UINT32 mBlockSize; \
  140. };
  141. /** @} */
  142. }}