BsVulkanGpuParams.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  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 "BsVulkanDescriptorLayout.h"
  13. #include "BsVulkanSamplerState.h"
  14. #include "BsVulkanGpuPipelineParamInfo.h"
  15. #include "BsVulkanCommandBuffer.h"
  16. #include "BsVulkanTextureManager.h"
  17. #include "BsVulkanHardwareBufferManager.h"
  18. #include "BsGpuParamDesc.h"
  19. namespace bs { namespace ct
  20. {
  21. VulkanGpuParams::VulkanGpuParams(const SPtr<GpuPipelineParamInfo>& paramInfo, GpuDeviceFlags deviceMask)
  22. : GpuParams(paramInfo, deviceMask), mPerDeviceData(), mDeviceMask(deviceMask), mSetsDirty(nullptr)
  23. {
  24. }
  25. VulkanGpuParams::~VulkanGpuParams()
  26. {
  27. Lock lock(mMutex);
  28. UINT32 numSets = mParamInfo->getNumSets();
  29. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  30. {
  31. if (mPerDeviceData[i].perSetData == nullptr)
  32. continue;
  33. for (UINT32 j = 0; j < numSets; j++)
  34. {
  35. for (auto& entry : mPerDeviceData[i].perSetData[j].sets)
  36. entry->destroy();
  37. mPerDeviceData[i].perSetData[j].sets.~Vector<VulkanDescriptorSet*>();
  38. }
  39. }
  40. }
  41. void VulkanGpuParams::initialize()
  42. {
  43. VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
  44. VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPI::instance());
  45. VulkanDevice* devices[BS_MAX_DEVICES];
  46. VulkanUtility::getDevices(rapi, mDeviceMask, devices);
  47. UINT32 numDevices = 0;
  48. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  49. {
  50. if (devices[i] != nullptr)
  51. numDevices++;
  52. }
  53. UINT32 numParamBlocks = vkParamInfo.getNumElements(GpuPipelineParamInfo::ParamType::ParamBlock);
  54. UINT32 numTextures = vkParamInfo.getNumElements(GpuPipelineParamInfo::ParamType::Texture);
  55. UINT32 numStorageTextures = vkParamInfo.getNumElements(GpuPipelineParamInfo::ParamType::LoadStoreTexture);
  56. UINT32 numBuffers = vkParamInfo.getNumElements(GpuPipelineParamInfo::ParamType::Buffer);
  57. UINT32 numSamplers = vkParamInfo.getNumElements(GpuPipelineParamInfo::ParamType::SamplerState);
  58. UINT32 numSets = vkParamInfo.getNumSets();
  59. UINT32 numBindings = vkParamInfo.getNumElements();
  60. if (numSets == 0)
  61. return;
  62. // Note: I'm assuming a single WriteInfo per binding, but if arrays sizes larger than 1 are eventually supported
  63. // I'll need to adjust the code.
  64. mAlloc.reserve<bool>(numSets)
  65. .reserve<PerSetData>(numSets * numDevices)
  66. .reserve<VkWriteDescriptorSet>(numBindings * numDevices)
  67. .reserve<WriteInfo>(numBindings * numDevices)
  68. .reserve<VkImage>(numTextures * numDevices)
  69. .reserve<VkImage>(numStorageTextures * numDevices)
  70. .reserve<VkBuffer>(numParamBlocks * numDevices)
  71. .reserve<VkBuffer>(numBuffers * numDevices)
  72. .reserve<VkSampler>(numSamplers * numDevices)
  73. .init();
  74. Lock lock(mMutex); // Set write operations need to be thread safe
  75. mSetsDirty = mAlloc.alloc<bool>(numSets);
  76. bs_zero_out(mSetsDirty, numSets);
  77. VulkanSamplerState* defaultSampler = static_cast<VulkanSamplerState*>(SamplerState::getDefault().get());
  78. VulkanTextureManager& vkTexManager = static_cast<VulkanTextureManager&>(TextureManager::instance());
  79. VulkanHardwareBufferManager& vkBufManager = static_cast<VulkanHardwareBufferManager&>(
  80. HardwareBufferManager::instance());
  81. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  82. {
  83. if (devices[i] == nullptr)
  84. {
  85. mPerDeviceData[i].perSetData = nullptr;
  86. continue;
  87. }
  88. mPerDeviceData[i].perSetData = mAlloc.alloc<PerSetData>(numSets);
  89. mPerDeviceData[i].sampledImages = mAlloc.alloc<VkImage>(numTextures);
  90. mPerDeviceData[i].storageImages = mAlloc.alloc<VkImage>(numStorageTextures);
  91. mPerDeviceData[i].uniformBuffers = mAlloc.alloc<VkBuffer>(numParamBlocks);
  92. mPerDeviceData[i].buffers = mAlloc.alloc<VkBuffer>(numBuffers);
  93. mPerDeviceData[i].samplers = mAlloc.alloc<VkSampler>(numSamplers);
  94. bs_zero_out(mPerDeviceData[i].sampledImages, numTextures);
  95. bs_zero_out(mPerDeviceData[i].storageImages, numStorageTextures);
  96. bs_zero_out(mPerDeviceData[i].uniformBuffers, numParamBlocks);
  97. bs_zero_out(mPerDeviceData[i].buffers, numBuffers);
  98. bs_zero_out(mPerDeviceData[i].samplers, numSamplers);
  99. VulkanDescriptorManager& descManager = devices[i]->getDescriptorManager();
  100. VulkanSampler* vkDefaultSampler = defaultSampler->getResource(i);
  101. for (UINT32 j = 0; j < numSets; j++)
  102. {
  103. UINT32 numBindingsPerSet = vkParamInfo.getNumBindings(j);
  104. PerSetData& perSetData = mPerDeviceData[i].perSetData[j];
  105. new (&perSetData.sets) Vector<VulkanDescriptorSet*>();
  106. perSetData.writeSetInfos = mAlloc.alloc<VkWriteDescriptorSet>(numBindingsPerSet);
  107. perSetData.writeInfos = mAlloc.alloc<WriteInfo>(numBindingsPerSet);
  108. VulkanDescriptorLayout* layout = vkParamInfo.getLayout(i, j);
  109. perSetData.numElements = numBindingsPerSet;
  110. perSetData.latestSet = descManager.createSet(layout);
  111. perSetData.sets.push_back(perSetData.latestSet);
  112. VkDescriptorSetLayoutBinding* perSetBindings = vkParamInfo.getBindings(j);
  113. for (UINT32 k = 0; k < numBindingsPerSet; k++)
  114. {
  115. // Note: Instead of using one structure per binding, it's possible to update multiple at once
  116. // by specifying larger descriptorCount, if they all share type and shader stages.
  117. VkWriteDescriptorSet& writeSetInfo = perSetData.writeSetInfos[k];
  118. writeSetInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  119. writeSetInfo.pNext = nullptr;
  120. writeSetInfo.dstSet = VK_NULL_HANDLE;
  121. writeSetInfo.dstBinding = perSetBindings[k].binding;
  122. writeSetInfo.dstArrayElement = 0;
  123. writeSetInfo.descriptorCount = perSetBindings[k].descriptorCount;
  124. writeSetInfo.descriptorType = perSetBindings[k].descriptorType;
  125. bool isImage = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
  126. writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
  127. writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
  128. if (isImage)
  129. {
  130. bool isLoadStore = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
  131. VkDescriptorImageInfo& imageInfo = perSetData.writeInfos[k].image;
  132. imageInfo.sampler = vkDefaultSampler->getHandle();
  133. if(isLoadStore)
  134. {
  135. imageInfo.imageView = vkTexManager.getDummyStorageImageView(i);
  136. imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
  137. }
  138. else
  139. {
  140. imageInfo.imageView = vkTexManager.getDummyReadImageView(i);
  141. imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  142. }
  143. writeSetInfo.pImageInfo = &imageInfo;
  144. writeSetInfo.pBufferInfo = nullptr;
  145. writeSetInfo.pTexelBufferView = nullptr;
  146. }
  147. else
  148. {
  149. bool useView = writeSetInfo.descriptorType != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER &&
  150. writeSetInfo.descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  151. if (!useView)
  152. {
  153. VkDescriptorBufferInfo& bufferInfo = perSetData.writeInfos[k].buffer;
  154. bufferInfo.offset = 0;
  155. bufferInfo.range = VK_WHOLE_SIZE;
  156. if(writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
  157. bufferInfo.buffer = vkBufManager.getDummyUniformBuffer(i);
  158. else
  159. bufferInfo.buffer = vkBufManager.getDummyStructuredBuffer(i);
  160. writeSetInfo.pBufferInfo = &bufferInfo;
  161. writeSetInfo.pTexelBufferView = nullptr;
  162. }
  163. else
  164. {
  165. writeSetInfo.pBufferInfo = nullptr;
  166. bool isLoadStore = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
  167. VkBufferView bufferView;
  168. if(isLoadStore)
  169. bufferView = vkBufManager.getDummyStorageBufferView(i);
  170. else
  171. bufferView = vkBufManager.getDummyReadBufferView(i);
  172. perSetData.writeInfos[k].bufferView = bufferView;
  173. writeSetInfo.pBufferInfo = nullptr;
  174. writeSetInfo.pTexelBufferView = &perSetData.writeInfos[k].bufferView;
  175. }
  176. writeSetInfo.pImageInfo = nullptr;
  177. }
  178. }
  179. }
  180. }
  181. GpuParams::initialize();
  182. }
  183. void VulkanGpuParams::setParamBlockBuffer(UINT32 set, UINT32 slot, const SPtr<GpuParamBlockBuffer>& paramBlockBuffer)
  184. {
  185. GpuParams::setParamBlockBuffer(set, slot, paramBlockBuffer);
  186. VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
  187. UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
  188. if(bindingIdx == -1)
  189. {
  190. LOGERR("Provided set/slot combination is not used by the GPU program: " + toString(set) + "," +
  191. toString(slot) + ".");
  192. return;
  193. }
  194. UINT32 sequentialIdx = vkParamInfo.getSequentialSlot(GpuPipelineParamInfo::ParamType::ParamBlock, set, slot);
  195. Lock(mMutex);
  196. VulkanGpuParamBlockBuffer* vulkanParamBlockBuffer =
  197. static_cast<VulkanGpuParamBlockBuffer*>(paramBlockBuffer.get());
  198. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  199. {
  200. if (mPerDeviceData[i].perSetData == nullptr)
  201. continue;
  202. VulkanBuffer* bufferRes;
  203. if (vulkanParamBlockBuffer != nullptr)
  204. bufferRes = vulkanParamBlockBuffer->getResource(i);
  205. else
  206. bufferRes = nullptr;
  207. PerSetData& perSetData = mPerDeviceData[i].perSetData[set];
  208. if (bufferRes != nullptr)
  209. {
  210. VkBuffer buffer = bufferRes->getHandle();
  211. perSetData.writeInfos[bindingIdx].buffer.buffer = buffer;
  212. mPerDeviceData[i].uniformBuffers[sequentialIdx] = buffer;
  213. }
  214. else
  215. {
  216. VulkanHardwareBufferManager& vkBufManager = static_cast<VulkanHardwareBufferManager&>(
  217. HardwareBufferManager::instance());
  218. perSetData.writeInfos[bindingIdx].buffer.buffer = vkBufManager.getDummyUniformBuffer(i);
  219. mPerDeviceData[i].uniformBuffers[sequentialIdx] = VK_NULL_HANDLE;
  220. }
  221. }
  222. mSetsDirty[set] = true;
  223. }
  224. void VulkanGpuParams::setTexture(UINT32 set, UINT32 slot, const SPtr<Texture>& texture, const TextureSurface& surface)
  225. {
  226. GpuParams::setTexture(set, slot, texture, surface);
  227. VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
  228. UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
  229. if (bindingIdx == -1)
  230. {
  231. LOGERR("Provided set/slot combination is not used by the GPU program: " + toString(set) + "," +
  232. toString(slot) + ".");
  233. return;
  234. }
  235. UINT32 sequentialIdx = vkParamInfo.getSequentialSlot(GpuPipelineParamInfo::ParamType::Texture, set, slot);
  236. Lock(mMutex);
  237. VulkanTexture* vulkanTexture = static_cast<VulkanTexture*>(texture.get());
  238. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  239. {
  240. if (mPerDeviceData[i].perSetData == nullptr)
  241. continue;
  242. VulkanImage* imageRes;
  243. if (vulkanTexture != nullptr)
  244. imageRes = vulkanTexture->getResource(i);
  245. else
  246. imageRes = nullptr;
  247. PerSetData& perSetData = mPerDeviceData[i].perSetData[set];
  248. if (imageRes != nullptr)
  249. {
  250. perSetData.writeInfos[bindingIdx].image.imageView = imageRes->getView(surface, false);
  251. mPerDeviceData[i].sampledImages[sequentialIdx] = imageRes->getHandle();
  252. }
  253. else
  254. {
  255. VulkanTextureManager& vkTexManager = static_cast<VulkanTextureManager&>(
  256. TextureManager::instance());
  257. perSetData.writeInfos[bindingIdx].image.imageView = vkTexManager.getDummyReadImageView(i);
  258. mPerDeviceData[i].sampledImages[sequentialIdx] = VK_NULL_HANDLE;
  259. }
  260. }
  261. mSetsDirty[set] = true;
  262. }
  263. void VulkanGpuParams::setLoadStoreTexture(UINT32 set, UINT32 slot, const SPtr<Texture>& texture,
  264. const TextureSurface& surface)
  265. {
  266. GpuParams::setLoadStoreTexture(set, slot, texture, surface);
  267. VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
  268. UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
  269. if (bindingIdx == -1)
  270. {
  271. LOGERR("Provided set/slot combination is not used by the GPU program: " + toString(set) + "," +
  272. toString(slot) + ".");
  273. return;
  274. }
  275. UINT32 sequentialIdx = vkParamInfo.getSequentialSlot(GpuPipelineParamInfo::ParamType::LoadStoreTexture, set, slot);
  276. Lock(mMutex);
  277. VulkanTexture* vulkanTexture = static_cast<VulkanTexture*>(texture.get());
  278. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  279. {
  280. if (mPerDeviceData[i].perSetData == nullptr)
  281. continue;
  282. VulkanImage* imageRes;
  283. if (vulkanTexture != nullptr)
  284. imageRes = vulkanTexture->getResource(i);
  285. else
  286. imageRes = nullptr;
  287. PerSetData& perSetData = mPerDeviceData[i].perSetData[set];
  288. if (imageRes != nullptr)
  289. {
  290. perSetData.writeInfos[bindingIdx].image.imageView = imageRes->getView(surface, false);
  291. mPerDeviceData[i].storageImages[sequentialIdx] = imageRes->getHandle();
  292. }
  293. else
  294. {
  295. VulkanTextureManager& vkTexManager = static_cast<VulkanTextureManager&>(
  296. TextureManager::instance());
  297. perSetData.writeInfos[bindingIdx].image.imageView = vkTexManager.getDummyStorageImageView(i);
  298. mPerDeviceData[i].storageImages[sequentialIdx] = VK_NULL_HANDLE;
  299. }
  300. }
  301. mSetsDirty[set] = true;
  302. }
  303. void VulkanGpuParams::setBuffer(UINT32 set, UINT32 slot, const SPtr<GpuBuffer>& buffer)
  304. {
  305. GpuParams::setBuffer(set, slot, buffer);
  306. VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
  307. UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
  308. if (bindingIdx == -1)
  309. {
  310. LOGERR("Provided set/slot combination is not used by the GPU program: " + toString(set) + "," +
  311. toString(slot) + ".");
  312. return;
  313. }
  314. UINT32 sequentialIdx = vkParamInfo.getSequentialSlot(GpuPipelineParamInfo::ParamType::Buffer, set, slot);
  315. Lock(mMutex);
  316. VulkanGpuBuffer* vulkanBuffer = static_cast<VulkanGpuBuffer*>(buffer.get());
  317. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  318. {
  319. if (mPerDeviceData[i].perSetData == nullptr)
  320. continue;
  321. VulkanBuffer* bufferRes;
  322. if (vulkanBuffer != nullptr)
  323. bufferRes = vulkanBuffer->getResource(i);
  324. else
  325. bufferRes = nullptr;
  326. PerSetData& perSetData = mPerDeviceData[i].perSetData[set];
  327. VkWriteDescriptorSet& writeSetInfo = perSetData.writeSetInfos[bindingIdx];
  328. bool useView = writeSetInfo.descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  329. if (useView)
  330. {
  331. VkBufferView bufferView;
  332. if (bufferRes != nullptr)
  333. {
  334. bufferView = bufferRes->getView();
  335. mPerDeviceData[i].buffers[sequentialIdx] = bufferRes->getHandle();
  336. }
  337. else
  338. {
  339. VulkanHardwareBufferManager& vkBufManager = static_cast<VulkanHardwareBufferManager&>(
  340. HardwareBufferManager::instance());
  341. bool isLoadStore = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
  342. if (isLoadStore)
  343. bufferView = vkBufManager.getDummyStorageBufferView(i);
  344. else
  345. bufferView = vkBufManager.getDummyReadBufferView(i);
  346. mPerDeviceData[i].buffers[sequentialIdx] = nullptr;
  347. }
  348. perSetData.writeInfos[bindingIdx].bufferView = bufferView;
  349. writeSetInfo.pTexelBufferView = &perSetData.writeInfos[bindingIdx].bufferView;
  350. }
  351. else // Structured storage buffer
  352. {
  353. if (bufferRes != nullptr)
  354. {
  355. VkBuffer vkBuffer = bufferRes->getHandle();
  356. perSetData.writeInfos[bindingIdx].buffer.buffer = vkBuffer;
  357. mPerDeviceData[i].buffers[sequentialIdx] = vkBuffer;
  358. }
  359. else
  360. {
  361. VulkanHardwareBufferManager& vkBufManager = static_cast<VulkanHardwareBufferManager&>(
  362. HardwareBufferManager::instance());
  363. perSetData.writeInfos[bindingIdx].buffer.buffer = vkBufManager.getDummyStructuredBuffer(i);
  364. mPerDeviceData[i].buffers[sequentialIdx] = nullptr;
  365. }
  366. writeSetInfo.pTexelBufferView = nullptr;
  367. }
  368. }
  369. mSetsDirty[set] = true;
  370. }
  371. void VulkanGpuParams::setSamplerState(UINT32 set, UINT32 slot, const SPtr<SamplerState>& sampler)
  372. {
  373. GpuParams::setSamplerState(set, slot, sampler);
  374. VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
  375. UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
  376. if (bindingIdx == -1)
  377. {
  378. LOGERR("Provided set/slot combination is not used by the GPU program: " + toString(set) + "," +
  379. toString(slot) + ".");
  380. return;
  381. }
  382. UINT32 sequentialIdx = vkParamInfo.getSequentialSlot(GpuPipelineParamInfo::ParamType::SamplerState, set, slot);
  383. Lock(mMutex);
  384. VulkanSamplerState* vulkanSampler = static_cast<VulkanSamplerState*>(sampler.get());
  385. for(UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  386. {
  387. if (mPerDeviceData[i].perSetData == nullptr)
  388. continue;
  389. PerSetData& perSetData = mPerDeviceData[i].perSetData[set];
  390. VulkanSampler* samplerRes;
  391. if (vulkanSampler != nullptr)
  392. samplerRes = vulkanSampler->getResource(i);
  393. else
  394. samplerRes = nullptr;
  395. if (samplerRes != nullptr)
  396. {
  397. VkSampler vkSampler = samplerRes->getHandle();
  398. perSetData.writeInfos[bindingIdx].image.sampler = vkSampler;
  399. mPerDeviceData[i].samplers[sequentialIdx] = vkSampler;
  400. }
  401. else
  402. {
  403. VulkanSamplerState* defaultSampler =
  404. static_cast<VulkanSamplerState*>(SamplerState::getDefault().get());
  405. VkSampler vkSampler = defaultSampler->getResource(i)->getHandle();;
  406. perSetData.writeInfos[bindingIdx].image.sampler = vkSampler;
  407. mPerDeviceData[i].samplers[sequentialIdx] = 0;
  408. }
  409. }
  410. mSetsDirty[set] = true;
  411. }
  412. UINT32 VulkanGpuParams::getNumSets() const
  413. {
  414. return mParamInfo->getNumSets();
  415. }
  416. void VulkanGpuParams::prepareForBind(VulkanCmdBuffer& buffer, VkDescriptorSet* sets)
  417. {
  418. UINT32 deviceIdx = buffer.getDeviceIdx();
  419. PerDeviceData& perDeviceData = mPerDeviceData[deviceIdx];
  420. if (perDeviceData.perSetData == nullptr)
  421. return;
  422. VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
  423. UINT32 numParamBlocks = vkParamInfo.getNumElements(GpuPipelineParamInfo::ParamType::ParamBlock);
  424. UINT32 numTextures = vkParamInfo.getNumElements(GpuPipelineParamInfo::ParamType::Texture);
  425. UINT32 numStorageTextures = vkParamInfo.getNumElements(GpuPipelineParamInfo::ParamType::LoadStoreTexture);
  426. UINT32 numBuffers = vkParamInfo.getNumElements(GpuPipelineParamInfo::ParamType::Buffer);
  427. UINT32 numSamplers = vkParamInfo.getNumElements(GpuPipelineParamInfo::ParamType::SamplerState);
  428. UINT32 numSets = vkParamInfo.getNumSets();
  429. Lock(mMutex);
  430. // Registers resources with the command buffer, and check if internal resource handled changed (in which case set
  431. // needs updating - this can happen due to resource writes, as internally system might find it more performant
  432. // to discard used resources and create new ones).
  433. // Note: Makes the assumption that this object (and all of the resources it holds) are externally locked, and will
  434. // not be modified on another thread while being bound.
  435. for (UINT32 i = 0; i < numParamBlocks; i++)
  436. {
  437. if (mParamBlockBuffers[i] == nullptr)
  438. continue;
  439. VulkanGpuParamBlockBuffer* element = static_cast<VulkanGpuParamBlockBuffer*>(mParamBlockBuffers[i].get());
  440. VulkanBuffer* resource = element->getResource(deviceIdx);
  441. if (resource == nullptr)
  442. continue;
  443. // Register with command buffer
  444. buffer.registerResource(resource, VK_ACCESS_UNIFORM_READ_BIT, VulkanUseFlag::Read);
  445. // Check if internal resource changed from what was previously bound in the descriptor set
  446. assert(perDeviceData.uniformBuffers[i] != VK_NULL_HANDLE);
  447. VkBuffer vkBuffer = resource->getHandle();
  448. if(perDeviceData.uniformBuffers[i] != vkBuffer)
  449. {
  450. perDeviceData.uniformBuffers[i] = vkBuffer;
  451. UINT32 set, slot;
  452. mParamInfo->getSetSlot(GpuPipelineParamInfo::ParamType::ParamBlock, i, set, slot);
  453. UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
  454. perDeviceData.perSetData[set].writeInfos[bindingIdx].buffer.buffer = vkBuffer;
  455. mSetsDirty[set] = true;
  456. }
  457. }
  458. for (UINT32 i = 0; i < numBuffers; i++)
  459. {
  460. if (mBuffers[i] == nullptr)
  461. continue;
  462. VulkanGpuBuffer* element = static_cast<VulkanGpuBuffer*>(mBuffers[i].get());
  463. VulkanBuffer* resource = element->getResource(deviceIdx);
  464. if (resource == nullptr)
  465. continue;
  466. // Register with command buffer
  467. VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT;
  468. VulkanUseFlags useFlags = VulkanUseFlag::Read;
  469. if (element->getProperties().getRandomGpuWrite())
  470. {
  471. accessFlags |= VK_ACCESS_SHADER_WRITE_BIT;
  472. useFlags |= VulkanUseFlag::Write;
  473. }
  474. buffer.registerResource(resource, accessFlags, useFlags);
  475. // Check if internal resource changed from what was previously bound in the descriptor set
  476. assert(perDeviceData.buffers[i] != VK_NULL_HANDLE);
  477. VkBuffer vkBuffer = resource->getHandle();
  478. if (perDeviceData.buffers[i] != vkBuffer)
  479. {
  480. perDeviceData.buffers[i] = vkBuffer;
  481. UINT32 set, slot;
  482. mParamInfo->getSetSlot(GpuPipelineParamInfo::ParamType::Buffer, i, set, slot);
  483. UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
  484. PerSetData& perSetData = perDeviceData.perSetData[set];
  485. VkWriteDescriptorSet& writeSetInfo = perSetData.writeSetInfos[bindingIdx];
  486. bool useView = writeSetInfo.descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  487. if (useView)
  488. {
  489. perSetData.writeInfos[bindingIdx].bufferView = resource->getView();
  490. perSetData.writeSetInfos[bindingIdx].pTexelBufferView = &perSetData.writeInfos[bindingIdx].bufferView;
  491. }
  492. else // Structured storage buffer
  493. {
  494. perSetData.writeInfos[bindingIdx].buffer.buffer = vkBuffer;
  495. perSetData.writeSetInfos[bindingIdx].pTexelBufferView = nullptr;
  496. }
  497. mSetsDirty[set] = true;
  498. }
  499. }
  500. for (UINT32 i = 0; i < numSamplers; i++)
  501. {
  502. if (mSamplerStates[i] == nullptr)
  503. continue;
  504. VulkanSamplerState* element = static_cast<VulkanSamplerState*>(mSamplerStates[i].get());
  505. VulkanSampler* resource = element->getResource(deviceIdx);
  506. if (resource == nullptr)
  507. continue;
  508. // Register with command buffer
  509. buffer.registerResource(resource, VulkanUseFlag::Read);
  510. // Check if internal resource changed from what was previously bound in the descriptor set
  511. assert(perDeviceData.samplers[i] != VK_NULL_HANDLE);
  512. VkSampler vkSampler = resource->getHandle();
  513. if (perDeviceData.samplers[i] != vkSampler)
  514. {
  515. perDeviceData.samplers[i] = vkSampler;
  516. UINT32 set, slot;
  517. mParamInfo->getSetSlot(GpuPipelineParamInfo::ParamType::SamplerState, i, set, slot);
  518. UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
  519. perDeviceData.perSetData[set].writeInfos[bindingIdx].image.sampler = vkSampler;
  520. mSetsDirty[set] = true;
  521. }
  522. }
  523. for (UINT32 i = 0; i < numStorageTextures; i++)
  524. {
  525. if (mLoadStoreTextureData[i].texture == nullptr)
  526. continue;
  527. VulkanTexture* element = static_cast<VulkanTexture*>(mLoadStoreTextureData[i].texture.get());
  528. VulkanImage* resource = element->getResource(deviceIdx);
  529. if (resource == nullptr)
  530. continue;
  531. const TextureSurface& surface = mLoadStoreTextureData[i].surface;
  532. VkImageSubresourceRange range = resource->getRange(surface);
  533. // Register with command buffer
  534. VulkanUseFlags useFlags = VulkanUseFlag::Read | VulkanUseFlag::Write;
  535. buffer.registerResource(resource, range, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, useFlags);
  536. // Check if internal resource changed from what was previously bound in the descriptor set
  537. assert(perDeviceData.storageImages[i] != VK_NULL_HANDLE);
  538. VkImage vkImage = resource->getHandle();
  539. if (perDeviceData.storageImages[i] != vkImage)
  540. {
  541. perDeviceData.storageImages[i] = vkImage;
  542. UINT32 set, slot;
  543. mParamInfo->getSetSlot(GpuPipelineParamInfo::ParamType::LoadStoreTexture, i, set, slot);
  544. UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
  545. perDeviceData.perSetData[set].writeInfos[bindingIdx].image.imageView = resource->getView(surface, false);;
  546. mSetsDirty[set] = true;
  547. }
  548. }
  549. for (UINT32 i = 0; i < numTextures; i++)
  550. {
  551. if (mSampledTextureData[i].texture == nullptr)
  552. continue;
  553. VulkanTexture* element = static_cast<VulkanTexture*>(mSampledTextureData[i].texture.get());
  554. VulkanImage* resource = element->getResource(deviceIdx);
  555. if (resource == nullptr)
  556. continue;
  557. // Register with command buffer
  558. const TextureProperties& props = element->getProperties();
  559. VkImageLayout layout;
  560. // Keep dynamic textures in general layout, so they can be easily mapped by CPU
  561. if (props.getUsage() & TU_DYNAMIC)
  562. layout = VK_IMAGE_LAYOUT_GENERAL;
  563. else
  564. layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  565. const TextureSurface& surface = mSampledTextureData[i].surface;
  566. VkImageSubresourceRange range = resource->getRange(surface);
  567. buffer.registerResource(resource, range, layout, layout, VulkanUseFlag::Read);
  568. // Check if internal resource changed from what was previously bound in the descriptor set
  569. assert(perDeviceData.sampledImages[i] != VK_NULL_HANDLE);
  570. VkImage vkImage = resource->getHandle();
  571. if (perDeviceData.sampledImages[i] != vkImage)
  572. {
  573. perDeviceData.sampledImages[i] = vkImage;
  574. UINT32 set, slot;
  575. mParamInfo->getSetSlot(GpuPipelineParamInfo::ParamType::Texture, i, set, slot);
  576. UINT32 bindingIdx = vkParamInfo.getBindingIdx(set, slot);
  577. perDeviceData.perSetData[set].writeInfos[bindingIdx].image.imageView = resource->getView(surface, false);
  578. mSetsDirty[set] = true;
  579. }
  580. }
  581. // Acquire sets as needed, and updated their contents if dirty
  582. VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPI::instance());
  583. VulkanDevice& device = *rapi._getDevice(deviceIdx);
  584. VulkanDescriptorManager& descManager = device.getDescriptorManager();
  585. for (UINT32 i = 0; i < numSets; i++)
  586. {
  587. PerSetData& perSetData = perDeviceData.perSetData[i];
  588. if (!mSetsDirty[i]) // Set not dirty, just use the last one we wrote (this is fine even across multiple command buffers)
  589. continue;
  590. // Set is dirty, we need to update
  591. //// Use latest unless already used, otherwise try to find an unused one
  592. if(perSetData.latestSet->isBound()) // Checking this is okay, because it's only modified below when we call registerResource, which is under the same lock as this
  593. {
  594. perSetData.latestSet = nullptr;
  595. for(auto& entry : perSetData.sets)
  596. {
  597. if(!entry->isBound())
  598. {
  599. perSetData.latestSet = entry;
  600. break;
  601. }
  602. }
  603. // Cannot find an empty set, allocate a new one
  604. if (perSetData.latestSet == nullptr)
  605. {
  606. VulkanDescriptorLayout* layout = vkParamInfo.getLayout(deviceIdx, i);
  607. perSetData.latestSet = descManager.createSet(layout);
  608. perSetData.sets.push_back(perSetData.latestSet);
  609. }
  610. }
  611. // Note: Currently I write to the entire set at once, but it might be beneficial to remember only the exact
  612. // entries that were updated, and only write to them individually.
  613. perSetData.latestSet->write(perSetData.writeSetInfos, perSetData.numElements);
  614. mSetsDirty[i] = false;
  615. }
  616. for (UINT32 i = 0; i < numSets; i++)
  617. {
  618. VulkanDescriptorSet* set = perDeviceData.perSetData[i].latestSet;
  619. buffer.registerResource(set, VulkanUseFlag::Read);
  620. sets[i] = set->getHandle();
  621. }
  622. }
  623. }}