BsGpuParamsProxy.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include "BsGpuParamsProxy.h"
  2. #include "BsGpuParams.h"
  3. #include "BsGpuParamDesc.h"
  4. #include "BsBindableGpuParamBlock.h"
  5. #include "BsGpuParamBlockBuffer.h"
  6. #include "BsDebug.h"
  7. #include "BsFrameAlloc.h"
  8. namespace BansheeEngine
  9. {
  10. /**
  11. * @brief Specialized class for send GPU parameters to the core thread. Represents a single
  12. * parameter block buffer and is used for temporary storage of GPU parameters.
  13. *
  14. * @note Due to the way allocation is handled, this class is not allowed to have a destructor.
  15. *
  16. * @see BindableGpuParams
  17. */
  18. class BS_CORE_EXPORT GpuParamsBlockProxy
  19. {
  20. public:
  21. GpuParamsBlockProxy()
  22. :mDirty(true), mData(nullptr), mSize(0)
  23. { }
  24. /**
  25. * @brief Uploads the current data to the specified buffer, and marks the block a non-dirty.
  26. *
  27. * @note Core thread only.
  28. */
  29. void uploadToBuffer(GpuParamBlockBufferPtr buffer)
  30. {
  31. buffer->writeData(mData);
  32. mDirty = false;
  33. }
  34. /**
  35. * @brief Query if this object is dirty. If dirty the data of this block
  36. * will need to be uploaded to a GPU buffer.
  37. *
  38. * @note Core thread only.
  39. */
  40. bool isDirty() const { return mDirty; }
  41. protected:
  42. friend class GpuParams;
  43. friend class GpuParamsProxy;
  44. UINT8* mData;
  45. UINT32 mSize;
  46. bool mDirty;
  47. };
  48. GpuParamsProxy::GpuParamsProxy(const GpuParamsPtr& params, FrameAlloc* allocator)
  49. :mParamDesc(params->getParamDesc()), mData(nullptr), mNumParamBlocks(0), mAllocator(allocator),
  50. mNumTextures(0), mNumSamplerStates(0),mParamBlocks(nullptr), mParamBlockBuffers(nullptr), mTextures(nullptr), mSamplerStates(nullptr)
  51. {
  52. // Allocate everything in a single block of memory to get rid of extra memory allocations
  53. UINT32 paramBlockBufferSize = params->mInternalData->mNumParamBlocks * sizeof(GpuParamsBlockProxy*);
  54. UINT32 paramBlockBuffersBufferSize = params->mInternalData->mNumParamBlocks * sizeof(GpuParamBlockBufferPtr);
  55. UINT32 textureBufferSize = params->mInternalData->mNumTextures * sizeof(HTexture);
  56. UINT32 samplerStateBufferSize = params->mInternalData->mNumSamplerStates * sizeof(HSamplerState);
  57. UINT32 bufferSize = paramBlockBufferSize + paramBlockBuffersBufferSize + textureBufferSize + samplerStateBufferSize;
  58. for (UINT32 i = 0; i < params->mInternalData->mNumParamBlocks; i++)
  59. {
  60. if (params->mInternalData->mParamBlockBuffers[i] != nullptr)
  61. bufferSize += sizeof(GpuParamsBlockProxy)+params->mInternalData->mParamBlockBuffers[i]->getSize();
  62. }
  63. mData = (UINT8*)allocator->alloc(bufferSize);
  64. mNumParamBlocks = params->mInternalData->mNumParamBlocks;
  65. mNumTextures = params->mInternalData->mNumTextures;
  66. mNumSamplerStates = params->mInternalData->mNumSamplerStates;
  67. UINT8* dataIter = mData;
  68. mParamBlocks = (GpuParamsBlockProxy**)dataIter;
  69. dataIter += paramBlockBufferSize;
  70. mParamBlockBuffers = (GpuParamBlockBufferPtr*)dataIter;
  71. dataIter += paramBlockBuffersBufferSize;
  72. mTextures = (HTexture*)dataIter;
  73. dataIter += textureBufferSize;
  74. mSamplerStates = (HSamplerState*)dataIter;
  75. dataIter += samplerStateBufferSize;
  76. // Copy data
  77. memcpy(mParamBlockBuffers, params->mInternalData->mParamBlockBuffers, paramBlockBuffersBufferSize);
  78. memcpy(mTextures, params->mInternalData->mTextures, textureBufferSize);
  79. memcpy(mSamplerStates, params->mInternalData->mSamplerStates, samplerStateBufferSize);
  80. for (UINT32 i = 0; i < params->mInternalData->mNumParamBlocks; i++)
  81. {
  82. if (params->mInternalData->mParamBlockBuffers[i] != nullptr)
  83. {
  84. GpuParamBlock* paramBlock = params->mInternalData->mParamBlockBuffers[i]->getParamBlock();
  85. UINT32 bufferSize = paramBlock->getSize();
  86. mParamBlocks[i] = (GpuParamsBlockProxy*)dataIter;
  87. dataIter += sizeof(GpuParamsBlockProxy);
  88. mParamBlocks[i]->mData = dataIter;
  89. dataIter += bufferSize;
  90. memcpy(mParamBlocks[i]->mData, paramBlock->getData(), bufferSize);
  91. mParamBlocks[i]->mSize = bufferSize;
  92. mParamBlocks[i]->mDirty = paramBlock->isDirty();
  93. }
  94. }
  95. }
  96. GpuParamsProxy::~GpuParamsProxy()
  97. {
  98. if(mData != nullptr)
  99. {
  100. mAllocator->dealloc(mData);
  101. }
  102. }
  103. GpuParamBlockBufferPtr GpuParamsProxy::getParamBlockBuffer(UINT32 slot) const
  104. {
  105. if(slot < 0 || slot >= mNumParamBlocks)
  106. {
  107. BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
  108. toString(mNumParamBlocks - 1) + ". Requested: " + toString(slot));
  109. }
  110. return mParamBlockBuffers[slot];
  111. }
  112. GpuParamBlockBufferPtr GpuParamsProxy::getParamBlockBuffer(const String& name) const
  113. {
  114. auto iterFind = mParamDesc.paramBlocks.find(name);
  115. if(iterFind == mParamDesc.paramBlocks.end())
  116. {
  117. LOGWRN("Cannot find parameter block with the name: " + name);
  118. return nullptr;
  119. }
  120. return mParamBlockBuffers[iterFind->second.slot];
  121. }
  122. HTexture GpuParamsProxy::getTexture(UINT32 slot)
  123. {
  124. if(slot < 0 || slot >= mNumTextures)
  125. {
  126. BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
  127. toString(mNumTextures - 1) + ". Requested: " + toString(slot));
  128. }
  129. return mTextures[slot];
  130. }
  131. HSamplerState GpuParamsProxy::getSamplerState(UINT32 slot)
  132. {
  133. if(slot < 0 || slot >= mNumSamplerStates)
  134. {
  135. BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
  136. toString(mNumSamplerStates - 1) + ". Requested: " + toString(slot));
  137. }
  138. return mSamplerStates[slot];
  139. }
  140. void GpuParamsProxy::updateHardwareBuffers()
  141. {
  142. for(size_t i = 0; i < mNumParamBlocks; i++)
  143. {
  144. if(mParamBlocks[i] != nullptr && mParamBlockBuffers[i] != nullptr)
  145. {
  146. if(mParamBlocks[i]->isDirty())
  147. mParamBlocks[i]->uploadToBuffer(mParamBlockBuffers[i]);
  148. }
  149. }
  150. }
  151. }