CommandBuffer.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Gr/GrObject.h>
  7. #include <AnKi/Gr/Buffer.h>
  8. #include <AnKi/Gr/Texture.h>
  9. #include <AnKi/Util/Functions.h>
  10. #include <AnKi/Util/WeakArray.h>
  11. #include <AnKi/Math.h>
  12. namespace anki {
  13. /// @addtogroup graphics
  14. /// @{
  15. class TextureBarrierInfo
  16. {
  17. public:
  18. TextureView m_textureView;
  19. TextureUsageBit m_previousUsage = TextureUsageBit::kNone;
  20. TextureUsageBit m_nextUsage = TextureUsageBit::kNone;
  21. };
  22. class BufferBarrierInfo
  23. {
  24. public:
  25. BufferView m_bufferView;
  26. BufferUsageBit m_previousUsage = BufferUsageBit::kNone;
  27. BufferUsageBit m_nextUsage = BufferUsageBit::kNone;
  28. };
  29. class AccelerationStructureBarrierInfo
  30. {
  31. public:
  32. AccelerationStructure* m_as = nullptr;
  33. AccelerationStructureUsageBit m_previousUsage = AccelerationStructureUsageBit::kNone;
  34. AccelerationStructureUsageBit m_nextUsage = AccelerationStructureUsageBit::kNone;
  35. };
  36. class CopyBufferToBufferInfo
  37. {
  38. public:
  39. PtrSize m_sourceOffset = 0;
  40. PtrSize m_destinationOffset = 0;
  41. PtrSize m_range = 0;
  42. };
  43. class RenderTarget
  44. {
  45. public:
  46. TextureView m_textureView;
  47. RenderTargetLoadOperation m_loadOperation = RenderTargetLoadOperation::kClear;
  48. RenderTargetStoreOperation m_storeOperation = RenderTargetStoreOperation::kStore;
  49. RenderTargetLoadOperation m_stencilLoadOperation = RenderTargetLoadOperation::kClear;
  50. RenderTargetStoreOperation m_stencilStoreOperation = RenderTargetStoreOperation::kStore;
  51. ClearValue m_clearValue;
  52. TextureUsageBit m_usage = TextureUsageBit::kRtvDsvWrite;
  53. RenderTarget() = default;
  54. RenderTarget(const TextureView& view)
  55. : m_textureView(view)
  56. {
  57. }
  58. };
  59. /// Command buffer initialization flags.
  60. enum class CommandBufferFlag : U8
  61. {
  62. kNone = 0,
  63. /// It will contain a handfull of commands.
  64. kSmallBatch = 1 << 0,
  65. /// Will contain graphics, compute and transfer work.
  66. kGeneralWork = 1 << 1,
  67. /// Will contain only compute work. It binds to async compute queues.
  68. kComputeWork = 1 << 2,
  69. };
  70. ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(CommandBufferFlag)
  71. /// Command buffer init info.
  72. class CommandBufferInitInfo : public GrBaseInitInfo
  73. {
  74. public:
  75. CommandBufferFlag m_flags = CommandBufferFlag::kGeneralWork;
  76. CommandBufferInitInfo(CString name = {})
  77. : GrBaseInitInfo(name)
  78. {
  79. }
  80. CommandBufferInitInfo(CommandBufferFlag flags, CString name = {})
  81. : GrBaseInitInfo(name)
  82. , m_flags(flags)
  83. {
  84. }
  85. };
  86. /// Maps to HLSL register(X#, S)
  87. class Register
  88. {
  89. public:
  90. U32 m_bindPoint = kMaxU32;
  91. HlslResourceType m_resourceType = HlslResourceType::kCount;
  92. U8 m_space = kMaxU8;
  93. Register(HlslResourceType type, U32 bindingPoint, U8 space = 0)
  94. : m_bindPoint(bindingPoint)
  95. , m_resourceType(type)
  96. , m_space(space)
  97. {
  98. validate();
  99. }
  100. /// Construct using a couple of strings like ("t0", "space10")
  101. Register(const Char* reg, const Char* space = "space0")
  102. {
  103. ANKI_ASSERT(reg && space);
  104. m_resourceType = toResourceType(reg[0]);
  105. ++reg;
  106. m_bindPoint = 0;
  107. do
  108. {
  109. ANKI_ASSERT(*reg >= '0' && *reg <= '9');
  110. m_bindPoint *= 10;
  111. m_bindPoint += *reg - '0';
  112. ++reg;
  113. } while(*reg != '\0');
  114. ANKI_ASSERT(strlen(space) == 6);
  115. ANKI_ASSERT(space[5] >= '0' && space[5] <= '9');
  116. m_space = U8(space[5] - '0');
  117. }
  118. void validate() const
  119. {
  120. ANKI_ASSERT(m_bindPoint != kMaxU32);
  121. ANKI_ASSERT(m_resourceType < HlslResourceType::kCount);
  122. ANKI_ASSERT(m_space < kMaxDescriptorSets);
  123. }
  124. private:
  125. static HlslResourceType toResourceType(Char c)
  126. {
  127. switch(c)
  128. {
  129. case 'b':
  130. return HlslResourceType::kCbv;
  131. case 'u':
  132. return HlslResourceType::kUav;
  133. case 't':
  134. return HlslResourceType::kSrv;
  135. case 's':
  136. return HlslResourceType::kSampler;
  137. default:
  138. ANKI_ASSERT(0);
  139. return HlslResourceType::kCount;
  140. }
  141. }
  142. };
  143. /// Break the code style to define something HLSL like
  144. #define ANKI_REG(reg) Register(ANKI_STRINGIZE(reg))
  145. #define ANKI_REG2(reg, space) Register(ANKI_STRINGIZE(reg), ANKI_STRINGIZE(space))
  146. /// Command buffer.
  147. class CommandBuffer : public GrObject
  148. {
  149. ANKI_GR_OBJECT
  150. public:
  151. static constexpr GrObjectType kClassType = GrObjectType::kCommandBuffer;
  152. CommandBufferFlag getFlags() const
  153. {
  154. return m_flags;
  155. }
  156. /// Finalize the command buffer.
  157. void endRecording();
  158. /// @name State manipulation
  159. /// @{
  160. /// Bind vertex buffer.
  161. void bindVertexBuffer(U32 binding, const BufferView& buff, U32 stride, VertexStepRate stepRate = VertexStepRate::kVertex);
  162. /// Setup a vertex attribute.
  163. void setVertexAttribute(VertexAttributeSemantic attribute, U32 buffBinding, Format fmt, U32 relativeOffset);
  164. /// Bind index buffer.
  165. void bindIndexBuffer(const BufferView& buff, IndexType type);
  166. /// Enable primitive restart.
  167. void setPrimitiveRestart(Bool enable);
  168. /// Set the viewport.
  169. void setViewport(U32 minx, U32 miny, U32 width, U32 height);
  170. /// Set the scissor rect. To disable the scissor just set a rect bigger than the viewport. By default it's disabled.
  171. void setScissor(U32 minx, U32 miny, U32 width, U32 height);
  172. /// Set fill mode.
  173. void setFillMode(FillMode mode);
  174. /// Set cull mode.
  175. /// By default it's FaceSelectionBit::BACK.
  176. void setCullMode(FaceSelectionBit mode);
  177. /// Set depth offset and units. Set zeros to both to disable it.
  178. void setPolygonOffset(F32 factor, F32 units);
  179. /// Set stencil operations. To disable stencil test put StencilOperation::KEEP to all operations.
  180. void setStencilOperations(FaceSelectionBit face, StencilOperation stencilFail, StencilOperation stencilPassDepthFail,
  181. StencilOperation stencilPassDepthPass);
  182. /// Set stencil compare operation.
  183. void setStencilCompareOperation(FaceSelectionBit face, CompareOperation comp);
  184. /// Set the stencil compare mask.
  185. void setStencilCompareMask(FaceSelectionBit face, U32 mask);
  186. /// Set the stencil write mask.
  187. void setStencilWriteMask(FaceSelectionBit face, U32 mask);
  188. /// Set the stencil reference.
  189. void setStencilReference(FaceSelectionBit face, U32 ref);
  190. /// Enable/disable depth write. To disable depth testing set depth write to false and depth compare operation to
  191. /// always.
  192. void setDepthWrite(Bool enable);
  193. /// Set depth compare operation. By default it's less.
  194. void setDepthCompareOperation(CompareOperation op);
  195. /// Enable/disable alpha to coverage.
  196. void setAlphaToCoverage(Bool enable);
  197. /// Set color channel write mask.
  198. void setColorChannelWriteMask(U32 attachment, ColorBit mask);
  199. /// Set blend factors seperate.
  200. /// By default the values of srcRgb, dstRgb, srcA and dstA are BlendFactor::ONE, BlendFactor::ZERO,
  201. /// BlendFactor::ONE, BlendFactor::ZERO respectively.
  202. void setBlendFactors(U32 attachment, BlendFactor srcRgb, BlendFactor dstRgb, BlendFactor srcA, BlendFactor dstA);
  203. /// Set blend factors.
  204. void setBlendFactors(U32 attachment, BlendFactor src, BlendFactor dst)
  205. {
  206. setBlendFactors(attachment, src, dst, src, dst);
  207. }
  208. /// Set the blend operation seperate.
  209. /// By default the values of funcRgb and funcA are BlendOperation::ADD, BlendOperation::ADD respectively.
  210. void setBlendOperation(U32 attachment, BlendOperation funcRgb, BlendOperation funcA);
  211. /// Set the blend operation.
  212. void setBlendOperation(U32 attachment, BlendOperation func)
  213. {
  214. setBlendOperation(attachment, func, func);
  215. }
  216. /// Set the line width. By default it's undefined.
  217. void setLineWidth(F32 lineWidth);
  218. /// Bind sampler.
  219. void bindSampler(Register reg, Sampler* sampler);
  220. /// Bind a texture.
  221. void bindTexture(Register reg, const TextureView& texView);
  222. /// Bind uniform buffer.
  223. void bindUniformBuffer(Register reg, const BufferView& buff);
  224. /// Bind storage buffer.
  225. void bindStorageBuffer(Register reg, const BufferView& buff);
  226. /// Bind texel buffer.
  227. void bindTexelBuffer(Register reg, const BufferView& buff, Format fmt);
  228. /// Bind AS.
  229. void bindAccelerationStructure(Register reg, AccelerationStructure* as);
  230. /// Set push constants.
  231. void setPushConstants(const void* data, U32 dataSize);
  232. /// Bind a program.
  233. void bindShaderProgram(ShaderProgram* prog);
  234. /// Begin a renderpass.
  235. /// The minx, miny, width, height control the area that the load and store operations will happen. If the scissor is bigger than the render area
  236. /// the results are undefined.
  237. void beginRenderPass(ConstWeakArray<RenderTarget> colorRts, RenderTarget* depthStencilRt, U32 minx = 0, U32 miny = 0, U32 width = kMaxU32,
  238. U32 height = kMaxU32, const TextureView& vrsRt = TextureView(), U8 vrsRtTexelSizeX = 0, U8 vrsRtTexelSizeY = 0);
  239. /// See beginRenderPass.
  240. void beginRenderPass(std::initializer_list<RenderTarget> colorRts, RenderTarget* depthStencilRt = nullptr, U32 minx = 0, U32 miny = 0,
  241. U32 width = kMaxU32, U32 height = kMaxU32, const TextureView& vrsRt = TextureView(), U8 vrsRtTexelSizeX = 0,
  242. U8 vrsRtTexelSizeY = 0)
  243. {
  244. beginRenderPass(ConstWeakArray(colorRts.begin(), U32(colorRts.size())), depthStencilRt, minx, miny, width, height, vrsRt, vrsRtTexelSizeX,
  245. vrsRtTexelSizeY);
  246. }
  247. /// End renderpass.
  248. void endRenderPass();
  249. /// Set VRS rate of the following drawcalls. By default it's 1x1.
  250. void setVrsRate(VrsRate rate);
  251. /// @}
  252. /// @name Jobs
  253. /// @{
  254. void drawIndexed(PrimitiveTopology topology, U32 count, U32 instanceCount = 1, U32 firstIndex = 0, U32 baseVertex = 0, U32 baseInstance = 0);
  255. void draw(PrimitiveTopology topology, U32 count, U32 instanceCount = 1, U32 first = 0, U32 baseInstance = 0);
  256. void drawIndexedIndirect(PrimitiveTopology topology, const BufferView& indirectBuff, U32 drawCount = 1);
  257. void drawIndirect(PrimitiveTopology topology, const BufferView& indirectBuff, U32 drawCount = 1);
  258. void drawIndexedIndirectCount(PrimitiveTopology topology, const BufferView& argBuffer, U32 argBufferStride, const BufferView& countBuffer,
  259. U32 maxDrawCount);
  260. void drawIndirectCount(PrimitiveTopology topology, const BufferView& argBuffer, U32 argBufferStride, const BufferView& countBuffer,
  261. U32 maxDrawCount);
  262. void drawMeshTasks(U32 groupCountX, U32 groupCountY, U32 groupCountZ);
  263. void drawMeshTasksIndirect(const BufferView& argBuffer, U32 drawCount = 1);
  264. void dispatchCompute(U32 groupCountX, U32 groupCountY, U32 groupCountZ);
  265. void dispatchComputeIndirect(const BufferView& argBuffer);
  266. void dispatchGraph(const BufferView& scratchBuffer, const void* records, U32 recordCount, U32 recordStride);
  267. /// Trace rays.
  268. ///
  269. /// The 1st thing in the sbtBuffer is the ray gen shader group handle:
  270. /// @code RG = RG_offset @endcode
  271. /// The RG_offset is equal to the stbBufferOffset.
  272. ///
  273. /// Then the sbtBuffer contains the miss shader group handles and their data. The indexing is as follows:
  274. /// @code M = M_offset + M_stride * R_miss @endcode
  275. /// The M_offset is equal to stbBufferOffset + GpuDeviceCapabilities::m_sbtRecordSize.
  276. /// The M_stride is equal to GpuDeviceCapabilities::m_sbtRecordSize.
  277. /// The R_miss is defined in the traceRayEXT and it's the "ray type".
  278. ///
  279. /// After the miss shaders the sbtBuffer has the hit group shader group handles and their data. The indexing is:
  280. /// @code HG = HG_offset + (HG_stride * (R_offset + R_stride * G_id + I_offset)) @endcode
  281. /// The HG_offset is equal to sbtBufferOffset + GpuDeviceCapabilities::m_sbtRecordSize * (missShaderCount + 1).
  282. /// The HG_stride is equal GpuDeviceCapabilities::m_sbtRecordSize * rayTypecount.
  283. /// The R_offset and R_stride are provided in traceRayEXT. The R_offset is the "ray type" and R_stride the number of ray types.
  284. /// The G_id is always 0 ATM.
  285. /// The I_offset is the AccelerationStructureInstance::m_hitgroupSbtRecordIndex.
  286. ///
  287. /// @param[in] sbtBuffer The SBT buffer.
  288. /// @param sbtRecordSize The size of an SBT record
  289. /// @param hitGroupSbtRecordCount The number of SBT records that contain hit groups.
  290. /// @param rayTypecount The number of ray types hosted in the pipeline. See above on how it's been used.
  291. /// @param width Width.
  292. /// @param height Height.
  293. /// @param depth Depth.
  294. void traceRays(const BufferView& sbtBuffer, U32 sbtRecordSize, U32 hitGroupSbtRecordCount, U32 rayTypeCount, U32 width, U32 height, U32 depth);
  295. /// Blit from surface to surface.
  296. void blitTexture(const TextureView& srcView, const TextureView& destView);
  297. /// Clear a single texture surface. Can be used for all textures except 3D.
  298. void clearTexture(const TextureView& texView, const ClearValue& clearValue);
  299. /// Copy a buffer to a texture surface or volume.
  300. void copyBufferToTexture(const BufferView& buff, const TextureView& texView);
  301. /// Fill a buffer with some value.
  302. void fillBuffer(const BufferView& buff, U32 value);
  303. /// Write the occlusion result to buffer.
  304. void writeOcclusionQueriesResultToBuffer(ConstWeakArray<OcclusionQuery*> queries, const BufferView& buff);
  305. /// Copy buffer to buffer.
  306. void copyBufferToBuffer(const BufferView& src, const BufferView& dst)
  307. {
  308. ANKI_ASSERT(src.getRange() == dst.getRange());
  309. Array<CopyBufferToBufferInfo, 1> copies = {{{src.getOffset(), dst.getOffset(), src.getRange()}}};
  310. copyBufferToBuffer(&src.getBuffer(), &dst.getBuffer(), copies);
  311. }
  312. /// Copy buffer to buffer.
  313. void copyBufferToBuffer(Buffer* src, Buffer* dst, ConstWeakArray<CopyBufferToBufferInfo> copies);
  314. /// Build the acceleration structure.
  315. void buildAccelerationStructure(AccelerationStructure* as, const BufferView& scratchBuffer);
  316. /// Do upscaling by an external upscaler
  317. /// @param[in] upscaler the upscaler to use for upscaling
  318. /// @param[in] inColor Source LowRes RenderTarget.
  319. /// @param[out] outUpscaledColor Destination HighRes RenderTarget
  320. /// @param[in] motionVectors Motion Vectors
  321. /// @param[in] depth Depth attachment
  322. /// @param[in] exposure 1x1 Texture containing exposure
  323. /// @param[in] resetAccumulation Whether to clean or not any temporal history
  324. /// @param[in] jitterOffset Jittering offset that was applied during the generation of sourceTexture
  325. /// @param[in] motionVectorsScale Any scale factor that might need to be applied to the motionVectorsTexture (i.e UV space to Pixel space
  326. /// conversion)
  327. void upscale(GrUpscaler* upscaler, const TextureView& inColor, const TextureView& outUpscaledColor, const TextureView& motionVectors,
  328. const TextureView& depth, const TextureView& exposure, Bool resetAccumulation, const Vec2& jitterOffset,
  329. const Vec2& motionVectorsScale);
  330. /// @}
  331. /// @name Sync
  332. /// @{
  333. void setPipelineBarrier(ConstWeakArray<TextureBarrierInfo> textures, ConstWeakArray<BufferBarrierInfo> buffers,
  334. ConstWeakArray<AccelerationStructureBarrierInfo> accelerationStructures);
  335. /// @}
  336. /// @name Other
  337. /// @{
  338. /// Begin query.
  339. void beginOcclusionQuery(OcclusionQuery* query);
  340. /// End query.
  341. void endOcclusionQuery(OcclusionQuery* query);
  342. /// Begin query.
  343. void beginPipelineQuery(PipelineQuery* query);
  344. /// End query.
  345. void endPipelineQuery(PipelineQuery* query);
  346. /// Write a timestamp.
  347. void writeTimestamp(TimestampQuery* query);
  348. Bool isEmpty() const;
  349. void pushDebugMarker(CString name, Vec3 color);
  350. void popDebugMarker();
  351. /// @}
  352. protected:
  353. CommandBufferFlag m_flags = CommandBufferFlag::kNone;
  354. /// Construct.
  355. CommandBuffer(CString name)
  356. : GrObject(kClassType, name)
  357. {
  358. }
  359. /// Destroy.
  360. ~CommandBuffer()
  361. {
  362. }
  363. private:
  364. /// Allocate and initialize a new instance.
  365. [[nodiscard]] static CommandBuffer* newInstance(const CommandBufferInitInfo& init);
  366. };
  367. /// @}
  368. } // end namespace anki