BsGpuPipelineParamInfo.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "RenderAPI/BsGpuPipelineParamInfo.h"
  4. #include "RenderAPI/BsGpuParamDesc.h"
  5. #include "Managers/BsRenderStateManager.h"
  6. namespace bs
  7. {
  8. GpuPipelineParamInfoBase::GpuPipelineParamInfoBase(const GPU_PIPELINE_PARAMS_DESC& desc)
  9. :mNumSets(0), mNumElements(0), mSetInfos(nullptr), mResourceInfos()
  10. {
  11. bs_zero_out(mNumElementsPerType);
  12. mParamDescs[GPT_FRAGMENT_PROGRAM] = desc.fragmentParams;
  13. mParamDescs[GPT_VERTEX_PROGRAM] = desc.vertexParams;
  14. mParamDescs[GPT_GEOMETRY_PROGRAM] = desc.geometryParams;
  15. mParamDescs[GPT_HULL_PROGRAM] = desc.hullParams;
  16. mParamDescs[GPT_DOMAIN_PROGRAM] = desc.domainParams;
  17. mParamDescs[GPT_COMPUTE_PROGRAM] = desc.computeParams;
  18. auto countElements = [&](auto& entry, ParamType type)
  19. {
  20. int typeIdx = (int)type;
  21. if ((entry.set + 1) > mNumSets)
  22. mNumSets = entry.set + 1;
  23. mNumElementsPerType[typeIdx]++;
  24. mNumElements++;
  25. };
  26. UINT32 numParamDescs = sizeof(mParamDescs) / sizeof(mParamDescs[0]);
  27. for (UINT32 i = 0; i < numParamDescs; i++)
  28. {
  29. const SPtr<GpuParamDesc>& paramDesc = mParamDescs[i];
  30. if (paramDesc == nullptr)
  31. continue;
  32. for (auto& paramBlock : paramDesc->paramBlocks)
  33. countElements(paramBlock.second, ParamType::ParamBlock);
  34. for (auto& texture : paramDesc->textures)
  35. countElements(texture.second, ParamType::Texture);
  36. for (auto& texture : paramDesc->loadStoreTextures)
  37. countElements(texture.second, ParamType::LoadStoreTexture);
  38. for (auto& buffer : paramDesc->buffers)
  39. countElements(buffer.second, ParamType::Buffer);
  40. for (auto& sampler : paramDesc->samplers)
  41. countElements(sampler.second, ParamType::SamplerState);
  42. }
  43. UINT32* numSlotsPerSet = (UINT32*)bs_stack_alloc(mNumSets * sizeof(UINT32));
  44. bs_zero_out(numSlotsPerSet, mNumSets);
  45. for (UINT32 i = 0; i < numParamDescs; i++)
  46. {
  47. const SPtr<GpuParamDesc>& paramDesc = mParamDescs[i];
  48. if (paramDesc == nullptr)
  49. continue;
  50. for (auto& paramBlock : paramDesc->paramBlocks)
  51. numSlotsPerSet[paramBlock.second.set] =
  52. std::max(numSlotsPerSet[paramBlock.second.set], paramBlock.second.slot + 1);
  53. for (auto& texture : paramDesc->textures)
  54. numSlotsPerSet[texture.second.set] =
  55. std::max(numSlotsPerSet[texture.second.set], texture.second.slot + 1);
  56. for (auto& texture : paramDesc->loadStoreTextures)
  57. numSlotsPerSet[texture.second.set] =
  58. std::max(numSlotsPerSet[texture.second.set], texture.second.slot + 1);
  59. for (auto& buffer : paramDesc->buffers)
  60. numSlotsPerSet[buffer.second.set] =
  61. std::max(numSlotsPerSet[buffer.second.set], buffer.second.slot + 1);
  62. for (auto& sampler : paramDesc->samplers)
  63. numSlotsPerSet[sampler.second.set] =
  64. std::max(numSlotsPerSet[sampler.second.set], sampler.second.slot + 1);
  65. }
  66. UINT32 totalNumSlots = 0;
  67. for (UINT32 i = 0; i < mNumSets; i++)
  68. totalNumSlots += numSlotsPerSet[i];
  69. mAlloc.reserve<SetInfo>(mNumSets)
  70. .reserve<UINT32>(totalNumSlots)
  71. .reserve<ParamType>(totalNumSlots)
  72. .reserve<UINT32>(totalNumSlots);
  73. for (UINT32 i = 0; i < (UINT32)ParamType::Count; i++)
  74. mAlloc.reserve<ResourceInfo>(mNumElementsPerType[i]);
  75. mAlloc.init();
  76. mSetInfos = mAlloc.alloc<SetInfo>(mNumSets);
  77. if(mSetInfos != nullptr)
  78. bs_zero_out(mSetInfos, mNumSets);
  79. for (UINT32 i = 0; i < mNumSets; i++)
  80. mSetInfos[i].numSlots = numSlotsPerSet[i];
  81. bs_stack_free(numSlotsPerSet);
  82. for(UINT32 i = 0; i < mNumSets; i++)
  83. {
  84. mSetInfos[i].slotIndices = mAlloc.alloc<UINT32>(mSetInfos[i].numSlots);
  85. memset(mSetInfos[i].slotIndices, -1, sizeof(UINT32) * mSetInfos[i].numSlots);
  86. mSetInfos[i].slotTypes = mAlloc.alloc<ParamType>(mSetInfos[i].numSlots);
  87. mSetInfos[i].slotSamplers = mAlloc.alloc<UINT32>(mSetInfos[i].numSlots);
  88. memset(mSetInfos[i].slotSamplers, -1, sizeof(UINT32) * mSetInfos[i].numSlots);
  89. }
  90. for (UINT32 i = 0; i < (UINT32)ParamType::Count; i++)
  91. {
  92. mResourceInfos[i] = mAlloc.alloc<ResourceInfo>(mNumElementsPerType[i]);
  93. mNumElementsPerType[i] = 0;
  94. }
  95. auto populateSetInfo = [&](auto& entry, ParamType type)
  96. {
  97. int typeIdx = (int)type;
  98. UINT32 sequentialIdx = mNumElementsPerType[typeIdx];
  99. SetInfo& setInfo = mSetInfos[entry.set];
  100. setInfo.slotIndices[entry.slot] = sequentialIdx;
  101. setInfo.slotTypes[entry.slot] = type;
  102. mResourceInfos[typeIdx][sequentialIdx].set = entry.set;
  103. mResourceInfos[typeIdx][sequentialIdx].slot = entry.slot;
  104. mNumElementsPerType[typeIdx]++;
  105. };
  106. for (UINT32 i = 0; i < numParamDescs; i++)
  107. {
  108. const SPtr<GpuParamDesc>& paramDesc = mParamDescs[i];
  109. if (paramDesc == nullptr)
  110. continue;
  111. for (auto& paramBlock : paramDesc->paramBlocks)
  112. populateSetInfo(paramBlock.second, ParamType::ParamBlock);
  113. for (auto& texture : paramDesc->textures)
  114. populateSetInfo(texture.second, ParamType::Texture);
  115. for (auto& texture : paramDesc->loadStoreTextures)
  116. populateSetInfo(texture.second, ParamType::LoadStoreTexture);
  117. for (auto& buffer : paramDesc->buffers)
  118. populateSetInfo(buffer.second, ParamType::Buffer);
  119. // Samplers need to be handled specially because certain slots could be texture/buffer + sampler combinations
  120. {
  121. int typeIdx = (int)ParamType::SamplerState;
  122. for (auto& entry : paramDesc->samplers)
  123. {
  124. const GpuParamObjectDesc& samplerDesc = entry.second;
  125. UINT32 sequentialIdx = mNumElementsPerType[typeIdx];
  126. SetInfo& setInfo = mSetInfos[samplerDesc.set];
  127. if (setInfo.slotIndices[samplerDesc.slot] == (UINT32)-1) // Slot is sampler only
  128. {
  129. setInfo.slotIndices[samplerDesc.slot] = sequentialIdx;
  130. setInfo.slotTypes[samplerDesc.slot] = ParamType::SamplerState;
  131. }
  132. else // Slot is a combination
  133. {
  134. setInfo.slotSamplers[samplerDesc.slot] = sequentialIdx;
  135. }
  136. mResourceInfos[typeIdx][sequentialIdx].set = samplerDesc.set;
  137. mResourceInfos[typeIdx][sequentialIdx].slot = samplerDesc.slot;
  138. mNumElementsPerType[typeIdx]++;
  139. }
  140. }
  141. }
  142. }
  143. GpuPipelineParamInfoBase::~GpuPipelineParamInfoBase()
  144. { }
  145. UINT32 GpuPipelineParamInfoBase::getSequentialSlot(ParamType type, UINT32 set, UINT32 slot) const
  146. {
  147. #if BS_DEBUG_MODE
  148. if (set >= mNumSets)
  149. {
  150. LOGERR("Set index out of range: Valid range: [0, " +
  151. toString(mNumSets) + "). Requested: " + toString(set) + ".");
  152. return -1;
  153. }
  154. if (slot >= mSetInfos[set].numSlots)
  155. {
  156. LOGERR("Slot index out of range: Valid range: [0, " +
  157. toString(mSetInfos[set].numSlots) + "). Requested: " + toString(slot) + ".");
  158. return -1;
  159. }
  160. ParamType slotType = mSetInfos[set].slotTypes[slot];
  161. if(slotType != type)
  162. {
  163. // Allow sampler states & textures/buffers to share the same slot, as some APIs combine them
  164. if(type == ParamType::SamplerState)
  165. {
  166. if (mSetInfos[set].slotSamplers[slot] != (UINT32)-1)
  167. return mSetInfos[set].slotSamplers[slot];
  168. }
  169. LOGERR("Requested parameter is not of the valid type. Requested: " + toString((UINT32)type) + ". Actual: " +
  170. toString((UINT32)mSetInfos[set].slotTypes[slot]) + ".");
  171. return -1;
  172. }
  173. #endif
  174. return mSetInfos[set].slotIndices[slot];
  175. }
  176. void GpuPipelineParamInfoBase::getBinding(ParamType type, UINT32 sequentialSlot, UINT32& set, UINT32& slot) const
  177. {
  178. #if BS_DEBUG_MODE
  179. if(sequentialSlot >= mNumElementsPerType[(int)type])
  180. {
  181. LOGERR("Sequential slot index out of range: Valid range: [0, " + toString(mNumElementsPerType[(int)type]) +
  182. "). Requested: " + toString(sequentialSlot) + ".");
  183. set = 0;
  184. slot = 0;
  185. return;
  186. }
  187. #endif
  188. set = mResourceInfos[(int)type][sequentialSlot].set;
  189. slot = mResourceInfos[(int)type][sequentialSlot].slot;
  190. }
  191. void GpuPipelineParamInfoBase::getBindings(ParamType type, const String& name, GpuParamBinding (& bindings)[GPT_COUNT])
  192. {
  193. constexpr UINT32 numParamDescs = sizeof(mParamDescs) / sizeof(mParamDescs[0]);
  194. static_assert(
  195. numParamDescs == GPT_COUNT,
  196. "Number of param descriptor structures must match the number of GPU program stages."
  197. );
  198. for (UINT32 i = 0; i < numParamDescs; i++)
  199. getBinding((GpuProgramType)i, type, name, bindings[i]);
  200. }
  201. void GpuPipelineParamInfoBase::getBinding(GpuProgramType progType, ParamType type, const String& name,
  202. GpuParamBinding &binding)
  203. {
  204. auto findBinding = [](auto& paramMap, const String& name, GpuParamBinding& binding)
  205. {
  206. auto iterFind = paramMap.find(name);
  207. if (iterFind != paramMap.end())
  208. {
  209. binding.set = iterFind->second.set;
  210. binding.slot = iterFind->second.slot;
  211. }
  212. else
  213. binding.set = binding.slot = (UINT32)-1;
  214. };
  215. const SPtr<GpuParamDesc>& paramDesc = mParamDescs[(UINT32)progType];
  216. if (paramDesc == nullptr)
  217. {
  218. binding.set = binding.slot = (UINT32)-1;
  219. return;
  220. }
  221. switch(type)
  222. {
  223. case ParamType::ParamBlock:
  224. findBinding(paramDesc->paramBlocks, name, binding);
  225. break;
  226. case ParamType::Texture:
  227. findBinding(paramDesc->textures, name, binding);
  228. break;
  229. case ParamType::LoadStoreTexture:
  230. findBinding(paramDesc->loadStoreTextures, name, binding);
  231. break;
  232. case ParamType::Buffer:
  233. findBinding(paramDesc->buffers, name, binding);
  234. break;
  235. case ParamType::SamplerState:
  236. findBinding(paramDesc->samplers, name, binding);
  237. break;
  238. default:
  239. break;
  240. }
  241. }
  242. GpuPipelineParamInfo::GpuPipelineParamInfo(const GPU_PIPELINE_PARAMS_DESC& desc)
  243. :GpuPipelineParamInfoBase(desc)
  244. { }
  245. SPtr<GpuPipelineParamInfo> GpuPipelineParamInfo::create(const GPU_PIPELINE_PARAMS_DESC& desc)
  246. {
  247. SPtr<GpuPipelineParamInfo> paramInfo =
  248. bs_core_ptr<GpuPipelineParamInfo>(new (bs_alloc<GpuPipelineParamInfo>()) GpuPipelineParamInfo(desc));
  249. paramInfo->_setThisPtr(paramInfo);
  250. paramInfo->initialize();
  251. return paramInfo;
  252. }
  253. SPtr<ct::GpuPipelineParamInfo> GpuPipelineParamInfo::getCore() const
  254. {
  255. return std::static_pointer_cast<ct::GpuPipelineParamInfo>(mCoreSpecific);
  256. }
  257. SPtr<ct::CoreObject> GpuPipelineParamInfo::createCore() const
  258. {
  259. GPU_PIPELINE_PARAMS_DESC desc;
  260. desc.fragmentParams = mParamDescs[GPT_FRAGMENT_PROGRAM];
  261. desc.vertexParams = mParamDescs[GPT_VERTEX_PROGRAM];
  262. desc.geometryParams = mParamDescs[GPT_GEOMETRY_PROGRAM];
  263. desc.hullParams = mParamDescs[GPT_HULL_PROGRAM];
  264. desc.domainParams = mParamDescs[GPT_DOMAIN_PROGRAM];
  265. desc.computeParams = mParamDescs[GPT_COMPUTE_PROGRAM];
  266. return ct::RenderStateManager::instance()._createPipelineParamInfo(desc);
  267. }
  268. namespace ct
  269. {
  270. GpuPipelineParamInfo::GpuPipelineParamInfo(const GPU_PIPELINE_PARAMS_DESC& desc, GpuDeviceFlags deviceMask)
  271. :GpuPipelineParamInfoBase(desc)
  272. { }
  273. SPtr<GpuPipelineParamInfo> GpuPipelineParamInfo::create(const GPU_PIPELINE_PARAMS_DESC& desc,
  274. GpuDeviceFlags deviceMask)
  275. {
  276. return RenderStateManager::instance().createPipelineParamInfo(desc, deviceMask);
  277. }
  278. }
  279. }