CommandBufferImpl.inl.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. // Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Gr/Vulkan/CommandBufferImpl.h>
  6. #include <AnKi/Gr/Vulkan/TextureImpl.h>
  7. #include <AnKi/Gr/OcclusionQuery.h>
  8. #include <AnKi/Gr/Vulkan/OcclusionQueryImpl.h>
  9. #include <AnKi/Gr/TimestampQuery.h>
  10. #include <AnKi/Gr/Vulkan/TimestampQueryImpl.h>
  11. #include <AnKi/Util/Tracer.h>
  12. namespace anki {
  13. ANKI_FORCE_INLINE void CommandBufferImpl::setStencilCompareMaskInternal(FaceSelectionBit face, U32 mask)
  14. {
  15. commandCommon();
  16. VkStencilFaceFlags flags = 0;
  17. if(!!(face & FaceSelectionBit::kFront) && m_stencilCompareMasks[0] != mask)
  18. {
  19. m_stencilCompareMasks[0] = mask;
  20. flags = VK_STENCIL_FACE_FRONT_BIT;
  21. }
  22. if(!!(face & FaceSelectionBit::kBack) && m_stencilCompareMasks[1] != mask)
  23. {
  24. m_stencilCompareMasks[1] = mask;
  25. flags |= VK_STENCIL_FACE_BACK_BIT;
  26. }
  27. if(flags)
  28. {
  29. vkCmdSetStencilCompareMask(m_handle, flags, mask);
  30. }
  31. }
  32. ANKI_FORCE_INLINE void CommandBufferImpl::setStencilWriteMaskInternal(FaceSelectionBit face, U32 mask)
  33. {
  34. commandCommon();
  35. VkStencilFaceFlags flags = 0;
  36. if(!!(face & FaceSelectionBit::kFront) && m_stencilWriteMasks[0] != mask)
  37. {
  38. m_stencilWriteMasks[0] = mask;
  39. flags = VK_STENCIL_FACE_FRONT_BIT;
  40. }
  41. if(!!(face & FaceSelectionBit::kBack) && m_stencilWriteMasks[1] != mask)
  42. {
  43. m_stencilWriteMasks[1] = mask;
  44. flags |= VK_STENCIL_FACE_BACK_BIT;
  45. }
  46. if(flags)
  47. {
  48. vkCmdSetStencilWriteMask(m_handle, flags, mask);
  49. }
  50. }
  51. ANKI_FORCE_INLINE void CommandBufferImpl::setStencilReferenceInternal(FaceSelectionBit face, U32 ref)
  52. {
  53. commandCommon();
  54. VkStencilFaceFlags flags = 0;
  55. if(!!(face & FaceSelectionBit::kFront) && m_stencilReferenceMasks[0] != ref)
  56. {
  57. m_stencilReferenceMasks[0] = ref;
  58. flags = VK_STENCIL_FACE_FRONT_BIT;
  59. }
  60. if(!!(face & FaceSelectionBit::kBack) && m_stencilReferenceMasks[1] != ref)
  61. {
  62. m_stencilWriteMasks[1] = ref;
  63. flags |= VK_STENCIL_FACE_BACK_BIT;
  64. }
  65. if(flags)
  66. {
  67. vkCmdSetStencilReference(m_handle, flags, ref);
  68. }
  69. }
  70. ANKI_FORCE_INLINE void CommandBufferImpl::setImageBarrier(VkPipelineStageFlags srcStage, VkAccessFlags srcAccess, VkImageLayout prevLayout,
  71. VkPipelineStageFlags dstStage, VkAccessFlags dstAccess, VkImageLayout newLayout,
  72. VkImage img, const VkImageSubresourceRange& range)
  73. {
  74. ANKI_ASSERT(img);
  75. commandCommon();
  76. VkImageMemoryBarrier inf = {};
  77. inf.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  78. inf.srcAccessMask = srcAccess;
  79. inf.dstAccessMask = dstAccess;
  80. inf.oldLayout = prevLayout;
  81. inf.newLayout = newLayout;
  82. inf.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  83. inf.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  84. inf.image = img;
  85. inf.subresourceRange = range;
  86. vkCmdPipelineBarrier(m_handle, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &inf);
  87. ANKI_TRACE_INC_COUNTER(VkBarrier, 1);
  88. }
  89. ANKI_FORCE_INLINE void CommandBufferImpl::dispatchComputeInternal(U32 groupCountX, U32 groupCountY, U32 groupCountZ)
  90. {
  91. ANKI_ASSERT(m_computeProg);
  92. ANKI_ASSERT(m_computeProg->getReflectionInfo().m_pushConstantsSize == m_setPushConstantsSize && "Forgot to set pushConstants");
  93. commandCommon();
  94. // Bind descriptors
  95. for(U32 i = 0; i < kMaxDescriptorSets; ++i)
  96. {
  97. if(m_computeProg->getReflectionInfo().m_descriptorSetMask.get(i))
  98. {
  99. DescriptorSet dset;
  100. Bool dirty;
  101. Array<PtrSize, kMaxBindingsPerDescriptorSet> dynamicOffsetsPtrSize;
  102. U32 dynamicOffsetCount;
  103. if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(*m_pool, m_dsetState[i], dset, dirty, dynamicOffsetsPtrSize,
  104. dynamicOffsetCount))
  105. {
  106. ANKI_VK_LOGF("Cannot recover");
  107. }
  108. if(dirty)
  109. {
  110. // Vulkan should have had the dynamic offsets as VkDeviceSize and not U32. Workaround that.
  111. Array<U32, kMaxBindingsPerDescriptorSet> dynamicOffsets;
  112. for(U32 i = 0; i < dynamicOffsetCount; ++i)
  113. {
  114. dynamicOffsets[i] = U32(dynamicOffsetsPtrSize[i]);
  115. }
  116. VkDescriptorSet dsHandle = dset.getHandle();
  117. vkCmdBindDescriptorSets(m_handle, VK_PIPELINE_BIND_POINT_COMPUTE, m_computeProg->getPipelineLayout().getHandle(), i, 1, &dsHandle,
  118. dynamicOffsetCount, &dynamicOffsets[0]);
  119. }
  120. }
  121. }
  122. vkCmdDispatch(m_handle, groupCountX, groupCountY, groupCountZ);
  123. }
  124. ANKI_FORCE_INLINE void CommandBufferImpl::traceRaysInternal(Buffer* sbtBuffer, PtrSize sbtBufferOffset, U32 sbtRecordSize32,
  125. U32 hitGroupSbtRecordCount, U32 rayTypeCount, U32 width, U32 height, U32 depth)
  126. {
  127. const PtrSize sbtRecordSize = sbtRecordSize32;
  128. ANKI_ASSERT(hitGroupSbtRecordCount > 0);
  129. ANKI_ASSERT(width > 0 && height > 0 && depth > 0);
  130. ANKI_ASSERT(m_rtProg);
  131. const ShaderProgramImpl& sprog = static_cast<const ShaderProgramImpl&>(*m_rtProg);
  132. ANKI_ASSERT(sprog.getReflectionInfo().m_pushConstantsSize == m_setPushConstantsSize && "Forgot to set pushConstants");
  133. ANKI_ASSERT(rayTypeCount == sprog.getMissShaderCount() && "All the miss shaders should be in use");
  134. ANKI_ASSERT((hitGroupSbtRecordCount % rayTypeCount) == 0);
  135. const PtrSize sbtRecordCount = 1 + rayTypeCount + hitGroupSbtRecordCount;
  136. [[maybe_unused]] const PtrSize sbtBufferSize = sbtRecordCount * sbtRecordSize;
  137. ANKI_ASSERT(sbtBufferSize + sbtBufferOffset <= sbtBuffer->getSize());
  138. ANKI_ASSERT(isAligned(getGrManagerImpl().getDeviceCapabilities().m_sbtRecordAlignment, sbtBufferOffset));
  139. commandCommon();
  140. // Bind descriptors
  141. for(U32 i = 0; i < kMaxDescriptorSets; ++i)
  142. {
  143. if(sprog.getReflectionInfo().m_descriptorSetMask.get(i))
  144. {
  145. DescriptorSet dset;
  146. Bool dirty;
  147. Array<PtrSize, kMaxBindingsPerDescriptorSet> dynamicOffsetsPtrSize;
  148. U32 dynamicOffsetCount;
  149. if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(*m_pool, m_dsetState[i], dset, dirty, dynamicOffsetsPtrSize,
  150. dynamicOffsetCount))
  151. {
  152. ANKI_VK_LOGF("Cannot recover");
  153. }
  154. if(dirty)
  155. {
  156. // Vulkan should have had the dynamic offsets as VkDeviceSize and not U32. Workaround that.
  157. Array<U32, kMaxBindingsPerDescriptorSet> dynamicOffsets;
  158. for(U32 i = 0; i < dynamicOffsetCount; ++i)
  159. {
  160. dynamicOffsets[i] = U32(dynamicOffsetsPtrSize[i]);
  161. }
  162. VkDescriptorSet dsHandle = dset.getHandle();
  163. vkCmdBindDescriptorSets(m_handle, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, sprog.getPipelineLayout().getHandle(), i, 1, &dsHandle,
  164. dynamicOffsetCount, &dynamicOffsets[0]);
  165. }
  166. }
  167. }
  168. Array<VkStridedDeviceAddressRegionKHR, 4> regions;
  169. const U64 stbBufferAddress = sbtBuffer->getGpuAddress() + sbtBufferOffset;
  170. ANKI_ASSERT(isAligned(getGrManagerImpl().getDeviceCapabilities().m_sbtRecordAlignment, stbBufferAddress));
  171. // Rgen
  172. regions[0].deviceAddress = stbBufferAddress;
  173. regions[0].stride = sbtRecordSize;
  174. regions[0].size = sbtRecordSize;
  175. // Miss
  176. regions[1].deviceAddress = regions[0].deviceAddress + regions[0].size;
  177. regions[1].stride = sbtRecordSize;
  178. regions[1].size = sbtRecordSize * rayTypeCount;
  179. // Hit
  180. regions[2].deviceAddress = regions[1].deviceAddress + regions[1].size;
  181. regions[2].stride = sbtRecordSize * rayTypeCount;
  182. regions[2].size = sbtRecordSize * hitGroupSbtRecordCount;
  183. // Callable, nothing for now
  184. regions[3] = VkStridedDeviceAddressRegionKHR();
  185. vkCmdTraceRaysKHR(m_handle, &regions[0], &regions[1], &regions[2], &regions[3], width, height, depth);
  186. }
  187. ANKI_FORCE_INLINE void CommandBufferImpl::pushSecondLevelCommandBuffersInternal(ConstWeakArray<CommandBuffer*> cmdbs)
  188. {
  189. ANKI_ASSERT(cmdbs.getSize() > 0);
  190. commandCommon();
  191. ANKI_ASSERT(insideRenderPass());
  192. ANKI_ASSERT(m_subpassContents == VK_SUBPASS_CONTENTS_MAX_ENUM || m_subpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
  193. m_subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
  194. if(m_rpCommandCount == 0) [[unlikely]]
  195. {
  196. beginRenderPassInternal();
  197. }
  198. DynamicArray<VkCommandBuffer, MemoryPoolPtrWrapper<StackMemoryPool>> handles(m_pool);
  199. handles.resize(cmdbs.getSize());
  200. for(U32 i = 0; i < cmdbs.getSize(); ++i)
  201. {
  202. ANKI_ASSERT(static_cast<const CommandBufferImpl&>(*cmdbs[i]).m_finalized);
  203. handles[i] = static_cast<const CommandBufferImpl&>(*cmdbs[i]).m_handle;
  204. m_microCmdb->pushObjectRef(cmdbs[i]);
  205. }
  206. vkCmdExecuteCommands(m_handle, handles.getSize(), handles.getBegin());
  207. ++m_rpCommandCount;
  208. }
  209. ANKI_FORCE_INLINE void CommandBufferImpl::drawcallCommon()
  210. {
  211. // Preconditions
  212. commandCommon();
  213. ANKI_ASSERT(m_graphicsProg);
  214. ANKI_ASSERT(insideRenderPass() || secondLevel());
  215. ANKI_ASSERT(m_subpassContents == VK_SUBPASS_CONTENTS_MAX_ENUM || m_subpassContents == VK_SUBPASS_CONTENTS_INLINE);
  216. ANKI_ASSERT(m_graphicsProg->getReflectionInfo().m_pushConstantsSize == m_setPushConstantsSize && "Forgot to set pushConstants");
  217. m_subpassContents = VK_SUBPASS_CONTENTS_INLINE;
  218. if(m_rpCommandCount == 0 && !secondLevel())
  219. {
  220. beginRenderPassInternal();
  221. }
  222. ++m_rpCommandCount;
  223. // Get or create ppline
  224. Pipeline ppline;
  225. Bool stateDirty;
  226. m_graphicsProg->getPipelineFactory().getOrCreatePipeline(m_state, ppline, stateDirty);
  227. if(stateDirty)
  228. {
  229. vkCmdBindPipeline(m_handle, VK_PIPELINE_BIND_POINT_GRAPHICS, ppline.getHandle());
  230. }
  231. // Bind dsets
  232. for(U32 i = 0; i < kMaxDescriptorSets; ++i)
  233. {
  234. if(m_graphicsProg->getReflectionInfo().m_descriptorSetMask.get(i))
  235. {
  236. DescriptorSet dset;
  237. Bool dirty;
  238. Array<PtrSize, kMaxBindingsPerDescriptorSet> dynamicOffsetsPtrSize;
  239. U32 dynamicOffsetCount;
  240. if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(*m_pool, m_dsetState[i], dset, dirty, dynamicOffsetsPtrSize,
  241. dynamicOffsetCount))
  242. {
  243. ANKI_VK_LOGF("Cannot recover");
  244. }
  245. if(dirty)
  246. {
  247. // Vulkan should have had the dynamic offsets as VkDeviceSize and not U32. Workaround that.
  248. Array<U32, kMaxBindingsPerDescriptorSet> dynamicOffsets;
  249. for(U32 i = 0; i < dynamicOffsetCount; ++i)
  250. {
  251. dynamicOffsets[i] = U32(dynamicOffsetsPtrSize[i]);
  252. }
  253. VkDescriptorSet dsHandle = dset.getHandle();
  254. vkCmdBindDescriptorSets(m_handle, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsProg->getPipelineLayout().getHandle(), i, 1, &dsHandle,
  255. dynamicOffsetCount, &dynamicOffsets[0]);
  256. }
  257. }
  258. }
  259. // Flush viewport
  260. if(m_viewportDirty) [[unlikely]]
  261. {
  262. const Bool flipvp = flipViewport();
  263. U32 fbWidth, fbHeight;
  264. static_cast<const FramebufferImpl&>(*m_activeFb).getAttachmentsSize(fbWidth, fbHeight);
  265. VkViewport vp = computeViewport(&m_viewport[0], fbWidth, fbHeight, flipvp);
  266. // Additional optimization
  267. if(memcmp(&vp, &m_lastViewport, sizeof(vp)) != 0)
  268. {
  269. vkCmdSetViewport(m_handle, 0, 1, &vp);
  270. m_lastViewport = vp;
  271. }
  272. m_viewportDirty = false;
  273. }
  274. // Flush scissor
  275. if(m_scissorDirty) [[unlikely]]
  276. {
  277. const Bool flipvp = flipViewport();
  278. U32 fbWidth, fbHeight;
  279. static_cast<const FramebufferImpl&>(*m_activeFb).getAttachmentsSize(fbWidth, fbHeight);
  280. VkRect2D scissor = computeScissor(&m_scissor[0], fbWidth, fbHeight, flipvp);
  281. // Additional optimization
  282. if(memcmp(&scissor, &m_lastScissor, sizeof(scissor)) != 0)
  283. {
  284. vkCmdSetScissor(m_handle, 0, 1, &scissor);
  285. m_lastScissor = scissor;
  286. }
  287. m_scissorDirty = false;
  288. }
  289. // VRS
  290. if(getGrManagerImpl().getDeviceCapabilities().m_vrs && m_vrsRateDirty)
  291. {
  292. const VkExtent2D extend = convertVrsShadingRate(m_vrsRate);
  293. Array<VkFragmentShadingRateCombinerOpKHR, 2> combiner;
  294. combiner[0] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; // Keep pipeline rating over primitive
  295. combiner[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR; // Max of attachment and pipeline rates
  296. vkCmdSetFragmentShadingRateKHR(m_handle, &extend, &combiner[0]);
  297. m_vrsRateDirty = false;
  298. }
  299. // Some checks
  300. #if ANKI_ASSERTIONS_ENABLED
  301. if(m_state.getPrimitiveTopology() == PrimitiveTopology::kLines || m_state.getPrimitiveTopology() == PrimitiveTopology::kLineStip)
  302. {
  303. ANKI_ASSERT(m_lineWidthSet == true);
  304. }
  305. #endif
  306. ANKI_TRACE_INC_COUNTER(VkDrawcall, 1);
  307. }
  308. ANKI_FORCE_INLINE void CommandBufferImpl::writeOcclusionQueriesResultToBufferInternal(ConstWeakArray<OcclusionQuery*> queries, PtrSize offset,
  309. Buffer* buff)
  310. {
  311. ANKI_ASSERT(queries.getSize() > 0);
  312. commandCommon();
  313. ANKI_ASSERT(!insideRenderPass());
  314. const BufferImpl& impl = static_cast<const BufferImpl&>(*buff);
  315. ANKI_ASSERT(impl.usageValid(BufferUsageBit::kTransferDestination));
  316. for(U32 i = 0; i < queries.getSize(); ++i)
  317. {
  318. ANKI_ASSERT(queries[i]);
  319. ANKI_ASSERT((offset % 4) == 0);
  320. ANKI_ASSERT((offset + sizeof(U32)) <= impl.getSize());
  321. OcclusionQueryImpl* q = static_cast<OcclusionQueryImpl*>(queries[i]);
  322. vkCmdCopyQueryPoolResults(m_handle, q->m_handle.getQueryPool(), q->m_handle.getQueryIndex(), 1, impl.getHandle(), offset, sizeof(U32),
  323. VK_QUERY_RESULT_PARTIAL_BIT);
  324. offset += sizeof(U32);
  325. m_microCmdb->pushObjectRef(q);
  326. }
  327. }
  328. ANKI_FORCE_INLINE void CommandBufferImpl::bindShaderProgramInternal(ShaderProgram* prog)
  329. {
  330. commandCommon();
  331. ShaderProgramImpl& impl = static_cast<ShaderProgramImpl&>(*prog);
  332. if(impl.isGraphics())
  333. {
  334. m_graphicsProg = &impl;
  335. m_computeProg = nullptr; // Unbind the compute prog. Doesn't work like vulkan
  336. m_rtProg = nullptr; // See above
  337. m_state.bindShaderProgram(&impl);
  338. }
  339. else if(!!(impl.getStages() & ShaderTypeBit::kCompute))
  340. {
  341. m_computeProg = &impl;
  342. m_graphicsProg = nullptr; // See comment in the if()
  343. m_rtProg = nullptr; // See above
  344. // Bind the pipeline now
  345. vkCmdBindPipeline(m_handle, VK_PIPELINE_BIND_POINT_COMPUTE, impl.getComputePipelineHandle());
  346. }
  347. else
  348. {
  349. ANKI_ASSERT(!!(impl.getStages() & ShaderTypeBit::kAllRayTracing));
  350. m_computeProg = nullptr;
  351. m_graphicsProg = nullptr;
  352. m_rtProg = &impl;
  353. // Bind now
  354. vkCmdBindPipeline(m_handle, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, impl.getRayTracingPipelineHandle());
  355. }
  356. for(U32 i = 0; i < kMaxDescriptorSets; ++i)
  357. {
  358. if(impl.getReflectionInfo().m_descriptorSetMask.get(i))
  359. {
  360. m_dsetState[i].setLayout(impl.getDescriptorSetLayout(i));
  361. }
  362. else
  363. {
  364. // According to the spec the bound DS may be disturbed if the ppline layout is not compatible. Play it safe
  365. // and dirty the slot. That will force rebind of the DS at drawcall time.
  366. m_dsetState[i].setLayout(DescriptorSetLayout());
  367. }
  368. }
  369. m_microCmdb->pushObjectRef(prog);
  370. #if ANKI_EXTRA_CHECKS
  371. m_setPushConstantsSize = 0;
  372. #endif
  373. }
  374. ANKI_FORCE_INLINE void CommandBufferImpl::copyBufferToBufferInternal(Buffer* src, Buffer* dst, ConstWeakArray<CopyBufferToBufferInfo> copies)
  375. {
  376. ANKI_ASSERT(static_cast<const BufferImpl&>(*src).usageValid(BufferUsageBit::kTransferSource));
  377. ANKI_ASSERT(static_cast<const BufferImpl&>(*dst).usageValid(BufferUsageBit::kTransferDestination));
  378. ANKI_ASSERT(copies.getSize() > 0);
  379. commandCommon();
  380. static_assert(sizeof(CopyBufferToBufferInfo) == sizeof(VkBufferCopy));
  381. const VkBufferCopy* vkCopies = reinterpret_cast<const VkBufferCopy*>(&copies[0]);
  382. vkCmdCopyBuffer(m_handle, static_cast<const BufferImpl&>(*src).getHandle(), static_cast<const BufferImpl&>(*dst).getHandle(), copies.getSize(),
  383. &vkCopies[0]);
  384. }
  385. ANKI_FORCE_INLINE Bool CommandBufferImpl::flipViewport() const
  386. {
  387. return static_cast<const FramebufferImpl&>(*m_activeFb).hasPresentableTexture();
  388. }
  389. ANKI_FORCE_INLINE void CommandBufferImpl::setPushConstantsInternal(const void* data, U32 dataSize)
  390. {
  391. ANKI_ASSERT(data && dataSize && dataSize % 16 == 0);
  392. const ShaderProgramImpl& prog = getBoundProgram();
  393. ANKI_ASSERT(prog.getReflectionInfo().m_pushConstantsSize == dataSize
  394. && "The bound program should have push constants equal to the \"dataSize\" parameter");
  395. commandCommon();
  396. vkCmdPushConstants(m_handle, prog.getPipelineLayout().getHandle(), VK_SHADER_STAGE_ALL, 0, dataSize, data);
  397. #if ANKI_EXTRA_CHECKS
  398. m_setPushConstantsSize = dataSize;
  399. #endif
  400. }
  401. ANKI_FORCE_INLINE void CommandBufferImpl::resetOcclusionQueriesInternal(ConstWeakArray<OcclusionQuery*> queries)
  402. {
  403. ANKI_ASSERT(queries.getSize() > 0);
  404. commandCommon();
  405. for(U32 i = 0; i < queries.getSize(); ++i)
  406. {
  407. OcclusionQuery* query = queries[i];
  408. ANKI_ASSERT(query);
  409. const VkQueryPool poolHandle = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryPool();
  410. const U32 idx = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryIndex();
  411. vkCmdResetQueryPool(m_handle, poolHandle, idx, 1);
  412. m_microCmdb->pushObjectRef(query);
  413. }
  414. }
  415. ANKI_FORCE_INLINE void CommandBufferImpl::beginOcclusionQueryInternal(OcclusionQuery* query)
  416. {
  417. commandCommon();
  418. const VkQueryPool handle = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryPool();
  419. const U32 idx = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryIndex();
  420. ANKI_ASSERT(handle);
  421. vkCmdBeginQuery(m_handle, handle, idx, 0);
  422. m_microCmdb->pushObjectRef(query);
  423. }
  424. ANKI_FORCE_INLINE void CommandBufferImpl::endOcclusionQueryInternal(OcclusionQuery* query)
  425. {
  426. commandCommon();
  427. const VkQueryPool handle = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryPool();
  428. const U32 idx = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryIndex();
  429. ANKI_ASSERT(handle);
  430. vkCmdEndQuery(m_handle, handle, idx);
  431. m_microCmdb->pushObjectRef(query);
  432. }
  433. ANKI_FORCE_INLINE void CommandBufferImpl::resetTimestampQueriesInternal(ConstWeakArray<TimestampQuery*> queries)
  434. {
  435. ANKI_ASSERT(queries.getSize() > 0);
  436. commandCommon();
  437. for(U32 i = 0; i < queries.getSize(); ++i)
  438. {
  439. TimestampQuery* query = queries[i];
  440. ANKI_ASSERT(query);
  441. const VkQueryPool poolHandle = static_cast<const TimestampQueryImpl&>(*query).m_handle.getQueryPool();
  442. const U32 idx = static_cast<const TimestampQueryImpl&>(*query).m_handle.getQueryIndex();
  443. vkCmdResetQueryPool(m_handle, poolHandle, idx, 1);
  444. m_microCmdb->pushObjectRef(query);
  445. }
  446. }
  447. ANKI_FORCE_INLINE void CommandBufferImpl::writeTimestampInternal(TimestampQuery* query)
  448. {
  449. commandCommon();
  450. const VkQueryPool handle = static_cast<const TimestampQueryImpl&>(*query).m_handle.getQueryPool();
  451. const U32 idx = static_cast<const TimestampQueryImpl&>(*query).m_handle.getQueryIndex();
  452. vkCmdWriteTimestamp(m_handle, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, handle, idx);
  453. m_microCmdb->pushObjectRef(query);
  454. }
  455. ANKI_FORCE_INLINE void CommandBufferImpl::clearTextureViewInternal(TextureView* texView, const ClearValue& clearValue)
  456. {
  457. commandCommon();
  458. const TextureViewImpl& view = static_cast<const TextureViewImpl&>(*texView);
  459. const TextureImpl& tex = view.getTextureImpl();
  460. VkClearColorValue vclear;
  461. static_assert(sizeof(vclear) == sizeof(clearValue), "See file");
  462. memcpy(&vclear, &clearValue, sizeof(clearValue));
  463. if(!view.getSubresource().m_depthStencilAspect)
  464. {
  465. VkImageSubresourceRange vkRange = view.getVkImageSubresourceRange();
  466. vkCmdClearColorImage(m_handle, tex.m_imageHandle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &vclear, 1, &vkRange);
  467. }
  468. else
  469. {
  470. ANKI_ASSERT(!"TODO");
  471. }
  472. }
  473. ANKI_FORCE_INLINE void CommandBufferImpl::fillBufferInternal(Buffer* buff, PtrSize offset, PtrSize size, U32 value)
  474. {
  475. commandCommon();
  476. ANKI_ASSERT(!insideRenderPass());
  477. const BufferImpl& impl = static_cast<const BufferImpl&>(*buff);
  478. ANKI_ASSERT(impl.usageValid(BufferUsageBit::kTransferDestination));
  479. ANKI_ASSERT(offset < impl.getSize());
  480. ANKI_ASSERT((offset % 4) == 0 && "Should be multiple of 4");
  481. size = (size == kMaxPtrSize) ? (impl.getActualSize() - offset) : size;
  482. alignRoundUp(4, size); // Needs to be multiple of 4
  483. ANKI_ASSERT(offset + size <= impl.getActualSize());
  484. ANKI_ASSERT((size % 4) == 0 && "Should be multiple of 4");
  485. vkCmdFillBuffer(m_handle, impl.getHandle(), offset, size, value);
  486. }
  487. } // end namespace anki