diff options
| author | azhirnov <zh1dron@gmail.com> | 2020-11-03 10:52:24 +0000 |
|---|---|---|
| committer | azhirnov <zh1dron@gmail.com> | 2020-11-03 11:16:11 +0000 |
| commit | efa43e2bd2475a4dec6771bf9759f6a99f7d77ed (patch) | |
| tree | bbb257c3825ff07078626e3e137468f99d235a07 /Tests | |
| parent | Few improvements to ray tracing tests (diff) | |
| download | DiligentCore-efa43e2bd2475a4dec6771bf9759f6a99f7d77ed.tar.gz DiligentCore-efa43e2bd2475a4dec6771bf9759f6a99f7d77ed.zip | |
fixed resource state transitions, some improvements for ray tracing
Diffstat (limited to 'Tests')
6 files changed, 1772 insertions, 360 deletions
diff --git a/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestGLSL.h b/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestGLSL.h index fe761719..7567e526 100644 --- a/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestGLSL.h +++ b/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestGLSL.h @@ -55,7 +55,7 @@ void main() gl_RayFlagsNoneEXT, // rayFlags 0xFF, // cullMask 0, // sbtRecordOffset - 0, // sbtRecordStride + 1, // sbtRecordStride 0, // missIndex origin, // ray origin 0.01, // ray min range @@ -122,7 +122,7 @@ void main() gl_RayFlagsSkipClosestHitShaderEXT, 0xFF, // cullMask 0, // sbtRecordOffset - 0, // sbtRecordStride + 1, // sbtRecordStride 0, // missIndex origin, // ray origin 0.01, // ray min range @@ -207,7 +207,7 @@ void main() gl_RayFlagsNoneEXT, // rayFlags 0xFF, // cullMask 0, // sbtRecordOffset - 0, // sbtRecordStride + 1, // sbtRecordStride 0, // missIndex origin, // ray origin 0.01, // ray min range @@ -280,6 +280,120 @@ void main() // clang-format on +// clang-format off +const std::string RayTracingTest4_RG{ +R"glsl( +#version 460 +#extension GL_EXT_ray_tracing : require + +layout(set=0, binding=0) uniform accelerationStructureEXT g_TLAS; +layout(set=0, binding=1, rgba8) uniform image2D g_ColorBuffer; + +layout(location=0) rayPayloadEXT vec4 payload; + +void main() +{ + const vec2 uv = vec2(gl_LaunchIDEXT.xy) / vec2(gl_LaunchSizeEXT.xy - 1); + const vec3 origin = vec3(uv.x, 1.0 - uv.y, -1.0); + const vec3 direction = vec3(0.0, 0.0, 1.0); + + payload = vec4(0.0); + traceRayEXT(g_TLAS, // acceleration structure + gl_RayFlagsNoneEXT, // rayFlags + 0xFF, // cullMask + 0, // sbtRecordOffset + 1, // sbtRecordStride + 0, // missIndex + origin, // ray origin + 0.01, // ray min range + direction, // ray direction + 10.0, // ray max range + 0); // payload location + + imageStore(g_ColorBuffer, ivec2(gl_LaunchIDEXT), payload); +} +)glsl" +}; + +const std::string RayTracingTest4_RM{ +R"glsl( +#version 460 +#extension GL_EXT_ray_tracing : require + +layout(location=0) rayPayloadInEXT vec4 payload; + +void main() +{ + payload = vec4(0.0, 0.0, 0.2, 1.0); +} +)glsl" +}; + +const std::string RayTracingTest4_Uniforms{ +R"glsl( +#version 460 +#extension GL_EXT_ray_tracing : require + +layout(shaderRecordEXT) buffer ShaderRecord +{ + vec4 Weights; +}; + +layout(location=0) rayPayloadInEXT vec4 payload; +hitAttributeEXT vec2 hitAttribs; + +layout(set=0, binding=2, std430) readonly buffer PerInstanceData { + uint PrimitiveOffsets[3]; +} g_PerInstance[2]; + +layout(set=0, binding=3, std430) readonly buffer PrimitiveData { + uvec4 g_Primitives[9]; +}; + +struct Vertex +{ + vec4 Pos; + vec4 Color1; + vec4 Color2; +}; +layout(set=0, binding=4, std430) readonly buffer VertexData { + Vertex g_Vertices[16]; +}; +)glsl" +}; + +const std::string RayTracingTest4_RCH1 = RayTracingTest4_Uniforms + +R"glsl( +void main() +{ + vec3 barycentrics = vec3(1.0f - hitAttribs.x - hitAttribs.y, hitAttribs.x, hitAttribs.y);// * Weights.xyz; + uint primOffset = g_PerInstance[gl_InstanceID].PrimitiveOffsets[gl_GeometryIndexEXT]; + uvec4 triFace = g_Primitives[primOffset + gl_PrimitiveID]; + Vertex v0 = g_Vertices[triFace.x]; + Vertex v1 = g_Vertices[triFace.y]; + Vertex v2 = g_Vertices[triFace.z]; + vec4 col = v0.Color2 * barycentrics.x + v1.Color2 * barycentrics.y + v2.Color2 * barycentrics.z; + payload = col; +} +)glsl"; + +const std::string RayTracingTest4_RCH2 = RayTracingTest4_Uniforms + +R"glsl( +void main() +{ + vec3 barycentrics = vec3(1.0f - hitAttribs.x - hitAttribs.y, hitAttribs.x, hitAttribs.y);// * Weights.xyz; + uint primOffset = g_PerInstance[gl_InstanceID].PrimitiveOffsets[gl_GeometryIndexEXT]; + uvec4 triFace = g_Primitives[primOffset + gl_PrimitiveID]; + Vertex v0 = g_Vertices[triFace.x]; + Vertex v1 = g_Vertices[triFace.y]; + Vertex v2 = g_Vertices[triFace.z]; + vec4 col = v0.Color1 * barycentrics.x + v1.Color1 * barycentrics.y + v2.Color1 * barycentrics.z; + payload = col; +} +)glsl"; +// clang-format on + + } // namespace GLSL } // namespace diff --git a/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestHLSL.h b/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestHLSL.h index ed64b700..c6b97b6e 100644 --- a/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestHLSL.h +++ b/Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestHLSL.h @@ -86,7 +86,7 @@ R"hlsl( [shader("closesthit")] void main(inout RTPayload payload, in BuiltInTriangleIntersectionAttributes attr) { - float3 barycentrics = float3(1 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y); + float3 barycentrics = float3(1.0 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y); payload.Color = float4(barycentrics, 1.0); } )hlsl"; @@ -147,7 +147,7 @@ R"hlsl( [shader("anyhit")] void main(inout RTPayload payload, in BuiltInTriangleIntersectionAttributes attr) { - float3 barycentrics = float3(1 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y); + float3 barycentrics = float3(1.0 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y); if (barycentrics.y > barycentrics.x) IgnoreHit(); else @@ -241,6 +241,101 @@ void main() )hlsl"; // clang-format on + +// clang-format off +const std::string RayTracingTest4_RG = RayTracingTest_Payload + +R"hlsl( +RaytracingAccelerationStructure g_TLAS : register(t0); +RWTexture2D<float4> g_ColorBuffer : register(u0); + +[shader("raygeneration")] +void main() +{ + const float2 uv = float2(DispatchRaysIndex().xy) / float2(DispatchRaysDimensions().xy - 1); + + RayDesc ray; + ray.Origin = float3(uv.x, 1.0 - uv.y, -1.0); + ray.Direction = float3(0.0, 0.0, 1.0); + ray.TMin = 0.01; + ray.TMax = 10.0; + + RTPayload payload = {float4(0, 0, 0, 0)}; + TraceRay(g_TLAS, // Acceleration Structure + RAY_FLAG_NONE, // Ray Flags + ~0, // Instance Inclusion Mask + 0, // Ray Contribution To Hit Group Index + 1, // Multiplier For Geometry Contribution To Hit Group Index + 0, // Miss Shader Index + ray, + payload); + + g_ColorBuffer[DispatchRaysIndex().xy] = payload.Color; +} +)hlsl"; + +const std::string RayTracingTest4_RM = RayTracingTest_Payload + +R"hlsl( +[shader("miss")] +void main(inout RTPayload payload) +{ + payload.Color = float4(0.0, 0.0, 0.2, 1.0); +} +)hlsl"; + +const std::string RayTracingTest4_Uniforms = RayTracingTest_Payload + +R"hlsl( +struct Vertex +{ + float4 Pos; + float4 Color1; + float4 Color2; +}; +StructuredBuffer<Vertex> g_Vertices : register(t1); // array size = 16 +StructuredBuffer<uint> g_PerInstance[2] : register(t2); // array size = 3 +StructuredBuffer<uint4> g_Primitives : register(t4); // array size = 9 + +// local root constants +struct LocalRootConst +{ + float4 Weight; +}; +//[[vk::shader_record_ext]] +//ConstantBuffer<LocalRootConst> g_LocalRoot : register(b0); +)hlsl"; + +const std::string RayTracingTest4_RCH1 = RayTracingTest4_Uniforms + +R"hlsl( +[shader("closesthit")] +void main(inout RTPayload payload, in BuiltInTriangleIntersectionAttributes attr) +{ + float3 barycentrics = float3(1.0 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y);// * g_LocalRoot.Weight.xyz; + uint primOffset = g_PerInstance[InstanceIndex()][GeometryIndex()]; + uint4 triFace = g_Primitives[primOffset + PrimitiveIndex()]; + Vertex v0 = g_Vertices[triFace.x]; + Vertex v1 = g_Vertices[triFace.y]; + Vertex v2 = g_Vertices[triFace.z]; + float4 col = v0.Color2 * barycentrics.x + v1.Color2 * barycentrics.y + v2.Color2 * barycentrics.z; + payload.Color = col; +} +)hlsl"; + +const std::string RayTracingTest4_RCH2 = RayTracingTest4_Uniforms + +R"hlsl( +[shader("closesthit")] +void main(inout RTPayload payload, in BuiltInTriangleIntersectionAttributes attr) +{ + float3 barycentrics = float3(1.0 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y);// * g_LocalRoot.Weight.xyz; + uint primOffset = g_PerInstance[InstanceIndex()][GeometryIndex()]; + uint4 triFace = g_Primitives[primOffset + PrimitiveIndex()]; + Vertex v0 = g_Vertices[triFace.x]; + Vertex v1 = g_Vertices[triFace.y]; + Vertex v2 = g_Vertices[triFace.z]; + float4 col = v0.Color1 * barycentrics.x + v1.Color1 * barycentrics.y + v2.Color1 * barycentrics.z; + payload.Color = col; +} +)hlsl"; +// clang-format on + } // namespace HLSL } // namespace diff --git a/Tests/DiligentCoreAPITest/include/RayTracingTestConstants.hpp b/Tests/DiligentCoreAPITest/include/RayTracingTestConstants.hpp new file mode 100644 index 00000000..99ab4bf0 --- /dev/null +++ b/Tests/DiligentCoreAPITest/include/RayTracingTestConstants.hpp @@ -0,0 +1,155 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "BasicMath.hpp" + +namespace Diligent +{ + +namespace TestingConstants +{ +// clang-format off + + namespace TriangleClosestHit + { + static const float3 Vertices[] = + { + float3{0.25f, 0.25f, 0.0f}, + float3{0.75f, 0.25f, 0.0f}, + float3{0.50f, 0.75f, 0.0f} + }; + } // namespace TriangleClosestHit + + namespace TriangleAnyHit + { + static const float3 Vertices[] = + { + float3{0.25f, 0.25f, 0.0f}, float3{0.75f, 0.25f, 0.0f}, float3{0.50f, 0.75f, 0.0f}, + float3{0.50f, 0.10f, 0.1f}, float3{0.90f, 0.90f, 0.1f}, float3{0.10f, 0.90f, 0.1f}, + float3{0.40f, 1.00f, 0.2f}, float3{0.20f, 0.40f, 0.2f}, float3{1.00f, 0.70f, 0.2f} + }; + } // namespace TriangleAnyHit + + namespace ProceduralIntersection + { + static const float3 Boxes[] = + { + float3{0.25f, 0.5f, 2.0f} - float3{1.0f, 1.0f, 1.0f}, + float3{0.25f, 0.5f, 2.0f} + float3{1.0f, 1.0f, 1.0f} + }; + } // namespace ProceduralIntersection + + namespace MultiGeometry + { + struct VertexType + { + float4 Pos; + float4 Color1; + float4 Color2; + + VertexType(float2 _Pos, float3 _Color1, float3 _Color2) : + Pos {_Pos.x, _Pos.y, 2.0f, 1.0f}, + Color1{_Color1.x, _Color1.y, _Color1.z, 1.0f}, + Color2{_Color2.x, _Color2.y, _Color2.z, 1.0f} + {} + }; + + static const VertexType Vertices[] = + { + // geometry 1 + VertexType{{0.10f, 0.10f}, {0.7f, 0.3f, 0.1f}, {0.2f, 0.9f, 0.4f}}, // 0 + VertexType{{0.17f, 0.30f}, {0.6f, 0.0f, 0.4f}, {0.2f, 0.5f, 0.8f}}, // 1 + VertexType{{0.10f, 0.31f}, {0.3f, 0.7f, 0.4f}, {0.9f, 0.2f, 0.6f}}, // 2 + VertexType{{0.22f, 0.45f}, {0.2f, 0.9f, 0.7f}, {0.1f, 0.7f, 0.1f}}, // 3 + // geometry 2 + VertexType{{0.27f, 0.10f}, {0.5f, 0.1f, 0.6f}, {0.3f, 0.1f, 0.5f}}, // 4 + VertexType{{0.40f, 0.30f}, {1.0f, 1.0f, 1.0f}, {0.3f, 1.0f, 0.7f}}, // 5 + VertexType{{0.26f, 0.30f}, {0.3f, 0.3f, 0.9f}, {1.0f, 0.0f, 0.3f}}, // 6 + VertexType{{0.40f, 0.47f}, {0.8f, 1.0f, 0.2f}, {1.0f, 0.7f, 0.0f}}, // 7 + VertexType{{0.54f, 0.30f}, {0.1f, 1.0f, 0.9f}, {0.0f, 1.0f, 0.6f}}, // 8 + VertexType{{0.53f, 0.10f}, {1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}}, // 9 + // geometry 3 + VertexType{{0.65f, 0.10f}, {0.3f, 0.6f, 0.8f}, {1.0f, 0.9f, 0.2f}}, // 10 + VertexType{{0.63f, 0.25f}, {0.9f, 1.0f, 0.2f}, {0.1f, 0.2f, 0.3f}}, // 11 + VertexType{{0.82f, 0.20f}, {0.4f, 0.5f, 0.0f}, {1.0f, 0.2f, 0.6f}}, // 12 + VertexType{{0.76f, 0.30f}, {1.0f, 0.0f, 0.0f}, {0.4f, 0.7f, 0.2f}}, // 13 + VertexType{{0.55f, 0.48f}, {0.5f, 0.1f, 0.2f}, {1.0f, 0.3f, 0.5f}}, // 14 + VertexType{{0.90f, 0.40f}, {0.8f, 0.2f, 1.0f}, {0.3f, 0.6f, 0.4f}}, // 15 + }; + static const uint Indices[] = + { + 0, 1, 2, 2, 1, 3, // geometry 1 + 4, 5, 6, 6, 7, 8, 8, 5, 9, // geometry 2 + 10, 12, 11, 11, 12, 13, 11, 13, 14, 13, 12, 15, // geometry 3 + }; + static const uint4 Primitives[] = + { + // geometry 1 + {Indices[ 0], Indices[ 1], Indices[ 2], 0}, // 0 + {Indices[ 3], Indices[ 4], Indices[ 5], 0}, // 1 + // geometry 2 + {Indices[ 6], Indices[ 7], Indices[ 8], 0}, // 2 + {Indices[ 9], Indices[10], Indices[11], 0}, // 3 + {Indices[12], Indices[13], Indices[14], 0}, // 4 + // geometry 3 + {Indices[15], Indices[16], Indices[17], 0}, // 5 + {Indices[18], Indices[19], Indices[20], 0}, // 6 + {Indices[21], Indices[22], Indices[23], 0}, // 7 + {Indices[24], Indices[25], Indices[26], 0} // 8 + }; + static const uint PrimitiveOffsets[] = + { + 0, 2, 5 + }; + + struct ShaderRecord + { + float4 Weight; + float4 Padding; + }; + static const ShaderRecord Weights[] = + { + ShaderRecord{{1.0f, 0.4f, 0.4f, 1.0f}, {}}, + ShaderRecord{{0.4f, 1.0f, 0.4f, 1.0f}, {}}, + ShaderRecord{{0.4f, 0.4f, 1.0f, 1.0f}, {}} + }; + static constexpr Uint32 ShaderRecordSize = sizeof(Weights[0]); + static constexpr Uint32 InstanceCount = 2; + + static_assert(_countof(Vertices) == 16, "Update array size in shaders"); + static_assert(_countof(PrimitiveOffsets) == 3, "Update array size in shaders"); + static_assert(_countof(Primitives) == 9, "Update array size in shaders"); + static_assert(_countof(Indices) % 3 == 0, "Invalid index count"); + static_assert(_countof(Indices) / 3 == _countof(Primitives), "Primitive count mismatch"); + + } // namespace MultiGeometry + +// clang-format on + +} // namespace TestingConstants + +} // namespace Diligent diff --git a/Tests/DiligentCoreAPITest/src/D3D12/RayTracingReferenceD3D12.cpp b/Tests/DiligentCoreAPITest/src/D3D12/RayTracingReferenceD3D12.cpp index 79eb6e96..cd709797 100644 --- a/Tests/DiligentCoreAPITest/src/D3D12/RayTracingReferenceD3D12.cpp +++ b/Tests/DiligentCoreAPITest/src/D3D12/RayTracingReferenceD3D12.cpp @@ -34,6 +34,7 @@ #include "BasicMath.hpp" #include "InlineShaders/RayTracingTestHLSL.h" +#include "RayTracingTestConstants.hpp" namespace Diligent { @@ -46,17 +47,21 @@ namespace struct RTContext { - ID3D12Device5* pDevice = nullptr; + struct AccelStruct + { + CComPtr<ID3D12Resource> pAS; + UINT64 BuildScratchSize = 0; + UINT64 UpdateScratchSize = 0; + }; + + CComPtr<ID3D12Device5> pDevice; CComPtr<ID3D12GraphicsCommandList4> pCmdList; CComPtr<ID3D12StateObject> pRayTracingSO; CComPtr<ID3D12StateObjectProperties> pStateObjectProperties; - CComPtr<ID3D12RootSignature> pRootSignature; - CComPtr<ID3D12Resource> pBLAS; - UINT64 BLASBuildScratchSize = 0; - UINT64 BLASUpdateScratchSize = 0; - CComPtr<ID3D12Resource> pTLAS; - UINT64 TLASBuildScratchSize = 0; - UINT64 TLASUpdateScratchSize = 0; + CComPtr<ID3D12RootSignature> pGlobalRootSignature; + CComPtr<ID3D12RootSignature> pLocalRootSignature; + AccelStruct BLAS; + AccelStruct TLAS; CComPtr<ID3D12Resource> pScratchBuffer; CComPtr<ID3D12Resource> pVertexBuffer; CComPtr<ID3D12Resource> pIndexBuffer; @@ -96,8 +101,8 @@ struct RTContext static constexpr UINT DescriptorHeapSize = 16; }; -template <typename PSOCtorType> -void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& PSOCtor) +template <typename PSOCtorType, typename RootSigCtorType> +void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, Uint32 ShaderRecordSize, PSOCtorType&& PSOCtor, RootSigCtorType&& RootSigCtor) { auto* pEnv = TestingEnvironmentD3D12::GetInstance(); auto* pTestingSwapChainD3D12 = ValidatedCast<TestingSwapChainD3D12>(pSwapChain); @@ -110,38 +115,90 @@ void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& P hr = pEnv->CreateGraphicsCommandList()->QueryInterface(IID_PPV_ARGS(&Ctx.pCmdList)); ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to get ID3D12GraphicsCommandList4"; - // create root signature + // create descriptor heap + { + D3D12_DESCRIPTOR_HEAP_DESC Desc = {}; + + Desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + Desc.NumDescriptors = Ctx.DescriptorHeapSize; + Desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + Desc.NodeMask = 0; + + hr = Ctx.pDevice->CreateDescriptorHeap(&Desc, IID_PPV_ARGS(&Ctx.pDescHeap)); + ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create descriptor heap"; + + Ctx.DescHeapCount = 0; + Ctx.DescHandleSize = Ctx.pDevice->GetDescriptorHandleIncrementSize(Desc.Type); + + D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {}; + + UAVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + + D3D12_CPU_DESCRIPTOR_HANDLE UAVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart(); + ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize); + ASSERT_TRUE(Ctx.DescHeapCount == 0); + UAVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++; + Ctx.pDevice->CreateUnorderedAccessView(pTestingSwapChainD3D12->GetD3D12RenderTarget(), nullptr, &UAVDesc, UAVHandle); + } + + // create global root signature { - D3D12_ROOT_SIGNATURE_DESC RootSignatureDesc = {}; - D3D12_DESCRIPTOR_RANGE DescriptorRanges[2] = {}; - D3D12_ROOT_PARAMETER Params[1] = {}; - - DescriptorRanges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; - DescriptorRanges[0].NumDescriptors = 1; - DescriptorRanges[0].BaseShaderRegister = 0; - DescriptorRanges[0].RegisterSpace = 0; - DescriptorRanges[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - - DescriptorRanges[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - DescriptorRanges[1].NumDescriptors = 1; - DescriptorRanges[1].BaseShaderRegister = 0; - DescriptorRanges[1].RegisterSpace = 0; - DescriptorRanges[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - - Params[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - Params[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - Params[0].DescriptorTable.NumDescriptorRanges = _countof(DescriptorRanges); - Params[0].DescriptorTable.pDescriptorRanges = DescriptorRanges; + D3D12_ROOT_SIGNATURE_DESC RootSignatureDesc = {}; + D3D12_ROOT_PARAMETER Param = {}; + D3D12_DESCRIPTOR_RANGE Range = {}; + std::vector<D3D12_DESCRIPTOR_RANGE> DescriptorRanges; + + RootSigCtor(DescriptorRanges); + + Range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + Range.NumDescriptors = 1; + Range.OffsetInDescriptorsFromTableStart = 0; + DescriptorRanges.push_back(Range); // g_TLAS + + Range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + Range.NumDescriptors = 1; + Range.OffsetInDescriptorsFromTableStart = 1; + DescriptorRanges.push_back(Range); // g_ColorBuffer + + Param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + Param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + Param.DescriptorTable.NumDescriptorRanges = static_cast<Uint32>(DescriptorRanges.size()); + Param.DescriptorTable.pDescriptorRanges = DescriptorRanges.data(); RootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; - RootSignatureDesc.NumParameters = _countof(Params); - RootSignatureDesc.pParameters = Params; + RootSignatureDesc.NumParameters = 1; + RootSignatureDesc.pParameters = &Param; + + CComPtr<ID3DBlob> signature; + hr = D3D12SerializeRootSignature(&RootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, nullptr); + ASSERT_HRESULT_SUCCEEDED(hr); + + hr = Ctx.pDevice->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&Ctx.pGlobalRootSignature)); + ASSERT_HRESULT_SUCCEEDED(hr); + } + + // create local root signature + if (ShaderRecordSize > 0) + { + D3D12_ROOT_SIGNATURE_DESC RootSignatureDesc = {}; + D3D12_ROOT_PARAMETER Param = {}; + + Param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + Param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + Param.Constants.Num32BitValues = ShaderRecordSize / 4; + Param.Constants.RegisterSpace = 1; + Param.Constants.ShaderRegister = 0; + + RootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE; + RootSignatureDesc.NumParameters = 1; + RootSignatureDesc.pParameters = &Param; CComPtr<ID3DBlob> signature; hr = D3D12SerializeRootSignature(&RootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, nullptr); ASSERT_HRESULT_SUCCEEDED(hr); - hr = Ctx.pDevice->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&Ctx.pRootSignature)); + hr = Ctx.pDevice->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&Ctx.pLocalRootSignature)); ASSERT_HRESULT_SUCCEEDED(hr); } @@ -165,9 +222,14 @@ void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& P Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG, &ShaderConfig}); D3D12_GLOBAL_ROOT_SIGNATURE GlobalRoot; - GlobalRoot.pGlobalRootSignature = Ctx.pRootSignature; + GlobalRoot.pGlobalRootSignature = Ctx.pGlobalRootSignature; Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &GlobalRoot}); + D3D12_LOCAL_ROOT_SIGNATURE LocalRoot; + LocalRoot.pLocalRootSignature = Ctx.pLocalRootSignature; + if (Ctx.pLocalRootSignature) + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &LocalRoot}); + D3D12_STATE_OBJECT_DESC RTPipelineDesc; RTPipelineDesc.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE; RTPipelineDesc.NumSubobjects = static_cast<UINT>(Subobjects.size()); @@ -179,32 +241,12 @@ void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& P hr = Ctx.pRayTracingSO->QueryInterface(IID_PPV_ARGS(&Ctx.pStateObjectProperties)); ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to get state object properties"; } +} - // create descriptor heap - { - D3D12_DESCRIPTOR_HEAP_DESC Desc = {}; - - Desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - Desc.NumDescriptors = Ctx.DescriptorHeapSize; - Desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - Desc.NodeMask = 0; - - hr = Ctx.pDevice->CreateDescriptorHeap(&Desc, IID_PPV_ARGS(&Ctx.pDescHeap)); - ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create descriptor heap"; - - Ctx.DescHeapCount = 0; - Ctx.DescHandleSize = Ctx.pDevice->GetDescriptorHandleIncrementSize(Desc.Type); - - D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {}; - - UAVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; - - D3D12_CPU_DESCRIPTOR_HANDLE UAVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart(); - ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize); - UAVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++; - Ctx.pDevice->CreateUnorderedAccessView(pTestingSwapChainD3D12->GetD3D12RenderTarget(), nullptr, &UAVDesc, UAVHandle); - } +template <typename PSOCtorType> +void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, Uint32 ShaderRecordSize, PSOCtorType&& PSOCtor) +{ + InitializeRTContext(Ctx, pSwapChain, ShaderRecordSize, PSOCtor, [](std::vector<D3D12_DESCRIPTOR_RANGE>&) {}); } void CreateBLAS(RTContext& Ctx, D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& BottomLevelInputs) @@ -240,11 +282,11 @@ void CreateBLAS(RTContext& Ctx, D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_IN auto hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, &ASDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, nullptr, - IID_PPV_ARGS(&Ctx.pBLAS)); + IID_PPV_ARGS(&Ctx.BLAS.pAS)); ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create acceleration structure"; - Ctx.BLASBuildScratchSize = BottomLevelPrebuildInfo.ScratchDataSizeInBytes; - Ctx.BLASUpdateScratchSize = BottomLevelPrebuildInfo.UpdateScratchDataSizeInBytes; + Ctx.BLAS.BuildScratchSize = BottomLevelPrebuildInfo.ScratchDataSizeInBytes; + Ctx.BLAS.UpdateScratchSize = BottomLevelPrebuildInfo.UpdateScratchDataSizeInBytes; } void CreateTLAS(RTContext& Ctx, D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& TopLevelInputs) @@ -280,26 +322,27 @@ void CreateTLAS(RTContext& Ctx, D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_IN auto hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, &ASDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, nullptr, - IID_PPV_ARGS(&Ctx.pTLAS)); + IID_PPV_ARGS(&Ctx.TLAS.pAS)); ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create acceleration structure"; - Ctx.TLASBuildScratchSize = TopLevelPrebuildInfo.ScratchDataSizeInBytes; - Ctx.TLASUpdateScratchSize = TopLevelPrebuildInfo.UpdateScratchDataSizeInBytes; + Ctx.TLAS.BuildScratchSize = TopLevelPrebuildInfo.ScratchDataSizeInBytes; + Ctx.TLAS.UpdateScratchSize = TopLevelPrebuildInfo.UpdateScratchDataSizeInBytes; D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {}; SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE; SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; SRVDesc.Format = DXGI_FORMAT_UNKNOWN; - SRVDesc.RaytracingAccelerationStructure.Location = Ctx.pTLAS->GetGPUVirtualAddress(); + SRVDesc.RaytracingAccelerationStructure.Location = Ctx.TLAS.pAS->GetGPUVirtualAddress(); D3D12_CPU_DESCRIPTOR_HANDLE DescHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart(); ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize); + ASSERT_TRUE(Ctx.DescHeapCount == 1); DescHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++; Ctx.pDevice->CreateShaderResourceView(nullptr, &SRVDesc, DescHandle); } -void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 InstanceCount, Uint32 NumMissShaders, Uint32 NumHitShaders) +void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 InstanceCount, Uint32 NumMissShaders, Uint32 NumHitShaders, Uint32 ShaderRecordSize = 0, size_t UploadSize = 0) { D3D12_RESOURCE_DESC BuffDesc = {}; BuffDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; @@ -320,17 +363,15 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan HeapProps.CreationNodeMask = 1; HeapProps.VisibleNodeMask = 1; - BuffDesc.Width = std::max(Ctx.BLASBuildScratchSize, Ctx.BLASUpdateScratchSize); - BuffDesc.Width = std::max(BuffDesc.Width, Ctx.TLASBuildScratchSize); - BuffDesc.Width = std::max(BuffDesc.Width, Ctx.TLASUpdateScratchSize); + BuffDesc.Width = std::max(Ctx.BLAS.BuildScratchSize, Ctx.BLAS.UpdateScratchSize); + BuffDesc.Width = std::max(BuffDesc.Width, Ctx.TLAS.BuildScratchSize); + BuffDesc.Width = std::max(BuffDesc.Width, Ctx.TLAS.UpdateScratchSize); auto hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, &BuffDesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, IID_PPV_ARGS(&Ctx.pScratchBuffer)); ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create buffer"; - size_t UploadSize = 0; - if (VBSize > 0) { BuffDesc.Width = VBSize; @@ -366,12 +407,12 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan // SBT { - const UINT64 handleSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES; + const UINT64 RecordSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES + ShaderRecordSize; const UINT64 align = D3D12_RAYTRACING_SHADER_TABLE_BYTE_ALIGNMENT; - BuffDesc.Width = Align(handleSize, align); - BuffDesc.Width = Align(BuffDesc.Width + NumMissShaders * handleSize, align); - BuffDesc.Width = Align(BuffDesc.Width + NumHitShaders * handleSize, align); + BuffDesc.Width = Align(RecordSize, align); + BuffDesc.Width = Align(BuffDesc.Width + NumMissShaders * RecordSize, align); + BuffDesc.Width = Align(BuffDesc.Width + NumHitShaders * RecordSize, align); hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, &BuffDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, @@ -420,7 +461,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain) const auto& SCDesc = pSwapChain->GetDesc(); RTContext Ctx = {}; - InitializeRTContext(Ctx, pSwapChain, + InitializeRTContext(Ctx, pSwapChain, 0, [pEnv](auto& Subobjects, auto& ExportDescs, auto& LibDescs, auto& HitGroups, auto& ShadersByteCode) { ShadersByteCode.resize(3); ExportDescs.resize(ShadersByteCode.size()); @@ -487,12 +528,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain) D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& TopLevelInputs = TLASDesc.Inputs; D3D12_RAYTRACING_INSTANCE_DESC Instance = {}; - const float3 Vertices[] = // - { - float3{0.25f, 0.25f, 0.0f}, - float3{0.75f, 0.25f, 0.0f}, - float3{0.50f, 0.75f, 0.0f} // - }; + const auto& Vertices = TestingConstants::TriangleClosestHit::Vertices; Geometry.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES; Geometry.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE; @@ -518,7 +554,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain) Instance.InstanceContributionToHitGroupIndex = 0; Instance.InstanceMask = 0xFF; Instance.Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE; - Instance.AccelerationStructure = Ctx.pBLAS->GetGPUVirtualAddress(); + Instance.AccelerationStructure = Ctx.BLAS.pAS->GetGPUVirtualAddress(); Instance.Transform[0][0] = 1.0f; Instance.Transform[1][1] = 1.0f; Instance.Transform[2][2] = 1.0f; @@ -557,7 +593,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain) Geometry.Triangles.VertexBuffer.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress(); - BLASDesc.DestAccelerationStructureData = Ctx.pBLAS->GetGPUVirtualAddress(); + BLASDesc.DestAccelerationStructureData = Ctx.BLAS.pAS->GetGPUVirtualAddress(); BLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress(); BLASDesc.SourceAccelerationStructureData = 0; @@ -579,7 +615,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain) TopLevelInputs.InstanceDescs = Ctx.pInstanceBuffer->GetGPUVirtualAddress(); - TLASDesc.DestAccelerationStructureData = Ctx.pTLAS->GetGPUVirtualAddress(); + TLASDesc.DestAccelerationStructureData = Ctx.TLAS.pAS->GetGPUVirtualAddress(); TLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress(); TLASDesc.SourceAccelerationStructureData = 0; @@ -598,7 +634,7 @@ void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain) ID3D12DescriptorHeap* DescHeaps[] = {Ctx.pDescHeap}; Ctx.pCmdList->SetPipelineState1(Ctx.pRayTracingSO); - Ctx.pCmdList->SetComputeRootSignature(Ctx.pRootSignature); + Ctx.pCmdList->SetComputeRootSignature(Ctx.pGlobalRootSignature); Ctx.pCmdList->SetDescriptorHeaps(_countof(DescHeaps), &DescHeaps[0]); Ctx.pCmdList->SetComputeRootDescriptorTable(0, DescHeaps[0]->GetGPUDescriptorHandleForHeapStart()); @@ -657,7 +693,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain) const auto& SCDesc = pSwapChain->GetDesc(); RTContext Ctx = {}; - InitializeRTContext(Ctx, pSwapChain, + InitializeRTContext(Ctx, pSwapChain, 0, [pEnv](auto& Subobjects, auto& ExportDescs, auto& LibDescs, auto& HitGroups, auto& ShadersByteCode) { ShadersByteCode.resize(4); ExportDescs.resize(ShadersByteCode.size()); @@ -738,12 +774,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain) D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& TopLevelInputs = TLASDesc.Inputs; D3D12_RAYTRACING_INSTANCE_DESC Instance = {}; - const float3 Vertices[] = // - { - float3{0.25f, 0.25f, 0.0f}, float3{0.75f, 0.25f, 0.0f}, float3{0.50f, 0.75f, 0.0f}, - float3{0.50f, 0.10f, 0.1f}, float3{0.90f, 0.90f, 0.1f}, float3{0.10f, 0.90f, 0.1f}, - float3{0.40f, 1.00f, 0.2f}, float3{0.20f, 0.40f, 0.2f}, float3{1.00f, 0.70f, 0.2f} // - }; + const auto& Vertices = TestingConstants::TriangleAnyHit::Vertices; Geometry.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES; Geometry.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_NONE; @@ -769,7 +800,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain) Instance.InstanceContributionToHitGroupIndex = 0; Instance.InstanceMask = 0xFF; Instance.Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE; - Instance.AccelerationStructure = Ctx.pBLAS->GetGPUVirtualAddress(); + Instance.AccelerationStructure = Ctx.BLAS.pAS->GetGPUVirtualAddress(); Instance.Transform[0][0] = 1.0f; Instance.Transform[1][1] = 1.0f; Instance.Transform[2][2] = 1.0f; @@ -808,7 +839,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain) Geometry.Triangles.VertexBuffer.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress(); - BLASDesc.DestAccelerationStructureData = Ctx.pBLAS->GetGPUVirtualAddress(); + BLASDesc.DestAccelerationStructureData = Ctx.BLAS.pAS->GetGPUVirtualAddress(); BLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress(); BLASDesc.SourceAccelerationStructureData = 0; @@ -830,7 +861,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain) TopLevelInputs.InstanceDescs = Ctx.pInstanceBuffer->GetGPUVirtualAddress(); - TLASDesc.DestAccelerationStructureData = Ctx.pTLAS->GetGPUVirtualAddress(); + TLASDesc.DestAccelerationStructureData = Ctx.TLAS.pAS->GetGPUVirtualAddress(); TLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress(); TLASDesc.SourceAccelerationStructureData = 0; @@ -849,7 +880,7 @@ void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain) ID3D12DescriptorHeap* DescHeaps[] = {Ctx.pDescHeap}; Ctx.pCmdList->SetPipelineState1(Ctx.pRayTracingSO); - Ctx.pCmdList->SetComputeRootSignature(Ctx.pRootSignature); + Ctx.pCmdList->SetComputeRootSignature(Ctx.pGlobalRootSignature); Ctx.pCmdList->SetDescriptorHeaps(_countof(DescHeaps), &DescHeaps[0]); Ctx.pCmdList->SetComputeRootDescriptorTable(0, DescHeaps[0]->GetGPUDescriptorHandleForHeapStart()); @@ -908,7 +939,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain) const auto& SCDesc = pSwapChain->GetDesc(); RTContext Ctx = {}; - InitializeRTContext(Ctx, pSwapChain, + InitializeRTContext(Ctx, pSwapChain, 0, [pEnv](auto& Subobjects, auto& ExportDescs, auto& LibDescs, auto& HitGroups, auto& ShadersByteCode) { ShadersByteCode.resize(4); ExportDescs.resize(ShadersByteCode.size()); @@ -989,11 +1020,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain) D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& TopLevelInputs = TLASDesc.Inputs; D3D12_RAYTRACING_INSTANCE_DESC Instance = {}; - const float3 Boxes[] = // - { - float3{0.25f, 0.5f, 2.0f} - float3{1.0f, 1.0f, 1.0f}, - float3{0.25f, 0.5f, 2.0f} + float3{1.0f, 1.0f, 1.0f} // - }; + const auto& Boxes = TestingConstants::ProceduralIntersection::Boxes; Geometry.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_PROCEDURAL_PRIMITIVE_AABBS; Geometry.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE; @@ -1014,7 +1041,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain) Instance.InstanceContributionToHitGroupIndex = 0; Instance.InstanceMask = 0xFF; Instance.Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE; - Instance.AccelerationStructure = Ctx.pBLAS->GetGPUVirtualAddress(); + Instance.AccelerationStructure = Ctx.BLAS.pAS->GetGPUVirtualAddress(); Instance.Transform[0][0] = 1.0f; Instance.Transform[1][1] = 1.0f; Instance.Transform[2][2] = 1.0f; @@ -1053,7 +1080,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain) Geometry.AABBs.AABBs.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress(); - BLASDesc.DestAccelerationStructureData = Ctx.pBLAS->GetGPUVirtualAddress(); + BLASDesc.DestAccelerationStructureData = Ctx.BLAS.pAS->GetGPUVirtualAddress(); BLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress(); BLASDesc.SourceAccelerationStructureData = 0; @@ -1075,7 +1102,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain) TopLevelInputs.InstanceDescs = Ctx.pInstanceBuffer->GetGPUVirtualAddress(); - TLASDesc.DestAccelerationStructureData = Ctx.pTLAS->GetGPUVirtualAddress(); + TLASDesc.DestAccelerationStructureData = Ctx.TLAS.pAS->GetGPUVirtualAddress(); TLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress(); TLASDesc.SourceAccelerationStructureData = 0; @@ -1094,7 +1121,7 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain) ID3D12DescriptorHeap* DescHeaps[] = {Ctx.pDescHeap}; Ctx.pCmdList->SetPipelineState1(Ctx.pRayTracingSO); - Ctx.pCmdList->SetComputeRootSignature(Ctx.pRootSignature); + Ctx.pCmdList->SetComputeRootSignature(Ctx.pGlobalRootSignature); Ctx.pCmdList->SetDescriptorHeaps(_countof(DescHeaps), &DescHeaps[0]); Ctx.pCmdList->SetComputeRootDescriptorTable(0, DescHeaps[0]->GetGPUDescriptorHandleForHeapStart()); @@ -1144,6 +1171,440 @@ void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain) pEnv->ExecuteCommandList(Ctx.pCmdList, true); } + +void RayTracingMultiGeometryReferenceD3D12(ISwapChain* pSwapChain) +{ + static constexpr Uint32 InstanceCount = TestingConstants::MultiGeometry::InstanceCount; + static constexpr Uint32 GeometryCount = 3; + static constexpr Uint32 HitGroupCount = InstanceCount * GeometryCount; + + auto* pEnv = TestingEnvironmentD3D12::GetInstance(); + auto* pTestingSwapChainD3D12 = ValidatedCast<TestingSwapChainD3D12>(pSwapChain); + + const auto& SCDesc = pSwapChain->GetDesc(); + + RTContext Ctx = {}; + InitializeRTContext( + Ctx, pSwapChain, + TestingConstants::MultiGeometry::ShaderRecordSize, + [pEnv](auto& Subobjects, auto& ExportDescs, auto& LibDescs, auto& HitGroups, auto& ShadersByteCode) { + ShadersByteCode.resize(4); + ExportDescs.resize(ShadersByteCode.size()); + LibDescs.resize(ShadersByteCode.size()); + HitGroups.resize(2); + + auto hr = pEnv->CompileDXILShader(HLSL::RayTracingTest4_RG, L"main", nullptr, 0, L"lib_6_5", &ShadersByteCode[0]); + ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to compile ray gen shader"; + + hr = pEnv->CompileDXILShader(HLSL::RayTracingTest4_RM, L"main", nullptr, 0, L"lib_6_5", &ShadersByteCode[1]); + ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to compile ray miss shader"; + + hr = pEnv->CompileDXILShader(HLSL::RayTracingTest4_RCH1, L"main", nullptr, 0, L"lib_6_5", &ShadersByteCode[2]); + ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to compile ray closest hit shader"; + + hr = pEnv->CompileDXILShader(HLSL::RayTracingTest4_RCH2, L"main", nullptr, 0, L"lib_6_5", &ShadersByteCode[3]); + ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to compile ray closest hit shader"; + + D3D12_EXPORT_DESC& RGExportDesc = ExportDescs[0]; + D3D12_DXIL_LIBRARY_DESC& RGLibDesc = LibDescs[0]; + RGExportDesc.Flags = D3D12_EXPORT_FLAG_NONE; + RGExportDesc.ExportToRename = L"main"; // shader entry name + RGExportDesc.Name = L"Main"; + RGLibDesc.DXILLibrary.BytecodeLength = ShadersByteCode[0]->GetBufferSize(); + RGLibDesc.DXILLibrary.pShaderBytecode = ShadersByteCode[0]->GetBufferPointer(); + RGLibDesc.NumExports = 1; + RGLibDesc.pExports = &RGExportDesc; + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &RGLibDesc}); + + D3D12_EXPORT_DESC& RMExportDesc = ExportDescs[1]; + D3D12_DXIL_LIBRARY_DESC& RMLibDesc = LibDescs[1]; + RMExportDesc.Flags = D3D12_EXPORT_FLAG_NONE; + RMExportDesc.ExportToRename = L"main"; // shader entry name + RMExportDesc.Name = L"Miss"; + RMLibDesc.DXILLibrary.BytecodeLength = ShadersByteCode[1]->GetBufferSize(); + RMLibDesc.DXILLibrary.pShaderBytecode = ShadersByteCode[1]->GetBufferPointer(); + RMLibDesc.NumExports = 1; + RMLibDesc.pExports = &RMExportDesc; + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &RMLibDesc}); + + D3D12_EXPORT_DESC& RCH1ExportDesc = ExportDescs[2]; + D3D12_DXIL_LIBRARY_DESC& RCH1LibDesc = LibDescs[2]; + RCH1ExportDesc.Flags = D3D12_EXPORT_FLAG_NONE; + RCH1ExportDesc.ExportToRename = L"main"; // shader entry name + RCH1ExportDesc.Name = L"ClosestHitShader1"; + RCH1LibDesc.DXILLibrary.BytecodeLength = ShadersByteCode[2]->GetBufferSize(); + RCH1LibDesc.DXILLibrary.pShaderBytecode = ShadersByteCode[2]->GetBufferPointer(); + RCH1LibDesc.NumExports = 1; + RCH1LibDesc.pExports = &RCH1ExportDesc; + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &RCH1LibDesc}); + + D3D12_EXPORT_DESC& RCH2ExportDesc = ExportDescs[3]; + D3D12_DXIL_LIBRARY_DESC& RCH2LibDesc = LibDescs[3]; + RCH2ExportDesc.Flags = D3D12_EXPORT_FLAG_NONE; + RCH2ExportDesc.ExportToRename = L"main"; // shader entry name + RCH2ExportDesc.Name = L"ClosestHitShader2"; + RCH2LibDesc.DXILLibrary.BytecodeLength = ShadersByteCode[3]->GetBufferSize(); + RCH2LibDesc.DXILLibrary.pShaderBytecode = ShadersByteCode[3]->GetBufferPointer(); + RCH2LibDesc.NumExports = 1; + RCH2LibDesc.pExports = &RCH2ExportDesc; + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &RCH2LibDesc}); + + D3D12_HIT_GROUP_DESC& HitGroup1Desc = HitGroups[0]; + HitGroup1Desc.HitGroupExport = L"HitGroup1"; + HitGroup1Desc.Type = D3D12_HIT_GROUP_TYPE_TRIANGLES; + HitGroup1Desc.ClosestHitShaderImport = L"ClosestHitShader1"; + HitGroup1Desc.AnyHitShaderImport = nullptr; + HitGroup1Desc.IntersectionShaderImport = nullptr; + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &HitGroup1Desc}); + + D3D12_HIT_GROUP_DESC& HitGroup2Desc = HitGroups[1]; + HitGroup2Desc.HitGroupExport = L"HitGroup2"; + HitGroup2Desc.Type = D3D12_HIT_GROUP_TYPE_TRIANGLES; + HitGroup2Desc.ClosestHitShaderImport = L"ClosestHitShader2"; + HitGroup2Desc.AnyHitShaderImport = nullptr; + HitGroup2Desc.IntersectionShaderImport = nullptr; + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &HitGroup2Desc}); + }, + [](std::vector<D3D12_DESCRIPTOR_RANGE>& DescriptorRanges) { + D3D12_DESCRIPTOR_RANGE Range = {}; + Range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + Range.NumDescriptors = 1; + + Range.BaseShaderRegister = 1; + Range.OffsetInDescriptorsFromTableStart = 2; + DescriptorRanges.push_back(Range); // g_Vertices + + Range.BaseShaderRegister = 4; + Range.OffsetInDescriptorsFromTableStart = 3; + DescriptorRanges.push_back(Range); // g_Primitives + + Range.BaseShaderRegister = 2; + Range.NumDescriptors = 2; + Range.OffsetInDescriptorsFromTableStart = 4; + DescriptorRanges.push_back(Range); // g_PerInstance[2] + }); + + const auto& PrimitiveOffsets = TestingConstants::MultiGeometry::PrimitiveOffsets; + const auto& Primitives = TestingConstants::MultiGeometry::Primitives; + const auto& Vertices = TestingConstants::MultiGeometry::Vertices; + + // create acceleration structurea + { + const auto& Indices = TestingConstants::MultiGeometry::Indices; + + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC BLASDesc = {}; + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& BottomLevelInputs = BLASDesc.Inputs; + D3D12_RAYTRACING_GEOMETRY_DESC Geometries[3] = {}; + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC TLASDesc = {}; + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& TopLevelInputs = TLASDesc.Inputs; + D3D12_RAYTRACING_INSTANCE_DESC Instances[2] = {}; + + static_assert(GeometryCount == _countof(Geometries), "size mismatch"); + static_assert(InstanceCount == _countof(Instances), "size mismatch"); + + Geometries[0].Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES; + Geometries[0].Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE; + Geometries[0].Triangles.VertexBuffer.StartAddress = 0; + Geometries[0].Triangles.VertexBuffer.StrideInBytes = sizeof(Vertices[0]); + Geometries[0].Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT; + Geometries[0].Triangles.VertexCount = _countof(Vertices); + Geometries[0].Triangles.IndexCount = PrimitiveOffsets[1] * 3; + Geometries[0].Triangles.IndexFormat = DXGI_FORMAT_R32_UINT; + Geometries[0].Triangles.IndexBuffer = 0; + Geometries[0].Triangles.Transform3x4 = 0; + + Geometries[1].Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES; + Geometries[1].Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE; + Geometries[1].Triangles.VertexBuffer.StartAddress = 0; + Geometries[1].Triangles.VertexBuffer.StrideInBytes = sizeof(Vertices[0]); + Geometries[1].Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT; + Geometries[1].Triangles.VertexCount = _countof(Vertices); + Geometries[1].Triangles.IndexCount = (PrimitiveOffsets[2] - PrimitiveOffsets[1]) * 3; + Geometries[1].Triangles.IndexFormat = DXGI_FORMAT_R32_UINT; + Geometries[1].Triangles.IndexBuffer = 0; + Geometries[1].Triangles.Transform3x4 = 0; + + Geometries[2].Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES; + Geometries[2].Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE; + Geometries[2].Triangles.VertexBuffer.StartAddress = 0; + Geometries[2].Triangles.VertexBuffer.StrideInBytes = sizeof(Vertices[0]); + Geometries[2].Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT; + Geometries[2].Triangles.VertexCount = _countof(Vertices); + Geometries[2].Triangles.IndexCount = (_countof(Primitives) - PrimitiveOffsets[2]) * 3; + Geometries[2].Triangles.IndexFormat = DXGI_FORMAT_R32_UINT; + Geometries[2].Triangles.IndexBuffer = 0; + Geometries[2].Triangles.Transform3x4 = 0; + + BottomLevelInputs.pGeometryDescs = Geometries; + BottomLevelInputs.NumDescs = _countof(Geometries); + + TopLevelInputs.NumDescs = _countof(Instances); + + CreateBLAS(Ctx, BottomLevelInputs); + CreateTLAS(Ctx, TopLevelInputs); + CreateRTBuffers(Ctx, sizeof(Vertices), sizeof(Indices), InstanceCount, 1, HitGroupCount, + TestingConstants::MultiGeometry::ShaderRecordSize, + sizeof(PrimitiveOffsets) + sizeof(Primitives)); + + Instances[0].InstanceID = 0; + Instances[0].InstanceContributionToHitGroupIndex = 0; + Instances[0].InstanceMask = 0xFF; + Instances[0].Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE; + Instances[0].AccelerationStructure = Ctx.BLAS.pAS->GetGPUVirtualAddress(); + Instances[0].Transform[0][0] = 1.0f; + Instances[0].Transform[1][1] = 1.0f; + Instances[0].Transform[2][2] = 1.0f; + + Instances[1].InstanceID = 0; + Instances[1].InstanceContributionToHitGroupIndex = HitGroupCount / 2; + Instances[1].InstanceMask = 0xFF; + Instances[1].Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE; + Instances[1].AccelerationStructure = Ctx.BLAS.pAS->GetGPUVirtualAddress(); + Instances[1].Transform[0][0] = 1.0f; + Instances[1].Transform[1][1] = 1.0f; + Instances[1].Transform[2][2] = 1.0f; + Instances[1].Transform[0][3] = 0.1f; + Instances[1].Transform[1][3] = 0.5f; + Instances[1].Transform[2][3] = 0.0f; + + UpdateBuffer(Ctx, Ctx.pVertexBuffer, 0, Vertices, sizeof(Vertices)); + UpdateBuffer(Ctx, Ctx.pIndexBuffer, 0, Indices, sizeof(Indices)); + UpdateBuffer(Ctx, Ctx.pInstanceBuffer, 0, Instances, sizeof(Instances)); + + // vertex & instance buffer barrier + { + std::vector<D3D12_RESOURCE_BARRIER> Barriers; + D3D12_RESOURCE_BARRIER Barrier; + + Barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + Barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + Barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + Barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + Barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + + if (Ctx.pVertexBuffer) + { + Barrier.Transition.pResource = Ctx.pVertexBuffer; + Barriers.push_back(Barrier); + } + if (Ctx.pIndexBuffer) + { + Barrier.Transition.pResource = Ctx.pIndexBuffer; + Barriers.push_back(Barrier); + } + if (Ctx.pInstanceBuffer) + { + Barrier.Transition.pResource = Ctx.pInstanceBuffer; + Barriers.push_back(Barrier); + } + Ctx.pCmdList->ResourceBarrier(static_cast<UINT>(Barriers.size()), Barriers.data()); + } + + Geometries[0].Triangles.VertexBuffer.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress(); + Geometries[1].Triangles.VertexBuffer.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress(); + Geometries[2].Triangles.VertexBuffer.StartAddress = Ctx.pVertexBuffer->GetGPUVirtualAddress(); + + Geometries[0].Triangles.IndexBuffer = Ctx.pIndexBuffer->GetGPUVirtualAddress() + PrimitiveOffsets[0] * sizeof(uint) * 3; + Geometries[1].Triangles.IndexBuffer = Ctx.pIndexBuffer->GetGPUVirtualAddress() + PrimitiveOffsets[1] * sizeof(uint) * 3; + Geometries[2].Triangles.IndexBuffer = Ctx.pIndexBuffer->GetGPUVirtualAddress() + PrimitiveOffsets[2] * sizeof(uint) * 3; + + BLASDesc.DestAccelerationStructureData = Ctx.BLAS.pAS->GetGPUVirtualAddress(); + BLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress(); + BLASDesc.SourceAccelerationStructureData = 0; + + ASSERT_TRUE(BLASDesc.DestAccelerationStructureData != 0); + ASSERT_TRUE(BLASDesc.ScratchAccelerationStructureData != 0); + + Ctx.pCmdList->BuildRaytracingAccelerationStructure(&BLASDesc, 0, nullptr); + + // UAV barrier for scratch buffer + { + D3D12_RESOURCE_BARRIER Barrier; + Barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + Barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + Barrier.UAV.pResource = Ctx.pScratchBuffer; + + Ctx.pCmdList->ResourceBarrier(1, &Barrier); + } + + TopLevelInputs.InstanceDescs = Ctx.pInstanceBuffer->GetGPUVirtualAddress(); + + TLASDesc.DestAccelerationStructureData = Ctx.TLAS.pAS->GetGPUVirtualAddress(); + TLASDesc.ScratchAccelerationStructureData = Ctx.pScratchBuffer->GetGPUVirtualAddress(); + TLASDesc.SourceAccelerationStructureData = 0; + + ASSERT_TRUE(TLASDesc.DestAccelerationStructureData != 0); + ASSERT_TRUE(TLASDesc.ScratchAccelerationStructureData != 0); + + Ctx.pCmdList->BuildRaytracingAccelerationStructure(&TLASDesc, 0, nullptr); + } + + // update descriptors + CComPtr<ID3D12Resource> pPerInstanceBuffer; + CComPtr<ID3D12Resource> pPrimitiveBuffer; + { + D3D12_RESOURCE_DESC BuffDesc = {}; + BuffDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + BuffDesc.Alignment = 0; + BuffDesc.Width = sizeof(PrimitiveOffsets); + BuffDesc.Height = 1; + BuffDesc.DepthOrArraySize = 1; + BuffDesc.MipLevels = 1; + BuffDesc.Format = DXGI_FORMAT_UNKNOWN; + BuffDesc.SampleDesc.Count = 1; + BuffDesc.SampleDesc.Quality = 0; + BuffDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + BuffDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + + D3D12_HEAP_PROPERTIES HeapProps; + HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + HeapProps.CreationNodeMask = 1; + HeapProps.VisibleNodeMask = 1; + + auto hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, + &BuffDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + IID_PPV_ARGS(&pPerInstanceBuffer)); + ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create per instance buffer"; + + BuffDesc.Width = sizeof(Primitives); + + hr = Ctx.pDevice->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, + &BuffDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + IID_PPV_ARGS(&pPrimitiveBuffer)); + ASSERT_HRESULT_SUCCEEDED(hr) << "Failed to create per instance buffer"; + + UpdateBuffer(Ctx, pPrimitiveBuffer, 0, Primitives, sizeof(Primitives)); + UpdateBuffer(Ctx, pPerInstanceBuffer, 0, PrimitiveOffsets, sizeof(PrimitiveOffsets)); + + // buffer barrier + { + D3D12_RESOURCE_BARRIER Barrier = {}; + Barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + Barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + Barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + Barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + Barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + Barrier.Transition.pResource = pPerInstanceBuffer; + Ctx.pCmdList->ResourceBarrier(1, &Barrier); + + Barrier.Transition.pResource = pPrimitiveBuffer; + Ctx.pCmdList->ResourceBarrier(1, &Barrier); + } + + D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {}; + D3D12_CPU_DESCRIPTOR_HANDLE SRVHandle; + + SRVDesc.Format = DXGI_FORMAT_UNKNOWN; + SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + SRVDesc.Buffer.NumElements = _countof(Vertices); + SRVDesc.Buffer.StructureByteStride = sizeof(Vertices[0]); + + ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize); + ASSERT_TRUE(Ctx.DescHeapCount == 2); + SRVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart(); + SRVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++; + Ctx.pDevice->CreateShaderResourceView(Ctx.pVertexBuffer, &SRVDesc, SRVHandle); // g_Vertices + + SRVDesc.Buffer.NumElements = _countof(Primitives); + SRVDesc.Buffer.StructureByteStride = sizeof(Primitives[0]); + ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize); + ASSERT_TRUE(Ctx.DescHeapCount == 3); + SRVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart(); + SRVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++; + Ctx.pDevice->CreateShaderResourceView(pPrimitiveBuffer, &SRVDesc, SRVHandle); // g_Primitives + + SRVDesc.Buffer.NumElements = _countof(PrimitiveOffsets); + SRVDesc.Buffer.StructureByteStride = sizeof(PrimitiveOffsets[0]); + ASSERT_LT(Ctx.DescHeapCount, Ctx.DescriptorHeapSize); + ASSERT_TRUE(Ctx.DescHeapCount == 4); + SRVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart(); + SRVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++; + Ctx.pDevice->CreateShaderResourceView(pPerInstanceBuffer, &SRVDesc, SRVHandle); // g_PerInstance[0] + + ASSERT_TRUE(Ctx.DescHeapCount == 5); + SRVHandle = Ctx.pDescHeap->GetCPUDescriptorHandleForHeapStart(); + SRVHandle.ptr += Ctx.DescHandleSize * Ctx.DescHeapCount++; + Ctx.pDevice->CreateShaderResourceView(pPerInstanceBuffer, &SRVDesc, SRVHandle); // g_PerInstance[1] + } + + Ctx.ClearRenderTarget(pTestingSwapChainD3D12); + + // trace rays + { + pTestingSwapChainD3D12->TransitionRenderTarget(Ctx.pCmdList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + ID3D12DescriptorHeap* DescHeaps[] = {Ctx.pDescHeap}; + + Ctx.pCmdList->SetPipelineState1(Ctx.pRayTracingSO); + Ctx.pCmdList->SetComputeRootSignature(Ctx.pGlobalRootSignature); + + Ctx.pCmdList->SetDescriptorHeaps(_countof(DescHeaps), &DescHeaps[0]); + Ctx.pCmdList->SetComputeRootDescriptorTable(0, DescHeaps[0]->GetGPUDescriptorHandleForHeapStart()); + + D3D12_DISPATCH_RAYS_DESC Desc = {}; + + Desc.Width = SCDesc.Width; + Desc.Height = SCDesc.Height; + Desc.Depth = 1; + + const UINT64 handleSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES; + const UINT64 align = D3D12_RAYTRACING_SHADER_TABLE_BYTE_ALIGNMENT; + const UINT64 ShaderRecordSize = handleSize + TestingConstants::MultiGeometry::ShaderRecordSize; + const size_t RayGenOffset = 0; + const size_t RayMissOffset = Align(RayGenOffset + handleSize, align); + const size_t HitGroupOffset = Align(RayMissOffset + handleSize, align); + const auto& Weights = TestingConstants::MultiGeometry::Weights; + + Desc.RayGenerationShaderRecord.StartAddress = Ctx.pSBTBuffer->GetGPUVirtualAddress() + RayGenOffset; + Desc.RayGenerationShaderRecord.SizeInBytes = ShaderRecordSize; + Desc.MissShaderTable.StartAddress = Ctx.pSBTBuffer->GetGPUVirtualAddress() + RayMissOffset; + Desc.MissShaderTable.SizeInBytes = ShaderRecordSize; + Desc.MissShaderTable.StrideInBytes = ShaderRecordSize; + Desc.HitGroupTable.StartAddress = Ctx.pSBTBuffer->GetGPUVirtualAddress() + HitGroupOffset; + Desc.HitGroupTable.SizeInBytes = ShaderRecordSize * HitGroupCount; + Desc.HitGroupTable.StrideInBytes = ShaderRecordSize; + + UpdateBuffer(Ctx, Ctx.pSBTBuffer, RayGenOffset, Ctx.pStateObjectProperties->GetShaderIdentifier(L"Main"), handleSize); + UpdateBuffer(Ctx, Ctx.pSBTBuffer, RayMissOffset, Ctx.pStateObjectProperties->GetShaderIdentifier(L"Miss"), handleSize); + + const auto SetHitGroup = [&](Uint32 Index, const wchar_t* GroupName, const void* ShaderRecord) { + VERIFY_EXPR(Index < HitGroupCount); + UINT64 Offset = HitGroupOffset + Index * ShaderRecordSize; + UpdateBuffer(Ctx, Ctx.pSBTBuffer, Offset, Ctx.pStateObjectProperties->GetShaderIdentifier(GroupName), handleSize); + UpdateBuffer(Ctx, Ctx.pSBTBuffer, Offset + handleSize, ShaderRecord, sizeof(Weights[0])); + }; + // instance 1 + SetHitGroup(0, L"HitGroup1", &Weights[2]); // geometry 1 + SetHitGroup(1, L"HitGroup1", &Weights[0]); // geometry 2 + SetHitGroup(2, L"HitGroup1", &Weights[1]); // geometry 3 + // instance 2 + SetHitGroup(3, L"HitGroup2", &Weights[2]); // geometry 1 + SetHitGroup(4, L"HitGroup2", &Weights[1]); // geometry 2 + SetHitGroup(5, L"HitGroup2", &Weights[0]); // geometry 3 + + // SBT buffer barrier + { + D3D12_RESOURCE_BARRIER Barrier; + Barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + Barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + Barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + Barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + Barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + Barrier.Transition.pResource = Ctx.pSBTBuffer; + Ctx.pCmdList->ResourceBarrier(1, &Barrier); + } + + Ctx.pCmdList->DispatchRays(&Desc); + } + + Ctx.pCmdList->Close(); + + pEnv->ExecuteCommandList(Ctx.pCmdList, true); +} + } // namespace Testing } // namespace Diligent diff --git a/Tests/DiligentCoreAPITest/src/RayTracingTest.cpp b/Tests/DiligentCoreAPITest/src/RayTracingTest.cpp index bd6b2223..fa71c6a7 100644 --- a/Tests/DiligentCoreAPITest/src/RayTracingTest.cpp +++ b/Tests/DiligentCoreAPITest/src/RayTracingTest.cpp @@ -34,6 +34,7 @@ #include "gtest/gtest.h" #include "InlineShaders/RayTracingTestHLSL.h" +#include "RayTracingTestConstants.hpp" namespace Diligent { @@ -45,12 +46,14 @@ namespace Testing void RayTracingTriangleClosestHitReferenceD3D12(ISwapChain* pSwapChain); void RayTracingTriangleAnyHitReferenceD3D12(ISwapChain* pSwapChain); void RayTracingProceduralIntersectionReferenceD3D12(ISwapChain* pSwapChain); +void RayTracingMultiGeometryReferenceD3D12(ISwapChain* pSwapChain); #endif #if VULKAN_SUPPORTED void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain); void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain); void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain); +void RayTracingMultiGeometryReferenceVk(ISwapChain* pSwapChain); #endif } // namespace Testing @@ -83,6 +86,7 @@ void CreateBLAS(IRenderDevice* pDevice, IDeviceContext* pContext, const BLASBuil BottomLevelASDesc ASDesc; ASDesc.Name = "Triangle BLAS"; + ASDesc.Flags = RAYTRACING_BUILD_AS_NONE; ASDesc.pTriangles = TriangleInfos.data(); ASDesc.TriangleCount = TriangleCount; @@ -130,6 +134,7 @@ void CreateBLAS(IRenderDevice* pDevice, IDeviceContext* pContext, const BLASBuil BottomLevelASDesc ASDesc; ASDesc.Name = "Boxes BLAS"; + ASDesc.Flags = RAYTRACING_BUILD_AS_NONE; ASDesc.pBoxes = BoxInfos.data(); ASDesc.BoxCount = BoxCount; @@ -262,12 +267,12 @@ TEST(RayTracingTest, TriangleClosestHitShader) ShaderCreateInfo ShaderCI; ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC; + ShaderCI.EntryPoint = "main"; // Create ray generation shader. RefCntAutoPtr<IShader> pRG; { ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_GEN; - ShaderCI.EntryPoint = "main"; ShaderCI.Desc.Name = "Ray tracing RG"; ShaderCI.Source = HLSL::RayTracingTest1_RG.c_str(); pDevice->CreateShader(ShaderCI, &pRG); @@ -278,7 +283,6 @@ TEST(RayTracingTest, TriangleClosestHitShader) RefCntAutoPtr<IShader> pRMiss; { ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_MISS; - ShaderCI.EntryPoint = "main"; ShaderCI.Desc.Name = "Miss shader"; ShaderCI.Source = HLSL::RayTracingTest1_RM.c_str(); pDevice->CreateShader(ShaderCI, &pRMiss); @@ -289,7 +293,6 @@ TEST(RayTracingTest, TriangleClosestHitShader) RefCntAutoPtr<IShader> pClosestHit; { ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_CLOSEST_HIT; - ShaderCI.EntryPoint = "main"; ShaderCI.Desc.Name = "Ray closest hit shader"; ShaderCI.Source = HLSL::RayTracingTest1_RCH.c_str(); pDevice->CreateShader(ShaderCI, &pClosestHit); @@ -315,12 +318,7 @@ TEST(RayTracingTest, TriangleClosestHitShader) pRayTracingPSO->CreateShaderResourceBinding(&pRayTracingSRB, true); VERIFY_EXPR(pRayTracingSRB != nullptr); - const float3 Vertices[] = // - { - float3{0.25f, 0.25f, 0.0f}, - float3{0.75f, 0.25f, 0.0f}, - float3{0.50f, 0.75f, 0.0f} // - }; + const auto& Vertices = TestingConstants::TriangleClosestHit::Vertices; RefCntAutoPtr<IBuffer> pVertexBuffer; { @@ -351,15 +349,9 @@ TEST(RayTracingTest, TriangleClosestHitShader) CreateBLAS(pDevice, pContext, &Triangle, 1, pBLAS); TLASBuildInstanceData Instance; - Instance.InstanceName = "Instance"; - Instance.pBLAS = pBLAS; - Instance.CustomId = 0; - Instance.Flags = RAYTRACING_INSTANCE_NONE; - Instance.Mask = 0xFF; - Instance.ContributionToHitGroupIndex = 0; - Instance.Transform[0][0] = 1.0f; - Instance.Transform[1][1] = 1.0f; - Instance.Transform[2][2] = 1.0f; + Instance.InstanceName = "Instance"; + Instance.pBLAS = pBLAS; + Instance.Flags = RAYTRACING_INSTANCE_NONE; RefCntAutoPtr<ITopLevelAS> pTLAS; CreateTLAS(pDevice, pContext, &Instance, 1, pTLAS); @@ -367,7 +359,6 @@ TEST(RayTracingTest, TriangleClosestHitShader) ShaderBindingTableDesc SBTDesc; SBTDesc.Name = "SBT"; SBTDesc.pPSO = pRayTracingPSO; - SBTDesc.ShaderRecordSize = 0; SBTDesc.HitShadersPerInstance = 1; RefCntAutoPtr<IShaderBindingTable> pSBT; @@ -447,12 +438,12 @@ TEST(RayTracingTest, TriangleAnyHitShader) ShaderCreateInfo ShaderCI; ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC; + ShaderCI.EntryPoint = "main"; // Create ray generation shader. RefCntAutoPtr<IShader> pRG; { ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_GEN; - ShaderCI.EntryPoint = "main"; ShaderCI.Desc.Name = "Ray tracing RG"; ShaderCI.Source = HLSL::RayTracingTest2_RG.c_str(); pDevice->CreateShader(ShaderCI, &pRG); @@ -463,7 +454,6 @@ TEST(RayTracingTest, TriangleAnyHitShader) RefCntAutoPtr<IShader> pRMiss; { ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_MISS; - ShaderCI.EntryPoint = "main"; ShaderCI.Desc.Name = "Miss shader"; ShaderCI.Source = HLSL::RayTracingTest2_RM.c_str(); pDevice->CreateShader(ShaderCI, &pRMiss); @@ -474,7 +464,6 @@ TEST(RayTracingTest, TriangleAnyHitShader) RefCntAutoPtr<IShader> pClosestHit; { ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_CLOSEST_HIT; - ShaderCI.EntryPoint = "main"; ShaderCI.Desc.Name = "Ray closest hit shader"; ShaderCI.Source = HLSL::RayTracingTest2_RCH.c_str(); pDevice->CreateShader(ShaderCI, &pClosestHit); @@ -485,7 +474,6 @@ TEST(RayTracingTest, TriangleAnyHitShader) RefCntAutoPtr<IShader> pAnyHit; { ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_ANY_HIT; - ShaderCI.EntryPoint = "main"; ShaderCI.Desc.Name = "Ray any hit shader"; ShaderCI.Source = HLSL::RayTracingTest2_RAH.c_str(); pDevice->CreateShader(ShaderCI, &pAnyHit); @@ -511,12 +499,7 @@ TEST(RayTracingTest, TriangleAnyHitShader) pRayTracingPSO->CreateShaderResourceBinding(&pRayTracingSRB, true); VERIFY_EXPR(pRayTracingSRB != nullptr); - const float3 Vertices[] = // - { - float3{0.25f, 0.25f, 0.0f}, float3{0.75f, 0.25f, 0.0f}, float3{0.50f, 0.75f, 0.0f}, - float3{0.50f, 0.10f, 0.1f}, float3{0.90f, 0.90f, 0.1f}, float3{0.10f, 0.90f, 0.1f}, - float3{0.40f, 1.00f, 0.2f}, float3{0.20f, 0.40f, 0.2f}, float3{1.00f, 0.70f, 0.2f} // - }; + const auto& Vertices = TestingConstants::TriangleAnyHit::Vertices; RefCntAutoPtr<IBuffer> pVertexBuffer; { @@ -547,15 +530,9 @@ TEST(RayTracingTest, TriangleAnyHitShader) CreateBLAS(pDevice, pContext, &Triangle, 1, pBLAS); TLASBuildInstanceData Instance; - Instance.InstanceName = "Instance"; - Instance.pBLAS = pBLAS; - Instance.CustomId = 0; - Instance.Flags = RAYTRACING_INSTANCE_NONE; - Instance.Mask = 0xFF; - Instance.ContributionToHitGroupIndex = 0; - Instance.Transform[0][0] = 1.0f; - Instance.Transform[1][1] = 1.0f; - Instance.Transform[2][2] = 1.0f; + Instance.InstanceName = "Instance"; + Instance.pBLAS = pBLAS; + Instance.Flags = RAYTRACING_INSTANCE_NONE; RefCntAutoPtr<ITopLevelAS> pTLAS; CreateTLAS(pDevice, pContext, &Instance, 1, pTLAS); @@ -563,7 +540,6 @@ TEST(RayTracingTest, TriangleAnyHitShader) ShaderBindingTableDesc SBTDesc; SBTDesc.Name = "SBT"; SBTDesc.pPSO = pRayTracingPSO; - SBTDesc.ShaderRecordSize = 0; SBTDesc.HitShadersPerInstance = 1; RefCntAutoPtr<IShaderBindingTable> pSBT; @@ -643,12 +619,12 @@ TEST(RayTracingTest, ProceduralIntersection) ShaderCreateInfo ShaderCI; ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC; + ShaderCI.EntryPoint = "main"; // Create ray generation shader. RefCntAutoPtr<IShader> pRG; { ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_GEN; - ShaderCI.EntryPoint = "main"; ShaderCI.Desc.Name = "Ray tracing RG"; ShaderCI.Source = HLSL::RayTracingTest3_RG.c_str(); pDevice->CreateShader(ShaderCI, &pRG); @@ -659,7 +635,6 @@ TEST(RayTracingTest, ProceduralIntersection) RefCntAutoPtr<IShader> pRMiss; { ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_MISS; - ShaderCI.EntryPoint = "main"; ShaderCI.Desc.Name = "Miss shader"; ShaderCI.Source = HLSL::RayTracingTest3_RM.c_str(); pDevice->CreateShader(ShaderCI, &pRMiss); @@ -670,7 +645,6 @@ TEST(RayTracingTest, ProceduralIntersection) RefCntAutoPtr<IShader> pClosestHit; { ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_CLOSEST_HIT; - ShaderCI.EntryPoint = "main"; ShaderCI.Desc.Name = "Ray closest hit shader"; ShaderCI.Source = HLSL::RayTracingTest3_RCH.c_str(); pDevice->CreateShader(ShaderCI, &pClosestHit); @@ -681,7 +655,6 @@ TEST(RayTracingTest, ProceduralIntersection) RefCntAutoPtr<IShader> pIntersection; { ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_INTERSECTION; - ShaderCI.EntryPoint = "main"; ShaderCI.Desc.Name = "Ray intersection shader"; ShaderCI.Source = HLSL::RayTracingTest3_RI.c_str(); pDevice->CreateShader(ShaderCI, &pIntersection); @@ -707,9 +680,7 @@ TEST(RayTracingTest, ProceduralIntersection) pRayTracingPSO->CreateShaderResourceBinding(&pRayTracingSRB, true); VERIFY_EXPR(pRayTracingSRB != nullptr); - const float3 Boxes[] = { - float3{0.25f, 0.5f, 2.0f} - float3{1.0f, 1.0f, 1.0f}, - float3{0.25f, 0.5f, 2.0f} + float3{1.0f, 1.0f, 1.0f}}; + const auto& Boxes = TestingConstants::ProceduralIntersection::Boxes; RefCntAutoPtr<IBuffer> pBoxBuffer; { @@ -738,15 +709,9 @@ TEST(RayTracingTest, ProceduralIntersection) CreateBLAS(pDevice, pContext, &Box, 1, pBLAS); TLASBuildInstanceData Instance; - Instance.InstanceName = "Instance"; - Instance.pBLAS = pBLAS; - Instance.CustomId = 0; - Instance.Flags = RAYTRACING_INSTANCE_NONE; - Instance.Mask = 0xFF; - Instance.ContributionToHitGroupIndex = 0; - Instance.Transform[0][0] = 1.0f; - Instance.Transform[1][1] = 1.0f; - Instance.Transform[2][2] = 1.0f; + Instance.InstanceName = "Instance"; + Instance.pBLAS = pBLAS; + Instance.Flags = RAYTRACING_INSTANCE_NONE; RefCntAutoPtr<ITopLevelAS> pTLAS; CreateTLAS(pDevice, pContext, &Instance, 1, pTLAS); @@ -754,7 +719,6 @@ TEST(RayTracingTest, ProceduralIntersection) ShaderBindingTableDesc SBTDesc; SBTDesc.Name = "SBT"; SBTDesc.pPSO = pRayTracingPSO; - SBTDesc.ShaderRecordSize = 0; SBTDesc.HitShadersPerInstance = 1; RefCntAutoPtr<IShaderBindingTable> pSBT; @@ -784,4 +748,261 @@ TEST(RayTracingTest, ProceduralIntersection) pSwapChain->Present(); } + +TEST(RayTracingTest, MultiGeometry) +{ + auto* pEnv = TestingEnvironment::GetInstance(); + auto* pDevice = pEnv->GetDevice(); + if (!pDevice->GetDeviceCaps().Features.RayTracing) + { + GTEST_SKIP() << "Ray tracing is not supported by this device"; + } + + auto* pSwapChain = pEnv->GetSwapChain(); + auto* pContext = pEnv->GetDeviceContext(); + + RefCntAutoPtr<ITestingSwapChain> pTestingSwapChain(pSwapChain, IID_TestingSwapChain); + if (pTestingSwapChain) + { + pContext->Flush(); + pContext->InvalidateState(); + + auto deviceType = pDevice->GetDeviceCaps().DevType; + switch (deviceType) + { +#if D3D12_SUPPORTED + case RENDER_DEVICE_TYPE_D3D12: + RayTracingMultiGeometryReferenceD3D12(pSwapChain); + break; +#endif + +#if VULKAN_SUPPORTED + case RENDER_DEVICE_TYPE_VULKAN: + RayTracingMultiGeometryReferenceVk(pSwapChain); + break; +#endif + + default: + LOG_ERROR_AND_THROW("Unsupported device type"); + } + + pTestingSwapChain->TakeSnapshot(); + } + TestingEnvironment::ScopedReleaseResources EnvironmentAutoReset; + + RayTracingPipelineStateCreateInfo PSOCreateInfo; + + PSOCreateInfo.PSODesc.Name = "Ray tracing PSO"; + PSOCreateInfo.PSODesc.PipelineType = PIPELINE_TYPE_RAY_TRACING; + + ShaderCreateInfo ShaderCI; + ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; + ShaderCI.ShaderCompiler = SHADER_COMPILER_DXC; + ShaderCI.EntryPoint = "main"; + + // Create ray generation shader. + RefCntAutoPtr<IShader> pRG; + { + ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_GEN; + ShaderCI.Desc.Name = "Ray tracing RG"; + ShaderCI.Source = HLSL::RayTracingTest4_RG.c_str(); + pDevice->CreateShader(ShaderCI, &pRG); + VERIFY_EXPR(pRG != nullptr); + } + + // Create ray miss shader. + RefCntAutoPtr<IShader> pRMiss; + { + ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_MISS; + ShaderCI.Desc.Name = "Miss shader"; + ShaderCI.Source = HLSL::RayTracingTest4_RM.c_str(); + pDevice->CreateShader(ShaderCI, &pRMiss); + VERIFY_EXPR(pRMiss != nullptr); + } + + // Create ray closest hit shader. + RefCntAutoPtr<IShader> pClosestHit1; + { + ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_CLOSEST_HIT; + ShaderCI.Desc.Name = "Ray closest hit shader 1"; + ShaderCI.Source = HLSL::RayTracingTest4_RCH1.c_str(); + pDevice->CreateShader(ShaderCI, &pClosestHit1); + VERIFY_EXPR(pClosestHit1 != nullptr); + } + + RefCntAutoPtr<IShader> pClosestHit2; + { + ShaderCI.Desc.ShaderType = SHADER_TYPE_RAY_CLOSEST_HIT; + ShaderCI.Desc.Name = "Ray closest hit shader 2"; + ShaderCI.Source = HLSL::RayTracingTest4_RCH2.c_str(); + pDevice->CreateShader(ShaderCI, &pClosestHit2); + VERIFY_EXPR(pClosestHit2 != nullptr); + } + + const RayTracingGeneralShaderGroup GeneralShaders[] = {{"Main", pRG}, {"Miss", pRMiss}}; + const RayTracingTriangleHitShaderGroup TriangleHitShaders[] = {{"HitGroup1", pClosestHit1}, {"HitGroup2", pClosestHit2}}; + + PSOCreateInfo.pGeneralShaders = GeneralShaders; + PSOCreateInfo.GeneralShaderCount = _countof(GeneralShaders); + PSOCreateInfo.pTriangleHitShaders = TriangleHitShaders; + PSOCreateInfo.TriangleHitShaderCount = _countof(TriangleHitShaders); + + PSOCreateInfo.RayTracingPipeline.MaxRecursionDepth = 0; + + PSOCreateInfo.RayTracingPipeline.ShaderRecordSize = TestingConstants::MultiGeometry::ShaderRecordSize; + PSOCreateInfo.ShaderRecordName = "g_LocalRoot"; + + PSOCreateInfo.PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE; + + RefCntAutoPtr<IPipelineState> pRayTracingPSO; + pDevice->CreateRayTracingPipelineState(PSOCreateInfo, &pRayTracingPSO); + VERIFY_EXPR(pRayTracingPSO != nullptr); + + RefCntAutoPtr<IShaderResourceBinding> pRayTracingSRB; + pRayTracingPSO->CreateShaderResourceBinding(&pRayTracingSRB, true); + VERIFY_EXPR(pRayTracingSRB != nullptr); + + const auto& Vertices = TestingConstants::MultiGeometry::Vertices; + const auto& Indices = TestingConstants::MultiGeometry::Indices; + const auto& Weights = TestingConstants::MultiGeometry::Weights; + const auto& PrimitiveOffsets = TestingConstants::MultiGeometry::PrimitiveOffsets; + const auto& Primitives = TestingConstants::MultiGeometry::Primitives; + + RefCntAutoPtr<IBuffer> pVertexBuffer; + RefCntAutoPtr<IBuffer> pIndexBuffer; + RefCntAutoPtr<IBuffer> pPerInstanceBuffer; + RefCntAutoPtr<IBuffer> pPrimitiveBuffer; + { + BufferDesc BuffDesc; + BuffDesc.Name = "Indices"; + BuffDesc.Usage = USAGE_IMMUTABLE; + BuffDesc.BindFlags = BIND_RAY_TRACING; + BuffDesc.uiSizeInBytes = sizeof(Indices); + BufferData BufData = {Indices, sizeof(Indices)}; + pDevice->CreateBuffer(BuffDesc, &BufData, &pIndexBuffer); + VERIFY_EXPR(pIndexBuffer != nullptr); + + BuffDesc.Name = "Vertices"; + BuffDesc.Mode = BUFFER_MODE_STRUCTURED; + BuffDesc.BindFlags = BIND_RAY_TRACING | BIND_SHADER_RESOURCE; + BuffDesc.uiSizeInBytes = sizeof(Vertices); + BuffDesc.ElementByteStride = sizeof(Vertices[0]); + BufData = {Vertices, sizeof(Vertices)}; + pDevice->CreateBuffer(BuffDesc, &BufData, &pVertexBuffer); + VERIFY_EXPR(pVertexBuffer != nullptr); + + BuffDesc.Name = "PerInstanceData"; + BuffDesc.BindFlags = BIND_SHADER_RESOURCE; + BuffDesc.uiSizeInBytes = sizeof(PrimitiveOffsets); + BuffDesc.ElementByteStride = sizeof(PrimitiveOffsets[0]); + BufData = {PrimitiveOffsets, sizeof(PrimitiveOffsets)}; + pDevice->CreateBuffer(BuffDesc, &BufData, &pPerInstanceBuffer); + VERIFY_EXPR(pPerInstanceBuffer != nullptr); + + BuffDesc.Name = "PrimitiveData"; + BuffDesc.uiSizeInBytes = sizeof(Primitives); + BuffDesc.ElementByteStride = sizeof(Primitives[0]); + BufData = {Primitives, sizeof(Primitives)}; + pDevice->CreateBuffer(BuffDesc, &BufData, &pPrimitiveBuffer); + VERIFY_EXPR(pPrimitiveBuffer != nullptr); + } + + BLASBuildTriangleData Triangles[3] = {}; + Triangles[0].GeometryName = "Geom 1"; + Triangles[0].pVertexBuffer = pVertexBuffer; + Triangles[0].VertexStride = sizeof(Vertices[0]); + Triangles[0].VertexCount = _countof(Vertices); + Triangles[0].VertexValueType = VT_FLOAT32; + Triangles[0].VertexComponentCount = 3; + Triangles[0].pIndexBuffer = pIndexBuffer; + Triangles[0].IndexType = VT_UINT32; + Triangles[0].IndexCount = (PrimitiveOffsets[1] - PrimitiveOffsets[0]) * 3; + Triangles[0].IndexOffset = PrimitiveOffsets[0] * sizeof(uint) * 3; + Triangles[0].Flags = RAYTRACING_GEOMETRY_OPAQUE; + + Triangles[1].GeometryName = "Geom 2"; + Triangles[1].pVertexBuffer = pVertexBuffer; + Triangles[1].VertexStride = sizeof(Vertices[0]); + Triangles[1].VertexCount = _countof(Vertices); + Triangles[1].VertexValueType = VT_FLOAT32; + Triangles[1].VertexComponentCount = 3; + Triangles[1].pIndexBuffer = pIndexBuffer; + Triangles[1].IndexType = VT_UINT32; + Triangles[1].IndexCount = (PrimitiveOffsets[2] - PrimitiveOffsets[1]) * 3; + Triangles[1].IndexOffset = PrimitiveOffsets[1] * sizeof(uint) * 3; + Triangles[1].Flags = RAYTRACING_GEOMETRY_OPAQUE; + + Triangles[2].GeometryName = "Geom 3"; + Triangles[2].pVertexBuffer = pVertexBuffer; + Triangles[2].VertexStride = sizeof(Vertices[0]); + Triangles[2].VertexCount = _countof(Vertices); + Triangles[2].VertexValueType = VT_FLOAT32; + Triangles[2].VertexComponentCount = 3; + Triangles[2].pIndexBuffer = pIndexBuffer; + Triangles[2].IndexType = VT_UINT32; + Triangles[2].IndexCount = (_countof(Primitives) - PrimitiveOffsets[2]) * 3; + Triangles[2].IndexOffset = PrimitiveOffsets[2] * sizeof(uint) * 3; + Triangles[2].Flags = RAYTRACING_GEOMETRY_OPAQUE; + + RefCntAutoPtr<IBottomLevelAS> pBLAS; + CreateBLAS(pDevice, pContext, Triangles, _countof(Triangles), pBLAS); + + TLASBuildInstanceData Instances[2] = {}; + + Instances[0].InstanceName = "Instance 1"; + Instances[0].pBLAS = pBLAS; + Instances[0].Flags = RAYTRACING_INSTANCE_NONE; + + Instances[1].InstanceName = "Instance 2"; + Instances[1].pBLAS = pBLAS; + Instances[1].Flags = RAYTRACING_INSTANCE_NONE; + Instances[1].Transform.SetTranslation(0.1f, 0.5f, 0.0f); + + RefCntAutoPtr<ITopLevelAS> pTLAS; + CreateTLAS(pDevice, pContext, Instances, _countof(Instances), pTLAS); + + ShaderBindingTableDesc SBTDesc; + SBTDesc.Name = "SBT"; + SBTDesc.pPSO = pRayTracingPSO; + SBTDesc.HitShadersPerInstance = 1; + + RefCntAutoPtr<IShaderBindingTable> pSBT; + pDevice->CreateSBT(SBTDesc, &pSBT); + VERIFY_EXPR(pSBT != nullptr); + + pSBT->BindRayGenShader("Main"); + pSBT->BindMissShader("Miss", 0); + pSBT->BindHitGroup(pTLAS, "Instance 1", "Geom 1", 0, "HitGroup1", &Weights[2], sizeof(Weights[0])); + pSBT->BindHitGroup(pTLAS, "Instance 1", "Geom 2", 0, "HitGroup1", &Weights[0], sizeof(Weights[0])); + pSBT->BindHitGroup(pTLAS, "Instance 1", "Geom 3", 0, "HitGroup1", &Weights[1], sizeof(Weights[0])); + pSBT->BindHitGroup(pTLAS, "Instance 2", "Geom 1", 0, "HitGroup2", &Weights[2], sizeof(Weights[0])); + pSBT->BindHitGroup(pTLAS, "Instance 2", "Geom 2", 0, "HitGroup2", &Weights[1], sizeof(Weights[0])); + pSBT->BindHitGroup(pTLAS, "Instance 2", "Geom 3", 0, "HitGroup2", &Weights[0], sizeof(Weights[0])); + + pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_GEN, "g_TLAS")->Set(pTLAS); + pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_GEN, "g_ColorBuffer")->Set(pTestingSwapChain->GetCurrentBackBufferUAV()); + + IDeviceObject* pObject = pPerInstanceBuffer->GetDefaultView(BUFFER_VIEW_SHADER_RESOURCE); + pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_CLOSEST_HIT, "g_PerInstance")->SetArray(&pObject, 0, 1); + pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_CLOSEST_HIT, "g_PerInstance")->SetArray(&pObject, 1, 1); + + pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_CLOSEST_HIT, "g_Primitives")->Set(pPrimitiveBuffer->GetDefaultView(BUFFER_VIEW_SHADER_RESOURCE)); + pRayTracingSRB->GetVariableByName(SHADER_TYPE_RAY_CLOSEST_HIT, "g_Vertices")->Set(pVertexBuffer->GetDefaultView(BUFFER_VIEW_SHADER_RESOURCE)); + + pContext->SetPipelineState(pRayTracingPSO); + pContext->CommitShaderResources(pRayTracingSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + + const auto& SCDesc = pSwapChain->GetDesc(); + + TraceRaysAttribs Attribs; + Attribs.DimensionX = SCDesc.Width; + Attribs.DimensionY = SCDesc.Height; + Attribs.pSBT = pSBT; + Attribs.TransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION; + + pContext->TraceRays(Attribs); + + pSwapChain->Present(); +} + } // namespace diff --git a/Tests/DiligentCoreAPITest/src/Vulkan/RayTracingReferenceVk.cpp b/Tests/DiligentCoreAPITest/src/Vulkan/RayTracingReferenceVk.cpp index 20788602..6c98a047 100644 --- a/Tests/DiligentCoreAPITest/src/Vulkan/RayTracingReferenceVk.cpp +++ b/Tests/DiligentCoreAPITest/src/Vulkan/RayTracingReferenceVk.cpp @@ -37,6 +37,7 @@ #include "volk/volk.h" #include "InlineShaders/RayTracingTestGLSL.h" +#include "RayTracingTestConstants.hpp" namespace Diligent { @@ -49,20 +50,36 @@ namespace struct RTContext { - VkDevice vkDevice = VK_NULL_HANDLE; - VkCommandBuffer vkCmdBuffer = VK_NULL_HANDLE; - VkImage vkRenderTarget = VK_NULL_HANDLE; - VkImageView vkRenderTargetView = VK_NULL_HANDLE; - VkPipelineLayout vkLayout = VK_NULL_HANDLE; - VkPipeline vkPipeline = VK_NULL_HANDLE; - VkDescriptorSetLayout vkSetLayout = VK_NULL_HANDLE; - VkDescriptorPool vkDescriptorPool = VK_NULL_HANDLE; - VkDescriptorSet vkDescriptorSet = VK_NULL_HANDLE; - VkDeviceMemory vkBLASMemory = VK_NULL_HANDLE; - VkAccelerationStructureKHR vkBLAS = VK_NULL_HANDLE; - VkDeviceAddress vkBLASAddress = 0; - VkDeviceMemory vkTLASMemory = VK_NULL_HANDLE; - VkAccelerationStructureKHR vkTLAS = VK_NULL_HANDLE; + struct AccelStruct + { + VkDevice vkDevice = VK_NULL_HANDLE; + VkDeviceMemory vkMemory = VK_NULL_HANDLE; + VkAccelerationStructureKHR vkAS = VK_NULL_HANDLE; + VkDeviceAddress vkAddress = 0; + + AccelStruct() + {} + + ~AccelStruct() + { + if (vkAS) + vkDestroyAccelerationStructureKHR(vkDevice, vkAS, nullptr); + if (vkMemory) + vkFreeMemory(vkDevice, vkMemory, nullptr); + } + }; + + VkDevice vkDevice = VK_NULL_HANDLE; + VkCommandBuffer vkCmdBuffer = VK_NULL_HANDLE; + VkImage vkRenderTarget = VK_NULL_HANDLE; + VkImageView vkRenderTargetView = VK_NULL_HANDLE; + VkPipelineLayout vkLayout = VK_NULL_HANDLE; + VkPipeline vkPipeline = VK_NULL_HANDLE; + VkDescriptorSetLayout vkSetLayout = VK_NULL_HANDLE; + VkDescriptorPool vkDescriptorPool = VK_NULL_HANDLE; + VkDescriptorSet vkDescriptorSet = VK_NULL_HANDLE; + AccelStruct BLAS; + AccelStruct TLAS; VkBuffer vkSBTBuffer = VK_NULL_HANDLE; VkBuffer vkScratchBuffer = VK_NULL_HANDLE; VkBuffer vkInstanceBuffer = VK_NULL_HANDLE; @@ -73,7 +90,6 @@ struct RTContext VkDeviceAddress vkVertexBufferAddress = 0; VkDeviceAddress vkIndexBufferAddress = 0; VkDeviceMemory vkBufferMemory = VK_NULL_HANDLE; - VkPhysicalDeviceMemoryProperties MemoryProperties = {}; VkPhysicalDeviceLimits DeviceLimits = {}; VkPhysicalDeviceRayTracingPropertiesKHR RayTracingProps = {}; @@ -88,16 +104,8 @@ struct RTContext vkDestroyPipelineLayout(vkDevice, vkLayout, nullptr); if (vkSetLayout) vkDestroyDescriptorSetLayout(vkDevice, vkSetLayout, nullptr); - if (vkBLAS) - vkDestroyAccelerationStructureKHR(vkDevice, vkBLAS, nullptr); - if (vkTLAS) - vkDestroyAccelerationStructureKHR(vkDevice, vkTLAS, nullptr); if (vkDescriptorPool) vkDestroyDescriptorPool(vkDevice, vkDescriptorPool, nullptr); - if (vkBLASMemory) - vkFreeMemory(vkDevice, vkBLASMemory, nullptr); - if (vkTLASMemory) - vkFreeMemory(vkDevice, vkTLASMemory, nullptr); if (vkBufferMemory) vkFreeMemory(vkDevice, vkBufferMemory, nullptr); if (vkSBTBuffer) @@ -136,8 +144,6 @@ void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& P Ctx.vkRenderTarget = pTestingSwapChainVk->GetVkRenderTargetImage(); Ctx.vkRenderTargetView = pTestingSwapChainVk->GetVkRenderTargetImageView(); - vkGetPhysicalDeviceMemoryProperties(pEnv->GetVkPhysicalDevice(), &Ctx.MemoryProperties); - VkPhysicalDeviceProperties2 Props2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2}; Props2.pNext = &Ctx.RayTracingProps; Ctx.RayTracingProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR; @@ -225,7 +231,7 @@ void InitializeRTContext(RTContext& Ctx, ISwapChain* pSwapChain, PSOCtorType&& P PoolSizes[0].descriptorCount = MaxDescriptorsInPool; PoolSizes[1].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; PoolSizes[1].descriptorCount = MaxDescriptorsInPool; - PoolSizes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; + PoolSizes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; PoolSizes[2].descriptorCount = MaxDescriptorsInPool; res = vkCreateDescriptorPool(Ctx.vkDevice, &DescriptorPoolCI, nullptr, &Ctx.vkDescriptorPool); @@ -269,14 +275,16 @@ void UpdateDescriptorSet(RTContext& Ctx) TLASInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; TLASInfo.accelerationStructureCount = 1; - TLASInfo.pAccelerationStructures = &Ctx.vkTLAS; + TLASInfo.pAccelerationStructures = &Ctx.TLAS.vkAS; DescriptorWrite[1].pNext = &TLASInfo; vkUpdateDescriptorSets(Ctx.vkDevice, _countof(DescriptorWrite), DescriptorWrite, 0, nullptr); } -void CreateBLAS(RTContext& Ctx, const VkAccelerationStructureCreateGeometryTypeInfoKHR* pGeometries, Uint32 GeometryCount) +void CreateBLAS(const RTContext& Ctx, const VkAccelerationStructureCreateGeometryTypeInfoKHR* pGeometries, Uint32 GeometryCount, RTContext::AccelStruct& BLAS) { + BLAS.vkDevice = Ctx.vkDevice; + VkResult res = VK_SUCCESS; VkAccelerationStructureCreateInfoKHR BLASCI = {}; @@ -290,12 +298,12 @@ void CreateBLAS(RTContext& Ctx, const VkAccelerationStructureCreateGeometryTypeI BLASCI.compactedSize = 0; BLASCI.pGeometryInfos = pGeometries; - res = vkCreateAccelerationStructureKHR(Ctx.vkDevice, &BLASCI, nullptr, &Ctx.vkBLAS); + res = vkCreateAccelerationStructureKHR(Ctx.vkDevice, &BLASCI, nullptr, &BLAS.vkAS); ASSERT_GE(res, VK_SUCCESS); - ASSERT_TRUE(Ctx.vkBLAS != VK_NULL_HANDLE); + ASSERT_TRUE(BLAS.vkAS != VK_NULL_HANDLE); MemInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR; - MemInfo.accelerationStructure = Ctx.vkBLAS; + MemInfo.accelerationStructure = BLAS.vkAS; MemInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR; @@ -307,32 +315,21 @@ void CreateBLAS(RTContext& Ctx, const VkAccelerationStructureCreateGeometryTypeI MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; MemAlloc.allocationSize = MemReqs.memoryRequirements.size; - MemAlloc.memoryTypeIndex = ~0u; - - for (Uint32 i = 0; i < Ctx.MemoryProperties.memoryTypeCount; ++i) - { - const auto PropFlags = Ctx.MemoryProperties.memoryTypes[i].propertyFlags; - - if (!!(MemReqs.memoryRequirements.memoryTypeBits & (1u << i)) && !!(PropFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) - { - MemAlloc.memoryTypeIndex = i; - break; - } - } + MemAlloc.memoryTypeIndex = TestingEnvironmentVk::GetInstance()->GetMemoryTypeIndex(MemReqs.memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); ASSERT_TRUE(MemAlloc.memoryTypeIndex != ~0u); - res = vkAllocateMemory(Ctx.vkDevice, &MemAlloc, nullptr, &Ctx.vkBLASMemory); + res = vkAllocateMemory(Ctx.vkDevice, &MemAlloc, nullptr, &BLAS.vkMemory); ASSERT_GE(res, VK_SUCCESS); - ASSERT_TRUE(Ctx.vkBLASMemory != VK_NULL_HANDLE); + ASSERT_TRUE(BLAS.vkMemory != VK_NULL_HANDLE); VkBindAccelerationStructureMemoryInfoKHR BindInfo = {}; BindInfo.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR; - BindInfo.memory = Ctx.vkBLASMemory; + BindInfo.memory = BLAS.vkMemory; BindInfo.memoryOffset = 0; BindInfo.deviceIndexCount = 0; BindInfo.pDeviceIndices = nullptr; - BindInfo.accelerationStructure = Ctx.vkBLAS; + BindInfo.accelerationStructure = BLAS.vkAS; res = vkBindAccelerationStructureMemoryKHR(Ctx.vkDevice, 1, &BindInfo); ASSERT_GE(res, VK_SUCCESS); @@ -340,13 +337,15 @@ void CreateBLAS(RTContext& Ctx, const VkAccelerationStructureCreateGeometryTypeI VkAccelerationStructureDeviceAddressInfoKHR AddressInfo = {}; AddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; - AddressInfo.accelerationStructure = Ctx.vkBLAS; + AddressInfo.accelerationStructure = BLAS.vkAS; - Ctx.vkBLASAddress = vkGetAccelerationStructureDeviceAddressKHR(Ctx.vkDevice, &AddressInfo); + BLAS.vkAddress = vkGetAccelerationStructureDeviceAddressKHR(Ctx.vkDevice, &AddressInfo); } -void CreateTLAS(RTContext& Ctx, Uint32 InstanceCount) +void CreateTLAS(const RTContext& Ctx, Uint32 InstanceCount, RTContext::AccelStruct& TLAS) { + TLAS.vkDevice = Ctx.vkDevice; + VkResult res = VK_SUCCESS; VkAccelerationStructureCreateInfoKHR TLASCI = {}; @@ -365,12 +364,12 @@ void CreateTLAS(RTContext& Ctx, Uint32 InstanceCount) TLASCI.maxGeometryCount = 1; TLASCI.pGeometryInfos = &Instances; - res = vkCreateAccelerationStructureKHR(Ctx.vkDevice, &TLASCI, nullptr, &Ctx.vkTLAS); + res = vkCreateAccelerationStructureKHR(Ctx.vkDevice, &TLASCI, nullptr, &TLAS.vkAS); ASSERT_GE(res, VK_SUCCESS); - ASSERT_TRUE(Ctx.vkTLAS != VK_NULL_HANDLE); + ASSERT_TRUE(TLAS.vkAS != VK_NULL_HANDLE); MemInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR; - MemInfo.accelerationStructure = Ctx.vkTLAS; + MemInfo.accelerationStructure = TLAS.vkAS; MemInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR; @@ -382,39 +381,34 @@ void CreateTLAS(RTContext& Ctx, Uint32 InstanceCount) MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; MemAlloc.allocationSize = MemReqs.memoryRequirements.size; - MemAlloc.memoryTypeIndex = ~0u; - - for (Uint32 i = 0; i < Ctx.MemoryProperties.memoryTypeCount; ++i) - { - const auto PropFlags = Ctx.MemoryProperties.memoryTypes[i].propertyFlags; - - if (!!(MemReqs.memoryRequirements.memoryTypeBits & (1u << i)) && !!(PropFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) - { - MemAlloc.memoryTypeIndex = i; - break; - } - } + MemAlloc.memoryTypeIndex = TestingEnvironmentVk::GetInstance()->GetMemoryTypeIndex(MemReqs.memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); ASSERT_TRUE(MemAlloc.memoryTypeIndex != ~0u); - res = vkAllocateMemory(Ctx.vkDevice, &MemAlloc, nullptr, &Ctx.vkTLASMemory); + res = vkAllocateMemory(Ctx.vkDevice, &MemAlloc, nullptr, &TLAS.vkMemory); ASSERT_GE(res, VK_SUCCESS); - ASSERT_TRUE(Ctx.vkTLASMemory != VK_NULL_HANDLE); + ASSERT_TRUE(TLAS.vkMemory != VK_NULL_HANDLE); VkBindAccelerationStructureMemoryInfoKHR BindInfo = {}; BindInfo.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR; - BindInfo.memory = Ctx.vkTLASMemory; + BindInfo.memory = TLAS.vkMemory; BindInfo.memoryOffset = 0; BindInfo.deviceIndexCount = 0; BindInfo.pDeviceIndices = nullptr; - BindInfo.accelerationStructure = Ctx.vkTLAS; + BindInfo.accelerationStructure = TLAS.vkAS; res = vkBindAccelerationStructureMemoryKHR(Ctx.vkDevice, 1, &BindInfo); ASSERT_GE(res, VK_SUCCESS); + + VkAccelerationStructureDeviceAddressInfoKHR AddressInfo = {}; + + AddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; + AddressInfo.accelerationStructure = TLAS.vkAS; + + TLAS.vkAddress = vkGetAccelerationStructureDeviceAddressKHR(Ctx.vkDevice, &AddressInfo); } -template <typename TCreateBufferFn> -void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 InstanceCount, Uint32 NumMissShaders, Uint32 NumHitShaders, TCreateBufferFn&& CreateBufferFn) +void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 InstanceCount, Uint32 NumMissShaders, Uint32 NumHitShaders, Uint32 ShaderRecordSize = 0) { VkResult res = VK_SUCCESS; @@ -431,9 +425,9 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan MemInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR; MemInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; - if (Ctx.vkBLAS) + if (Ctx.BLAS.vkAS) { - MemInfo.accelerationStructure = Ctx.vkBLAS; + MemInfo.accelerationStructure = Ctx.BLAS.vkAS; MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; vkGetAccelerationStructureMemoryRequirementsKHR(Ctx.vkDevice, &MemInfo, &MemReqs); @@ -444,9 +438,9 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan ScratchSize = std::max(ScratchSize, MemReqs.memoryRequirements.size); } - if (Ctx.vkTLAS) + if (Ctx.TLAS.vkAS) { - MemInfo.accelerationStructure = Ctx.vkTLAS; + MemInfo.accelerationStructure = Ctx.TLAS.vkAS; MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; vkGetAccelerationStructureMemoryRequirementsKHR(Ctx.vkDevice, &MemInfo, &MemReqs); @@ -466,7 +460,7 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan BufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR; BuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - BuffCI.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + BuffCI.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; MemInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2; std::vector<std::function<void(VkDeviceMemory Mem, VkDeviceSize & Offset)>> BindMem; @@ -569,9 +563,11 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan // SBT { - BuffCI.size = Align(Ctx.RayTracingProps.shaderGroupBaseAlignment, Ctx.RayTracingProps.shaderGroupHandleSize); - BuffCI.size = Align(BuffCI.size + Ctx.RayTracingProps.shaderGroupHandleSize * NumMissShaders, Ctx.RayTracingProps.shaderGroupBaseAlignment); - BuffCI.size = Align(BuffCI.size + Ctx.RayTracingProps.shaderGroupHandleSize * NumHitShaders, Ctx.RayTracingProps.shaderGroupBaseAlignment); + const Uint32 GroupSize = Ctx.RayTracingProps.shaderGroupHandleSize + ShaderRecordSize; + + BuffCI.size = Align(GroupSize, Ctx.RayTracingProps.shaderGroupBaseAlignment); + BuffCI.size = Align(BuffCI.size + GroupSize * NumMissShaders, Ctx.RayTracingProps.shaderGroupBaseAlignment); + BuffCI.size = Align(BuffCI.size + GroupSize * NumHitShaders, Ctx.RayTracingProps.shaderGroupBaseAlignment); res = vkCreateBuffer(Ctx.vkDevice, &BuffCI, nullptr, &Ctx.vkSBTBuffer); ASSERT_GE(res, VK_SUCCESS); @@ -591,31 +587,18 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan }); } - CreateBufferFn(MemSize, MemTypeBits, BindMem); - VkMemoryAllocateInfo MemAlloc = {}; VkMemoryAllocateFlagsInfo MemFlagInfo = {}; MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; MemAlloc.allocationSize = MemSize; - MemAlloc.memoryTypeIndex = ~0u; + MemAlloc.memoryTypeIndex = TestingEnvironmentVk::GetInstance()->GetMemoryTypeIndex(MemReqs.memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + ASSERT_TRUE(MemAlloc.memoryTypeIndex != ~0u); MemAlloc.pNext = &MemFlagInfo; MemFlagInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; MemFlagInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT; - for (Uint32 i = 0; i < Ctx.MemoryProperties.memoryTypeCount; ++i) - { - const auto PropFlags = Ctx.MemoryProperties.memoryTypes[i].propertyFlags; - - if (!!(MemTypeBits & (1u << i)) && !!(PropFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) - { - MemAlloc.memoryTypeIndex = i; - break; - } - } - ASSERT_TRUE(MemAlloc.memoryTypeIndex != ~0u); - res = vkAllocateMemory(Ctx.vkDevice, &MemAlloc, nullptr, &Ctx.vkBufferMemory); ASSERT_GE(res, VK_SUCCESS); ASSERT_TRUE(Ctx.vkBufferMemory != VK_NULL_HANDLE); @@ -628,9 +611,15 @@ void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 Instan ASSERT_GE(MemSize, Offset); } -void CreateRTBuffers(RTContext& Ctx, Uint32 VBSize, Uint32 IBSize, Uint32 InstanceCount, Uint32 NumMissShaders, Uint32 NumHitShaders) +void ClearRenderTarget(RTContext& Ctx, TestingSwapChainVk* pTestingSwapChainVk) { - return CreateRTBuffers(Ctx, VBSize, IBSize, InstanceCount, NumMissShaders, NumHitShaders, [](auto& MemSize, auto& MemTypeBits, auto& BindMem) {}); + pTestingSwapChainVk->TransitionRenderTarget(Ctx.vkCmdBuffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0); + + VkImageSubresourceRange Range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + VkClearColorValue ClearValue = {}; + vkCmdClearColorImage(Ctx.vkCmdBuffer, Ctx.vkRenderTarget, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &ClearValue, 1, &Range); + + pTestingSwapChainVk->TransitionRenderTarget(Ctx.vkCmdBuffer, VK_IMAGE_LAYOUT_GENERAL, 0); } } // namespace @@ -709,12 +698,7 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain) VkMemoryBarrier Barrier = {}; Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; - const float3 Vertices[] = // - { - float3{0.25f, 0.25f, 0.0f}, - float3{0.75f, 0.25f, 0.0f}, - float3{0.50f, 0.75f, 0.0f} // - }; + const auto& Vertices = TestingConstants::TriangleClosestHit::Vertices; VkAccelerationStructureCreateGeometryTypeInfoKHR GeometryCI = {}; @@ -726,11 +710,11 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain) GeometryCI.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; GeometryCI.allowsTransforms = VK_FALSE; - CreateBLAS(Ctx, &GeometryCI, 1); - CreateTLAS(Ctx, 1); + CreateBLAS(Ctx, &GeometryCI, 1, Ctx.BLAS); + CreateTLAS(Ctx, 1, Ctx.TLAS); CreateRTBuffers(Ctx, sizeof(Vertices), 0, 1, 1, 1); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Vertices), &Vertices); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Vertices), Vertices); // barrier for vertex & index buffers Barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; @@ -746,16 +730,14 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain) VkAccelerationStructureGeometryKHR const* GeometryPtr = &Geometry; VkAccelerationStructureBuildOffsetInfoKHR const* OffsetPtr = &Offset; - Geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - Geometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; - Geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - Geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - Geometry.geometry.triangles.vertexFormat = GeometryCI.vertexFormat; - Geometry.geometry.triangles.vertexStride = sizeof(Vertices[0]); - Geometry.geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress; - Geometry.geometry.triangles.indexType = VK_INDEX_TYPE_NONE_KHR; - Geometry.geometry.triangles.indexData.deviceAddress = 0; - Geometry.geometry.triangles.transformData.deviceAddress = 0; + Geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + Geometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; + Geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + Geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + Geometry.geometry.triangles.vertexFormat = GeometryCI.vertexFormat; + Geometry.geometry.triangles.vertexStride = sizeof(Vertices[0]); + Geometry.geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress; + Geometry.geometry.triangles.indexType = VK_INDEX_TYPE_NONE_KHR; Offset.primitiveCount = GeometryCI.maxPrimitiveCount; Offset.firstVertex = 0; @@ -767,7 +749,7 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain) ASBuildInfo.flags = 0; ASBuildInfo.update = VK_FALSE; ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE; - ASBuildInfo.dstAccelerationStructure = Ctx.vkBLAS; + ASBuildInfo.dstAccelerationStructure = Ctx.BLAS.vkAS; ASBuildInfo.geometryArrayOfPointers = VK_FALSE; ASBuildInfo.geometryCount = 1; ASBuildInfo.ppGeometries = &GeometryPtr; @@ -780,7 +762,7 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain) InstanceData.instanceShaderBindingTableRecordOffset = 0; InstanceData.mask = 0xFF; InstanceData.flags = 0; - InstanceData.accelerationStructureReference = Ctx.vkBLASAddress; + InstanceData.accelerationStructureReference = Ctx.BLAS.vkAddress; InstanceData.transform.matrix[0][0] = 1.0f; InstanceData.transform.matrix[1][1] = 1.0f; InstanceData.transform.matrix[2][2] = 1.0f; @@ -812,7 +794,7 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain) ASBuildInfo.flags = 0; ASBuildInfo.update = VK_FALSE; ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE; - ASBuildInfo.dstAccelerationStructure = Ctx.vkTLAS; + ASBuildInfo.dstAccelerationStructure = Ctx.TLAS.vkAS; ASBuildInfo.geometryArrayOfPointers = VK_FALSE; ASBuildInfo.geometryCount = 1; ASBuildInfo.ppGeometries = &GeometryPtr; @@ -831,33 +813,34 @@ void RayTracingTriangleClosestHitReferenceVk(ISwapChain* pSwapChain) VkStridedBufferRegionKHR MissShaderBindingTable = {}; VkStridedBufferRegionKHR HitShaderBindingTable = {}; VkStridedBufferRegionKHR CallableShaderBindingTable = {}; + const Uint32 ShaderGroupHandleSize = Ctx.RayTracingProps.shaderGroupHandleSize; RaygenShaderBindingTable.buffer = Ctx.vkSBTBuffer; RaygenShaderBindingTable.offset = 0; - RaygenShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize; - MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize; + RaygenShaderBindingTable.size = ShaderGroupHandleSize; + MissShaderBindingTable.stride = ShaderGroupHandleSize; MissShaderBindingTable.buffer = Ctx.vkSBTBuffer; MissShaderBindingTable.offset = Align(RaygenShaderBindingTable.offset + RaygenShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment); - MissShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize; - MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize; + MissShaderBindingTable.size = ShaderGroupHandleSize; + MissShaderBindingTable.stride = ShaderGroupHandleSize; HitShaderBindingTable.buffer = Ctx.vkSBTBuffer; HitShaderBindingTable.offset = Align(MissShaderBindingTable.offset + MissShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment); - HitShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize; - HitShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize; + HitShaderBindingTable.size = ShaderGroupHandleSize; + HitShaderBindingTable.stride = ShaderGroupHandleSize; char ShaderHandle[64] = {}; - ASSERT_GE(sizeof(ShaderHandle), Ctx.RayTracingProps.shaderGroupHandleSize); + ASSERT_GE(sizeof(ShaderHandle), ShaderGroupHandleSize); - vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle); - vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle); - vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle); // Barriers for TLAS & SBT VkMemoryBarrier Barrier = {}; @@ -965,12 +948,7 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain) VkMemoryBarrier Barrier = {}; Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; - const float3 Vertices[] = // - { - float3{0.25f, 0.25f, 0.0f}, float3{0.75f, 0.25f, 0.0f}, float3{0.50f, 0.75f, 0.0f}, - float3{0.50f, 0.10f, 0.1f}, float3{0.90f, 0.90f, 0.1f}, float3{0.10f, 0.90f, 0.1f}, - float3{0.40f, 1.00f, 0.2f}, float3{0.20f, 0.40f, 0.2f}, float3{1.00f, 0.70f, 0.2f} // - }; + const auto& Vertices = TestingConstants::TriangleAnyHit::Vertices; VkAccelerationStructureCreateGeometryTypeInfoKHR GeometryCI = {}; @@ -982,11 +960,11 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain) GeometryCI.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; GeometryCI.allowsTransforms = VK_FALSE; - CreateBLAS(Ctx, &GeometryCI, 1); - CreateTLAS(Ctx, 1); + CreateBLAS(Ctx, &GeometryCI, 1, Ctx.BLAS); + CreateTLAS(Ctx, 1, Ctx.TLAS); CreateRTBuffers(Ctx, sizeof(Vertices), 0, 1, 1, 1); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Vertices), &Vertices); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Vertices), Vertices); // barrier for vertex & index buffers Barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; @@ -1002,16 +980,14 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain) VkAccelerationStructureGeometryKHR const* GeometryPtr = &Geometry; VkAccelerationStructureBuildOffsetInfoKHR const* OffsetPtr = &Offset; - Geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - Geometry.flags = 0; - Geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - Geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - Geometry.geometry.triangles.vertexFormat = GeometryCI.vertexFormat; - Geometry.geometry.triangles.vertexStride = sizeof(Vertices[0]); - Geometry.geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress; - Geometry.geometry.triangles.indexType = VK_INDEX_TYPE_NONE_KHR; - Geometry.geometry.triangles.indexData.deviceAddress = 0; - Geometry.geometry.triangles.transformData.deviceAddress = 0; + Geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + Geometry.flags = 0; + Geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + Geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + Geometry.geometry.triangles.vertexFormat = GeometryCI.vertexFormat; + Geometry.geometry.triangles.vertexStride = sizeof(Vertices[0]); + Geometry.geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress; + Geometry.geometry.triangles.indexType = VK_INDEX_TYPE_NONE_KHR; Offset.primitiveCount = GeometryCI.maxPrimitiveCount; Offset.firstVertex = 0; @@ -1023,7 +999,7 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain) ASBuildInfo.flags = 0; ASBuildInfo.update = VK_FALSE; ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE; - ASBuildInfo.dstAccelerationStructure = Ctx.vkBLAS; + ASBuildInfo.dstAccelerationStructure = Ctx.BLAS.vkAS; ASBuildInfo.geometryArrayOfPointers = VK_FALSE; ASBuildInfo.geometryCount = 1; ASBuildInfo.ppGeometries = &GeometryPtr; @@ -1036,7 +1012,7 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain) InstanceData.instanceShaderBindingTableRecordOffset = 0; InstanceData.mask = 0xFF; InstanceData.flags = 0; - InstanceData.accelerationStructureReference = Ctx.vkBLASAddress; + InstanceData.accelerationStructureReference = Ctx.BLAS.vkAddress; InstanceData.transform.matrix[0][0] = 1.0f; InstanceData.transform.matrix[1][1] = 1.0f; InstanceData.transform.matrix[2][2] = 1.0f; @@ -1068,7 +1044,7 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain) ASBuildInfo.flags = 0; ASBuildInfo.update = VK_FALSE; ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE; - ASBuildInfo.dstAccelerationStructure = Ctx.vkTLAS; + ASBuildInfo.dstAccelerationStructure = Ctx.TLAS.vkAS; ASBuildInfo.geometryArrayOfPointers = VK_FALSE; ASBuildInfo.geometryCount = 1; ASBuildInfo.ppGeometries = &GeometryPtr; @@ -1087,33 +1063,34 @@ void RayTracingTriangleAnyHitReferenceVk(ISwapChain* pSwapChain) VkStridedBufferRegionKHR MissShaderBindingTable = {}; VkStridedBufferRegionKHR HitShaderBindingTable = {}; VkStridedBufferRegionKHR CallableShaderBindingTable = {}; + const Uint32 ShaderGroupHandleSize = Ctx.RayTracingProps.shaderGroupHandleSize; RaygenShaderBindingTable.buffer = Ctx.vkSBTBuffer; RaygenShaderBindingTable.offset = 0; - RaygenShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize; - MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize; + RaygenShaderBindingTable.size = ShaderGroupHandleSize; + MissShaderBindingTable.stride = ShaderGroupHandleSize; MissShaderBindingTable.buffer = Ctx.vkSBTBuffer; MissShaderBindingTable.offset = Align(RaygenShaderBindingTable.offset + RaygenShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment); - MissShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize; - MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize; + MissShaderBindingTable.size = ShaderGroupHandleSize; + MissShaderBindingTable.stride = ShaderGroupHandleSize; HitShaderBindingTable.buffer = Ctx.vkSBTBuffer; HitShaderBindingTable.offset = Align(MissShaderBindingTable.offset + MissShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment); - HitShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize; - HitShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize; + HitShaderBindingTable.size = ShaderGroupHandleSize; + HitShaderBindingTable.stride = ShaderGroupHandleSize; char ShaderHandle[64] = {}; - ASSERT_GE(sizeof(ShaderHandle), Ctx.RayTracingProps.shaderGroupHandleSize); + ASSERT_GE(sizeof(ShaderHandle), ShaderGroupHandleSize); - vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle); - vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle); - vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle); // Barriers for TLAS & SBT VkMemoryBarrier Barrier = {}; @@ -1221,11 +1198,7 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain) VkMemoryBarrier Barrier = {}; Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; - const float3 Boxes[] = // - { - float3{0.25f, 0.5f, 2.0f} - float3{1.0f, 1.0f, 1.0f}, - float3{0.25f, 0.5f, 2.0f} + float3{1.0f, 1.0f, 1.0f} // - }; + const auto& Boxes = TestingConstants::ProceduralIntersection::Boxes; VkAccelerationStructureCreateGeometryTypeInfoKHR GeometryCI = {}; @@ -1234,11 +1207,11 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain) GeometryCI.maxPrimitiveCount = 1; GeometryCI.indexType = VK_INDEX_TYPE_NONE_KHR; - CreateBLAS(Ctx, &GeometryCI, 1); - CreateTLAS(Ctx, 1); + CreateBLAS(Ctx, &GeometryCI, 1, Ctx.BLAS); + CreateTLAS(Ctx, 1, Ctx.TLAS); CreateRTBuffers(Ctx, sizeof(Boxes), 0, 1, 1, 1); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Boxes), &Boxes); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Boxes), Boxes); // barrier for vertex & index buffers Barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; @@ -1272,7 +1245,7 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain) ASBuildInfo.flags = 0; ASBuildInfo.update = VK_FALSE; ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE; - ASBuildInfo.dstAccelerationStructure = Ctx.vkBLAS; + ASBuildInfo.dstAccelerationStructure = Ctx.BLAS.vkAS; ASBuildInfo.geometryArrayOfPointers = VK_FALSE; ASBuildInfo.geometryCount = 1; ASBuildInfo.ppGeometries = &GeometryPtr; @@ -1285,7 +1258,7 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain) InstanceData.instanceShaderBindingTableRecordOffset = 0; InstanceData.mask = 0xFF; InstanceData.flags = 0; - InstanceData.accelerationStructureReference = Ctx.vkBLASAddress; + InstanceData.accelerationStructureReference = Ctx.BLAS.vkAddress; InstanceData.transform.matrix[0][0] = 1.0f; InstanceData.transform.matrix[1][1] = 1.0f; InstanceData.transform.matrix[2][2] = 1.0f; @@ -1317,7 +1290,7 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain) ASBuildInfo.flags = 0; ASBuildInfo.update = VK_FALSE; ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE; - ASBuildInfo.dstAccelerationStructure = Ctx.vkTLAS; + ASBuildInfo.dstAccelerationStructure = Ctx.TLAS.vkAS; ASBuildInfo.geometryArrayOfPointers = VK_FALSE; ASBuildInfo.geometryCount = 1; ASBuildInfo.ppGeometries = &GeometryPtr; @@ -1336,33 +1309,34 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain) VkStridedBufferRegionKHR MissShaderBindingTable = {}; VkStridedBufferRegionKHR HitShaderBindingTable = {}; VkStridedBufferRegionKHR CallableShaderBindingTable = {}; + const Uint32 ShaderGroupHandleSize = Ctx.RayTracingProps.shaderGroupHandleSize; RaygenShaderBindingTable.buffer = Ctx.vkSBTBuffer; RaygenShaderBindingTable.offset = 0; - RaygenShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize; - MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize; + RaygenShaderBindingTable.size = ShaderGroupHandleSize; + MissShaderBindingTable.stride = ShaderGroupHandleSize; MissShaderBindingTable.buffer = Ctx.vkSBTBuffer; MissShaderBindingTable.offset = Align(RaygenShaderBindingTable.offset + RaygenShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment); - MissShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize; - MissShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize; + MissShaderBindingTable.size = ShaderGroupHandleSize; + MissShaderBindingTable.stride = ShaderGroupHandleSize; HitShaderBindingTable.buffer = Ctx.vkSBTBuffer; HitShaderBindingTable.offset = Align(MissShaderBindingTable.offset + MissShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment); - HitShaderBindingTable.size = Ctx.RayTracingProps.shaderGroupHandleSize; - HitShaderBindingTable.stride = Ctx.RayTracingProps.shaderGroupHandleSize; + HitShaderBindingTable.size = ShaderGroupHandleSize; + HitShaderBindingTable.stride = ShaderGroupHandleSize; char ShaderHandle[64] = {}; - ASSERT_GE(sizeof(ShaderHandle), Ctx.RayTracingProps.shaderGroupHandleSize); + ASSERT_GE(sizeof(ShaderHandle), ShaderGroupHandleSize); - vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle); - vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle); - vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); - vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, Ctx.RayTracingProps.shaderGroupHandleSize, ShaderHandle); + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, HIT_GROUP, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, HitShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle); // barrier for TLAS & SBT VkMemoryBarrier Barrier = {}; @@ -1388,6 +1362,398 @@ void RayTracingProceduralIntersectionReferenceVk(ISwapChain* pSwapChain) pEnv->SubmitCommandBuffer(Ctx.vkCmdBuffer, true); } + +void RayTracingMultiGeometryReferenceVk(ISwapChain* pSwapChain) +{ + static constexpr Uint32 InstanceCount = TestingConstants::MultiGeometry::InstanceCount; + static constexpr Uint32 GeometryCount = 3; + static constexpr Uint32 HitGroupCount = InstanceCount * GeometryCount; + + enum + { + RAYGEN_SHADER, + MISS_SHADER, + HIT_SHADER_1, + HIT_SHADER_2, + NUM_SHADERS + }; + enum + { + RAYGEN_GROUP, + MISS_GROUP, + HIT_GROUP_1, + HIT_GROUP_2, + NUM_GROUPS + }; + + auto* pEnv = TestingEnvironmentVk::GetInstance(); + auto* pTestingSwapChainVk = ValidatedCast<TestingSwapChainVk>(pSwapChain); + + const auto& SCDesc = pSwapChain->GetDesc(); + + RTContext Ctx = {}; + InitializeRTContext(Ctx, pSwapChain, + [pEnv](auto& Bindings, auto& Modules, auto& Stages, auto& Groups) { + Bindings.resize(3); + Bindings[0] = {2u, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, InstanceCount, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, nullptr}; + Bindings[1] = {3u, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, nullptr}; + Bindings[2] = {4u, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, nullptr}; + + Modules.resize(NUM_SHADERS); + Stages.resize(NUM_SHADERS); + Groups.resize(NUM_GROUPS); + + Modules[RAYGEN_SHADER] = pEnv->CreateShaderModule(SHADER_TYPE_RAY_GEN, GLSL::RayTracingTest4_RG); + Stages[RAYGEN_SHADER].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + Stages[RAYGEN_SHADER].stage = VK_SHADER_STAGE_RAYGEN_BIT_KHR; + Stages[RAYGEN_SHADER].module = Modules[RAYGEN_SHADER]; + Stages[RAYGEN_SHADER].pName = "main"; + + Modules[MISS_SHADER] = pEnv->CreateShaderModule(SHADER_TYPE_RAY_MISS, GLSL::RayTracingTest4_RM); + Stages[MISS_SHADER].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + Stages[MISS_SHADER].stage = VK_SHADER_STAGE_MISS_BIT_KHR; + Stages[MISS_SHADER].module = Modules[MISS_SHADER]; + Stages[MISS_SHADER].pName = "main"; + + Modules[HIT_SHADER_1] = pEnv->CreateShaderModule(SHADER_TYPE_RAY_CLOSEST_HIT, GLSL::RayTracingTest4_RCH1); + Stages[HIT_SHADER_1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + Stages[HIT_SHADER_1].stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; + Stages[HIT_SHADER_1].module = Modules[HIT_SHADER_1]; + Stages[HIT_SHADER_1].pName = "main"; + + Modules[HIT_SHADER_2] = pEnv->CreateShaderModule(SHADER_TYPE_RAY_CLOSEST_HIT, GLSL::RayTracingTest4_RCH2); + Stages[HIT_SHADER_2].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + Stages[HIT_SHADER_2].stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; + Stages[HIT_SHADER_2].module = Modules[HIT_SHADER_2]; + Stages[HIT_SHADER_2].pName = "main"; + + Groups[RAYGEN_GROUP].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + Groups[RAYGEN_GROUP].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + Groups[RAYGEN_GROUP].generalShader = RAYGEN_SHADER; + Groups[RAYGEN_GROUP].closestHitShader = VK_SHADER_UNUSED_KHR; + Groups[RAYGEN_GROUP].anyHitShader = VK_SHADER_UNUSED_KHR; + Groups[RAYGEN_GROUP].intersectionShader = VK_SHADER_UNUSED_KHR; + + Groups[HIT_GROUP_1].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + Groups[HIT_GROUP_1].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; + Groups[HIT_GROUP_1].generalShader = VK_SHADER_UNUSED_KHR; + Groups[HIT_GROUP_1].closestHitShader = HIT_SHADER_1; + Groups[HIT_GROUP_1].anyHitShader = VK_SHADER_UNUSED_KHR; + Groups[HIT_GROUP_1].intersectionShader = VK_SHADER_UNUSED_KHR; + + Groups[HIT_GROUP_2].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + Groups[HIT_GROUP_2].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; + Groups[HIT_GROUP_2].generalShader = VK_SHADER_UNUSED_KHR; + Groups[HIT_GROUP_2].closestHitShader = HIT_SHADER_2; + Groups[HIT_GROUP_2].anyHitShader = VK_SHADER_UNUSED_KHR; + Groups[HIT_GROUP_2].intersectionShader = VK_SHADER_UNUSED_KHR; + + Groups[MISS_GROUP].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + Groups[MISS_GROUP].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + Groups[MISS_GROUP].generalShader = MISS_SHADER; + Groups[MISS_GROUP].closestHitShader = VK_SHADER_UNUSED_KHR; + Groups[MISS_GROUP].anyHitShader = VK_SHADER_UNUSED_KHR; + Groups[MISS_GROUP].intersectionShader = VK_SHADER_UNUSED_KHR; + }); + + const auto& PrimitiveOffsets = TestingConstants::MultiGeometry::PrimitiveOffsets; + const auto& Primitives = TestingConstants::MultiGeometry::Primitives; + + // create acceleration structurea + { + VkMemoryBarrier Barrier = {}; + Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + + const auto& Vertices = TestingConstants::MultiGeometry::Vertices; + const auto& Indices = TestingConstants::MultiGeometry::Indices; + + VkAccelerationStructureCreateGeometryTypeInfoKHR GeometryCI[3] = {}; + + GeometryCI[0].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + GeometryCI[0].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + GeometryCI[0].maxPrimitiveCount = PrimitiveOffsets[1]; + GeometryCI[0].indexType = VK_INDEX_TYPE_UINT32; + GeometryCI[0].maxVertexCount = _countof(Vertices); + GeometryCI[0].vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; + GeometryCI[0].allowsTransforms = VK_FALSE; + + GeometryCI[1].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + GeometryCI[1].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + GeometryCI[1].maxPrimitiveCount = PrimitiveOffsets[2] - PrimitiveOffsets[1]; + GeometryCI[1].indexType = VK_INDEX_TYPE_UINT32; + GeometryCI[1].maxVertexCount = _countof(Vertices); + GeometryCI[1].vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; + GeometryCI[1].allowsTransforms = VK_FALSE; + + GeometryCI[2].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + GeometryCI[2].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + GeometryCI[2].maxPrimitiveCount = _countof(Primitives) - PrimitiveOffsets[2]; + GeometryCI[2].indexType = VK_INDEX_TYPE_UINT32; + GeometryCI[2].maxVertexCount = _countof(Vertices); + GeometryCI[2].vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; + GeometryCI[2].allowsTransforms = VK_FALSE; + + CreateBLAS(Ctx, GeometryCI, _countof(GeometryCI), Ctx.BLAS); + CreateTLAS(Ctx, 1, Ctx.TLAS); + CreateRTBuffers(Ctx, sizeof(Vertices), sizeof(Indices), InstanceCount, 1, HitGroupCount, TestingConstants::MultiGeometry::ShaderRecordSize); + + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkVertexBuffer, 0, sizeof(Vertices), Vertices); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkIndexBuffer, 0, sizeof(Indices), Indices); + + // barrier for vertex & index buffers + Barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + Barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; + vkCmdPipelineBarrier(Ctx.vkCmdBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + 0, 1, &Barrier, 0, nullptr, 0, nullptr); + + VkAccelerationStructureBuildGeometryInfoKHR ASBuildInfo = {}; + VkAccelerationStructureBuildOffsetInfoKHR Offsets[3] = {}; + VkAccelerationStructureGeometryKHR Geometries[3] = {}; + VkAccelerationStructureGeometryKHR const* GeometriyPtr = Geometries; + VkAccelerationStructureBuildOffsetInfoKHR const* OffsetPtr = Offsets; + static_assert(_countof(Offsets) == _countof(Geometries), "size mismatch"); + static_assert(_countof(GeometryCI) == _countof(Geometries), "size mismatch"); + static_assert(GeometryCount == _countof(Geometries), "size mismatch"); + + Geometries[0].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + Geometries[0].flags = VK_GEOMETRY_OPAQUE_BIT_KHR; + Geometries[0].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + Geometries[0].geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + Geometries[0].geometry.triangles.vertexFormat = GeometryCI[0].vertexFormat; + Geometries[0].geometry.triangles.vertexStride = sizeof(Vertices[0]); + Geometries[0].geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress; + Geometries[0].geometry.triangles.indexType = GeometryCI[0].indexType; + Geometries[0].geometry.triangles.indexData.deviceAddress = Ctx.vkIndexBufferAddress + PrimitiveOffsets[0] * sizeof(uint) * 3; + + Geometries[1].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + Geometries[1].flags = VK_GEOMETRY_OPAQUE_BIT_KHR; + Geometries[1].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + Geometries[1].geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + Geometries[1].geometry.triangles.vertexFormat = GeometryCI[1].vertexFormat; + Geometries[1].geometry.triangles.vertexStride = sizeof(Vertices[0]); + Geometries[1].geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress; + Geometries[1].geometry.triangles.indexType = GeometryCI[1].indexType; + Geometries[1].geometry.triangles.indexData.deviceAddress = Ctx.vkIndexBufferAddress + PrimitiveOffsets[1] * sizeof(uint) * 3; + + Geometries[2].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + Geometries[2].flags = VK_GEOMETRY_OPAQUE_BIT_KHR; + Geometries[2].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + Geometries[2].geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + Geometries[2].geometry.triangles.vertexFormat = GeometryCI[2].vertexFormat; + Geometries[2].geometry.triangles.vertexStride = sizeof(Vertices[0]); + Geometries[2].geometry.triangles.vertexData.deviceAddress = Ctx.vkVertexBufferAddress; + Geometries[2].geometry.triangles.indexType = GeometryCI[2].indexType; + Geometries[2].geometry.triangles.indexData.deviceAddress = Ctx.vkIndexBufferAddress + PrimitiveOffsets[2] * sizeof(uint) * 3; + + Offsets[0].primitiveCount = GeometryCI[0].maxPrimitiveCount; + Offsets[1].primitiveCount = GeometryCI[1].maxPrimitiveCount; + Offsets[2].primitiveCount = GeometryCI[2].maxPrimitiveCount; + + ASBuildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + ASBuildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + ASBuildInfo.flags = 0; + ASBuildInfo.update = VK_FALSE; + ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE; + ASBuildInfo.dstAccelerationStructure = Ctx.BLAS.vkAS; + ASBuildInfo.geometryArrayOfPointers = VK_FALSE; + ASBuildInfo.geometryCount = _countof(Geometries); + ASBuildInfo.ppGeometries = &GeometriyPtr; + ASBuildInfo.scratchData.deviceAddress = Ctx.vkScratchBufferAddress; + + vkCmdBuildAccelerationStructureKHR(Ctx.vkCmdBuffer, 1, &ASBuildInfo, &OffsetPtr); + + VkAccelerationStructureInstanceKHR InstanceData[2] = {}; + + InstanceData[0].instanceCustomIndex = 0; + InstanceData[0].instanceShaderBindingTableRecordOffset = 0; + InstanceData[0].mask = 0xFF; + InstanceData[0].flags = 0; + InstanceData[0].accelerationStructureReference = Ctx.BLAS.vkAddress; + InstanceData[0].transform.matrix[0][0] = 1.0f; + InstanceData[0].transform.matrix[1][1] = 1.0f; + InstanceData[0].transform.matrix[2][2] = 1.0f; + + InstanceData[1].instanceCustomIndex = 2; + InstanceData[1].instanceShaderBindingTableRecordOffset = HitGroupCount / 2; + InstanceData[1].mask = 0xFF; + InstanceData[1].flags = 0; + InstanceData[1].accelerationStructureReference = Ctx.BLAS.vkAddress; + InstanceData[1].transform.matrix[0][0] = 1.0f; + InstanceData[1].transform.matrix[1][1] = 1.0f; + InstanceData[1].transform.matrix[2][2] = 1.0f; + InstanceData[1].transform.matrix[0][3] = 0.1f; + InstanceData[1].transform.matrix[1][3] = 0.5f; + InstanceData[1].transform.matrix[2][3] = 0.0f; + + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkInstanceBuffer, 0, sizeof(InstanceData), InstanceData); + + // barrier for BLAS, scratch buffer, instance buffer + Barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_TRANSFER_WRITE_BIT; + Barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; + vkCmdPipelineBarrier(Ctx.vkCmdBuffer, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + 0, 1, &Barrier, 0, nullptr, 0, nullptr); + + VkAccelerationStructureBuildOffsetInfoKHR InstOffsets = {}; + VkAccelerationStructureGeometryKHR Instances[2] = {}; + static_assert(_countof(InstanceData) == _countof(Instances), "size mismatch"); + static_assert(InstanceCount == _countof(Instances), "size mismatch"); + + GeometriyPtr = Instances; + OffsetPtr = &InstOffsets; + InstOffsets.primitiveCount = _countof(Instances); + + Instances[0].flags = 0; + Instances[0].geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + Instances[0].geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; + Instances[0].geometry.instances.pNext = nullptr; + Instances[0].geometry.instances.arrayOfPointers = VK_FALSE; + Instances[0].geometry.instances.data.deviceAddress = Ctx.vkInstanceBufferAddress; + + Instances[1].flags = 0; + Instances[1].geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + Instances[1].geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; + Instances[1].geometry.instances.pNext = nullptr; + Instances[1].geometry.instances.arrayOfPointers = VK_FALSE; + Instances[1].geometry.instances.data.deviceAddress = Ctx.vkInstanceBufferAddress + sizeof(VkAccelerationStructureInstanceKHR); + + ASBuildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + ASBuildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + ASBuildInfo.flags = 0; + ASBuildInfo.update = VK_FALSE; + ASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE; + ASBuildInfo.dstAccelerationStructure = Ctx.TLAS.vkAS; + ASBuildInfo.geometryArrayOfPointers = VK_FALSE; + ASBuildInfo.geometryCount = 1; + ASBuildInfo.ppGeometries = &GeometriyPtr; + ASBuildInfo.scratchData.deviceAddress = Ctx.vkScratchBufferAddress; + + vkCmdBuildAccelerationStructureKHR(Ctx.vkCmdBuffer, 1, &ASBuildInfo, &OffsetPtr); + } + + ClearRenderTarget(Ctx, pTestingSwapChainVk); + UpdateDescriptorSet(Ctx); + + VkBuffer vkPerInstanceBuffer = VK_NULL_HANDLE; + VkDeviceMemory vkPerInstanceBufferMemory = VK_NULL_HANDLE; + VkBuffer vkPrimitiveBuffer = VK_NULL_HANDLE; + VkDeviceMemory vkPrimitiveBufferMemory = VK_NULL_HANDLE; + { + pEnv->CreateBuffer(sizeof(PrimitiveOffsets), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vkPerInstanceBufferMemory, vkPerInstanceBuffer); + pEnv->CreateBuffer(sizeof(Primitives), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vkPrimitiveBufferMemory, vkPrimitiveBuffer); + + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, vkPerInstanceBuffer, 0, sizeof(PrimitiveOffsets), PrimitiveOffsets); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, vkPrimitiveBuffer, 0, sizeof(Primitives), Primitives); + + VkWriteDescriptorSet DescriptorWrite = {}; + VkDescriptorBufferInfo BufInfo = {}; + + DescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + DescriptorWrite.dstSet = Ctx.vkDescriptorSet; + DescriptorWrite.dstBinding = 4; + DescriptorWrite.dstArrayElement = 0; + DescriptorWrite.descriptorCount = 1; + DescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + DescriptorWrite.pBufferInfo = &BufInfo; + BufInfo.buffer = Ctx.vkVertexBuffer; + BufInfo.range = VK_WHOLE_SIZE; + vkUpdateDescriptorSets(Ctx.vkDevice, 1, &DescriptorWrite, 0, nullptr); + + DescriptorWrite.dstBinding = 3; + BufInfo.buffer = vkPrimitiveBuffer; + vkUpdateDescriptorSets(Ctx.vkDevice, 1, &DescriptorWrite, 0, nullptr); + + DescriptorWrite.dstBinding = 2; + BufInfo.buffer = vkPerInstanceBuffer; + vkUpdateDescriptorSets(Ctx.vkDevice, 1, &DescriptorWrite, 0, nullptr); + + DescriptorWrite.dstArrayElement = 1; + vkUpdateDescriptorSets(Ctx.vkDevice, 1, &DescriptorWrite, 0, nullptr); + } + + // trace rays + { + VkStridedBufferRegionKHR RaygenShaderBindingTable = {}; + VkStridedBufferRegionKHR MissShaderBindingTable = {}; + VkStridedBufferRegionKHR HitShaderBindingTable = {}; + VkStridedBufferRegionKHR CallableShaderBindingTable = {}; + const Uint32 ShaderGroupHandleSize = Ctx.RayTracingProps.shaderGroupHandleSize; + const Uint32 ShaderRecordSize = ShaderGroupHandleSize + TestingConstants::MultiGeometry::ShaderRecordSize; + const auto& Weights = TestingConstants::MultiGeometry::Weights; + + RaygenShaderBindingTable.buffer = Ctx.vkSBTBuffer; + RaygenShaderBindingTable.offset = 0; + RaygenShaderBindingTable.size = ShaderRecordSize; + MissShaderBindingTable.stride = ShaderRecordSize; + + MissShaderBindingTable.buffer = Ctx.vkSBTBuffer; + MissShaderBindingTable.offset = Align(RaygenShaderBindingTable.offset + RaygenShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment); + MissShaderBindingTable.size = ShaderRecordSize; + MissShaderBindingTable.stride = ShaderRecordSize; + + HitShaderBindingTable.buffer = Ctx.vkSBTBuffer; + HitShaderBindingTable.offset = Align(MissShaderBindingTable.offset + MissShaderBindingTable.size, Ctx.RayTracingProps.shaderGroupBaseAlignment); + HitShaderBindingTable.size = ShaderRecordSize * HitGroupCount; + HitShaderBindingTable.stride = ShaderRecordSize; + + char ShaderHandle[64] = {}; + ASSERT_GE(sizeof(ShaderHandle), ShaderGroupHandleSize); + + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, RAYGEN_GROUP, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, RaygenShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle); + + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, MISS_GROUP, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, MissShaderBindingTable.offset, ShaderGroupHandleSize, ShaderHandle); + + const auto SetHitGroup = [&](Uint32 Index, Uint32 ShaderIndex, const void* ShaderRecord) { + VERIFY_EXPR(Index < HitGroupCount); + VkDeviceSize Offset = HitShaderBindingTable.offset + Index * ShaderRecordSize; + vkGetRayTracingShaderGroupHandlesKHR(Ctx.vkDevice, Ctx.vkPipeline, ShaderIndex, 1, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, Offset, ShaderGroupHandleSize, ShaderHandle); + vkCmdUpdateBuffer(Ctx.vkCmdBuffer, Ctx.vkSBTBuffer, Offset + ShaderGroupHandleSize, sizeof(Weights[0]), ShaderRecord); + }; + // instance 1 + SetHitGroup(0, HIT_GROUP_1, &Weights[2]); // geometry 1 + SetHitGroup(1, HIT_GROUP_1, &Weights[0]); // geometry 2 + SetHitGroup(2, HIT_GROUP_1, &Weights[1]); // geometry 3 + // instance 2 + SetHitGroup(3, HIT_GROUP_2, &Weights[2]); // geometry 1 + SetHitGroup(4, HIT_GROUP_2, &Weights[1]); // geometry 2 + SetHitGroup(5, HIT_GROUP_2, &Weights[0]); // geometry 3 + + // barrier for TLAS & SBT + VkMemoryBarrier Barrier = {}; + Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + Barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_TRANSFER_WRITE_BIT; + Barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + vkCmdPipelineBarrier(Ctx.vkCmdBuffer, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + 0, 1, &Barrier, 0, nullptr, 0, nullptr); + + vkCmdBindPipeline(Ctx.vkCmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, Ctx.vkPipeline); + vkCmdBindDescriptorSets(Ctx.vkCmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, Ctx.vkLayout, 0, 1, &Ctx.vkDescriptorSet, 0, nullptr); + + vkCmdTraceRaysKHR(Ctx.vkCmdBuffer, &RaygenShaderBindingTable, &MissShaderBindingTable, &HitShaderBindingTable, &CallableShaderBindingTable, SCDesc.Width, SCDesc.Height, 1); + + pTestingSwapChainVk->TransitionRenderTarget(Ctx.vkCmdBuffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0); + } + + auto res = vkEndCommandBuffer(Ctx.vkCmdBuffer); + VERIFY(res >= 0, "Failed to end command buffer"); + + pEnv->SubmitCommandBuffer(Ctx.vkCmdBuffer, true); + + vkDestroyBuffer(Ctx.vkDevice, vkPerInstanceBuffer, nullptr); + vkDestroyBuffer(Ctx.vkDevice, vkPrimitiveBuffer, nullptr); + vkFreeMemory(Ctx.vkDevice, vkPerInstanceBufferMemory, nullptr); + vkFreeMemory(Ctx.vkDevice, vkPrimitiveBufferMemory, nullptr); +} + + } // namespace Testing } // namespace Diligent |
