BsVulkanGpuParams.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanGpuParams.h"
  4. #include "BsVulkanUtility.h"
  5. #include "BsVulkanRenderAPI.h"
  6. #include "BsVulkanDevice.h"
  7. #include "BsVulkanGpuParamBlockBuffer.h"
  8. #include "BsVulkanGpuBuffer.h"
  9. #include "BsVulkanTexture.h"
  10. #include "BsVulkanHardwareBuffer.h"
  11. #include "BsVulkanDescriptorSet.h"
  12. #include "BsVulkanSamplerState.h"
  13. #include "BsGpuParamDesc.h"
  14. namespace BansheeEngine
  15. {
  16. VulkanGpuParams::VulkanGpuParams(const GPU_PARAMS_DESC& desc, GpuDeviceFlags deviceMask)
  17. : GpuParamsCore(desc, deviceMask), mPerDeviceData(), mDeviceMask(deviceMask), mData(nullptr), mSetsDirty(nullptr)
  18. {
  19. // Generate all required bindings
  20. UINT32 numBindings = 0;
  21. UINT32 numSets = 0;
  22. UINT32 numElementTypes = (UINT32)ElementType::Count;
  23. for (UINT32 i = 0; i < numElementTypes; i++)
  24. {
  25. numBindings += mNumElements[i];
  26. numSets = std::max(numSets, mNumSets[i]);
  27. }
  28. UINT32 bindingsPerSetBytes = sizeof(UINT32) * numSets;
  29. UINT32* bindingsPerSet = (UINT32*)bs_stack_alloc(bindingsPerSetBytes);
  30. UINT32 bindingsSize = sizeof(VkDescriptorSetLayoutBinding) * numBindings;
  31. VkDescriptorSetLayoutBinding* bindings = (VkDescriptorSetLayoutBinding*)bs_stack_alloc(bindingsSize);
  32. memset(bindings, 0, bindingsSize);
  33. UINT32 globalBindingIdx = 0;
  34. for (UINT32 i = 0; i < numSets; i++)
  35. {
  36. bindingsPerSet[i] = 0;
  37. for (UINT32 j = 0; j < numElementTypes; j++)
  38. {
  39. if (i >= mNumSets[j])
  40. continue;
  41. UINT32 start = mOffsets[j][i];
  42. UINT32 end;
  43. if (i < (mNumSets[j] - 1))
  44. end = mOffsets[j][i + 1];
  45. else
  46. end = mNumElements[j];
  47. UINT32 elementsInSet = end - start;
  48. for (UINT32 k = 0; k < elementsInSet; k++)
  49. {
  50. VkDescriptorSetLayoutBinding& binding = bindings[globalBindingIdx + k];
  51. binding.binding = bindingsPerSet[i] + k;
  52. }
  53. globalBindingIdx += elementsInSet;
  54. bindingsPerSet[i] += elementsInSet;
  55. }
  56. }
  57. UINT32* bindingOffsets = (UINT32*)bs_stack_alloc(sizeof(UINT32) * numSets);
  58. if (numSets > 0)
  59. {
  60. bindingOffsets[0] = 0;
  61. for (UINT32 i = 1; i < numSets; i++)
  62. bindingOffsets[i] = bindingsPerSet[i - 1];
  63. }
  64. VkShaderStageFlags stageFlagsLookup[6];
  65. stageFlagsLookup[GPT_VERTEX_PROGRAM] = VK_SHADER_STAGE_VERTEX_BIT;
  66. stageFlagsLookup[GPT_HULL_PROGRAM] = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
  67. stageFlagsLookup[GPT_DOMAIN_PROGRAM] = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
  68. stageFlagsLookup[GPT_GEOMETRY_PROGRAM] = VK_SHADER_STAGE_GEOMETRY_BIT;
  69. stageFlagsLookup[GPT_FRAGMENT_PROGRAM] = VK_SHADER_STAGE_FRAGMENT_BIT;
  70. stageFlagsLookup[GPT_COMPUTE_PROGRAM] = VK_SHADER_STAGE_COMPUTE_BIT;
  71. UINT32 numParamDescs = sizeof(mParamDescs) / sizeof(mParamDescs[0]);
  72. for (UINT32 i = 0; i < numParamDescs; i++)
  73. {
  74. const SPtr<GpuParamDesc>& paramDesc = mParamDescs[i];
  75. if (paramDesc == nullptr)
  76. continue;
  77. auto setUpBindings = [&](auto& params, VkDescriptorType descType)
  78. {
  79. for (auto& entry : params)
  80. {
  81. UINT32 bindingIdx = bindingOffsets[entry.second.set] + entry.second.slot;
  82. VkDescriptorSetLayoutBinding& binding = bindings[bindingIdx];
  83. binding.descriptorCount = 1;
  84. binding.stageFlags |= stageFlagsLookup[i];
  85. binding.descriptorType = descType;
  86. }
  87. };
  88. // Note: Assuming all textures and samplers use the same set/slot combination, and that they're combined
  89. setUpBindings(paramDesc->paramBlocks, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
  90. setUpBindings(paramDesc->textures, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
  91. setUpBindings(paramDesc->loadStoreTextures, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
  92. setUpBindings(paramDesc->samplers, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
  93. // Set up buffer bindings
  94. for (auto& entry : paramDesc->buffers)
  95. {
  96. bool isLoadStore = entry.second.type != GPOT_BYTE_BUFFER &&
  97. entry.second.type != GPOT_STRUCTURED_BUFFER;
  98. UINT32 bindingIdx = bindingOffsets[entry.second.set] + entry.second.slot;
  99. VkDescriptorSetLayoutBinding& binding = bindings[bindingIdx];
  100. binding.descriptorCount = 1;
  101. binding.stageFlags |= stageFlagsLookup[i];
  102. binding.descriptorType = isLoadStore ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
  103. }
  104. }
  105. VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPICore::instance());
  106. VulkanDevice* devices[BS_MAX_DEVICES];
  107. // Allocate layouts per-device
  108. UINT32 numDevices = 0;
  109. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  110. {
  111. if (VulkanUtility::isDeviceIdxSet(rapi, i, deviceMask))
  112. devices[i] = rapi._getDevice(i).get();
  113. else
  114. devices[i] = nullptr;
  115. numDevices++;
  116. }
  117. // Note: I'm assuming a single WriteInfo per binding, but if arrays sizes larger than 1 are eventually supported
  118. // I'll need to adjust the code.
  119. UINT32 setsDirtyBytes = sizeof(bool) * numSets;
  120. UINT32 perSetBytes = sizeof(PerSetData) * numSets;
  121. UINT32 writeSetInfosBytes = sizeof(VkWriteDescriptorSet) * numBindings;
  122. UINT32 writeInfosBytes = sizeof(WriteInfo) * numBindings;
  123. mData = (UINT8*)bs_alloc(setsDirtyBytes + (perSetBytes + writeSetInfosBytes + writeInfosBytes) * numDevices);
  124. UINT8* dataIter = mData;
  125. mSetsDirty = (bool*)dataIter;
  126. memset(mSetsDirty, 1, setsDirtyBytes);
  127. dataIter += setsDirtyBytes;
  128. for(UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  129. {
  130. if(devices[i] == nullptr)
  131. {
  132. mPerDeviceData[i].numSets = 0;
  133. mPerDeviceData[i].perSetData = nullptr;
  134. continue;
  135. }
  136. mPerDeviceData[i].numSets = numSets;
  137. mPerDeviceData[i].perSetData = (PerSetData*)dataIter;
  138. dataIter += sizeof(perSetBytes);
  139. VulkanDescriptorManager& descManager = devices[i]->getDescriptorManager();
  140. UINT32 bindingOffset = 0;
  141. for (UINT32 j = 0; j < numSets; j++)
  142. {
  143. UINT32 numBindingsPerSet = bindingsPerSet[j];
  144. PerSetData& perSetData = mPerDeviceData[i].perSetData[j];
  145. perSetData.writeSetInfos = (VkWriteDescriptorSet*)dataIter;
  146. dataIter += sizeof(VkWriteDescriptorSet) * numBindingsPerSet;
  147. perSetData.writeInfos = (WriteInfo*)dataIter;
  148. dataIter += sizeof(WriteInfo) * numBindingsPerSet;
  149. VkDescriptorSetLayoutBinding* perSetBindings = &bindings[bindingOffset];
  150. perSetData.layout = descManager.getLayout(perSetBindings, numBindingsPerSet);
  151. perSetData.set = descManager.createSet(perSetData.layout);
  152. perSetData.numElements = numBindingsPerSet;
  153. for(UINT32 k = 0; k < numBindingsPerSet; k++)
  154. {
  155. // Note: Instead of using one structure per binding, it's possible to update multiple at once
  156. // by specifying larger descriptorCount, if they all share type and shader stages.
  157. VkWriteDescriptorSet& writeSetInfo = perSetData.writeSetInfos[k];
  158. writeSetInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  159. writeSetInfo.pNext = nullptr;
  160. writeSetInfo.dstSet = VK_NULL_HANDLE; // TODO
  161. writeSetInfo.dstBinding = perSetBindings[k].binding;
  162. writeSetInfo.dstArrayElement = 0;
  163. writeSetInfo.descriptorCount = perSetBindings[k].descriptorCount;
  164. writeSetInfo.descriptorType = perSetBindings[k].descriptorType;
  165. bool isImage = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
  166. writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
  167. writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
  168. if(isImage)
  169. {
  170. bool isLoadStore = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
  171. VkDescriptorImageInfo& imageInfo = perSetData.writeInfos[k].image;
  172. imageInfo.sampler = VK_NULL_HANDLE;
  173. imageInfo.imageView = VK_NULL_HANDLE;
  174. imageInfo.imageLayout = isLoadStore ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  175. writeSetInfo.pImageInfo = &imageInfo;
  176. writeSetInfo.pBufferInfo = nullptr;
  177. writeSetInfo.pTexelBufferView = nullptr;
  178. }
  179. else
  180. {
  181. bool isLoadStore = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
  182. if (!isLoadStore)
  183. {
  184. VkDescriptorBufferInfo& bufferInfo = perSetData.writeInfos[k].buffer;
  185. bufferInfo.buffer = VK_NULL_HANDLE;
  186. bufferInfo.offset = 0;
  187. bufferInfo.range = VK_WHOLE_SIZE;
  188. writeSetInfo.pBufferInfo = &bufferInfo;
  189. }
  190. else
  191. writeSetInfo.pBufferInfo = nullptr;
  192. writeSetInfo.pTexelBufferView = nullptr;
  193. writeSetInfo.pImageInfo = nullptr;
  194. }
  195. }
  196. bindingOffset += numBindingsPerSet;
  197. }
  198. }
  199. bs_stack_free(bindingOffsets);
  200. bs_stack_free(bindings);
  201. bs_stack_free(bindingsPerSet);
  202. }
  203. VulkanGpuParams::~VulkanGpuParams()
  204. {
  205. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  206. {
  207. for (UINT32 j = 0; j < mPerDeviceData[i].numSets; j++)
  208. mPerDeviceData[i].perSetData[j].set->destroy();
  209. }
  210. bs_free(mData); // Everything allocated under a single buffer to a single free is enough
  211. }
  212. void VulkanGpuParams::setParamBlockBuffer(UINT32 set, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& paramBlockBuffer)
  213. {
  214. GpuParamsCore::setParamBlockBuffer(set, slot, paramBlockBuffer);
  215. VulkanGpuParamBlockBufferCore* vulkanParamBlockBuffer =
  216. static_cast<VulkanGpuParamBlockBufferCore*>(paramBlockBuffer.get());
  217. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  218. {
  219. if (mPerDeviceData[i].perSetData == nullptr)
  220. continue;
  221. VulkanBuffer* bufferRes = vulkanParamBlockBuffer->getResource(i);
  222. if (bufferRes != nullptr)
  223. mPerDeviceData[i].perSetData[set].writeInfos[slot].buffer.buffer = bufferRes->getHandle();
  224. else
  225. mPerDeviceData[i].perSetData[set].writeInfos[slot].buffer.buffer = VK_NULL_HANDLE;
  226. }
  227. mSetsDirty[set] = true;
  228. }
  229. void VulkanGpuParams::setTexture(UINT32 set, UINT32 slot, const SPtr<TextureCore>& texture)
  230. {
  231. GpuParamsCore::setTexture(set, slot, texture);
  232. VulkanTextureCore* vulkanTexture = static_cast<VulkanTextureCore*>(texture.get());
  233. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  234. {
  235. if (mPerDeviceData[i].perSetData == nullptr)
  236. continue;
  237. mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = vulkanTexture->getView(i);
  238. }
  239. mSetsDirty[set] = true;
  240. }
  241. void VulkanGpuParams::setLoadStoreTexture(UINT32 set, UINT32 slot, const SPtr<TextureCore>& texture,
  242. const TextureSurface& surface)
  243. {
  244. GpuParamsCore::setLoadStoreTexture(set, slot, texture, surface);
  245. VulkanTextureCore* vulkanTexture = static_cast<VulkanTextureCore*>(texture.get());
  246. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  247. {
  248. if (mPerDeviceData[i].perSetData == nullptr)
  249. continue;
  250. mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = vulkanTexture->getView(i, surface);
  251. }
  252. mSetsDirty[set] = true;
  253. }
  254. void VulkanGpuParams::setBuffer(UINT32 set, UINT32 slot, const SPtr<GpuBufferCore>& buffer)
  255. {
  256. GpuParamsCore::setBuffer(set, slot, buffer);
  257. VulkanGpuBufferCore* vulkanBuffer = static_cast<VulkanGpuBufferCore*>(buffer.get());
  258. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  259. {
  260. if (mPerDeviceData[i].perSetData == nullptr)
  261. continue;
  262. VulkanBuffer* bufferRes = vulkanBuffer->getResource(i);
  263. if (bufferRes != nullptr)
  264. mPerDeviceData[i].perSetData[set].writeInfos[slot].bufferView = bufferRes->getView();
  265. else
  266. mPerDeviceData[i].perSetData[set].writeInfos[slot].bufferView = VK_NULL_HANDLE;
  267. }
  268. mSetsDirty[set] = true;
  269. }
  270. void VulkanGpuParams::setSamplerState(UINT32 set, UINT32 slot, const SPtr<SamplerStateCore>& sampler)
  271. {
  272. GpuParamsCore::setSamplerState(set, slot, sampler);
  273. VulkanSamplerStateCore* vulkanSampler = static_cast<VulkanSamplerStateCore*>(sampler.get());
  274. for(UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  275. {
  276. if (mPerDeviceData[i].perSetData == nullptr)
  277. continue;
  278. VulkanSampler* samplerRes = vulkanSampler->getResource(i);
  279. if (samplerRes != nullptr)
  280. mPerDeviceData[i].perSetData[set].writeInfos[slot].image.sampler = samplerRes->getHandle();
  281. else
  282. mPerDeviceData[i].perSetData[set].writeInfos[slot].image.sampler = VK_NULL_HANDLE;
  283. }
  284. mSetsDirty[set] = true;
  285. }
  286. void VulkanGpuParams::setLoadStoreSurface(UINT32 set, UINT32 slot, const TextureSurface& surface)
  287. {
  288. GpuParamsCore::setLoadStoreSurface(set, slot, surface);
  289. SPtr<TextureCore> texture = getLoadStoreTexture(set, slot);
  290. if (texture == nullptr)
  291. return;
  292. VulkanTextureCore* vulkanTexture = static_cast<VulkanTextureCore*>(texture.get());
  293. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  294. {
  295. if (mPerDeviceData[i].perSetData == nullptr)
  296. continue;
  297. mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = vulkanTexture->getView(i, surface);
  298. }
  299. mSetsDirty[set] = true;
  300. }
  301. }