git.s-ol.nu ~forks/DiligentCore / 3efd896
Added inline ray tracing & trace rays indirect command. azhirnov authored 6 months ago assiduous committed 6 months ago
25 changed file(s) with 1040 addition(s) and 56 deletion(s). Raw diff Collapse all Expand all
7171 bool VerifyWriteBLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteBLASCompactedSizeAttribs& Attribs);
7272 bool VerifyWriteTLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteTLASCompactedSizeAttribs& Attribs);
7373 bool VerifyTraceRaysAttribs(const TraceRaysAttribs& Attribs);
74 bool VerifyTraceRaysIndirectAttribs(const IRenderDevice* pDevice, const TraceRaysIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer, Uint32 SBTSize);
7475
7576
7677
331332 bool WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const;
332333 bool WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const;
333334 bool TraceRays(const TraceRaysAttribs& Attribs, int) const;
335 bool TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer, int) const;
336
337 static constexpr Uint32 TraceRaysIndirectCommandSBTSize = 88; // D3D12: 88 bytes, size of SBT offsets
338 // Vulkan: 0 bytes, SBT offsets placed directly into function call
334339
335340 /// Strong reference to the device.
336341 RefCntAutoPtr<DeviceImplType> m_pDevice;
16661671 return true;
16671672 }
16681673
1674 template <typename ImplementationTraits>
1675 bool DeviceContextBase<ImplementationTraits>::TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer, int) const
1676 {
1677 #ifdef DILIGENT_DEVELOPMENT
1678 if (m_pDevice->GetDeviceCaps().Features.RayTracing2 != DEVICE_FEATURE_STATE_ENABLED)
1679 {
1680 LOG_ERROR_MESSAGE("IDeviceContext::TraceRaysIndirect: indirect trace rays is not supported by this device");
1681 return false;
1682 }
1683
1684 if (!m_pPipelineState)
1685 {
1686 LOG_ERROR_MESSAGE("IDeviceContext::TraceRaysIndirect command arguments are invalid: no pipeline state is bound.");
1687 return false;
1688 }
1689
1690 if (!m_pPipelineState->GetDesc().IsRayTracingPipeline())
1691 {
1692 LOG_ERROR_MESSAGE("IDeviceContext::TraceRaysIndirect command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a ray tracing pipeline.");
1693 return false;
1694 }
1695
1696 if (m_pActiveRenderPass != nullptr)
1697 {
1698 LOG_ERROR_MESSAGE("IDeviceContext::TraceRaysIndirect must be performed outside of render pass");
1699 return false;
1700 }
1701
1702 if (!VerifyTraceRaysIndirectAttribs(m_pDevice, Attribs, pAttribsBuffer, TraceRaysIndirectCommandSBTSize))
1703 return false;
1704
1705 if (!PipelineStateImplType::IsSameObject(m_pPipelineState, ValidatedCast<PipelineStateImplType>(Attribs.pSBT->GetDesc().pPSO)))
1706 {
1707 LOG_ERROR_MESSAGE("IDeviceContext::TraceRaysIndirect command arguments are invalid: currently bound pipeline '", m_pPipelineState->GetDesc().Name,
1708 "' doesn't match the pipeline '", Attribs.pSBT->GetDesc().pPSO->GetDesc().Name, "' that was used in ShaderBindingTable");
1709 return false;
1710 }
1711 #endif
1712
1713 return true;
1714 }
16691715
16701716
16711717
12361236 typedef struct TraceRaysAttribs TraceRaysAttribs;
12371237
12381238
1239 /// This structure is used by IDeviceContext::TraceRaysIndirect().
1240 struct TraceRaysIndirectAttribs
1241 {
1242 /// Shader binding table.
1243 IShaderBindingTable* pSBT DEFAULT_INITIALIZER(nullptr);
1244
1245 /// State transition mode for indirect trace rays attributes buffer.
1246 RESOURCE_STATE_TRANSITION_MODE IndirectAttribsBufferStateTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
1247
1248 /// The offset from the beginning of the buffer to the trace rays command arguments.
1249 Uint32 ArgsByteOffset DEFAULT_INITIALIZER(0);
1250
1251 /// For Direct3D12 backend size must be 104 bytes,
1252 /// for Vulkan backend size must be 12 bytes (only uint3) or 104 bytes for D3D12 compatibility.
1253 Uint32 ArgsByteSize DEFAULT_INITIALIZER(104);
1254
1255 #if DILIGENT_CPP_INTERFACE
1256 TraceRaysIndirectAttribs() noexcept {}
1257 #endif
1258 };
1259 typedef struct TraceRaysIndirectAttribs TraceRaysIndirectAttribs;
1260
1261
12391262 static const Uint32 REMAINING_MIP_LEVELS = ~0u;
12401263 static const Uint32 REMAINING_ARRAY_SLICES = ~0u;
12411264
22012224 /// to the shader binding table passed as an argument to the function.
22022225 VIRTUAL void METHOD(TraceRays)(THIS_
22032226 const TraceRaysAttribs REF Attribs) PURE;
2227
2228
2229 /// Executes an indirect trace rays command.
2230 ///
2231 /// \param [in] pAttribsBuffer - Pointer to the buffer containing indirect trace rays attributes.
2232 /// The buffer must contain the following arguments at the specified offset:
2233 /// [88 bytes reserved] - for Direct3D12 backend
2234 /// Uint32 DimensionX;
2235 /// Uint32 DimensionY;
2236 /// Uint32 DimensionZ;
2237 VIRTUAL void METHOD(TraceRaysIndirect)(THIS_
2238 const TraceRaysIndirectAttribs REF Attribs,
2239 IBuffer* pAttribsBuffer) PURE;
22042240 };
22052241 DILIGENT_END_INTERFACE
22062242
22592295 # define IDeviceContext_WriteBLASCompactedSize(This, ...) CALL_IFACE_METHOD(DeviceContext, WriteBLASCompactedSize, This, __VA_ARGS__)
22602296 # define IDeviceContext_WriteTLASCompactedSize(This, ...) CALL_IFACE_METHOD(DeviceContext, WriteTLASCompactedSize, This, __VA_ARGS__)
22612297 # define IDeviceContext_TraceRays(This, ...) CALL_IFACE_METHOD(DeviceContext, TraceRays, This, __VA_ARGS__)
2298 # define IDeviceContext_TraceRaysIndirect(This, ...) CALL_IFACE_METHOD(DeviceContext, TraceRaysIndirect, This, __VA_ARGS__)
22622299
22632300 // clang-format on
22642301
15591559
15601560 /// Indicates if device supports geometry shaders
15611561 DEVICE_FEATURE_STATE GeometryShaders DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
1562
1562
15631563 /// Indicates if device supports tessellation
15641564 DEVICE_FEATURE_STATE Tessellation DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
1565
1565
15661566 /// Indicates if device supports mesh and amplification shaders
15671567 DEVICE_FEATURE_STATE MeshShaders DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
1568
1568
15691569 /// Indicates if device supports ray tracing shaders
15701570 DEVICE_FEATURE_STATE RayTracing DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
1571
1572 /// Indicates if device supports inline ray tracing and indirect commands
1573 DEVICE_FEATURE_STATE RayTracing2 DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
15711574
15721575 /// Indicates if device supports bindless resources
15731576 DEVICE_FEATURE_STATE BindlessResources DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
16651668 Tessellation {State},
16661669 MeshShaders {State},
16671670 RayTracing {State},
1671 RayTracing2 {State},
16681672 BindlessResources {State},
16691673 OcclusionQueries {State},
16701674 BinaryOcclusionQueries {State},
16901694 ShaderResourceRuntimeArray {State}
16911695 {
16921696 # if defined(_MSC_VER) && defined(_WIN64)
1693 static_assert(sizeof(*this) == 33, "Did you add a new feature to DeviceFeatures? Please handle its status above.");
1697 static_assert(sizeof(*this) == 34, "Did you add a new feature to DeviceFeatures? Please handle its status above.");
16941698 # endif
16951699 }
16961700 #endif
251251 /// Enable unbounded resource arrays (e.g. Texture2D g_Texture[]).
252252 SHADER_COMPILE_FLAG_ENABLE_UNBOUNDED_ARRAYS = 0x01,
253253
254 /// Enable inline ray tracing for graphics and compute shaders.
255 /// Requires RayTracing2 device feature.
256 SHADER_COMPILE_FLAG_ENABLE_INLINE_RAY_TRACING = 0x02,
257
254258 SHADER_COMPILE_FLAG_LAST = SHADER_COMPILE_FLAG_ENABLE_UNBOUNDED_ARRAYS
255259 };
256260 DEFINE_FLAG_ENUM_OPERATORS(SHADER_COMPILE_FLAGS);
773773 return true;
774774 }
775775
776 bool VerifyTraceRaysIndirectAttribs(const IRenderDevice* pDevice, const TraceRaysIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer, Uint32 SBTSize)
777 {
778 #define CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Trace rays indirect attribs are invalid: ", __VA_ARGS__)
779 CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Attribs.pSBT != nullptr, "pSBT must not be null");
780
781 #ifdef DILIGENT_DEVELOPMENT
782 CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Attribs.pSBT->Verify(VERIFY_SBT_FLAG_SHADER_ONLY | VERIFY_SBT_FLAG_TLAS),
783 "not all shaders in SBT are bound or instance to shader mapping is incorrect.");
784 #endif // DILIGENT_DEVELOPMENT
785
786 CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(pAttribsBuffer != nullptr, "indirect dispatch arguments buffer must not be null.");
787
788 const auto& Desc = pAttribsBuffer->GetDesc();
789 CHECK_TRACE_RAYS_INDIRECT_ATTRIBS((Desc.BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0,
790 "indirect trace rays arguments buffer '", Desc.Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
791 CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Attribs.ArgsByteOffset + Attribs.ArgsByteSize <= Desc.uiSizeInBytes,
792 "indirect trace rays arguments buffer '", Desc.Name, "' is too small.");
793
794 constexpr Uint32 DimSize = sizeof(Uint32) * 3;
795 if (pDevice->GetDeviceCaps().IsVulkanDevice())
796 {
797 CHECK_TRACE_RAYS_INDIRECT_ATTRIBS((Desc.BindFlags & BIND_RAY_TRACING) != 0,
798 "indirect trace rays arguments buffer '", Desc.Name, "' was not created with BIND_RAY_TRACING flag.");
799 CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Attribs.ArgsByteSize == DimSize || Attribs.ArgsByteSize == DimSize + SBTSize,
800 "ArgsByteSize must be (", DimSize, ") or (", DimSize + SBTSize, ") bytes");
801 }
802 else
803 {
804 CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Attribs.ArgsByteSize == DimSize + SBTSize, "ArgsByteSize must be (", DimSize + SBTSize, ") bytes");
805 CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Desc.Usage == USAGE_DEFAULT,
806 "pAttribsBuffer will be updated inside TraceRaysIndirect(), buffer must be created only with USAGE_DEFAULT");
807 }
808
809 #undef CHECK_TRACE_RAYS_INDIRECT_ATTRIBS
810
811 return true;
812 }
813
776814 } // namespace Diligent
259259 /// Implementation of IDeviceContext::TraceRays().
260260 virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final;
261261
262 /// Implementation of IDeviceContext::TraceRaysIndirect().
263 virtual void DILIGENT_CALL_TYPE TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
264
262265 /// Implementation of IDeviceContextD3D11::GetD3D11DeviceContext().
263266 virtual ID3D11DeviceContext* DILIGENT_CALL_TYPE GetD3D11DeviceContext() override final { return m_pd3d11DeviceContext; }
264267
22912291 UNSUPPORTED("TraceRays is not supported in DirectX 11");
22922292 }
22932293
2294 void DeviceContextD3D11Impl::TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
2295 {
2296 UNSUPPORTED("TraceRaysIndirect is not supported in DirectX 11");
2297 }
2298
22942299 // clang-format off
22952300 #ifdef VERIFY_CONTEXT_BINDINGS
22962301 DEFINE_D3D11CTX_FUNC_POINTERS(GetCBMethods, GetConstantBuffers)
144144 UNSUPPORTED_FEATURE(VertexPipelineUAVWritesAndAtomics, "Vertex pipeline UAV writes and atomics are");
145145 UNSUPPORTED_FEATURE(MeshShaders, "Mesh shaders are");
146146 UNSUPPORTED_FEATURE(RayTracing, "Ray tracing is");
147 UNSUPPORTED_FEATURE(RayTracing2, "Inline ray tracing is");
147148 UNSUPPORTED_FEATURE(ShaderResourceRuntimeArray, "Runtime-sized array is");
148149 // clang-format on
149150
175176 #undef UNSUPPORTED_FEATURE
176177
177178 #if defined(_MSC_VER) && defined(_WIN64)
178 static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
179 static_assert(sizeof(DeviceFeatures) == 34, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
179180 #endif
180181
181182 auto& TexCaps = m_DeviceCaps.TexCaps;
275275 /// Implementation of IDeviceContext::TraceRays() in Direct3D12 backend.
276276 virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final;
277277
278 /// Implementation of IDeviceContext::TraceRaysIndirect() in Direct3D12 backend.
279 virtual void DILIGENT_CALL_TYPE TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
280
278281 /// Implementation of IDeviceContextD3D12::ID3D12GraphicsCommandList() in Direct3D12 backend.
279282 virtual ID3D12GraphicsCommandList* DILIGENT_CALL_TYPE GetD3D12CommandList() override final;
280283
372375 __forceinline void PrepareForDispatchCompute(ComputeContext& GraphCtx);
373376 __forceinline void PrepareForDispatchRays(GraphicsContext& GraphCtx);
374377
375 __forceinline void PrepareDrawIndirectBuffer(GraphicsContext& GraphCtx,
376 IBuffer* pAttribsBuffer,
377 RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode,
378 ID3D12Resource*& pd3d12ArgsBuff,
379 Uint64& BuffDataStartByteOffset);
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);
380384
381385 struct RootTableInfo
382386 {
457461 CComPtr<ID3D12CommandSignature> m_pDrawIndexedIndirectSignature;
458462 CComPtr<ID3D12CommandSignature> m_pDispatchIndirectSignature;
459463 CComPtr<ID3D12CommandSignature> m_pDrawMeshIndirectSignature;
464 CComPtr<ID3D12CommandSignature> m_pTraceRaysIndirectSignature;
460465
461466 D3D12DynamicHeap m_DynamicHeap;
462467
134134 CHECK_D3D_RESULT_THROW(hr, "Failed to create draw mesh indirect command signature");
135135 }
136136 #endif
137 if (pDeviceD3D12Impl->GetDeviceCaps().Features.RayTracing2 == DEVICE_FEATURE_STATE_ENABLED)
138 {
139 CmdSignatureDesc.ByteStride = sizeof(D3D12_DISPATCH_RAYS_DESC);
140 IndirectArg.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH_RAYS;
141 hr = pd3d12Device->CreateCommandSignature(&CmdSignatureDesc, nullptr, __uuidof(m_pTraceRaysIndirectSignature), reinterpret_cast<void**>(static_cast<ID3D12CommandSignature**>(&m_pTraceRaysIndirectSignature)));
142 CHECK_D3D_RESULT_THROW(hr, "Failed to create trace rays indirect command signature");
143 static_assert(TraceRaysIndirectCommandSBTSize == offsetof(D3D12_DISPATCH_RAYS_DESC, Width), "Invalid SBT offsets size");
144 }
137145 }
138146
139147 DeviceContextD3D12Impl::~DeviceContextD3D12Impl()
618626 ++m_State.NumCommands;
619627 }
620628
621 void DeviceContextD3D12Impl::PrepareDrawIndirectBuffer(GraphicsContext& GraphCtx,
622 IBuffer* pAttribsBuffer,
623 RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode,
624 ID3D12Resource*& pd3d12ArgsBuff,
625 Uint64& BuffDataStartByteOffset)
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)
626635 {
627636 DEV_CHECK_ERR(pAttribsBuffer != nullptr, "Indirect draw attribs buffer must not be null");
628637
633642 #endif
634643
635644 TransitionOrVerifyBufferState(GraphCtx, *pIndirectDrawAttribsD3D12, BufferStateTransitionMode,
636 RESOURCE_STATE_INDIRECT_ARGUMENT,
637 "Indirect draw (DeviceContextD3D12Impl::PrepareDrawIndirectBuffer)");
645 RESOURCE_STATE_INDIRECT_ARGUMENT, OpName);
638646
639647 pd3d12ArgsBuff = pIndirectDrawAttribsD3D12->GetD3D12Buffer(BuffDataStartByteOffset, this);
640648 }
649657
650658 ID3D12Resource* pd3d12ArgsBuff;
651659 Uint64 BuffDataStartByteOffset;
652 PrepareDrawIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset);
660 PrepareIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset,
661 "Indirect draw (DeviceContextD3D12Impl::DrawIndirect)");
653662
654663 GraphCtx.ExecuteIndirect(m_pDrawIndirectSignature, pd3d12ArgsBuff, Attribs.IndirectDrawArgsOffset + BuffDataStartByteOffset);
655664 ++m_State.NumCommands;
665674
666675 ID3D12Resource* pd3d12ArgsBuff;
667676 Uint64 BuffDataStartByteOffset;
668 PrepareDrawIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset);
677 PrepareIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset,
678 "Indexed indirect draw (DeviceContextD3D12Impl::DrawIndexedIndirect)");
669679
670680 GraphCtx.ExecuteIndirect(m_pDrawIndexedIndirectSignature, pd3d12ArgsBuff, Attribs.IndirectDrawArgsOffset + BuffDataStartByteOffset);
671681 ++m_State.NumCommands;
693703
694704 ID3D12Resource* pd3d12ArgsBuff;
695705 Uint64 BuffDataStartByteOffset;
696 PrepareDrawIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset);
706 PrepareIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset,
707 "Indirect draw mesh (DeviceContextD3D12Impl::DrawMeshIndirect)");
697708
698709 GraphCtx.ExecuteIndirect(m_pDrawMeshIndirectSignature, pd3d12ArgsBuff, Attribs.IndirectDrawArgsOffset + BuffDataStartByteOffset);
699710 ++m_State.NumCommands;
27712782 ++m_State.NumCommands;
27722783 }
27732784
2785 void DeviceContextD3D12Impl::TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
2786 {
2787 if (!TDeviceContextBase::TraceRaysIndirect(Attribs, pAttribsBuffer, 0))
2788 return;
2789
2790 auto& CmdCtx = GetCmdContext().AsGraphicsContext4();
2791 auto* pSBTD3D12 = ValidatedCast<ShaderBindingTableD3D12Impl>(Attribs.pSBT);
2792 IBuffer* pSBTBuffer = nullptr;
2793
2794 ShaderBindingTableD3D12Impl::BindingTable RayGenShaderRecord = {};
2795 ShaderBindingTableD3D12Impl::BindingTable MissShaderTable = {};
2796 ShaderBindingTableD3D12Impl::BindingTable HitGroupTable = {};
2797 ShaderBindingTableD3D12Impl::BindingTable CallableShaderTable = {};
2798
2799 pSBTD3D12->GetData(pSBTBuffer, RayGenShaderRecord, MissShaderTable, HitGroupTable, CallableShaderTable);
2800
2801 auto* pSBTBufferD3D12 = ValidatedCast<BufferD3D12Impl>(pSBTBuffer);
2802
2803 const char* OpName = "Trace rays indirect (DeviceContextD3D12Impl::TraceRaysIndirect)";
2804
2805 if (RayGenShaderRecord.pData || MissShaderTable.pData || HitGroupTable.pData || CallableShaderTable.pData)
2806 {
2807 TransitionOrVerifyBufferState(CmdCtx, *pSBTBufferD3D12, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_COPY_DEST, OpName);
2808
2809 // buffer ranges are not intersected, so we don't need to add barriers between them
2810 if (RayGenShaderRecord.pData)
2811 UpdateBuffer(pSBTBufferD3D12, RayGenShaderRecord.Offset, RayGenShaderRecord.Size, RayGenShaderRecord.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
2812
2813 if (MissShaderTable.pData)
2814 UpdateBuffer(pSBTBufferD3D12, MissShaderTable.Offset, MissShaderTable.Size, MissShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
2815
2816 if (HitGroupTable.pData)
2817 UpdateBuffer(pSBTBufferD3D12, HitGroupTable.Offset, HitGroupTable.Size, HitGroupTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
2818
2819 if (CallableShaderTable.pData)
2820 UpdateBuffer(pSBTBufferD3D12, CallableShaderTable.Offset, CallableShaderTable.Size, CallableShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
2821 }
2822 TransitionOrVerifyBufferState(CmdCtx, *pSBTBufferD3D12, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_RAY_TRACING, OpName);
2823
2824 D3D12_DISPATCH_RAYS_DESC d3d12DispatchDesc = {};
2825
2826 d3d12DispatchDesc.RayGenerationShaderRecord.StartAddress = pSBTBufferD3D12->GetGPUAddress() + RayGenShaderRecord.Offset;
2827 d3d12DispatchDesc.RayGenerationShaderRecord.SizeInBytes = RayGenShaderRecord.Size;
2828
2829 d3d12DispatchDesc.MissShaderTable.StartAddress = pSBTBufferD3D12->GetGPUAddress() + MissShaderTable.Offset;
2830 d3d12DispatchDesc.MissShaderTable.SizeInBytes = MissShaderTable.Size;
2831 d3d12DispatchDesc.MissShaderTable.StrideInBytes = MissShaderTable.Stride;
2832
2833 d3d12DispatchDesc.HitGroupTable.StartAddress = pSBTBufferD3D12->GetGPUAddress() + HitGroupTable.Offset;
2834 d3d12DispatchDesc.HitGroupTable.SizeInBytes = HitGroupTable.Size;
2835 d3d12DispatchDesc.HitGroupTable.StrideInBytes = HitGroupTable.Stride;
2836
2837 d3d12DispatchDesc.CallableShaderTable.StartAddress = pSBTBufferD3D12->GetGPUAddress() + CallableShaderTable.Offset;
2838 d3d12DispatchDesc.CallableShaderTable.SizeInBytes = CallableShaderTable.Size;
2839 d3d12DispatchDesc.CallableShaderTable.StrideInBytes = CallableShaderTable.Stride;
2840
2841 // copy dispath description with shader table data and keep dimension
2842 UpdateBuffer(pAttribsBuffer, Attribs.ArgsByteOffset, offsetof(D3D12_DISPATCH_RAYS_DESC, Width), &d3d12DispatchDesc, Attribs.IndirectAttribsBufferStateTransitionMode);
2843
2844 auto* pAttribsBufferD3D12 = ValidatedCast<BufferD3D12Impl>(pAttribsBuffer);
2845 TransitionOrVerifyBufferState(CmdCtx, *pAttribsBufferD3D12, Attribs.IndirectAttribsBufferStateTransitionMode, RESOURCE_STATE_INDIRECT_ARGUMENT, OpName);
2846
2847 PrepareForDispatchRays(CmdCtx);
2848
2849 CmdCtx.ExecuteIndirect(m_pTraceRaysIndirectSignature, pAttribsBufferD3D12->GetD3D12Resource(), Attribs.ArgsByteOffset);
2850 ++m_State.NumCommands;
2851 }
2852
27742853 } // namespace Diligent
250250 {
251251 m_DeviceCaps.Features.RayTracing = DEVICE_FEATURE_STATE_ENABLED;
252252 }
253 if (d3d12Features.RaytracingTier >= D3D12_RAYTRACING_TIER_1_1)
254 {
255 m_DeviceCaps.Features.RayTracing2 = DEVICE_FEATURE_STATE_ENABLED;
256 }
253257 }
254258 }
255259
298302 CHECK_REQUIRED_FEATURE(UniformBuffer8BitAccess, "8-bit uniform buffer access is");
299303
300304 CHECK_REQUIRED_FEATURE(RayTracing, "ray tracing is");
305 CHECK_REQUIRED_FEATURE(RayTracing2, "inline ray tracing is");
301306 // clang-format on
302307 #undef CHECK_REQUIRED_FEATURE
303308
304309 #if defined(_MSC_VER) && defined(_WIN64)
305 static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
310 static_assert(sizeof(DeviceFeatures) == 34, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
306311 #endif
307312
308313 auto& TexCaps = m_DeviceCaps.TexCaps;
260260 /// Implementation of IDeviceContext::TraceRays() in OpenGL backend.
261261 virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final;
262262
263 /// Implementation of IDeviceContext::TraceRaysIndirect() in OpenGL backend.
264 virtual void DILIGENT_CALL_TYPE TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
265
263266 /// Implementation of IDeviceContextGL::UpdateCurrentGLContext().
264267 virtual bool DILIGENT_CALL_TYPE UpdateCurrentGLContext() override final;
265268
16471647 UNSUPPORTED("TraceRays is not supported in OpenGL");
16481648 }
16491649
1650 void DeviceContextGLImpl::TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
1651 {
1652 UNSUPPORTED("TraceRaysIndirect is not supported in OpenGL");
1653 }
1654
16501655 } // namespace Diligent
301301 } \
302302 } while (false)
303303
304 // clang-format off
304305 SET_FEATURE_STATE(VertexPipelineUAVWritesAndAtomics, false, "Vertex pipeline UAV writes and atomics are");
305 SET_FEATURE_STATE(MeshShaders, false, "Mesh shaders are");
306 SET_FEATURE_STATE(RayTracing, false, "Ray tracing is");
306 SET_FEATURE_STATE(MeshShaders, false, "Mesh shaders are");
307 SET_FEATURE_STATE(RayTracing, false, "Ray tracing is");
308 SET_FEATURE_STATE(RayTracing2, false, "Inline ray tracing is");
309 // clang-format on
307310
308311 {
309312 bool WireframeFillSupported = (glPolygonMode != nullptr);
456459 #undef SET_FEATURE_STATE
457460
458461 #if defined(_MSC_VER) && defined(_WIN64)
459 static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
462 static_assert(sizeof(DeviceFeatures) == 34, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
460463 #endif
461464
462465 // get device limits
268268 /// Implementation of IDeviceContext::TraceRays() in Vulkan backend.
269269 virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final;
270270
271 /// Implementation of IDeviceContext::TraceRaysIndirect() in Vulkan backend.
272 virtual void DILIGENT_CALL_TYPE TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
273
271274 // Transitions texture subresources from OldState to NewState, and optionally updates
272275 // internal texture state.
273276 // If OldState == RESOURCE_STATE_UNKNOWN, internal texture state is used as old state.
450453
451454 __forceinline void PrepareForDraw(DRAW_FLAGS Flags);
452455 __forceinline void PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE IndexType);
453 __forceinline BufferVkImpl* PrepareIndirectDrawAttribsBuffer(IBuffer* pAttribsBuffer, RESOURCE_STATE_TRANSITION_MODE TransitonMode);
456 __forceinline BufferVkImpl* PrepareIndirectAttribsBuffer(IBuffer* pAttribsBuffer, RESOURCE_STATE_TRANSITION_MODE TransitonMode, const char* OpName);
454457 __forceinline void PrepareForDispatchCompute();
455458 __forceinline void PrepareForRayTracing();
456459
669669 #endif
670670 }
671671
672 __forceinline void TraceRaysIndirect(const VkStridedDeviceAddressRegionKHR& RaygenShaderBindingTable,
673 const VkStridedDeviceAddressRegionKHR& MissShaderBindingTable,
674 const VkStridedDeviceAddressRegionKHR& HitShaderBindingTable,
675 const VkStridedDeviceAddressRegionKHR& CallableShaderBindingTable,
676 VkDeviceAddress indirectDeviceAddress)
677 {
678 #if DILIGENT_USE_VOLK
679 VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
680 VERIFY(m_State.RayTracingPipeline != VK_NULL_HANDLE, "No ray tracing pipeline bound");
681
682 vkCmdTraceRaysIndirectKHR(m_VkCmdBuffer, &RaygenShaderBindingTable, &MissShaderBindingTable, &HitShaderBindingTable, &CallableShaderBindingTable, indirectDeviceAddress);
683 #else
684 UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically");
685 #endif
686 }
687
672688 void FlushBarriers();
673689
674690 __forceinline void SetVkCmdBuffer(VkCommandBuffer VkCmdBuffer)
4444 VkPhysicalDeviceShaderFloat16Int8FeaturesKHR ShaderFloat16Int8 = {};
4545 VkPhysicalDeviceAccelerationStructureFeaturesKHR AccelStruct = {};
4646 VkPhysicalDeviceRayTracingPipelineFeaturesKHR RayTracingPipeline = {};
47 VkPhysicalDeviceRayQueryFeaturesKHR RayQuery = {};
4748 bool Spirv14 = false; // Ray tracing requires Vulkan 1.2 or SPIRV 1.4 extension
4849 bool Spirv15 = false; // DXC shaders with ray tracing requires Vulkan 1.2 with SPIRV 1.5
4950 VkPhysicalDeviceBufferDeviceAddressFeaturesKHR BufferDeviceAddress = {};
791791 #endif
792792 }
793793
794 BufferVkImpl* DeviceContextVkImpl::PrepareIndirectDrawAttribsBuffer(IBuffer* pAttribsBuffer, RESOURCE_STATE_TRANSITION_MODE TransitonMode)
794 BufferVkImpl* DeviceContextVkImpl::PrepareIndirectAttribsBuffer(IBuffer* pAttribsBuffer,
795 RESOURCE_STATE_TRANSITION_MODE TransitonMode,
796 const char* OpName)
795797 {
796798 DEV_CHECK_ERR(pAttribsBuffer, "Indirect draw attribs buffer must not be null");
797799 auto* pIndirectDrawAttribsVk = ValidatedCast<BufferVkImpl>(pAttribsBuffer);
803805
804806 // Buffer memory barries must be executed outside of render pass
805807 TransitionOrVerifyBufferState(*pIndirectDrawAttribsVk, TransitonMode, RESOURCE_STATE_INDIRECT_ARGUMENT,
806 VK_ACCESS_INDIRECT_COMMAND_READ_BIT, "Indirect draw (DeviceContextVkImpl::Draw)");
808 VK_ACCESS_INDIRECT_COMMAND_READ_BIT, OpName);
807809 return pIndirectDrawAttribsVk;
808810 }
809811
851853
852854 // We must prepare indirect draw attribs buffer first because state transitions must
853855 // be performed outside of render pass, and PrepareForDraw commits render pass
854 BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode);
856 BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, "Indirect draw (DeviceContextVkImpl::DrawIndirect)");
855857
856858 PrepareForDraw(Attribs.Flags);
857859
866868
867869 // We must prepare indirect draw attribs buffer first because state transitions must
868870 // be performed outside of render pass, and PrepareForDraw commits render pass
869 BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode);
871 BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, "Indirect draw (DeviceContextVkImpl::DrawIndexedIndirect)");
870872
871873 PrepareForIndexedDraw(Attribs.Flags, Attribs.IndexType);
872874
892894
893895 // We must prepare indirect draw attribs buffer first because state transitions must
894896 // be performed outside of render pass, and PrepareForDraw commits render pass
895 BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode);
897 BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, "Indirect draw (DeviceContextVkImpl::DrawMeshIndirect)");
896898
897899 PrepareForDraw(Attribs.Flags);
898900
34703472 ++m_State.NumCommands;
34713473 }
34723474
3475 void DeviceContextVkImpl::TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
3476 {
3477 if (!TDeviceContextBase::TraceRaysIndirect(Attribs, pAttribsBuffer, 0))
3478 return;
3479
3480 auto* pSBTVk = ValidatedCast<ShaderBindingTableVkImpl>(Attribs.pSBT);
3481 IBuffer* pBuffer = nullptr;
3482
3483 ShaderBindingTableVkImpl::BindingTable RayGenShaderRecord = {};
3484 ShaderBindingTableVkImpl::BindingTable MissShaderTable = {};
3485 ShaderBindingTableVkImpl::BindingTable HitGroupTable = {};
3486 ShaderBindingTableVkImpl::BindingTable CallableShaderTable = {};
3487
3488 pSBTVk->GetData(pBuffer, RayGenShaderRecord, MissShaderTable, HitGroupTable, CallableShaderTable);
3489
3490 const char* OpName = "Trace rays indirect (DeviceContextVkImpl::TraceRaysIndirect)";
3491 auto* const pSBTBufferVk = ValidatedCast<BufferVkImpl>(pBuffer);
3492 auto* const pIndirectAttribsVk = PrepareIndirectAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, OpName);
3493 const auto IndirectBuffOffset = Attribs.ArgsByteOffset + (Attribs.ArgsByteSize == sizeof(Uint32) * 3 ? 0 : TraceRaysIndirectCommandSBTSize);
3494
3495 if (RayGenShaderRecord.pData || MissShaderTable.pData || HitGroupTable.pData || CallableShaderTable.pData)
3496 {
3497 TransitionOrVerifyBufferState(*pSBTBufferVk, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, OpName);
3498
3499 // buffer ranges are not intersected, so we don't need to add barriers between them
3500 if (RayGenShaderRecord.pData)
3501 UpdateBuffer(pBuffer, RayGenShaderRecord.Offset, RayGenShaderRecord.Size, RayGenShaderRecord.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
3502
3503 if (MissShaderTable.pData)
3504 UpdateBuffer(pBuffer, MissShaderTable.Offset, MissShaderTable.Size, MissShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
3505
3506 if (HitGroupTable.pData)
3507 UpdateBuffer(pBuffer, HitGroupTable.Offset, HitGroupTable.Size, HitGroupTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
3508
3509 if (CallableShaderTable.pData)
3510 UpdateBuffer(pBuffer, CallableShaderTable.Offset, CallableShaderTable.Size, CallableShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
3511 }
3512 TransitionOrVerifyBufferState(*pSBTBufferVk, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_RAY_TRACING, VK_ACCESS_SHADER_READ_BIT, OpName);
3513
3514 // clang-format off
3515 VkStridedDeviceAddressRegionKHR RaygenShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + RayGenShaderRecord.Offset, RayGenShaderRecord.Stride, RayGenShaderRecord.Size };
3516 VkStridedDeviceAddressRegionKHR MissShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + MissShaderTable.Offset, MissShaderTable.Stride, MissShaderTable.Size };
3517 VkStridedDeviceAddressRegionKHR HitShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + HitGroupTable.Offset, HitGroupTable.Stride, HitGroupTable.Size };
3518 VkStridedDeviceAddressRegionKHR CallableShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + CallableShaderTable.Offset, CallableShaderTable.Stride, CallableShaderTable.Size};
3519 // clang-format on
3520
3521 PrepareForRayTracing();
3522 m_CommandBuffer.TraceRaysIndirect(RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable,
3523 pIndirectAttribsVk->GetVkDeviceAddress() + IndirectBuffOffset);
3524 ++m_State.NumCommands;
3525 }
3526
34733527 } // namespace Diligent
137137 try
138138 {
139139 Uint32 Version = VK_API_VERSION_1_0;
140 if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED)
140 if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED || EngineCI.Features.RayTracing2 != DEVICE_FEATURE_STATE_DISABLED)
141141 Version = VK_API_VERSION_1_2;
142142
143143 auto Instance = VulkanUtilities::VulkanInstance::Create(
279279
280280 const auto& DescrIndexingFeats = DeviceExtFeatures.DescriptorIndexing;
281281 ENABLE_FEATURE(DescrIndexingFeats.runtimeDescriptorArray != VK_FALSE, ShaderResourceRuntimeArray, "Shader resource runtime array is");
282
283 ENABLE_FEATURE(DeviceExtFeatures.AccelStruct.accelerationStructure != VK_FALSE && DeviceExtFeatures.RayTracingPipeline.rayTracingPipeline != VK_FALSE, RayTracing, "Ray tracing is");
282 const auto& AccelStructFeats = DeviceExtFeatures.AccelStruct;
283 const auto& RayTracingFeats = DeviceExtFeatures.RayTracingPipeline;
284 const auto& RayQueryFeats = DeviceExtFeatures.RayQuery;
285 // clang-format off
286 ENABLE_FEATURE(AccelStructFeats.accelerationStructure != VK_FALSE &&
287 RayTracingFeats.rayTracingPipeline != VK_FALSE, RayTracing, "Ray tracing is");
288 ENABLE_FEATURE(AccelStructFeats.accelerationStructure != VK_FALSE &&
289 RayTracingFeats.rayTracingPipeline != VK_FALSE &&
290 RayTracingFeats.rayTracingPipelineTraceRaysIndirect != VK_FALSE &&
291 RayTracingFeats.rayTraversalPrimitiveCulling != VK_FALSE &&
292 RayQueryFeats.rayQuery != VK_FALSE, RayTracing2, "Inline ray tracing is");
293 // clang-format on
284294 #undef FeatureSupport
285295
286296
416426 }
417427
418428 // Ray tracing
419 if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED)
429 if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED || EngineCI.Features.RayTracing2 != DEVICE_FEATURE_STATE_DISABLED)
420430 {
421431 // this extensions added to Vulkan 1.2 core
422432 if (!DeviceExtFeatures.Spirv15)
423433 {
424434 DeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); // required for VK_KHR_spirv_1_4
425 DeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); // required for VK_KHR_ray_tracing_pipeline
435 DeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); // required for VK_KHR_ray_tracing_pipeline or VK_KHR_ray_query
426436 EnabledExtFeats.Spirv14 = DeviceExtFeatures.Spirv14;
427437 VERIFY_EXPR(DeviceExtFeatures.Spirv14);
428438 }
438448
439449 // disable unused features
440450 EnabledExtFeats.AccelStruct.accelerationStructureCaptureReplay = false;
441 EnabledExtFeats.AccelStruct.accelerationStructureIndirectBuild = false;
442451 EnabledExtFeats.AccelStruct.accelerationStructureHostCommands = false;
443452 EnabledExtFeats.AccelStruct.descriptorBindingAccelerationStructureUpdateAfterBind = false;
444453
445454 EnabledExtFeats.RayTracingPipeline.rayTracingPipelineShaderGroupHandleCaptureReplay = false;
446455 EnabledExtFeats.RayTracingPipeline.rayTracingPipelineShaderGroupHandleCaptureReplayMixed = false;
447 EnabledExtFeats.RayTracingPipeline.rayTracingPipelineTraceRaysIndirect = false;
448 EnabledExtFeats.RayTracingPipeline.rayTraversalPrimitiveCulling = false; // for GLSL_EXT_ray_flags_primitive_culling
449456
450457 *NextExt = &EnabledExtFeats.AccelStruct;
451458 NextExt = &EnabledExtFeats.AccelStruct.pNext;
453460 NextExt = &EnabledExtFeats.RayTracingPipeline.pNext;
454461 *NextExt = &EnabledExtFeats.BufferDeviceAddress;
455462 NextExt = &EnabledExtFeats.BufferDeviceAddress.pNext;
463
464 // Inline ray tracing from any shader.
465 if (EngineCI.Features.RayTracing2 != DEVICE_FEATURE_STATE_DISABLED)
466 {
467 DeviceExtensions.push_back(VK_KHR_RAY_QUERY_EXTENSION_NAME);
468
469 EnabledExtFeats.RayQuery = RayQueryFeats;
470
471 *NextExt = &EnabledExtFeats.RayQuery;
472 NextExt = &EnabledExtFeats.RayQuery.pNext;
473 }
474 else
475 {
476 EnabledExtFeats.AccelStruct.accelerationStructureIndirectBuild = false;
477 EnabledExtFeats.RayTracingPipeline.rayTracingPipelineTraceRaysIndirect = false;
478 EnabledExtFeats.RayTracingPipeline.rayTraversalPrimitiveCulling = false; // for GLSL_EXT_ray_flags_primitive_culling
479 }
456480 }
457481
458482 // make sure that last pNext is null
460484 }
461485
462486 #if defined(_MSC_VER) && defined(_WIN64)
463 static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
487 static_assert(sizeof(DeviceFeatures) == 34, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
464488 #endif
465489
466490 DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data();
233233 Features.DurationQueries = DEVICE_FEATURE_STATE_ENABLED;
234234
235235 #if defined(_MSC_VER) && defined(_WIN64)
236 static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary).");
236 static_assert(sizeof(DeviceFeatures) == 34, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary).");
237237 #endif
238238
239239 const auto& vkDeviceLimits = m_PhysicalDevice->GetProperties().limits;
145145 m_ExtProperties.RayTracingPipeline.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
146146 }
147147
148 // Get inline ray tracing features.
149 if (IsExtensionSupported(VK_KHR_RAY_QUERY_EXTENSION_NAME))
150 {
151 *NextFeat = &m_ExtFeatures.RayQuery;
152 NextFeat = &m_ExtFeatures.RayQuery.pNext;
153
154 m_ExtFeatures.RayQuery.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR;
155 }
156
148157 // Additional extension that is required for ray tracing.
149158 if (IsExtensionSupported(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME))
150159 {
724724 else
725725 DxilArgs.push_back(L"-Od"); // TODO: something goes wrong if optimization is enabled
726726 #endif
727 DEV_CHECK_ERR((ShaderCI.CompileFlags & SHADER_COMPILE_FLAG_ENABLE_INLINE_RAY_TRACING) == 0 ||
728 (ShaderModel.Major > 6 || (ShaderModel.Major == 6 && ShaderModel.Minor >= 5)),
729 "Inline ray tracing requires Shader Model 6.5 and above");
727730 }
728731 else if (m_Target == DXCompilerTarget::Vulkan)
729732 {
730 const Uint32 RayTracingStages =
731 SHADER_TYPE_RAY_GEN | SHADER_TYPE_RAY_MISS | SHADER_TYPE_RAY_CLOSEST_HIT |
732 SHADER_TYPE_RAY_ANY_HIT | SHADER_TYPE_RAY_INTERSECTION | SHADER_TYPE_CALLABLE;
733
734733 DxilArgs.assign(
735734 {
736735 L"-spirv",
739738 L"-O3", // Optimization level 3
740739 });
741740
742 if (ShaderCI.Desc.ShaderType & RayTracingStages)
743 {
744 DxilArgs.push_back(L"-fspv-target-env=vulkan1.2"); // required for SPV_KHR_ray_tracing
741 if ((ShaderCI.Desc.ShaderType & SHADER_TYPE_ALL_RAY_TRACING) != 0 ||
742 (ShaderCI.CompileFlags & SHADER_COMPILE_FLAG_ENABLE_INLINE_RAY_TRACING) != 0)
743 {
744 DxilArgs.push_back(L"-fspv-target-env=vulkan1.2"); // required for SPV_KHR_ray_tracing and SPV_KHR_ray_query
745745 }
746746 }
747747 else
4545
4646 void main()
4747 {
48 const vec2 uv = vec2(gl_LaunchIDEXT.xy) / vec2(gl_LaunchSizeEXT.xy - 1);
48 const vec2 uv = vec2(gl_LaunchIDEXT.xy + 0.5) / vec2(gl_LaunchSizeEXT.xy);
4949 const vec3 origin = vec3(uv.x, 1.0 - uv.y, -1.0);
5050 const vec3 direction = vec3(0.0, 0.0, 1.0);
5151
112112
113113 void main()
114114 {
115 const vec2 uv = vec2(gl_LaunchIDEXT.xy) / vec2(gl_LaunchSizeEXT.xy - 1);
115 const vec2 uv = vec2(gl_LaunchIDEXT.xy + 0.5) / vec2(gl_LaunchSizeEXT.xy);
116116 const vec3 origin = vec3(uv.x, 1.0 - uv.y, -1.0);
117117 const vec3 direction = vec3(0.0, 0.0, 1.0);
118118
198198
199199 void main()
200200 {
201 const vec2 uv = vec2(gl_LaunchIDEXT.xy) / vec2(gl_LaunchSizeEXT.xy - 1);
201 const vec2 uv = vec2(gl_LaunchIDEXT.xy + 0.5) / vec2(gl_LaunchSizeEXT.xy);
202202 const vec3 origin = vec3(uv.x, 1.0 - uv.y, 0.0);
203203 const vec3 direction = vec3(0.0, 0.0, 1.0);
204204
293293
294294 void main()
295295 {
296 const vec2 uv = vec2(gl_LaunchIDEXT.xy) / vec2(gl_LaunchSizeEXT.xy - 1);
296 const vec2 uv = vec2(gl_LaunchIDEXT.xy + 0.5) / vec2(gl_LaunchSizeEXT.xy);
297297 const vec3 origin = vec3(uv.x, 1.0 - uv.y, -1.0);
298298 const vec3 direction = vec3(0.0, 0.0, 1.0);
299299
4949 [shader("raygeneration")]
5050 void main()
5151 {
52 const float2 uv = float2(DispatchRaysIndex().xy) / float2(DispatchRaysDimensions().xy - 1);
52 const float2 uv = float2(DispatchRaysIndex().xy + 0.5) / float2(DispatchRaysDimensions().xy);
5353
5454 RayDesc ray;
5555 ray.Origin = float3(uv.x, 1.0 - uv.y, -1.0);
101101 [shader("raygeneration")]
102102 void main()
103103 {
104 const float2 uv = float2(DispatchRaysIndex().xy) / float2(DispatchRaysDimensions().xy - 1);
104 const float2 uv = float2(DispatchRaysIndex().xy + 0.5) / float2(DispatchRaysDimensions().xy);
105105
106106 RayDesc ray;
107107 ray.Origin = float3(uv.x, 1.0 - uv.y, -1.0);
165165 [shader("raygeneration")]
166166 void main()
167167 {
168 const float2 uv = float2(DispatchRaysIndex().xy) / float2(DispatchRaysDimensions().xy - 1);
168 const float2 uv = float2(DispatchRaysIndex().xy + 0.5) / float2(DispatchRaysDimensions().xy);
169169
170170 RayDesc ray;
171171 ray.Origin = float3(uv.x, 1.0 - uv.y, 0.0);
250250 [shader("raygeneration")]
251251 void main()
252252 {
253 const float2 uv = float2(DispatchRaysIndex().xy) / float2(DispatchRaysDimensions().xy - 1);
253 const float2 uv = float2(DispatchRaysIndex().xy + 0.5) / float2(DispatchRaysDimensions().xy);
254254
255255 RayDesc ray;
256256 ray.Origin = float3(uv.x, 1.0 - uv.y, -1.0);
348348 [shader("raygeneration")]
349349 void main()
350350 {
351 const float2 uv = float2(DispatchRaysIndex().xy) / float2(DispatchRaysDimensions().xy - 1);
351 const float2 uv = float2(DispatchRaysIndex().xy + 0.5) / float2(DispatchRaysDimensions().xy);
352352
353353 RayDesc ray;
354354 ray.Origin = float3(uv.x, 1.0 - uv.y, -1.0);
427427 // clang-format on
428428
429429
430 // clang-format off
431 const std::string RayTracingTest6_RG{R"hlsl(
432 RaytracingAccelerationStructure g_TLAS;
433 RWTexture2D<float4> g_ColorBuffer;
434
435 float4 HitShader(float2 attrBarycentrics)
436 {
437 float3 barycentrics = float3(1.0 - attrBarycentrics.x - attrBarycentrics.y, attrBarycentrics.x, attrBarycentrics.y);
438 return float4(barycentrics, 1.0);
439 }
440
441 float4 MissShader()
442 {
443 return float4(1.0, 0.0, 0.0, 1.0);
444 }
445
446 [shader("raygeneration")]
447 void main()
448 {
449 const float2 uv = float2(DispatchRaysIndex().xy + 0.5) / float2(DispatchRaysDimensions().xy);
450
451 RayDesc ray;
452 ray.Origin = float3(uv.x, 1.0 - uv.y, -1.0);
453 ray.Direction = float3(0.0, 0.0, 1.0);
454 ray.TMin = 0.01;
455 ray.TMax = 10.0;
456
457 RayQuery<RAY_FLAG_NONE> q;
458
459 q.TraceRayInline(g_TLAS, // Acceleration Structure
460 RAY_FLAG_NONE, // Ray Flags
461 ~0, // Instance Inclusion Mask
462 ray);
463
464 q.Proceed();
465
466 float4 Color;
467 if (q.CommittedStatus() == COMMITTED_TRIANGLE_HIT)
468 {
469 Color = HitShader(q.CommittedTriangleBarycentrics());
470 }
471 else
472 {
473 Color = MissShader();
474 }
475 g_ColorBuffer[DispatchRaysIndex().xy] = Color;
476 }
477 )hlsl"};
478 // clang-format on
479
480
481 // clang-format offstruct PSInput
482 const std::string RayTracingTest7_VS{R"hlsl(
483 struct PSInput
484 {
485 float4 Pos : SV_POSITION;
486 float2 UV : TEX_COORD;
487 };
488
489 void main(in uint vid : SV_VertexID,
490 out PSInput PSIn)
491 {
492 PSIn.UV = float2(vid & 1, vid >> 1);
493 PSIn.Pos = float4(PSIn.UV * 2.0 - 1.0, 0.0, 1.0);
494 }
495 )hlsl"};
496
497 const std::string RayTracingTest7_PS{R"hlsl(
498 struct PSInput
499 {
500 float4 Pos : SV_POSITION;
501 float2 UV : TEX_COORD;
502 };
503
504 RaytracingAccelerationStructure g_TLAS;
505 RWTexture2D<float4> g_ColorBuffer;
506
507 float4 HitShader(float2 attrBarycentrics)
508 {
509 float3 barycentrics = float3(1.0 - attrBarycentrics.x - attrBarycentrics.y, attrBarycentrics.x, attrBarycentrics.y);
510 return float4(barycentrics, 1.0);
511 }
512
513 float4 MissShader()
514 {
515 return float4(1.0, 0.0, 0.0, 1.0);
516 }
517
518 float4 main(in PSInput PSIn) : SV_Target
519 {
520 const float2 uv = PSIn.UV;
521
522 RayDesc ray;
523 ray.Origin = float3(uv.x, uv.y, -1.0);
524 ray.Direction = float3(0.0, 0.0, 1.0);
525 ray.TMin = 0.01;
526 ray.TMax = 10.0;
527
528 RayQuery<RAY_FLAG_NONE> q;
529
530 q.TraceRayInline(g_TLAS, // Acceleration Structure
531 RAY_FLAG_NONE, // Ray Flags
532 ~0, // Instance Inclusion Mask
533 ray);
534
535 q.Proceed();
536
537 float4 Color;
538 if (q.CommittedStatus() == COMMITTED_TRIANGLE_HIT)
539 {
540 Color = HitShader(q.CommittedTriangleBarycentrics());
541 }
542 else
543 {
544 Color = MissShader();
545 }
546 return Color;
547 }
548 )hlsl"};
549 // clang-format on
550
430551 } // namespace HLSL
431552
432553 } // namespace
14901490 ASSERT_NE(pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_CLOSEST_HIT, "g_Texture2"), nullptr);
14911491 }
14921492
1493
1494 class RT5 : public testing::TestWithParam<int>
1495 {};
1496
1497 TEST_P(RT5, InlineRayTracing_RayTracingPSO)
1498 {
1499 Uint32 TestId = GetParam();
1500 auto* pEnv = TestingEnvironment::GetInstance();
1501 auto* pDevice = pEnv->GetDevice();
1502 if (!pDevice->GetDeviceCaps().Features.RayTracing2)
1503 {
1504 GTEST_SKIP() << "Inline ray tracing is not supported by this device";
1505 }
1506
1507 auto* pSwapChain = pEnv->GetSwapChain();
1508 auto* pContext = pEnv->GetDeviceContext();
1509
1510 RefCntAutoPtr<ITestingSwapChain> pTestingSwapChain(pSwapChain, IID_TestingSwapChain);
1511 if (pTestingSwapChain)
1512 {
1513 pContext->Flush();
1514 pContext->InvalidateState();
1515
1516 auto deviceType = pDevice->GetDeviceCaps().DevType;
1517 switch (deviceType)
1518 {
1519 #if D3D12_SUPPORTED
1520 case RENDER_DEVICE_TYPE_D3D12:
1521 RayTracingTriangleClosestHitReferenceD3D12(pSwapChain);
1522 break;
1523 #endif
1524
1525 #if VULKAN_SUPPORTED
1526 case RENDER_DEVICE_TYPE_VULKAN:
1527 RayTracingTriangleClosestHitReferenceVk(pSwapChain);
1528 break;
1529 #endif
1530
1531 default:
1532 LOG_ERROR_AND_THROW("Unsupported device type");
1533 }
1534
1535 pTestingSwapChain->TakeSnapshot();
1536 }
1537 TestingEnvironment::ScopedReleaseResources EnvironmentAutoReset;
1538
1539 RayTracingPipelineStateCreateInfo PSOCreateInfo;
1540
1541 PSOCreateInfo.PSODesc.Name = "Inline ray tracing test PSO";
1542 PSOCreateInfo.PSODesc.PipelineType = PIPELINE_TYPE_RAY_TRACING;
1543
1544 ShaderCreateInfo ShaderCI;
1545 ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
1546 ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC;
1547 ShaderCI.HLSLVersion = {6, 5};
1548 ShaderCI.EntryPoint = "main";
1549
1550 RefCntAutoPtr<IShader> pRG;
1551 {
1552 ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_GEN;
1553 ShaderCI.Desc.Name = "Ray tracing RG";
1554 ShaderCI.Source = HLSL::RayTracingTest6_RG.c_str();
1555 pDevice->CreateShader(ShaderCI, &pRG);
1556 ASSERT_NE(pRG, nullptr);
1557 }
1558
1559 const RayTracingGeneralShaderGroup GeneralShaders[] = {{"Main", pRG}};
1560
1561 PSOCreateInfo.pGeneralShaders = GeneralShaders;
1562 PSOCreateInfo.GeneralShaderCount = _countof(GeneralShaders);
1563
1564 PSOCreateInfo.RayTracingPipeline.MaxRecursionDepth = 0;
1565 PSOCreateInfo.PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
1566
1567 RefCntAutoPtr<IPipelineState> pRayTracingPSO;
1568 pDevice->CreateRayTracingPipelineState(PSOCreateInfo, &pRayTracingPSO);
1569 ASSERT_NE(pRayTracingPSO, nullptr);
1570
1571 RefCntAutoPtr<IShaderResourceBinding> pRayTracingSRB;
1572 pRayTracingPSO->CreateShaderResourceBinding(&pRayTracingSRB, true);
1573 ASSERT_NE(pRayTracingSRB, nullptr);
1574
1575 const auto& Vertices = TestingConstants::TriangleClosestHit::Vertices;
1576
1577 RefCntAutoPtr<IBuffer> pVertexBuffer;
1578 {
1579 BufferDesc BuffDesc;
1580 BuffDesc.Name = "Triangle vertices";
1581 BuffDesc.Usage = USAGE_IMMUTABLE;
1582 BuffDesc.BindFlags = BIND_RAY_TRACING;
1583 BuffDesc.uiSizeInBytes = sizeof(Vertices);
1584
1585 BufferData BufData;
1586 BufData.pData = Vertices;
1587 BufData.DataSize = sizeof(Vertices);
1588
1589 pDevice->CreateBuffer(BuffDesc, &BufData, &pVertexBuffer);
1590 ASSERT_NE(pVertexBuffer, nullptr);
1591 }
1592
1593 BLASBuildTriangleData Triangle;
1594 Triangle.GeometryName = "Triangle";
1595 Triangle.pVertexBuffer = pVertexBuffer;
1596 Triangle.VertexStride = sizeof(Vertices[0]);
1597 Triangle.VertexCount = _countof(Vertices);
1598 Triangle.VertexValueType = VT_FLOAT32;
1599 Triangle.VertexComponentCount = 3;
1600 Triangle.Flags = RAYTRACING_GEOMETRY_FLAG_OPAQUE;
1601
1602 RefCntAutoPtr<IBottomLevelAS> pTempBLAS;
1603 CreateBLAS(pDevice, pContext, &Triangle, 1, TestBLASUpdate(TestId), pTempBLAS);
1604
1605 RefCntAutoPtr<IBottomLevelAS> pBLAS;
1606 BLASCompaction(TestId, pDevice, pContext, pTempBLAS, pBLAS);
1607
1608 TLASBuildInstanceData Instance;
1609 Instance.InstanceName = "Instance";
1610 Instance.pBLAS = pBLAS;
1611 Instance.Flags = RAYTRACING_INSTANCE_NONE;
1612
1613 RefCntAutoPtr<ITopLevelAS> pTempTLAS;
1614 const Uint32 HitGroupStride = 1;
1615 CreateTLAS(pDevice, pContext, &Instance, 1, HitGroupStride, TestTLASUpdate(TestId), pTempTLAS);
1616
1617 RefCntAutoPtr<ITopLevelAS> pTLAS;
1618 TLASCompaction(TestId, pDevice, pContext, pTempTLAS, pTLAS);
1619
1620 ShaderBindingTableDesc SBTDesc;
1621 SBTDesc.Name = "SBT";
1622 SBTDesc.pPSO = pRayTracingPSO;
1623
1624 RefCntAutoPtr<IShaderBindingTable> pSBT;
1625 pDevice->CreateSBT(SBTDesc, &pSBT);
1626 ASSERT_NE(pSBT, nullptr);
1627
1628 pSBT->BindRayGenShader("Main");
1629
1630 pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_GEN, "g_TLAS")->Set(pTLAS);
1631 pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_GEN, "g_ColorBuffer")->Set(pTestingSwapChain->GetCurrentBackBufferUAV());
1632
1633 pContext->SetPipelineState(pRayTracingPSO);
1634 pContext->CommitShaderResources(pRayTracingSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
1635
1636 const auto& SCDesc = pSwapChain->GetDesc();
1637
1638 TraceRaysAttribs Attribs;
1639 Attribs.DimensionX = SCDesc.Width;
1640 Attribs.DimensionY = SCDesc.Height;
1641 Attribs.pSBT = pSBT;
1642
1643 pContext->TraceRays(Attribs);
1644
1645 pSwapChain->Present();
1646 }
1647 INSTANTIATE_TEST_SUITE_P(RayTracingTest, RT5, TestParamRange, TestIdToString);
1648
1649
1650 class RT6 : public testing::TestWithParam<int>
1651 {};
1652
1653 TEST_P(RT6, InlineRayTracing_GraphicsPSO)
1654 {
1655 Uint32 TestId = GetParam();
1656 auto* pEnv = TestingEnvironment::GetInstance();
1657 auto* pDevice = pEnv->GetDevice();
1658 if (!pDevice->GetDeviceCaps().Features.RayTracing2 || !pDevice->GetDeviceCaps().IsVulkanDevice())
1659 {
1660 GTEST_SKIP() << "Inline ray tracing is not supported by this device";
1661 }
1662
1663 auto* pSwapChain = pEnv->GetSwapChain();
1664 auto* pContext = pEnv->GetDeviceContext();
1665
1666 RefCntAutoPtr<ITestingSwapChain> pTestingSwapChain(pSwapChain, IID_TestingSwapChain);
1667 if (pTestingSwapChain)
1668 {
1669 pContext->Flush();
1670 pContext->InvalidateState();
1671
1672 auto deviceType = pDevice->GetDeviceCaps().DevType;
1673 switch (deviceType)
1674 {
1675 #if D3D12_SUPPORTED
1676 case RENDER_DEVICE_TYPE_D3D12:
1677 RayTracingTriangleClosestHitReferenceD3D12(pSwapChain);
1678 break;
1679 #endif
1680
1681 #if VULKAN_SUPPORTED
1682 case RENDER_DEVICE_TYPE_VULKAN:
1683 RayTracingTriangleClosestHitReferenceVk(pSwapChain);
1684 break;
1685 #endif
1686
1687 default:
1688 LOG_ERROR_AND_THROW("Unsupported device type");
1689 }
1690
1691 pTestingSwapChain->TakeSnapshot();
1692 }
1693 TestingEnvironment::ScopedReleaseResources EnvironmentAutoReset;
1694
1695 GraphicsPipelineStateCreateInfo PSOCreateInfo;
1696 auto& PSODesc = PSOCreateInfo.PSODesc;
1697 auto& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline;
1698
1699 PSODesc.Name = "Inline ray tracing test PSO";
1700 PSODesc.PipelineType = PIPELINE_TYPE_GRAPHICS;
1701 GraphicsPipeline.NumRenderTargets = 1;
1702 GraphicsPipeline.RTVFormats[0] = pSwapChain->GetDesc().ColorBufferFormat;
1703 GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1704 GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE;
1705 GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
1706 PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
1707
1708 ShaderCreateInfo ShaderCI;
1709 ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
1710 ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC;
1711 ShaderCI.HLSLVersion = {6, 5};
1712 ShaderCI.EntryPoint = "main";
1713
1714 RefCntAutoPtr<IShader> pVS;
1715 {
1716 ShaderCI.Desc.ShaderType = SHADER_TYPE_VERTEX;
1717 ShaderCI.Desc.Name = "VS";
1718 ShaderCI.Source = HLSL::RayTracingTest7_VS.c_str();
1719 pDevice->CreateShader(ShaderCI, &pVS);
1720 ASSERT_NE(pVS, nullptr);
1721 }
1722
1723 RefCntAutoPtr<IShader> pPS;
1724 {
1725 ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL;
1726 ShaderCI.Desc.Name = "PS";
1727 ShaderCI.Source = HLSL::RayTracingTest7_PS.c_str();
1728 ShaderCI.CompileFlags = SHADER_COMPILE_FLAG_ENABLE_INLINE_RAY_TRACING;
1729 pDevice->CreateShader(ShaderCI, &pPS);
1730 ASSERT_NE(pPS, nullptr);
1731 }
1732
1733 PSOCreateInfo.pVS = pVS;
1734 PSOCreateInfo.pPS = pPS;
1735
1736 RefCntAutoPtr<IPipelineState> pPSO;
1737 pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &pPSO);
1738 ASSERT_NE(pPSO, nullptr);
1739
1740 RefCntAutoPtr<IShaderResourceBinding> pSRB;
1741 pPSO->CreateShaderResourceBinding(&pSRB, true);
1742 ASSERT_NE(pSRB, nullptr);
1743
1744 const auto& Vertices = TestingConstants::TriangleClosestHit::Vertices;
1745
1746 RefCntAutoPtr<IBuffer> pVertexBuffer;
1747 {
1748 BufferDesc BuffDesc;
1749 BuffDesc.Name = "Triangle vertices";
1750 BuffDesc.Usage = USAGE_IMMUTABLE;
1751 BuffDesc.BindFlags = BIND_RAY_TRACING;
1752 BuffDesc.uiSizeInBytes = sizeof(Vertices);
1753
1754 BufferData BufData;
1755 BufData.pData = Vertices;
1756 BufData.DataSize = sizeof(Vertices);
1757
1758 pDevice->CreateBuffer(BuffDesc, &BufData, &pVertexBuffer);
1759 ASSERT_NE(pVertexBuffer, nullptr);
1760 }
1761
1762 BLASBuildTriangleData Triangle;
1763 Triangle.GeometryName = "Triangle";
1764 Triangle.pVertexBuffer = pVertexBuffer;
1765 Triangle.VertexStride = sizeof(Vertices[0]);
1766 Triangle.VertexCount = _countof(Vertices);
1767 Triangle.VertexValueType = VT_FLOAT32;
1768 Triangle.VertexComponentCount = 3;
1769 Triangle.Flags = RAYTRACING_GEOMETRY_FLAG_OPAQUE;
1770
1771 RefCntAutoPtr<IBottomLevelAS> pTempBLAS;
1772 CreateBLAS(pDevice, pContext, &Triangle, 1, TestBLASUpdate(TestId), pTempBLAS);
1773
1774 RefCntAutoPtr<IBottomLevelAS> pBLAS;
1775 BLASCompaction(TestId, pDevice, pContext, pTempBLAS, pBLAS);
1776
1777 TLASBuildInstanceData Instance;
1778 Instance.InstanceName = "Instance";
1779 Instance.pBLAS = pBLAS;
1780 Instance.Flags = RAYTRACING_INSTANCE_NONE;
1781
1782 RefCntAutoPtr<ITopLevelAS> pTempTLAS;
1783 const Uint32 HitGroupStride = 1;
1784 CreateTLAS(pDevice, pContext, &Instance, 1, HitGroupStride, TestTLASUpdate(TestId), pTempTLAS);
1785
1786 RefCntAutoPtr<ITopLevelAS> pTLAS;
1787 TLASCompaction(TestId, pDevice, pContext, pTempTLAS, pTLAS);
1788
1789 pSRB->GetVariableByName(SHADER_TYPE_PIXEL, "g_TLAS")->Set(pTLAS);
1790
1791 ITextureView* pRTVs[] = {pSwapChain->GetCurrentBackBufferRTV()};
1792 pContext->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
1793
1794 pContext->SetPipelineState(pPSO);
1795 pContext->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
1796
1797 DrawAttribs drawAttrs{4, DRAW_FLAG_VERIFY_ALL};
1798 pContext->Draw(drawAttrs);
1799
1800 pSwapChain->Present();
1801 }
1802 INSTANTIATE_TEST_SUITE_P(RayTracingTest, RT6, TestParamRange, TestIdToString);
1803
1804
1805 class RT7 : public testing::TestWithParam<int>
1806 {};
1807
1808 TEST_P(RT7, TraceRaysIndirect)
1809 {
1810 Uint32 TestId = GetParam();
1811 auto* pEnv = TestingEnvironment::GetInstance();
1812 auto* pDevice = pEnv->GetDevice();
1813 if (!pDevice->GetDeviceCaps().Features.RayTracing2 || !pDevice->GetDeviceCaps().IsVulkanDevice())
1814 {
1815 GTEST_SKIP() << "Indirect ray tracing is not supported by this device";
1816 }
1817
1818 auto* pSwapChain = pEnv->GetSwapChain();
1819 auto* pContext = pEnv->GetDeviceContext();
1820
1821 RefCntAutoPtr<ITestingSwapChain> pTestingSwapChain(pSwapChain, IID_TestingSwapChain);
1822 if (pTestingSwapChain)
1823 {
1824 pContext->Flush();
1825 pContext->InvalidateState();
1826
1827 auto deviceType = pDevice->GetDeviceCaps().DevType;
1828 switch (deviceType)
1829 {
1830 #if D3D12_SUPPORTED
1831 case RENDER_DEVICE_TYPE_D3D12:
1832 RayTracingTriangleClosestHitReferenceD3D12(pSwapChain);
1833 break;
1834 #endif
1835
1836 #if VULKAN_SUPPORTED
1837 case RENDER_DEVICE_TYPE_VULKAN:
1838 RayTracingTriangleClosestHitReferenceVk(pSwapChain);
1839 break;
1840 #endif
1841
1842 default:
1843 LOG_ERROR_AND_THROW("Unsupported device type");
1844 }
1845
1846 pTestingSwapChain->TakeSnapshot();
1847 }
1848 TestingEnvironment::ScopedReleaseResources EnvironmentAutoReset;
1849
1850 RayTracingPipelineStateCreateInfo PSOCreateInfo;
1851
1852 PSOCreateInfo.PSODesc.Name = "Ray tracing PSO";
1853 PSOCreateInfo.PSODesc.PipelineType = PIPELINE_TYPE_RAY_TRACING;
1854
1855 ShaderCreateInfo ShaderCI;
1856 ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
1857 ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC;
1858 ShaderCI.HLSLVersion = {6, 3};
1859 ShaderCI.EntryPoint = "main";
1860
1861 // Create ray generation shader.
1862 RefCntAutoPtr<IShader> pRG;
1863 {
1864 ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_GEN;
1865 ShaderCI.Desc.Name = "Ray tracing RG";
1866 ShaderCI.Source = HLSL::RayTracingTest1_RG.c_str();
1867 pDevice->CreateShader(ShaderCI, &pRG);
1868 ASSERT_NE(pRG, nullptr);
1869 }
1870
1871 // Create ray miss shader.
1872 RefCntAutoPtr<IShader> pRMiss;
1873 {
1874 ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_MISS;
1875 ShaderCI.Desc.Name = "Miss shader";
1876 ShaderCI.Source = HLSL::RayTracingTest1_RM.c_str();
1877 pDevice->CreateShader(ShaderCI, &pRMiss);
1878 ASSERT_NE(pRMiss, nullptr);
1879 }
1880
1881 // Create ray closest hit shader.
1882 RefCntAutoPtr<IShader> pClosestHit;
1883 {
1884 ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_CLOSEST_HIT;
1885 ShaderCI.Desc.Name = "Ray closest hit shader";
1886 ShaderCI.Source = HLSL::RayTracingTest1_RCH.c_str();
1887 pDevice->CreateShader(ShaderCI, &pClosestHit);
1888 ASSERT_NE(pClosestHit, nullptr);
1889 }
1890
1891 const RayTracingGeneralShaderGroup GeneralShaders[] = {{"Main", pRG}, {"Miss", pRMiss}};
1892 const RayTracingTriangleHitShaderGroup TriangleHitShaders[] = {{"HitGroup", pClosestHit}};
1893
1894 PSOCreateInfo.pGeneralShaders = GeneralShaders;
1895 PSOCreateInfo.GeneralShaderCount = _countof(GeneralShaders);
1896 PSOCreateInfo.pTriangleHitShaders = TriangleHitShaders;
1897 PSOCreateInfo.TriangleHitShaderCount = _countof(TriangleHitShaders);
1898
1899 PSOCreateInfo.RayTracingPipeline.MaxRecursionDepth = 1;
1900 PSOCreateInfo.PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
1901
1902 RefCntAutoPtr<IPipelineState> pRayTracingPSO;
1903 pDevice->CreateRayTracingPipelineState(PSOCreateInfo, &pRayTracingPSO);
1904 ASSERT_NE(pRayTracingPSO, nullptr);
1905
1906 RefCntAutoPtr<IShaderResourceBinding> pRayTracingSRB;
1907 pRayTracingPSO->CreateShaderResourceBinding(&pRayTracingSRB, true);
1908 ASSERT_NE(pRayTracingSRB, nullptr);
1909
1910 const auto& Vertices = TestingConstants::TriangleClosestHit::Vertices;
1911
1912 RefCntAutoPtr<IBuffer> pVertexBuffer;
1913 {
1914 BufferDesc BuffDesc;
1915 BuffDesc.Name = "Triangle vertices";
1916 BuffDesc.Usage = USAGE_IMMUTABLE;
1917 BuffDesc.BindFlags = BIND_RAY_TRACING;
1918 BuffDesc.uiSizeInBytes = sizeof(Vertices);
1919
1920 BufferData BufData;
1921 BufData.pData = Vertices;
1922 BufData.DataSize = sizeof(Vertices);
1923
1924 pDevice->CreateBuffer(BuffDesc, &BufData, &pVertexBuffer);
1925 ASSERT_NE(pVertexBuffer, nullptr);
1926 }
1927
1928 BLASBuildTriangleData Triangle;
1929 Triangle.GeometryName = "Triangle";
1930 Triangle.pVertexBuffer = pVertexBuffer;
1931 Triangle.VertexStride = sizeof(Vertices[0]);
1932 Triangle.VertexCount = _countof(Vertices);
1933 Triangle.VertexValueType = VT_FLOAT32;
1934 Triangle.VertexComponentCount = 3;
1935 Triangle.Flags = RAYTRACING_GEOMETRY_FLAG_OPAQUE;
1936
1937 RefCntAutoPtr<IBottomLevelAS> pTempBLAS;
1938 CreateBLAS(pDevice, pContext, &Triangle, 1, TestBLASUpdate(TestId), pTempBLAS);
1939
1940 RefCntAutoPtr<IBottomLevelAS> pBLAS;
1941 BLASCompaction(TestId, pDevice, pContext, pTempBLAS, pBLAS);
1942
1943 TLASBuildInstanceData Instance;
1944 Instance.InstanceName = "Instance";
1945 Instance.pBLAS = pBLAS;
1946 Instance.Flags = RAYTRACING_INSTANCE_NONE;
1947
1948 RefCntAutoPtr<ITopLevelAS> pTempTLAS;
1949 const Uint32 HitGroupStride = 1;
1950 CreateTLAS(pDevice, pContext, &Instance, 1, HitGroupStride, TestTLASUpdate(TestId), pTempTLAS);
1951
1952 RefCntAutoPtr<ITopLevelAS> pTLAS;
1953 TLASCompaction(TestId, pDevice, pContext, pTempTLAS, pTLAS);
1954
1955 ShaderBindingTableDesc SBTDesc;
1956 SBTDesc.Name = "SBT";
1957 SBTDesc.pPSO = pRayTracingPSO;
1958
1959 RefCntAutoPtr<IShaderBindingTable> pSBT;
1960 pDevice->CreateSBT(SBTDesc, &pSBT);
1961 ASSERT_NE(pSBT, nullptr);
1962
1963 pSBT->BindRayGenShader("Main");
1964 pSBT->BindMissShader("Miss", 0);
1965 pSBT->BindHitGroupForGeometry(pTLAS, "Instance", "Triangle", 0, "HitGroup");
1966
1967 pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_GEN, "g_TLAS")->Set(pTLAS);
1968 pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_GEN, "g_ColorBuffer")->Set(pTestingSwapChain->GetCurrentBackBufferUAV());
1969
1970 struct TraceRaysIndirectArgs
1971 {
1972 char Unused[16];
1973 char Reserved[88];
1974 Uint32 DimensionX = 1;
1975 Uint32 DimensionY = 1;
1976 Uint32 DimensionZ = 1;
1977 Uint32 End;
1978 };
1979 TraceRaysIndirectArgs IndirectArgs;
1980 const auto& SCDesc = pSwapChain->GetDesc();
1981
1982 IndirectArgs.DimensionX = SCDesc.Width;
1983 IndirectArgs.DimensionY = SCDesc.Height;
1984
1985 BufferDesc BuffDesc;
1986 BuffDesc.Name = "Indirect args buffer";
1987 BuffDesc.Usage = USAGE_DEFAULT;
1988 BuffDesc.uiSizeInBytes = sizeof(IndirectArgs);
1989 BuffDesc.BindFlags = BIND_INDIRECT_DRAW_ARGS | BIND_RAY_TRACING;
1990
1991 BufferData BuffData{&IndirectArgs, sizeof(IndirectArgs)};
1992
1993 RefCntAutoPtr<IBuffer> pAttribsBuf;
1994 pDevice->CreateBuffer(BuffDesc, &BuffData, &pAttribsBuf);
1995
1996 pContext->SetPipelineState(pRayTracingPSO);
1997 pContext->CommitShaderResources(pRayTracingSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
1998
1999 TraceRaysIndirectAttribs Attribs;
2000 Attribs.pSBT = pSBT;
2001 Attribs.IndirectAttribsBufferStateTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
2002 Attribs.ArgsByteOffset = offsetof(TraceRaysIndirectArgs, Reserved);
2003 Attribs.ArgsByteSize = offsetof(TraceRaysIndirectArgs, End) - offsetof(TraceRaysIndirectArgs, Reserved);
2004
2005 pContext->TraceRaysIndirect(Attribs, pAttribsBuf);
2006
2007 pSwapChain->Present();
2008 }
2009 INSTANTIATE_TEST_SUITE_P(RayTracingTest, RT7, TestParamRange, TestIdToString);
2010
14932011 } // namespace