CommandBufferImpl.inl.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  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. 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. 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. 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. inline void CommandBufferImpl::setImageBarrier(VkPipelineStageFlags srcStage, VkAccessFlags srcAccess,
  71. VkImageLayout prevLayout, VkPipelineStageFlags dstStage,
  72. VkAccessFlags dstAccess, VkImageLayout newLayout, VkImage img,
  73. const VkImageSubresourceRange& range)
  74. {
  75. ANKI_ASSERT(img);
  76. commandCommon();
  77. VkImageMemoryBarrier inf = {};
  78. inf.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  79. inf.srcAccessMask = srcAccess;
  80. inf.dstAccessMask = dstAccess;
  81. inf.oldLayout = prevLayout;
  82. inf.newLayout = newLayout;
  83. inf.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  84. inf.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  85. inf.image = img;
  86. inf.subresourceRange = range;
  87. vkCmdPipelineBarrier(m_handle, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &inf);
  88. ANKI_TRACE_INC_COUNTER(VkBarrier, 1);
  89. }
  90. inline void CommandBufferImpl::drawArraysInternal(PrimitiveTopology topology, U32 count, U32 instanceCount, U32 first,
  91. U32 baseInstance)
  92. {
  93. m_state.setPrimitiveTopology(topology);
  94. drawcallCommon();
  95. vkCmdDraw(m_handle, count, instanceCount, first, baseInstance);
  96. }
  97. inline void CommandBufferImpl::drawElementsInternal(PrimitiveTopology topology, U32 count, U32 instanceCount,
  98. U32 firstIndex, U32 baseVertex, U32 baseInstance)
  99. {
  100. m_state.setPrimitiveTopology(topology);
  101. drawcallCommon();
  102. vkCmdDrawIndexed(m_handle, count, instanceCount, firstIndex, baseVertex, baseInstance);
  103. }
  104. inline void CommandBufferImpl::drawArraysIndirectInternal(PrimitiveTopology topology, U32 drawCount, PtrSize offset,
  105. const BufferPtr& buff)
  106. {
  107. m_state.setPrimitiveTopology(topology);
  108. drawcallCommon();
  109. const BufferImpl& impl = static_cast<const BufferImpl&>(*buff);
  110. ANKI_ASSERT(impl.usageValid(BufferUsageBit::kIndirectDraw));
  111. ANKI_ASSERT((offset % 4) == 0);
  112. ANKI_ASSERT((offset + sizeof(DrawIndirectInfo) * drawCount) <= impl.getSize());
  113. vkCmdDrawIndirect(m_handle, impl.getHandle(), offset, drawCount, sizeof(DrawIndirectInfo));
  114. }
  115. inline void CommandBufferImpl::drawElementsIndirectInternal(PrimitiveTopology topology, U32 drawCount, PtrSize offset,
  116. const BufferPtr& buff)
  117. {
  118. m_state.setPrimitiveTopology(topology);
  119. drawcallCommon();
  120. const BufferImpl& impl = static_cast<const BufferImpl&>(*buff);
  121. ANKI_ASSERT(impl.usageValid(BufferUsageBit::kIndirectDraw));
  122. ANKI_ASSERT((offset % 4) == 0);
  123. ANKI_ASSERT((offset + sizeof(DrawIndexedIndirectInfo) * drawCount) <= impl.getSize());
  124. vkCmdDrawIndexedIndirect(m_handle, impl.getHandle(), offset, drawCount, sizeof(DrawIndexedIndirectInfo));
  125. }
  126. inline void CommandBufferImpl::dispatchComputeInternal(U32 groupCountX, U32 groupCountY, U32 groupCountZ)
  127. {
  128. ANKI_ASSERT(m_computeProg);
  129. ANKI_ASSERT(m_computeProg->getReflectionInfo().m_pushConstantsSize == m_setPushConstantsSize
  130. && "Forgot to set pushConstants");
  131. commandCommon();
  132. getGrManagerImpl().beginMarker(m_handle, m_computeProg->getName(), Vec3(1.0f, 1.0f, 0.0f));
  133. // Bind descriptors
  134. for(U32 i = 0; i < kMaxDescriptorSets; ++i)
  135. {
  136. if(m_computeProg->getReflectionInfo().m_descriptorSetMask.get(i))
  137. {
  138. DescriptorSet dset;
  139. Bool dirty;
  140. Array<PtrSize, kMaxBindingsPerDescriptorSet> dynamicOffsetsPtrSize;
  141. U32 dynamicOffsetCount;
  142. if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(*m_pool, m_dsetState[i], dset, dirty,
  143. dynamicOffsetsPtrSize, dynamicOffsetCount))
  144. {
  145. ANKI_VK_LOGF("Cannot recover");
  146. }
  147. if(dirty)
  148. {
  149. // Vulkan should have had the dynamic offsets as VkDeviceSize and not U32. Workaround that.
  150. Array<U32, kMaxBindingsPerDescriptorSet> dynamicOffsets;
  151. for(U32 i = 0; i < dynamicOffsetCount; ++i)
  152. {
  153. dynamicOffsets[i] = U32(dynamicOffsetsPtrSize[i]);
  154. }
  155. VkDescriptorSet dsHandle = dset.getHandle();
  156. vkCmdBindDescriptorSets(m_handle, VK_PIPELINE_BIND_POINT_COMPUTE,
  157. m_computeProg->getPipelineLayout().getHandle(), i, 1, &dsHandle,
  158. dynamicOffsetCount, &dynamicOffsets[0]);
  159. }
  160. }
  161. }
  162. vkCmdDispatch(m_handle, groupCountX, groupCountY, groupCountZ);
  163. getGrManagerImpl().endMarker(m_handle);
  164. }
  165. inline void CommandBufferImpl::traceRaysInternal(const BufferPtr& sbtBuffer, PtrSize sbtBufferOffset,
  166. U32 sbtRecordSize32, U32 hitGroupSbtRecordCount, U32 rayTypeCount,
  167. U32 width, U32 height, U32 depth)
  168. {
  169. const PtrSize sbtRecordSize = sbtRecordSize32;
  170. ANKI_ASSERT(hitGroupSbtRecordCount > 0);
  171. ANKI_ASSERT(width > 0 && height > 0 && depth > 0);
  172. ANKI_ASSERT(m_rtProg);
  173. const ShaderProgramImpl& sprog = static_cast<const ShaderProgramImpl&>(*m_rtProg);
  174. ANKI_ASSERT(sprog.getReflectionInfo().m_pushConstantsSize == m_setPushConstantsSize
  175. && "Forgot to set pushConstants");
  176. ANKI_ASSERT(rayTypeCount == sprog.getMissShaderCount() && "All the miss shaders should be in use");
  177. ANKI_ASSERT((hitGroupSbtRecordCount % rayTypeCount) == 0);
  178. const PtrSize sbtRecordCount = 1 + rayTypeCount + hitGroupSbtRecordCount;
  179. [[maybe_unused]] const PtrSize sbtBufferSize = sbtRecordCount * sbtRecordSize;
  180. ANKI_ASSERT(sbtBufferSize + sbtBufferOffset <= sbtBuffer->getSize());
  181. ANKI_ASSERT(isAligned(getGrManagerImpl().getDeviceCapabilities().m_sbtRecordAlignment, sbtBufferOffset));
  182. commandCommon();
  183. getGrManagerImpl().beginMarker(m_handle, m_rtProg->getName(), Vec3(0.0f, 0.0f, 1.0f));
  184. // Bind descriptors
  185. for(U32 i = 0; i < kMaxDescriptorSets; ++i)
  186. {
  187. if(sprog.getReflectionInfo().m_descriptorSetMask.get(i))
  188. {
  189. DescriptorSet dset;
  190. Bool dirty;
  191. Array<PtrSize, kMaxBindingsPerDescriptorSet> dynamicOffsetsPtrSize;
  192. U32 dynamicOffsetCount;
  193. if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(*m_pool, m_dsetState[i], dset, dirty,
  194. dynamicOffsetsPtrSize, dynamicOffsetCount))
  195. {
  196. ANKI_VK_LOGF("Cannot recover");
  197. }
  198. if(dirty)
  199. {
  200. // Vulkan should have had the dynamic offsets as VkDeviceSize and not U32. Workaround that.
  201. Array<U32, kMaxBindingsPerDescriptorSet> dynamicOffsets;
  202. for(U32 i = 0; i < dynamicOffsetCount; ++i)
  203. {
  204. dynamicOffsets[i] = U32(dynamicOffsetsPtrSize[i]);
  205. }
  206. VkDescriptorSet dsHandle = dset.getHandle();
  207. vkCmdBindDescriptorSets(m_handle, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR,
  208. sprog.getPipelineLayout().getHandle(), i, 1, &dsHandle, dynamicOffsetCount,
  209. &dynamicOffsets[0]);
  210. }
  211. }
  212. }
  213. Array<VkStridedDeviceAddressRegionKHR, 4> regions;
  214. const U64 stbBufferAddress = sbtBuffer->getGpuAddress() + sbtBufferOffset;
  215. ANKI_ASSERT(isAligned(getGrManagerImpl().getDeviceCapabilities().m_sbtRecordAlignment, stbBufferAddress));
  216. // Rgen
  217. regions[0].deviceAddress = stbBufferAddress;
  218. regions[0].stride = sbtRecordSize;
  219. regions[0].size = sbtRecordSize;
  220. // Miss
  221. regions[1].deviceAddress = regions[0].deviceAddress + regions[0].size;
  222. regions[1].stride = sbtRecordSize;
  223. regions[1].size = sbtRecordSize * rayTypeCount;
  224. // Hit
  225. regions[2].deviceAddress = regions[1].deviceAddress + regions[1].size;
  226. regions[2].stride = sbtRecordSize * rayTypeCount;
  227. regions[2].size = sbtRecordSize * hitGroupSbtRecordCount;
  228. // Callable, nothing for now
  229. regions[3] = VkStridedDeviceAddressRegionKHR();
  230. vkCmdTraceRaysKHR(m_handle, &regions[0], &regions[1], &regions[2], &regions[3], width, height, depth);
  231. getGrManagerImpl().endMarker(m_handle);
  232. }
  233. inline void CommandBufferImpl::resetOcclusionQueriesInternal(ConstWeakArray<OcclusionQuery*> queries)
  234. {
  235. ANKI_ASSERT(queries.getSize() > 0);
  236. commandCommon();
  237. for(U32 i = 0; i < queries.getSize(); ++i)
  238. {
  239. OcclusionQuery* query = queries[i];
  240. ANKI_ASSERT(query);
  241. const VkQueryPool poolHandle = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryPool();
  242. const U32 idx = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryIndex();
  243. vkCmdResetQueryPool(m_handle, poolHandle, idx, 1);
  244. m_microCmdb->pushObjectRef(query);
  245. }
  246. }
  247. inline void CommandBufferImpl::beginOcclusionQueryInternal(const OcclusionQueryPtr& query)
  248. {
  249. commandCommon();
  250. const VkQueryPool handle = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryPool();
  251. const U32 idx = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryIndex();
  252. ANKI_ASSERT(handle);
  253. vkCmdBeginQuery(m_handle, handle, idx, 0);
  254. m_microCmdb->pushObjectRef(query);
  255. }
  256. inline void CommandBufferImpl::endOcclusionQueryInternal(const OcclusionQueryPtr& query)
  257. {
  258. commandCommon();
  259. const VkQueryPool handle = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryPool();
  260. const U32 idx = static_cast<const OcclusionQueryImpl&>(*query).m_handle.getQueryIndex();
  261. ANKI_ASSERT(handle);
  262. vkCmdEndQuery(m_handle, handle, idx);
  263. m_microCmdb->pushObjectRef(query);
  264. }
  265. inline void CommandBufferImpl::resetTimestampQueriesInternal(ConstWeakArray<TimestampQuery*> queries)
  266. {
  267. ANKI_ASSERT(queries.getSize() > 0);
  268. commandCommon();
  269. for(U32 i = 0; i < queries.getSize(); ++i)
  270. {
  271. TimestampQuery* query = queries[i];
  272. ANKI_ASSERT(query);
  273. const VkQueryPool poolHandle = static_cast<const TimestampQueryImpl&>(*query).m_handle.getQueryPool();
  274. const U32 idx = static_cast<const TimestampQueryImpl&>(*query).m_handle.getQueryIndex();
  275. vkCmdResetQueryPool(m_handle, poolHandle, idx, 1);
  276. m_microCmdb->pushObjectRef(query);
  277. }
  278. }
  279. inline void CommandBufferImpl::writeTimestampInternal(const TimestampQueryPtr& query)
  280. {
  281. commandCommon();
  282. const VkQueryPool handle = static_cast<const TimestampQueryImpl&>(*query).m_handle.getQueryPool();
  283. const U32 idx = static_cast<const TimestampQueryImpl&>(*query).m_handle.getQueryIndex();
  284. vkCmdWriteTimestamp(m_handle, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, handle, idx);
  285. m_microCmdb->pushObjectRef(query);
  286. }
  287. inline void CommandBufferImpl::clearTextureViewInternal(const TextureViewPtr& texView, const ClearValue& clearValue)
  288. {
  289. commandCommon();
  290. const TextureViewImpl& view = static_cast<const TextureViewImpl&>(*texView);
  291. const TextureImpl& tex = view.getTextureImpl();
  292. VkClearColorValue vclear;
  293. static_assert(sizeof(vclear) == sizeof(clearValue), "See file");
  294. memcpy(&vclear, &clearValue, sizeof(clearValue));
  295. if(!view.getSubresource().m_depthStencilAspect)
  296. {
  297. VkImageSubresourceRange vkRange = view.getVkImageSubresourceRange();
  298. vkCmdClearColorImage(m_handle, tex.m_imageHandle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &vclear, 1, &vkRange);
  299. }
  300. else
  301. {
  302. ANKI_ASSERT(!"TODO");
  303. }
  304. m_microCmdb->pushObjectRef(texView);
  305. }
  306. inline void CommandBufferImpl::pushSecondLevelCommandBuffersInternal(ConstWeakArray<CommandBuffer*> cmdbs)
  307. {
  308. ANKI_ASSERT(cmdbs.getSize() > 0);
  309. commandCommon();
  310. ANKI_ASSERT(insideRenderPass());
  311. ANKI_ASSERT(m_subpassContents == VK_SUBPASS_CONTENTS_MAX_ENUM
  312. || m_subpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
  313. m_subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
  314. if(m_rpCommandCount == 0) [[unlikely]]
  315. {
  316. beginRenderPassInternal();
  317. }
  318. DynamicArrayRaii<VkCommandBuffer> handles(m_pool, cmdbs.getSize());
  319. for(U32 i = 0; i < cmdbs.getSize(); ++i)
  320. {
  321. ANKI_ASSERT(static_cast<const CommandBufferImpl&>(*cmdbs[i]).m_finalized);
  322. handles[i] = static_cast<const CommandBufferImpl&>(*cmdbs[i]).m_handle;
  323. m_microCmdb->pushObjectRef(cmdbs[i]);
  324. }
  325. vkCmdExecuteCommands(m_handle, handles.getSize(), handles.getBegin());
  326. ++m_rpCommandCount;
  327. }
  328. inline void CommandBufferImpl::drawcallCommon()
  329. {
  330. // Preconditions
  331. commandCommon();
  332. ANKI_ASSERT(m_graphicsProg);
  333. ANKI_ASSERT(insideRenderPass() || secondLevel());
  334. ANKI_ASSERT(m_subpassContents == VK_SUBPASS_CONTENTS_MAX_ENUM || m_subpassContents == VK_SUBPASS_CONTENTS_INLINE);
  335. ANKI_ASSERT(m_graphicsProg->getReflectionInfo().m_pushConstantsSize == m_setPushConstantsSize
  336. && "Forgot to set pushConstants");
  337. m_subpassContents = VK_SUBPASS_CONTENTS_INLINE;
  338. if(m_rpCommandCount == 0 && !secondLevel())
  339. {
  340. beginRenderPassInternal();
  341. }
  342. ++m_rpCommandCount;
  343. // Get or create ppline
  344. Pipeline ppline;
  345. Bool stateDirty;
  346. m_graphicsProg->getPipelineFactory().getOrCreatePipeline(m_state, ppline, stateDirty);
  347. if(stateDirty)
  348. {
  349. vkCmdBindPipeline(m_handle, VK_PIPELINE_BIND_POINT_GRAPHICS, ppline.getHandle());
  350. }
  351. // Bind dsets
  352. for(U32 i = 0; i < kMaxDescriptorSets; ++i)
  353. {
  354. if(m_graphicsProg->getReflectionInfo().m_descriptorSetMask.get(i))
  355. {
  356. DescriptorSet dset;
  357. Bool dirty;
  358. Array<PtrSize, kMaxBindingsPerDescriptorSet> dynamicOffsetsPtrSize;
  359. U32 dynamicOffsetCount;
  360. if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(*m_pool, m_dsetState[i], dset, dirty,
  361. dynamicOffsetsPtrSize, dynamicOffsetCount))
  362. {
  363. ANKI_VK_LOGF("Cannot recover");
  364. }
  365. if(dirty)
  366. {
  367. // Vulkan should have had the dynamic offsets as VkDeviceSize and not U32. Workaround that.
  368. Array<U32, kMaxBindingsPerDescriptorSet> dynamicOffsets;
  369. for(U32 i = 0; i < dynamicOffsetCount; ++i)
  370. {
  371. dynamicOffsets[i] = U32(dynamicOffsetsPtrSize[i]);
  372. }
  373. VkDescriptorSet dsHandle = dset.getHandle();
  374. vkCmdBindDescriptorSets(m_handle, VK_PIPELINE_BIND_POINT_GRAPHICS,
  375. m_graphicsProg->getPipelineLayout().getHandle(), i, 1, &dsHandle,
  376. dynamicOffsetCount, &dynamicOffsets[0]);
  377. }
  378. }
  379. }
  380. // Flush viewport
  381. if(m_viewportDirty) [[unlikely]]
  382. {
  383. const Bool flipvp = flipViewport();
  384. U32 fbWidth, fbHeight;
  385. static_cast<const FramebufferImpl&>(*m_activeFb).getAttachmentsSize(fbWidth, fbHeight);
  386. VkViewport vp = computeViewport(&m_viewport[0], fbWidth, fbHeight, flipvp);
  387. // Additional optimization
  388. if(memcmp(&vp, &m_lastViewport, sizeof(vp)) != 0)
  389. {
  390. vkCmdSetViewport(m_handle, 0, 1, &vp);
  391. m_lastViewport = vp;
  392. }
  393. m_viewportDirty = false;
  394. }
  395. // Flush scissor
  396. if(m_scissorDirty) [[unlikely]]
  397. {
  398. const Bool flipvp = flipViewport();
  399. U32 fbWidth, fbHeight;
  400. static_cast<const FramebufferImpl&>(*m_activeFb).getAttachmentsSize(fbWidth, fbHeight);
  401. VkRect2D scissor = computeScissor(&m_scissor[0], fbWidth, fbHeight, flipvp);
  402. // Additional optimization
  403. if(memcmp(&scissor, &m_lastScissor, sizeof(scissor)) != 0)
  404. {
  405. vkCmdSetScissor(m_handle, 0, 1, &scissor);
  406. m_lastScissor = scissor;
  407. }
  408. m_scissorDirty = false;
  409. }
  410. // VRS
  411. if(getGrManagerImpl().getDeviceCapabilities().m_vrs && m_vrsRateDirty)
  412. {
  413. const VkExtent2D extend = convertVrsShadingRate(m_vrsRate);
  414. Array<VkFragmentShadingRateCombinerOpKHR, 2> combiner;
  415. combiner[0] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; // Keep pipeline rating over primitive
  416. combiner[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR; // Max of attachment and pipeline rates
  417. vkCmdSetFragmentShadingRateKHR(m_handle, &extend, &combiner[0]);
  418. m_vrsRateDirty = false;
  419. }
  420. // Some checks
  421. #if ANKI_ENABLE_ASSERTIONS
  422. if(m_state.getPrimitiveTopology() == PrimitiveTopology::kLines
  423. || m_state.getPrimitiveTopology() == PrimitiveTopology::kLineStip)
  424. {
  425. ANKI_ASSERT(m_lineWidthSet == true);
  426. }
  427. #endif
  428. ANKI_TRACE_INC_COUNTER(VkDrawcall, 1);
  429. }
  430. inline void CommandBufferImpl::fillBufferInternal(const BufferPtr& buff, PtrSize offset, PtrSize size, U32 value)
  431. {
  432. commandCommon();
  433. ANKI_ASSERT(!insideRenderPass());
  434. const BufferImpl& impl = static_cast<const BufferImpl&>(*buff);
  435. ANKI_ASSERT(impl.usageValid(BufferUsageBit::kTransferDestination));
  436. ANKI_ASSERT(offset < impl.getSize());
  437. ANKI_ASSERT((offset % 4) == 0 && "Should be multiple of 4");
  438. size = (size == kMaxPtrSize) ? (impl.getActualSize() - offset) : size;
  439. alignRoundUp(4, size); // Needs to be multiple of 4
  440. ANKI_ASSERT(offset + size <= impl.getActualSize());
  441. ANKI_ASSERT((size % 4) == 0 && "Should be multiple of 4");
  442. vkCmdFillBuffer(m_handle, impl.getHandle(), offset, size, value);
  443. m_microCmdb->pushObjectRef(buff);
  444. }
  445. inline void CommandBufferImpl::writeOcclusionQueriesResultToBufferInternal(ConstWeakArray<OcclusionQuery*> queries,
  446. PtrSize offset, const BufferPtr& buff)
  447. {
  448. ANKI_ASSERT(queries.getSize() > 0);
  449. commandCommon();
  450. ANKI_ASSERT(!insideRenderPass());
  451. const BufferImpl& impl = static_cast<const BufferImpl&>(*buff);
  452. ANKI_ASSERT(impl.usageValid(BufferUsageBit::kTransferDestination));
  453. for(U32 i = 0; i < queries.getSize(); ++i)
  454. {
  455. ANKI_ASSERT(queries[i]);
  456. ANKI_ASSERT((offset % 4) == 0);
  457. ANKI_ASSERT((offset + sizeof(U32)) <= impl.getSize());
  458. OcclusionQueryImpl* q = static_cast<OcclusionQueryImpl*>(queries[i]);
  459. vkCmdCopyQueryPoolResults(m_handle, q->m_handle.getQueryPool(), q->m_handle.getQueryIndex(), 1,
  460. impl.getHandle(), offset, sizeof(U32), VK_QUERY_RESULT_PARTIAL_BIT);
  461. offset += sizeof(U32);
  462. m_microCmdb->pushObjectRef(q);
  463. }
  464. m_microCmdb->pushObjectRef(buff);
  465. }
  466. inline void CommandBufferImpl::bindShaderProgramInternal(const ShaderProgramPtr& prog)
  467. {
  468. commandCommon();
  469. ShaderProgramImpl& impl = static_cast<ShaderProgramImpl&>(*prog);
  470. if(impl.isGraphics())
  471. {
  472. m_graphicsProg = &impl;
  473. m_computeProg = nullptr; // Unbind the compute prog. Doesn't work like vulkan
  474. m_rtProg = nullptr; // See above
  475. m_state.bindShaderProgram(&impl);
  476. }
  477. else if(!!(impl.getStages() & ShaderTypeBit::kCompute))
  478. {
  479. m_computeProg = &impl;
  480. m_graphicsProg = nullptr; // See comment in the if()
  481. m_rtProg = nullptr; // See above
  482. // Bind the pipeline now
  483. vkCmdBindPipeline(m_handle, VK_PIPELINE_BIND_POINT_COMPUTE, impl.getComputePipelineHandle());
  484. }
  485. else
  486. {
  487. ANKI_ASSERT(!!(impl.getStages() & ShaderTypeBit::kAllRayTracing));
  488. m_computeProg = nullptr;
  489. m_graphicsProg = nullptr;
  490. m_rtProg = &impl;
  491. // Bind now
  492. vkCmdBindPipeline(m_handle, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, impl.getRayTracingPipelineHandle());
  493. }
  494. for(U32 i = 0; i < kMaxDescriptorSets; ++i)
  495. {
  496. if(impl.getReflectionInfo().m_descriptorSetMask.get(i))
  497. {
  498. m_dsetState[i].setLayout(impl.getDescriptorSetLayout(i));
  499. }
  500. else
  501. {
  502. // According to the spec the bound DS may be disturbed if the ppline layout is not compatible. Play it safe
  503. // and dirty the slot. That will force rebind of the DS at drawcall time.
  504. m_dsetState[i].setLayout(DescriptorSetLayout());
  505. }
  506. }
  507. m_microCmdb->pushObjectRef(prog);
  508. #if ANKI_EXTRA_CHECKS
  509. m_setPushConstantsSize = 0;
  510. #endif
  511. }
  512. inline void CommandBufferImpl::copyBufferToBufferInternal(const BufferPtr& src, const BufferPtr& dst,
  513. ConstWeakArray<CopyBufferToBufferInfo> copies)
  514. {
  515. ANKI_ASSERT(static_cast<const BufferImpl&>(*src).usageValid(BufferUsageBit::kTransferSource));
  516. ANKI_ASSERT(static_cast<const BufferImpl&>(*dst).usageValid(BufferUsageBit::kTransferDestination));
  517. ANKI_ASSERT(copies.getSize() > 0);
  518. commandCommon();
  519. static_assert(sizeof(CopyBufferToBufferInfo) == sizeof(VkBufferCopy));
  520. const VkBufferCopy* vkCopies = reinterpret_cast<const VkBufferCopy*>(&copies[0]);
  521. vkCmdCopyBuffer(m_handle, static_cast<const BufferImpl&>(*src).getHandle(),
  522. static_cast<const BufferImpl&>(*dst).getHandle(), copies.getSize(), &vkCopies[0]);
  523. m_microCmdb->pushObjectRef(src);
  524. m_microCmdb->pushObjectRef(dst);
  525. }
  526. inline Bool CommandBufferImpl::flipViewport() const
  527. {
  528. return static_cast<const FramebufferImpl&>(*m_activeFb).hasPresentableTexture();
  529. }
  530. inline void CommandBufferImpl::setPushConstantsInternal(const void* data, U32 dataSize)
  531. {
  532. ANKI_ASSERT(data && dataSize && dataSize % 16 == 0);
  533. const ShaderProgramImpl& prog = getBoundProgram();
  534. ANKI_ASSERT(prog.getReflectionInfo().m_pushConstantsSize == dataSize
  535. && "The bound program should have push constants equal to the \"dataSize\" parameter");
  536. commandCommon();
  537. vkCmdPushConstants(m_handle, prog.getPipelineLayout().getHandle(), VK_SHADER_STAGE_ALL, 0, dataSize, data);
  538. #if ANKI_EXTRA_CHECKS
  539. m_setPushConstantsSize = dataSize;
  540. #endif
  541. }
  542. inline void CommandBufferImpl::setRasterizationOrderInternal(RasterizationOrder order)
  543. {
  544. commandCommon();
  545. if(!!(getGrManagerImpl().getExtensions() & VulkanExtensions::kAMD_rasterization_order))
  546. {
  547. m_state.setRasterizationOrder(order);
  548. }
  549. }
  550. inline void CommandBufferImpl::setLineWidthInternal(F32 width)
  551. {
  552. commandCommon();
  553. vkCmdSetLineWidth(m_handle, width);
  554. #if ANKI_ENABLE_ASSERTIONS
  555. m_lineWidthSet = true;
  556. #endif
  557. }
  558. inline void CommandBufferImpl::setVrsRateInternal(VrsRate rate)
  559. {
  560. ANKI_ASSERT(getGrManagerImpl().getDeviceCapabilities().m_vrs);
  561. ANKI_ASSERT(rate < VrsRate::kCount);
  562. commandCommon();
  563. if(m_vrsRate != rate)
  564. {
  565. m_vrsRate = rate;
  566. m_vrsRateDirty = true;
  567. }
  568. }
  569. } // end namespace anki