summaryrefslogtreecommitdiffstats
path: root/Tests
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-11-03 10:52:24 +0000
committerazhirnov <zh1dron@gmail.com>2020-11-03 11:16:11 +0000
commitefa43e2bd2475a4dec6771bf9759f6a99f7d77ed (patch)
treebbb257c3825ff07078626e3e137468f99d235a07 /Tests
parentFew improvements to ray tracing tests (diff)
downloadDiligentCore-efa43e2bd2475a4dec6771bf9759f6a99f7d77ed.tar.gz
DiligentCore-efa43e2bd2475a4dec6771bf9759f6a99f7d77ed.zip
fixed resource state transitions, some improvements for ray tracing
Diffstat (limited to 'Tests')
-rw-r--r--Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestGLSL.h120
-rw-r--r--Tests/DiligentCoreAPITest/include/InlineShaders/RayTracingTestHLSL.h99
-rw-r--r--Tests/DiligentCoreAPITest/include/RayTracingTestConstants.hpp155
-rw-r--r--Tests/DiligentCoreAPITest/src/D3D12/RayTracingReferenceD3D12.cpp679
-rw-r--r--Tests/DiligentCoreAPITest/src/RayTracingTest.cpp333
-rw-r--r--Tests/DiligentCoreAPITest/src/Vulkan/RayTracingReferenceVk.cpp746
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