git.s-ol.nu ~forks/DiligentCore / 408db3c
Added DrawMeshIndirectCount command. azhirnov authored 6 months ago assiduous committed 6 months ago
15 changed file(s) with 476 addition(s) and 63 deletion(s). Raw diff Collapse all Expand all
5656
5757 bool VerifyDrawMeshAttribs(Uint32 MaxDrawMeshTasksCount, const DrawMeshAttribs& Attribs);
5858 bool VerifyDrawMeshIndirectAttribs(const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer);
59 bool VerifyDrawMeshIndirectCountAttribs(const DrawMeshIndirectCountAttribs& Attribs, const IBuffer* pAttribsBuffer, const IBuffer* pCountBuff, Uint32 IndirectCmdStride);
5960
6061 bool VerifyResolveTextureSubresourceAttribs(const ResolveTextureSubresourceAttribs& ResolveAttribs,
6162 const TextureDesc& SrcTexDesc,
7172 bool VerifyWriteBLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteBLASCompactedSizeAttribs& Attribs);
7273 bool VerifyWriteTLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteTLASCompactedSizeAttribs& Attribs);
7374 bool VerifyTraceRaysAttribs(const TraceRaysAttribs& Attribs);
74 bool VerifyTraceRaysIndirectAttribs(const IRenderDevice* pDevice, const TraceRaysIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer, Uint32 SBTSize);
75 bool VerifyTraceRaysIndirectAttribs(const IRenderDevice* pDevice,
76 const TraceRaysIndirectAttribs& Attribs,
77 const IBuffer* pAttribsBuffer,
78 Uint32 SBTSize);
7579
7680
7781
289293
290294 #ifdef DILIGENT_DEVELOPMENT
291295 // clang-format off
292 bool DvpVerifyDrawArguments (const DrawAttribs& Attribs) const;
293 bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs) const;
294 bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs) const;
295 bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
296 bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
297 bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
296 bool DvpVerifyDrawArguments (const DrawAttribs& Attribs) const;
297 bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs) const;
298 bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs) const;
299 bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
300 bool DvpVerifyDrawIndexedIndirectArguments (const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
301 bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
302 bool DvpVerifyDrawMeshIndirectCountArguments(const DrawMeshIndirectCountAttribs& Attribs, const IBuffer* pAttribsBuffer, const IBuffer* pCountBuff) const;
298303
299304 bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs) const;
300305 bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const;
306311 bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName) const;
307312 bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName) const;
308313 #else
309 bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const {return true;}
310 bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const {return true;}
311 bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs)const {return true;}
312 bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
313 bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
314 bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
314 bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const {return true;}
315 bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const {return true;}
316 bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs)const {return true;}
317 bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
318 bool DvpVerifyDrawIndexedIndirectArguments (const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
319 bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
320 bool DvpVerifyDrawMeshIndirectCountArguments(const DrawMeshIndirectCountAttribs& Attribs, const IBuffer* pAttribsBuffer, const IBuffer* pCountBuff) const {return true;}
315321
316322 bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const {return true;}
317323 bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
334340 bool TraceRays(const TraceRaysAttribs& Attribs, int) const;
335341 bool TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer, int) const;
336342
337 static constexpr Uint32 TraceRaysIndirectCommandSBTSize = 88; // D3D12: 88 bytes, size of SBT offsets
338 // Vulkan: 0 bytes, SBT offsets placed directly into function call
343 static constexpr Uint32 DrawMeshIndirectCommandStride = sizeof(uint) * 3; // D3D12: 12 bytes (x, y, z dimension)
344 // Vulkan: 8 bytes (task count, first task)
345 static constexpr Uint32 TraceRaysIndirectCommandSBTSize = 88; // D3D12: 88 bytes, size of SBT offsets
346 // Vulkan: 0 bytes, SBT offsets placed directly into function call
339347
340348 /// Strong reference to the device.
341349 RefCntAutoPtr<DeviceImplType> m_pDevice;
18941902 }
18951903
18961904 template <typename ImplementationTraits>
1905 inline bool DeviceContextBase<ImplementationTraits>::DvpVerifyDrawMeshIndirectCountArguments(
1906 const DrawMeshIndirectCountAttribs& Attribs,
1907 const IBuffer* pAttribsBuffer,
1908 const IBuffer* pCountBuff) const
1909 {
1910 if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
1911 return true;
1912
1913 if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED)
1914 {
1915 LOG_ERROR_MESSAGE("DrawMeshIndirectCount: mesh shaders are not supported by this device");
1916 return false;
1917 }
1918
1919 if (!m_pPipelineState)
1920 {
1921 LOG_ERROR_MESSAGE("DrawMeshIndirectCount command arguments are invalid: no pipeline state is bound.");
1922 return false;
1923 }
1924
1925 if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_MESH)
1926 {
1927 LOG_ERROR_MESSAGE("DrawMeshIndirectCount command arguments are invalid: pipeline state '",
1928 m_pPipelineState->GetDesc().Name, "' is not a mesh pipeline.");
1929 return false;
1930 }
1931
1932 return VerifyDrawMeshIndirectCountAttribs(Attribs, pAttribsBuffer, pCountBuff, DrawMeshIndirectCommandStride);
1933 }
1934
1935 template <typename ImplementationTraits>
18971936 inline bool DeviceContextBase<ImplementationTraits>::DvpVerifyRenderTargets() const
18981937 {
18991938 if (!m_pPipelineState)
433433 typedef struct DrawMeshIndirectAttribs DrawMeshIndirectAttribs;
434434
435435
436 /// Defines the mesh indirect draw count command attributes.
437
438 /// This structure is used by IDeviceContext::DrawMeshIndirectCount().
439 struct DrawMeshIndirectCountAttribs
440 {
441 /// Additional flags, see Diligent::DRAW_FLAGS.
442 DRAW_FLAGS Flags DEFAULT_INITIALIZER(DRAW_FLAG_NONE);
443
444 /// The maximum number of commands that will be read from the count buffer.
445 Uint32 MaxCommandCount DEFAULT_INITIALIZER(1);
446
447 /// State transition mode for indirect draw arguments buffer.
448 RESOURCE_STATE_TRANSITION_MODE IndirectAttribsBufferStateTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
449
450 /// Offset from the beginning of the buffer to the location of draw command attributes.
451 Uint32 IndirectDrawArgsOffset DEFAULT_INITIALIZER(0);
452
453 /// State transition mode for the count buffer.
454 RESOURCE_STATE_TRANSITION_MODE CountBufferStateTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
455
456 /// Offset from the beginning of the buffer to the location of the command counter.
457 Uint32 CountBufferOffset DEFAULT_INITIALIZER(0);
458
459 #if DILIGENT_CPP_INTERFACE
460 DrawMeshIndirectCountAttribs()noexcept{}
461
462 /// Initializes the structure members with user-specified values.
463 DrawMeshIndirectCountAttribs(DRAW_FLAGS _Flags,
464 RESOURCE_STATE_TRANSITION_MODE _IndirectAttribsBufferStateTransitionMode,
465 Uint32 _IndirectDrawArgsOffset,
466 RESOURCE_STATE_TRANSITION_MODE _CountBufferStateTransitionMode,
467 Uint32 _CountBufferOffset)noexcept :
468 Flags {_Flags },
469 IndirectAttribsBufferStateTransitionMode{_IndirectAttribsBufferStateTransitionMode},
470 IndirectDrawArgsOffset {_IndirectDrawArgsOffset },
471 CountBufferStateTransitionMode {_CountBufferStateTransitionMode },
472 CountBufferOffset {_CountBufferOffset }
473 {}
474 #endif
475 };
476 typedef struct DrawMeshIndirectCountAttribs DrawMeshIndirectCountAttribs;
477
478
436479 /// Defines which parts of the depth-stencil buffer to clear.
437480
438481 /// These flags are used by IDeviceContext::ClearDepthStencil().
17641807 IBuffer* pAttribsBuffer) PURE;
17651808
17661809
1810 /// Executes an mesh indirect draw command with indirect command count buffer.
1811
1812 /// \param [in] Attribs - Structure describing the command attributes, see Diligent::DrawMeshIndirectCountAttribs for details.
1813 /// \param [in] pAttribsBuffer - Pointer to the buffer, from which indirect draw attributes will be read.
1814 /// The buffer must contain the following arguments at the specified offset:
1815 /// Direct3D12:
1816 /// Uint32 ThreadGroupCountX;
1817 /// Uint32 ThreadGroupCountY;
1818 /// Uint32 ThreadGroupCountZ;
1819 /// Vulkan:
1820 /// Uint32 TaskCount;
1821 /// Uint32 FirstTask;
1822 /// Size of the buffer must be sizeof(Uint32[3]) * Attribs.MaxDrawCommands.
1823 /// \param [in] pCountBuffer - Pointer to the buffer, from which Uint32 value with draw count will be read.
1824 ///
1825 /// \remarks For compatibility between Direct3D12 and Vulkan and with direct call (DrawMesh) use the first element in the structure,
1826 /// for example: Direct3D12 {TaskCount, 1, 1}, Vulkan {TaskCount, 0}.
1827 ///
1828 /// \remarks If IndirectAttribsBufferStateTransitionMode member is Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
1829 /// the method may transition the state of the indirect draw arguments buffer. This is not a thread safe operation,
1830 /// so no other thread is allowed to read or write the state of the buffer.
1831 ///
1832 /// If the application intends to use the same resources in other threads simultaneously, it needs to
1833 /// explicitly manage the states using IDeviceContext::TransitionResourceStates() method.
1834 VIRTUAL void METHOD(DrawMeshIndirectCount)(THIS_
1835 const DrawMeshIndirectCountAttribs REF Attribs,
1836 IBuffer* pAttribsBuffer,
1837 IBuffer* pCountBuffer) PURE;
1838
1839
17671840 /// Executes a dispatch compute command.
1768
1841
17691842 /// \param [in] Attribs - Dispatch command attributes, see Diligent::DispatchComputeAttribs for details.
17701843 VIRTUAL void METHOD(DispatchCompute)(THIS_
17711844 const DispatchComputeAttribs REF Attribs) PURE;
22632336 # define IDeviceContext_DrawIndexedIndirect(This, ...) CALL_IFACE_METHOD(DeviceContext, DrawIndexedIndirect, This, __VA_ARGS__)
22642337 # define IDeviceContext_DrawMesh(This, ...) CALL_IFACE_METHOD(DeviceContext, DrawMesh, This, __VA_ARGS__)
22652338 # define IDeviceContext_DrawMeshIndirect(This, ...) CALL_IFACE_METHOD(DeviceContext, DrawMeshIndirect, This, __VA_ARGS__)
2339 # define IDeviceContext_DrawMeshIndirectCount(This, ...) CALL_IFACE_METHOD(DeviceContext, DrawMeshIndirectCount, This, __VA_ARGS__)
22662340 # define IDeviceContext_DispatchCompute(This, ...) CALL_IFACE_METHOD(DeviceContext, DispatchCompute, This, __VA_ARGS__)
22672341 # define IDeviceContext_DispatchComputeIndirect(This, ...) CALL_IFACE_METHOD(DeviceContext, DispatchComputeIndirect, This, __VA_ARGS__)
22682342 # define IDeviceContext_ClearDepthStencil(This, ...) CALL_IFACE_METHOD(DeviceContext, ClearDepthStencil, This, __VA_ARGS__)
135135 return true;
136136 }
137137
138 bool VerifyDrawMeshIndirectCountAttribs(const DrawMeshIndirectCountAttribs& Attribs, const IBuffer* pAttribsBuffer, const IBuffer* pCountBuff, Uint32 IndirectCmdStride)
139 {
140 #define CHECK_DRAW_MESH_INDIRECT_COUNT_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw mesh indirect count attribs are invalid: ", __VA_ARGS__)
141
142 CHECK_DRAW_MESH_INDIRECT_COUNT_ATTRIBS(pAttribsBuffer != nullptr, "indirect draw arguments buffer must not be null.");
143
144 const auto& IDesc = pAttribsBuffer->GetDesc();
145 CHECK_DRAW_MESH_INDIRECT_COUNT_ATTRIBS((IDesc.BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0,
146 "indirect draw arguments buffer '", IDesc.Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
147 CHECK_DRAW_MESH_INDIRECT_COUNT_ATTRIBS(Attribs.IndirectDrawArgsOffset + IndirectCmdStride * Attribs.MaxCommandCount <= IDesc.uiSizeInBytes,
148 "invalid IndirectDrawArgsOffset or indirect draw arguments buffer '", IDesc.Name, "' is too small.");
149
150 CHECK_DRAW_MESH_INDIRECT_COUNT_ATTRIBS(pCountBuff != nullptr, "count buffer must not be null.");
151
152 const auto& CDesc = pAttribsBuffer->GetDesc();
153 CHECK_DRAW_MESH_INDIRECT_COUNT_ATTRIBS((CDesc.BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0,
154 "count buffer '", CDesc.Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
155 CHECK_DRAW_MESH_INDIRECT_COUNT_ATTRIBS(Attribs.CountBufferOffset + 4 <= CDesc.uiSizeInBytes,
156 "invalid CountBufferOffset or count buffer '", CDesc.Name, "' is too small.");
157
158 #undef CHECK_DRAW_MESH_INDIRECT_COUNT_ATTRIBS
159
160 return true;
161 }
162
138163
139164 bool VerifyDispatchComputeAttribs(const DispatchComputeAttribs& Attribs)
140165 {
137137 virtual void DILIGENT_CALL_TYPE DrawMesh(const DrawMeshAttribs& Attribs) override final;
138138 /// Implementation of IDeviceContext::DrawMeshIndirect() in Direct3D11 backend.
139139 virtual void DILIGENT_CALL_TYPE DrawMeshIndirect(const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
140 /// Implementation of IDeviceContext::DrawMeshIndirectCount() in Direct3D11 backend.
141 virtual void DILIGENT_CALL_TYPE DrawMeshIndirectCount(const DrawMeshIndirectCountAttribs& Attribs, IBuffer* pAttribsBuffer, IBuffer* pCountBuffer) override final;
140142
141143 /// Implementation of IDeviceContext::DispatchCompute() in Direct3D11 backend.
142144 virtual void DILIGENT_CALL_TYPE DispatchCompute(const DispatchComputeAttribs& Attribs) override final;
849849 UNSUPPORTED("DrawMeshIndirect is not supported in DirectX 11");
850850 }
851851
852 void DeviceContextD3D11Impl::DrawMeshIndirectCount(const DrawMeshIndirectCountAttribs& Attribs, IBuffer* pAttribsBuffer, IBuffer* pCountBuffer)
853 {
854 UNSUPPORTED("DrawMeshIndirectCount is not supported in DirectX 11");
855 }
856
852857 void DeviceContextD3D11Impl::DispatchCompute(const DispatchComputeAttribs& Attribs)
853858 {
854859 if (!DvpVerifyDispatchArguments(Attribs))
173173 m_pCommandList->ExecuteIndirect(pCmdSignature, 1, pBuff, ArgsOffset, nullptr, 0);
174174 }
175175
176 void ExecuteIndirect(ID3D12CommandSignature* pCmdSignature, Uint32 MaxCommandCount, ID3D12Resource* pArgsBuff, Uint64 ArgsOffset, ID3D12Resource* pCountBuff, Uint64 CountOffset)
177 {
178 FlushResourceBarriers();
179 m_pCommandList->ExecuteIndirect(pCmdSignature, MaxCommandCount, pArgsBuff, ArgsOffset, pCountBuff, CountOffset);
180 }
181
176182 void SetID(const Char* ID) { m_ID = ID; }
177183 ID3D12GraphicsCommandList* GetCommandList() { return m_pCommandList; }
178184
143143 virtual void DILIGENT_CALL_TYPE DrawMesh (const DrawMeshAttribs& Attribs) override final;
144144 /// Implementation of IDeviceContext::DrawMeshIndirect() in Direct3D12 backend.
145145 virtual void DILIGENT_CALL_TYPE DrawMeshIndirect (const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
146 /// Implementation of IDeviceContext::DrawMeshIndirectCount() in Direct3D12 backend.
147 virtual void DILIGENT_CALL_TYPE DrawMeshIndirectCount(const DrawMeshIndirectCountAttribs& Attribs, IBuffer* pAttribsBuffer, IBuffer* pCountBuffer) override final;
146148
147149
148150 /// Implementation of IDeviceContext::DispatchCompute() in Direct3D12 backend.
375377 __forceinline void PrepareForDispatchCompute(ComputeContext& GraphCtx);
376378 __forceinline void PrepareForDispatchRays(GraphicsContext& GraphCtx);
377379
378 __forceinline void PrepareIndirectBuffer(GraphicsContext& GraphCtx,
379 IBuffer* pAttribsBuffer,
380 RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode,
381 ID3D12Resource*& pd3d12ArgsBuff,
382 Uint64& BuffDataStartByteOffset,
383 const char* OpName);
380 __forceinline void PrepareIndirectAttribsBuffer(CommandContext& CmdCtx,
381 IBuffer* pAttribsBuffer,
382 RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode,
383 ID3D12Resource*& pd3d12ArgsBuff,
384 Uint64& BuffDataStartByteOffset,
385 const char* OpName);
384386
385387 struct RootTableInfo
386388 {
132132 IndirectArg.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH_MESH;
133133 hr = pd3d12Device->CreateCommandSignature(&CmdSignatureDesc, nullptr, __uuidof(m_pDrawMeshIndirectSignature), reinterpret_cast<void**>(static_cast<ID3D12CommandSignature**>(&m_pDrawMeshIndirectSignature)));
134134 CHECK_D3D_RESULT_THROW(hr, "Failed to create draw mesh indirect command signature");
135 VERIFY_EXPR(CmdSignatureDesc.ByteStride == DrawMeshIndirectCommandStride);
135136 }
136137 #endif
137138 if (pDeviceD3D12Impl->GetDeviceCaps().Features.RayTracing2 == DEVICE_FEATURE_STATE_ENABLED)
626627 ++m_State.NumCommands;
627628 }
628629
629 void DeviceContextD3D12Impl::PrepareIndirectBuffer(GraphicsContext& GraphCtx,
630 IBuffer* pAttribsBuffer,
631 RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode,
632 ID3D12Resource*& pd3d12ArgsBuff,
633 Uint64& BuffDataStartByteOffset,
634 const char* OpName)
630 void DeviceContextD3D12Impl::PrepareIndirectAttribsBuffer(CommandContext& CmdCtx,
631 IBuffer* pAttribsBuffer,
632 RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode,
633 ID3D12Resource*& pd3d12ArgsBuff,
634 Uint64& BuffDataStartByteOffset,
635 const char* OpName)
635636 {
636637 DEV_CHECK_ERR(pAttribsBuffer != nullptr, "Indirect draw attribs buffer must not be null");
637638
641642 pIndirectDrawAttribsD3D12->DvpVerifyDynamicAllocation(this);
642643 #endif
643644
644 TransitionOrVerifyBufferState(GraphCtx, *pIndirectDrawAttribsD3D12, BufferStateTransitionMode,
645 RESOURCE_STATE_INDIRECT_ARGUMENT, OpName);
645 TransitionOrVerifyBufferState(CmdCtx, *pIndirectDrawAttribsD3D12, BufferStateTransitionMode,
646 RESOURCE_STATE_INDIRECT_ARGUMENT,
647 OpName);
646648
647649 pd3d12ArgsBuff = pIndirectDrawAttribsD3D12->GetD3D12Buffer(BuffDataStartByteOffset, this);
648650 }
657659
658660 ID3D12Resource* pd3d12ArgsBuff;
659661 Uint64 BuffDataStartByteOffset;
660 PrepareIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset,
661 "Indirect draw (DeviceContextD3D12Impl::DrawIndirect)");
662 PrepareIndirectAttribsBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset,
663 "Indirect draw (DeviceContextD3D12Impl::DrawIndirect)");
662664
663665 GraphCtx.ExecuteIndirect(m_pDrawIndirectSignature, pd3d12ArgsBuff, Attribs.IndirectDrawArgsOffset + BuffDataStartByteOffset);
664666 ++m_State.NumCommands;
674676
675677 ID3D12Resource* pd3d12ArgsBuff;
676678 Uint64 BuffDataStartByteOffset;
677 PrepareIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset,
678 "Indexed indirect draw (DeviceContextD3D12Impl::DrawIndexedIndirect)");
679 PrepareIndirectAttribsBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset,
680 "indexed Indirect draw (DeviceContextD3D12Impl::DrawIndexedIndirect)");
679681
680682 GraphCtx.ExecuteIndirect(m_pDrawIndexedIndirectSignature, pd3d12ArgsBuff, Attribs.IndirectDrawArgsOffset + BuffDataStartByteOffset);
681683 ++m_State.NumCommands;
703705
704706 ID3D12Resource* pd3d12ArgsBuff;
705707 Uint64 BuffDataStartByteOffset;
706 PrepareIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset,
707 "Indirect draw mesh (DeviceContextD3D12Impl::DrawMeshIndirect)");
708 PrepareIndirectAttribsBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset,
709 "Indirect draw mesh (DeviceContextD3D12Impl::DrawMeshIndirect)");
708710
709711 GraphCtx.ExecuteIndirect(m_pDrawMeshIndirectSignature, pd3d12ArgsBuff, Attribs.IndirectDrawArgsOffset + BuffDataStartByteOffset);
712 ++m_State.NumCommands;
713 }
714
715 void DeviceContextD3D12Impl::DrawMeshIndirectCount(const DrawMeshIndirectCountAttribs& Attribs, IBuffer* pAttribsBuffer, IBuffer* pCountBuffer)
716 {
717 if (!DvpVerifyDrawMeshIndirectCountArguments(Attribs, pAttribsBuffer, pCountBuffer))
718 return;
719
720 auto& GraphCtx = GetCmdContext().AsGraphicsContext();
721 PrepareForDraw(GraphCtx, Attribs.Flags);
722
723 ID3D12Resource* pd3d12ArgsBuff;
724 ID3D12Resource* pd3d12CountBuff;
725 Uint64 ArgsBuffDataStartByteOffset;
726 Uint64 CountBuffDataStartByteOffset;
727 PrepareIndirectAttribsBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, ArgsBuffDataStartByteOffset,
728 "Indirect buffer (DeviceContextD3D12Impl::DrawMeshIndirectCount)");
729 PrepareIndirectAttribsBuffer(GraphCtx, pCountBuffer, Attribs.CountBufferStateTransitionMode, pd3d12CountBuff, CountBuffDataStartByteOffset,
730 "Count buffer (DeviceContextD3D12Impl::DrawMeshIndirectCount)");
731
732 GraphCtx.ExecuteIndirect(m_pDrawMeshIndirectSignature, Attribs.MaxCommandCount,
733 pd3d12ArgsBuff, Attribs.IndirectDrawArgsOffset + ArgsBuffDataStartByteOffset,
734 pd3d12CountBuff, Attribs.CountBufferOffset + CountBuffDataStartByteOffset);
710735 ++m_State.NumCommands;
711736 }
712737
755780 auto& ComputeCtx = GetCmdContext().AsComputeContext();
756781 PrepareForDispatchCompute(ComputeCtx);
757782
758 auto* pBufferD3D12 = ValidatedCast<BufferD3D12Impl>(pAttribsBuffer);
759
760 #ifdef DILIGENT_DEVELOPMENT
761 if (pBufferD3D12->GetDesc().Usage == USAGE_DYNAMIC)
762 pBufferD3D12->DvpVerifyDynamicAllocation(this);
763 #endif
764
765 TransitionOrVerifyBufferState(ComputeCtx, *pBufferD3D12, Attribs.IndirectAttribsBufferStateTransitionMode,
766 RESOURCE_STATE_INDIRECT_ARGUMENT, "Indirect dispatch (DeviceContextD3D12Impl::DispatchComputeIndirect)");
783 ID3D12Resource* pd3d12ArgsBuff;
767784 Uint64 BuffDataStartByteOffset;
768 ID3D12Resource* pd3d12ArgsBuff = pBufferD3D12->GetD3D12Buffer(BuffDataStartByteOffset, this);
785 PrepareIndirectAttribsBuffer(ComputeCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset,
786 "Indirect dispatch (DeviceContextD3D12Impl::DispatchComputeIndirect)");
787
769788 ComputeCtx.ExecuteIndirect(m_pDispatchIndirectSignature, pd3d12ArgsBuff, Attribs.DispatchArgsByteOffset + BuffDataStartByteOffset);
770789 ++m_State.NumCommands;
771790 }
134134 virtual void DILIGENT_CALL_TYPE DrawMesh (const DrawMeshAttribs& Attribs) override final;
135135 /// Implementation of IDeviceContext::DrawMeshIndirect() in OpenGL backend.
136136 virtual void DILIGENT_CALL_TYPE DrawMeshIndirect (const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
137 /// Implementation of IDeviceContext::DrawMeshIndirectCount() in OpenGL backend.
138 virtual void DILIGENT_CALL_TYPE DrawMeshIndirectCount(const DrawMeshIndirectCountAttribs& Attribs, IBuffer* pAttribsBuffer, IBuffer* pCountBuffer) override final;
137139
138140 /// Implementation of IDeviceContext::DispatchCompute() in OpenGL backend.
139141 virtual void DILIGENT_CALL_TYPE DispatchCompute (const DispatchComputeAttribs& Attribs) override final;
994994 UNSUPPORTED("DrawMeshIndirect is not supported in OpenGL");
995995 }
996996
997 void DeviceContextGLImpl::DrawMeshIndirectCount(const DrawMeshIndirectCountAttribs& Attribs, IBuffer* pAttribsBuffer, IBuffer* pCountBuffer)
998 {
999 UNSUPPORTED("DrawMeshIndirectCount is not supported in OpenGL");
1000 }
1001
9971002
9981003 void DeviceContextGLImpl::DispatchCompute(const DispatchComputeAttribs& Attribs)
9991004 {
154154 virtual void DILIGENT_CALL_TYPE DrawMesh (const DrawMeshAttribs& Attribs) override final;
155155 /// Implementation of IDeviceContext::DrawMeshIndirect() in Vulkan backend.
156156 virtual void DILIGENT_CALL_TYPE DrawMeshIndirect (const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
157 /// Implementation of IDeviceContext::DrawMeshIndirectCount() in Vulkan backend.
158 virtual void DILIGENT_CALL_TYPE DrawMeshIndirectCount(const DrawMeshIndirectCountAttribs& Attribs, IBuffer* pAttribsBuffer, IBuffer* pCountBuffer) override final;
157159
158160 /// Implementation of IDeviceContext::DispatchCompute() in Vulkan backend.
159161 virtual void DILIGENT_CALL_TYPE DispatchCompute (const DispatchComputeAttribs& Attribs) override final;
163163 #endif
164164 }
165165
166 __forceinline void DrawMeshIndirectCount(VkBuffer Buffer, VkDeviceSize Offset, VkBuffer CountBuffer, VkDeviceSize CountBufferOffset, uint32_t MaxDrawCount, uint32_t Stride)
167 {
168 #if DILIGENT_USE_VOLK
169 VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
170 VERIFY(m_State.RenderPass != VK_NULL_HANDLE, "vkCmdDrawMeshTasksIndirectCountNV() must be called inside render pass");
171 VERIFY(m_State.GraphicsPipeline != VK_NULL_HANDLE, "No graphics pipeline bound");
172
173 vkCmdDrawMeshTasksIndirectCountNV(m_VkCmdBuffer, Buffer, Offset, CountBuffer, CountBufferOffset, MaxDrawCount, Stride);
174 #else
175 UNSUPPORTED("DrawMeshIndirectCount is not supported when vulkan library is linked statically");
176 #endif
177 }
178
166179 __forceinline void Dispatch(uint32_t GroupCountX, uint32_t GroupCountY, uint32_t GroupCountZ)
167180 {
168181 VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
902902 ++m_State.NumCommands;
903903 }
904904
905 void DeviceContextVkImpl::DrawMeshIndirectCount(const DrawMeshIndirectCountAttribs& Attribs, IBuffer* pAttribsBuffer, IBuffer* pCountBuffer)
906 {
907 if (!DvpVerifyDrawMeshIndirectCountArguments(Attribs, pAttribsBuffer, pCountBuffer))
908 return;
909
910 // We must prepare indirect draw attribs buffer first because state transitions must
911 // be performed outside of render pass, and PrepareForDraw commits render pass
912 BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, "Indirect buffer (DeviceContextVkImpl::DrawMeshIndirectCount)");
913 BufferVkImpl* pCountBufferVk = PrepareIndirectAttribsBuffer(pCountBuffer, Attribs.CountBufferStateTransitionMode, "Count buffer (DeviceContextVkImpl::DrawMeshIndirectCount)");
914
915 PrepareForDraw(Attribs.Flags);
916
917 m_CommandBuffer.DrawMeshIndirectCount(pIndirectDrawAttribsVk->GetVkBuffer(),
918 pIndirectDrawAttribsVk->GetDynamicOffset(m_ContextId, this) + Attribs.IndirectDrawArgsOffset,
919 pCountBufferVk->GetVkBuffer(),
920 pCountBufferVk->GetDynamicOffset(m_ContextId, this) + Attribs.CountBufferOffset,
921 Attribs.MaxCommandCount,
922 DrawMeshIndirectCommandStride);
923 ++m_State.NumCommands;
924 }
925
926
905927 void DeviceContextVkImpl::PrepareForDispatchCompute()
906928 {
907929 EnsureVkCmdBuffer();
5959 namespace
6060 {
6161
62 TEST(MeshShaderTest, DrawQuad)
62 TEST(MeshShaderTest, DrawTriangle)
6363 {
6464 auto* pEnv = TestingEnvironment::GetInstance();
6565 auto* pDevice = pEnv->GetDevice();
169169 pSwapChain->Present();
170170 }
171171
172 TEST(MeshShaderTest, DrawQuadIndirect)
172
173 TEST(MeshShaderTest, DrawTriangleIndirect)
173174 {
174175 auto* pEnv = TestingEnvironment::GetInstance();
175176 auto* pDevice = pEnv->GetDevice();
273274 pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &pPSO);
274275 ASSERT_NE(pPSO, nullptr);
275276
276 Uint32 IndirectBufferData[3];
277
278 if (pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_VULKAN)
279 {
280 IndirectBufferData[0] = 1; // TaskCount
281 IndirectBufferData[1] = 0; // FirstTask
277 struct IndirectAndCountBuffData
278 {
279 char Unused[16];
280 Uint32 IndirectData[3] = {};
281 Uint32 End;
282 };
283 IndirectAndCountBuffData Data;
284
285 if (pDevice->GetDeviceCaps().IsVulkanDevice())
286 {
287 Data.IndirectData[0] = 1; // TaskCount
288 Data.IndirectData[1] = 0; // FirstTask
289 Data.IndirectData[2] = ~0u; // ignored
282290 }
283291 else
284292 {
285 IndirectBufferData[0] = 1; // ThreadGroupCountX
286 IndirectBufferData[1] = 1; // ThreadGroupCountY
287 IndirectBufferData[2] = 1; // ThreadGroupCountZ
293 Data.IndirectData[0] = 1; // ThreadGroupCountX
294 Data.IndirectData[1] = 1; // ThreadGroupCountY
295 Data.IndirectData[2] = 1; // ThreadGroupCountZ
288296 }
289297
290298 BufferDesc IndirectBufferDesc;
291299 IndirectBufferDesc.Name = "Indirect buffer";
292300 IndirectBufferDesc.Usage = USAGE_IMMUTABLE;
293 IndirectBufferDesc.uiSizeInBytes = sizeof(IndirectBufferData);
301 IndirectBufferDesc.uiSizeInBytes = sizeof(Data);
294302 IndirectBufferDesc.BindFlags = BIND_INDIRECT_DRAW_ARGS;
295303
296 BufferData InitData;
297 InitData.pData = &IndirectBufferData;
298 InitData.DataSize = IndirectBufferDesc.uiSizeInBytes;
304 BufferData InitData{&Data, sizeof(Data)};
299305
300306 RefCntAutoPtr<IBuffer> pBuffer;
301307 pDevice->CreateBuffer(IndirectBufferDesc, &InitData, &pBuffer);
302308
303309 pContext->SetPipelineState(pPSO);
304310
305 DrawMeshIndirectAttribs drawAttrs(DRAW_FLAG_VERIFY_ALL, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
311 DrawMeshIndirectAttribs drawAttrs;
312 drawAttrs.Flags = DRAW_FLAG_VERIFY_ALL;
313 drawAttrs.IndirectDrawArgsOffset = offsetof(IndirectAndCountBuffData, IndirectData);
314 drawAttrs.IndirectAttribsBufferStateTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
315
306316 pContext->DrawMeshIndirect(drawAttrs, pBuffer);
307317
308318 pSwapChain->Present();
309319 }
310320
311 TEST(MeshShaderTest, DrawQuadsWithAmplificationShader)
321
322 TEST(MeshShaderTest, DrawTriangleIndirectCount)
323 {
324 auto* pEnv = TestingEnvironment::GetInstance();
325 auto* pDevice = pEnv->GetDevice();
326 if (!pDevice->GetDeviceCaps().Features.MeshShaders)
327 {
328 GTEST_SKIP() << "Mesh shader is not supported by this device";
329 }
330
331 TestingEnvironment::ScopedReset EnvironmentAutoReset;
332
333 auto* pSwapChain = pEnv->GetSwapChain();
334 auto* pConext = pEnv->GetDeviceContext();
335
336 RefCntAutoPtr<ITestingSwapChain> pTestingSwapChain(pSwapChain, IID_TestingSwapChain);
337 if (pTestingSwapChain)
338 {
339 pConext->Flush();
340 pConext->InvalidateState();
341
342 auto deviceType = pDevice->GetDeviceCaps().DevType;
343 switch (deviceType)
344 {
345 #if D3D12_SUPPORTED
346 case RENDER_DEVICE_TYPE_D3D12:
347 MeshShaderIndirectDrawReferenceD3D12(pSwapChain);
348 break;
349 #endif
350
351 #if VULKAN_SUPPORTED
352 case RENDER_DEVICE_TYPE_VULKAN:
353 MeshShaderIndirectDrawReferenceVk(pSwapChain);
354 break;
355 #endif
356
357 case RENDER_DEVICE_TYPE_D3D11:
358 case RENDER_DEVICE_TYPE_GL:
359 case RENDER_DEVICE_TYPE_GLES:
360 case RENDER_DEVICE_TYPE_METAL:
361 default:
362 LOG_ERROR_AND_THROW("Unsupported device type");
363 }
364
365 pTestingSwapChain->TakeSnapshot();
366 }
367
368 auto* pContext = pEnv->GetDeviceContext();
369
370 ITextureView* pRTVs[] = {pSwapChain->GetCurrentBackBufferRTV()};
371 pContext->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
372
373 float ClearColor[] = {0.f, 0.f, 0.f, 0.f};
374 pContext->ClearRenderTarget(pRTVs[0], ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
375
376 GraphicsPipelineStateCreateInfo PSOCreateInfo;
377
378 auto& PSODesc = PSOCreateInfo.PSODesc;
379 auto& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline;
380
381 PSODesc.Name = "Mesh shader test";
382
383 PSODesc.PipelineType = PIPELINE_TYPE_MESH;
384 GraphicsPipeline.NumRenderTargets = 1;
385 GraphicsPipeline.RTVFormats[0] = pSwapChain->GetDesc().ColorBufferFormat;
386 GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
387 GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_BACK;
388 GraphicsPipeline.RasterizerDesc.FillMode = FILL_MODE_SOLID;
389 GraphicsPipeline.RasterizerDesc.FrontCounterClockwise = pDevice->GetDeviceCaps().IsGLDevice();
390
391 GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
392
393 ShaderCreateInfo ShaderCI;
394 ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
395 ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC;
396 ShaderCI.UseCombinedTextureSamplers = true;
397
398 RefCntAutoPtr<IShader> pMS;
399 {
400 ShaderCI.Desc.ShaderType = SHADER_TYPE_MESH;
401 ShaderCI.EntryPoint = "main";
402 ShaderCI.Desc.Name = "Mesh shader test - MS";
403 ShaderCI.Source = HLSL::MeshShaderTest_MS.c_str();
404
405 pDevice->CreateShader(ShaderCI, &pMS);
406 ASSERT_NE(pMS, nullptr);
407 }
408
409 RefCntAutoPtr<IShader> pPS;
410 {
411 ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL;
412 ShaderCI.EntryPoint = "main";
413 ShaderCI.Desc.Name = "Mesh shader test - PS";
414 ShaderCI.Source = HLSL::MeshShaderTest_PS.c_str();
415
416 pDevice->CreateShader(ShaderCI, &pPS);
417 ASSERT_NE(pPS, nullptr);
418 }
419
420 PSOCreateInfo.pMS = pMS;
421 PSOCreateInfo.pPS = pPS;
422 RefCntAutoPtr<IPipelineState> pPSO;
423 pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &pPSO);
424 ASSERT_NE(pPSO, nullptr);
425
426 struct IndirectAndCountBuffData
427 {
428 char Unused[16];
429 Uint32 Count;
430 Uint32 IndirectData[3];
431 };
432 IndirectAndCountBuffData Data;
433
434 if (pDevice->GetDeviceCaps().IsVulkanDevice())
435 {
436 Data.IndirectData[0] = 1; // TaskCount
437 Data.IndirectData[1] = 0; // FirstTask
438 Data.IndirectData[2] = ~0u; // ignored
439 }
440 else
441 {
442 Data.IndirectData[0] = 1; // ThreadGroupCountX
443 Data.IndirectData[1] = 1; // ThreadGroupCountY
444 Data.IndirectData[2] = 1; // ThreadGroupCountZ
445 }
446 Data.Count = 1;
447
448 BufferDesc IndirectBufferDesc;
449 IndirectBufferDesc.Name = "Indirect & Count buffer";
450 IndirectBufferDesc.Usage = USAGE_IMMUTABLE;
451 IndirectBufferDesc.uiSizeInBytes = sizeof(Data);
452 IndirectBufferDesc.BindFlags = BIND_INDIRECT_DRAW_ARGS;
453
454 BufferData InitData{&Data, sizeof(Data)};
455
456 RefCntAutoPtr<IBuffer> pBuffer;
457 pDevice->CreateBuffer(IndirectBufferDesc, &InitData, &pBuffer);
458
459 pContext->SetPipelineState(pPSO);
460
461 DrawMeshIndirectCountAttribs drawAttrs;
462 drawAttrs.Flags = DRAW_FLAG_VERIFY_ALL;
463 drawAttrs.CountBufferOffset = offsetof(IndirectAndCountBuffData, Count);
464 drawAttrs.CountBufferStateTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
465 drawAttrs.IndirectDrawArgsOffset = offsetof(IndirectAndCountBuffData, IndirectData);
466 drawAttrs.IndirectAttribsBufferStateTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
467 drawAttrs.MaxCommandCount = Data.Count;
468
469 pContext->DrawMeshIndirectCount(drawAttrs, pBuffer, pBuffer);
470
471 pSwapChain->Present();
472 }
473
474
475 TEST(MeshShaderTest, DrawTrisWithAmplificationShader)
312476 {
313477 auto* pEnv = TestingEnvironment::GetInstance();
314478 auto* pDevice = pEnv->GetDevice();
4040 IDeviceContext_DrawIndexed(pCtx, &drawIndexedAttribs);
4141 IDeviceContext_DrawIndirect(pCtx, &drawIndirectAttribs, pIndirectBuffer);
4242 IDeviceContext_DrawIndexedIndirect(pCtx, &drawIndexedIndirectAttribs, pIndirectBuffer);
43
44 struct DrawMeshAttribs drawMeshAttribs = {0};
45 IDeviceContext_DrawMesh(pCtx, &drawMeshAttribs);
46
47 struct DrawMeshIndirectAttribs drawMeshIndirectAttribs = {0};
48 IDeviceContext_DrawMeshIndirect(pCtx, &drawMeshIndirectAttribs, pIndirectBuffer);
49
50 struct DrawMeshIndirectCountAttribs drawMeshIndirectCountAttribs = {0};
51 IDeviceContext_DrawMeshIndirectCount(pCtx, &drawMeshIndirectCountAttribs, pIndirectBuffer, pIndirectBuffer);
52
53 struct BuildBLASAttribs buildBLASAttribs = {0};
54 IDeviceContext_BuildBLAS(pCtx, &buildBLASAttribs);
55
56 struct BuildTLASAttribs buildTLASAttribs = {0};
57 IDeviceContext_BuildTLAS(pCtx, &buildTLASAttribs);
58
59 struct CopyBLASAttribs copyBLASAttribs = {0};
60 IDeviceContext_CopyBLAS(pCtx, &copyBLASAttribs);
61
62 struct CopyTLASAttribs copyTLASAttribs = {0};
63 IDeviceContext_CopyTLAS(pCtx, &copyTLASAttribs);
64
65 struct WriteBLASCompactedSizeAttribs writeBLASCompactedSizeAttribs = {0};
66 IDeviceContext_WriteBLASCompactedSize(pCtx, &writeBLASCompactedSizeAttribs);
67
68 struct WriteTLASCompactedSizeAttribs writeTLASCompactedSizeAttribs = {0};
69 IDeviceContext_WriteTLASCompactedSize(pCtx, &writeTLASCompactedSizeAttribs);
70
71 struct TraceRaysAttribs traceRaysAttribs = {0};
72 IDeviceContext_TraceRays(pCtx, &traceRaysAttribs);
73
74 struct TraceRaysIndirectAttribs traceRaysIndirectAttribs = {0};
75 IDeviceContext_TraceRaysIndirect(pCtx, &traceRaysIndirectAttribs, pIndirectBuffer);
4376 }