Skip to content

Commit b3800bf

Browse files
MarijnS95claude
authored andcommitted
Add per-instance InstanceFlags YAML field and front-CCW test
Introduces AccelerationStructureInstanceFlags with bit values that intentionally match D3D12_RAYTRACING_INSTANCE_FLAGS, VkGeometryInstance- FlagBitsKHR, and MTLAccelerationStructureInstanceOptions so backends can pass the value through unchanged. YAML exposes the field as a bitset list (e.g. `InstanceFlags: [TriangleCullDisable, ForceOpaque]`). The covering test sets TriangleFrontCounterclockwise on one of two instances and verifies CommittedTriangleFrontFace() flips against the same BLAS. Part of the inline-RT test coverage epic (#1258). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d4e7a81 commit b3800bf

8 files changed

Lines changed: 135 additions & 3 deletions

File tree

include/API/AccelerationStructure.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,26 @@
1414
#include "API/Resources.h"
1515

1616
#include "llvm/ADT/ArrayRef.h"
17+
#include "llvm/ADT/BitmaskEnum.h"
1718
#include "llvm/ADT/SmallVector.h"
1819
#include "llvm/Support/Error.h"
1920

2021
#include <cstdint>
2122
#include <variant>
2223

2324
namespace offloadtest {
25+
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
26+
27+
// Bit values match D3D12_RAYTRACING_INSTANCE_FLAGS, VkGeometryInstanceFlagBits-
28+
// KHR, and MTLAccelerationStructureInstanceOptions so backends can pass the
29+
// value through unchanged.
30+
enum AccelerationStructureInstanceFlags : uint32_t {
31+
InstanceFlagNone = 0,
32+
TriangleCullDisable = 1 << 0,
33+
TriangleFrontCounterclockwise = 1 << 1,
34+
ForceOpaque = 1 << 2,
35+
ForceNonOpaque = 1 << 3,
36+
};
2437

2538
struct AccelerationStructureSizes {
2639
uint64_t ResultDataMaxSizeInBytes = 0;
@@ -57,6 +70,7 @@ struct AccelerationStructureInstance {
5770
uint8_t InstanceMask = 0xFF;
5871
// 24-bit; high bits are truncated by the backend to match DXR's bitfield.
5972
uint32_t InstanceContributionToHitGroupIndex = 0;
73+
AccelerationStructureInstanceFlags Flags = InstanceFlagNone;
6074
AccelerationStructure *BLAS = nullptr;
6175
};
6276

@@ -178,4 +192,9 @@ class AccelerationStructure {
178192

179193
} // namespace offloadtest
180194

195+
namespace llvm {
196+
LLVM_DECLARE_ENUM_AS_BITMASK(::offloadtest::AccelerationStructureInstanceFlags,
197+
::offloadtest::ForceNonOpaque);
198+
} // namespace llvm
199+
181200
#endif // OFFLOADTEST_API_ACCELERATIONSTRUCTURE_H

include/Support/Pipeline.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef OFFLOADTEST_SUPPORT_PIPELINE_H
1414
#define OFFLOADTEST_SUPPORT_PIPELINE_H
1515

16+
#include "API/AccelerationStructure.h"
1617
#include "API/Enums.h"
1718
#include "API/Resources.h"
1819
#include "llvm/ADT/SmallVector.h"
@@ -554,6 +555,7 @@ struct InstanceDesc {
554555
uint32_t InstanceID = 0;
555556
uint8_t InstanceMask = 0xFF;
556557
uint32_t InstanceContributionToHitGroupIndex = 0;
558+
AccelerationStructureInstanceFlags Flags = InstanceFlagNone;
557559
};
558560

559561
struct TLASDesc {
@@ -830,6 +832,19 @@ template <> struct MappingTraits<offloadtest::ShaderBindingTableDesc> {
830832
static void mapping(IO &I, offloadtest::ShaderBindingTableDesc &S);
831833
};
832834

835+
template <>
836+
struct ScalarBitSetTraits<offloadtest::AccelerationStructureInstanceFlags> {
837+
static void bitset(IO &I,
838+
offloadtest::AccelerationStructureInstanceFlags &V) {
839+
#define BIT_CASE(Val) I.bitSetCase(V, #Val, offloadtest::Val)
840+
BIT_CASE(TriangleCullDisable);
841+
BIT_CASE(TriangleFrontCounterclockwise);
842+
BIT_CASE(ForceOpaque);
843+
BIT_CASE(ForceNonOpaque);
844+
#undef BIT_CASE
845+
}
846+
};
847+
833848
template <> struct ScalarEnumerationTraits<offloadtest::Rule> {
834849
static void enumeration(IO &I, offloadtest::Rule &V) {
835850
#define ENUM_CASE(Val) I.enumCase(V, #Val, offloadtest::Rule::Val)

lib/API/DX/Device.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3278,7 +3278,9 @@ llvm::Error DXComputeEncoder::batchBuildAS(llvm::ArrayRef<ASBuildItem> Items) {
32783278
NI.InstanceMask = Inst.InstanceMask;
32793279
NI.InstanceContributionToHitGroupIndex =
32803280
Inst.InstanceContributionToHitGroupIndex & 0xFFFFFFu;
3281-
NI.Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE;
3281+
// Bits in AccelerationStructureInstanceFlags match
3282+
// D3D12_RAYTRACING_INSTANCE_FLAGS by design.
3283+
NI.Flags = static_cast<D3D12_RAYTRACING_INSTANCE_FLAGS>(Inst.Flags);
32823284
auto *BLASPtr = llvm::cast<DXAccelerationStructure>(Inst.BLAS);
32833285
NI.AccelerationStructure = BLASPtr->getGPUVirtualAddress();
32843286
Native.push_back(NI);

lib/API/Device.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ llvm::Error offloadtest::buildPipelineAccelerationStructures(
248248
Inst.InstanceMask = I.InstanceMask;
249249
Inst.InstanceContributionToHitGroupIndex =
250250
I.InstanceContributionToHitGroupIndex;
251+
Inst.Flags = I.Flags;
251252
Inst.BLAS = It->second;
252253
Req.Instances.push_back(Inst);
253254
}

lib/API/MTL/MTLDevice.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2578,7 +2578,10 @@ llvm::Error MTLComputeEncoder::batchBuildAS(llvm::ArrayRef<ASBuildItem> Items) {
25782578
for (int Row = 0; Row < 3; ++Row)
25792579
for (int Col = 0; Col < 4; ++Col)
25802580
D.transformationMatrix.columns[Col][Row] = Src.Transform[Row][Col];
2581-
D.options = MTL::AccelerationStructureInstanceOptionNone;
2581+
// Bits in AccelerationStructureInstanceFlags match
2582+
// MTLAccelerationStructureInstanceOptions by design.
2583+
D.options =
2584+
static_cast<MTL::AccelerationStructureInstanceOptions>(Src.Flags);
25822585
D.mask = Src.InstanceMask;
25832586
D.intersectionFunctionTableOffset = 0;
25842587
D.accelerationStructureIndex = InstanceASIdx[I];

lib/API/VK/Device.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4818,7 +4818,9 @@ llvm::Error VKComputeEncoder::batchBuildAS(llvm::ArrayRef<ASBuildItem> Items) {
48184818
NI.mask = Inst.InstanceMask;
48194819
NI.instanceShaderBindingTableRecordOffset =
48204820
Inst.InstanceContributionToHitGroupIndex & 0xFFFFFFu;
4821-
NI.flags = 0;
4821+
// Bits in AccelerationStructureInstanceFlags match
4822+
// VkGeometryInstanceFlagBitsKHR by design.
4823+
NI.flags = static_cast<VkGeometryInstanceFlagsKHR>(Inst.Flags);
48224824
auto *BLASPtr = llvm::cast<VulkanAccelerationStructure>(Inst.BLAS);
48234825
NI.accelerationStructureReference = BLASPtr->getDeviceAddress();
48244826
Native.push_back(NI);

lib/Support/Pipeline.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,7 @@ void MappingTraits<offloadtest::InstanceDesc>::mapping(
674674
D.InstanceMask = static_cast<uint8_t>(Mask);
675675
I.mapOptional("InstanceContributionToHitGroupIndex",
676676
D.InstanceContributionToHitGroupIndex, 0u);
677+
I.mapOptional("InstanceFlags", D.Flags, offloadtest::InstanceFlagNone);
677678
}
678679

679680
void MappingTraits<offloadtest::TLASDesc>::mapping(IO &I,
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#--- source.hlsl
2+
3+
[[vk::binding(0, 0)]] RaytracingAccelerationStructure Scene : register(t0);
4+
[[vk::binding(1, 0)]] RWStructuredBuffer<uint> Output : register(u0);
5+
6+
[numthreads(2,1,1)]
7+
void main(uint3 tid : SV_DispatchThreadID) {
8+
// The triangle vertices wind CW from +z under the DX / VK / MTL ray-
9+
// traversal convention. Two instances tiled along x: instance 0 has no
10+
// flags (front-facing), instance 1 has TriangleFrontCounterclockwise
11+
// (winding interpretation flips → back-facing).
12+
RayDesc Ray;
13+
Ray.Origin = float3((float(tid.x) - 0.5) * 4.0, 0, 1);
14+
Ray.Direction = float3(0, 0, -1);
15+
Ray.TMin = 0.0;
16+
Ray.TMax = 100.0;
17+
RayQuery<RAY_FLAG_NONE> Q;
18+
Q.TraceRayInline(Scene, RAY_FLAG_NONE, 0xFF, Ray);
19+
Q.Proceed();
20+
Output[tid.x] = Q.CommittedStatus() == COMMITTED_TRIANGLE_HIT
21+
? (uint)Q.CommittedTriangleFrontFace()
22+
: 0xFFFFFFFF;
23+
}
24+
//--- pipeline.yaml
25+
---
26+
Shaders:
27+
- Stage: Compute
28+
Entry: main
29+
Buffers:
30+
- Name: Vertices
31+
Format: Float32
32+
Stride: 12
33+
Data: [ 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0 ]
34+
- Name: Output
35+
Format: UInt32
36+
Stride: 4
37+
FillSize: 8
38+
- Name: Expected
39+
Format: UInt32
40+
Stride: 4
41+
# Instance 0: default winding → front face (1)
42+
# Instance 1: TriangleFrontCounterclockwise flips → back face (0)
43+
Data: [ 1, 0 ]
44+
AccelerationStructures:
45+
BLAS:
46+
- Name: TriangleBLAS
47+
Triangles:
48+
- VertexBuffer: Vertices
49+
VertexFormat: RGB32Float
50+
VertexStride: 12
51+
VertexCount: 3
52+
TLAS:
53+
- Name: Scene
54+
Instances:
55+
- BLAS: TriangleBLAS
56+
Transform: [1, 0, 0, -2, 0, 1, 0, 0, 0, 0, 1, 0]
57+
- BLAS: TriangleBLAS
58+
Transform: [1, 0, 0, 2, 0, 1, 0, 0, 0, 0, 1, 0]
59+
InstanceFlags: [TriangleFrontCounterclockwise]
60+
DescriptorSets:
61+
- Resources:
62+
- Name: Scene
63+
Kind: AccelerationStructure
64+
DirectXBinding:
65+
Register: 0
66+
Space: 0
67+
VulkanBinding:
68+
Binding: 0
69+
- Name: Output
70+
Kind: RWStructuredBuffer
71+
DirectXBinding:
72+
Register: 0
73+
Space: 0
74+
VulkanBinding:
75+
Binding: 1
76+
Results:
77+
- Result: InstanceFlags
78+
Rule: BufferExact
79+
Actual: Output
80+
Expected: Expected
81+
...
82+
#--- end
83+
84+
# REQUIRES: acceleration-structure
85+
# XFAIL: Clang
86+
87+
# RUN: split-file %s %t
88+
# RUN: %dxc_target -T cs_6_5 -Fo %t.o %t/source.hlsl
89+
# RUN: %offloader %t/pipeline.yaml %t.o

0 commit comments

Comments
 (0)