Skip to content

Commit a446ce7

Browse files
MarijnS95claude
andauthored
Add per-instance InstanceFlags YAML field and front-CCW test (#1287)
Depends on #1245, #1286 ## Summary Introduces `AccelerationStructureInstanceFlags` with bit values that intentionally match `D3D12_RAYTRACING_INSTANCE_FLAGS`, `VkGeometryInstanceFlagBitsKHR`, and `MTLAccelerationStructureInstanceOptions` so the value passes straight through each backend's instance fill with a single `static_cast`. YAML exposes the field as a bitset list (e.g. `InstanceFlags: [TriangleCullDisable, ForceOpaque]`). The covering test (`Feature/InlineRT/instance-flags.test`) sets `TriangleFrontCounterclockwise` on one of two instances of the same single-triangle BLAS and verifies `CommittedTriangleFrontFace()` flips — same world-space ray, same vertices, only the per-instance flag changes. Part of the inline-RT test coverage epic (#1258). ## Test plan Local on an NVIDIA RTX 3060: - [x] Linux Vulkan (native `offloader`) - [ ] Linux D3D12 (Wine + vkd3d-proton + cross-compiled `offloader.exe`) - [ ] Windows Vulkan (native `offloader.exe`) - [ ] Windows D3D12 (native `offloader.exe`) CI (RT-capable runners): - [x] windows-nvidia D3D12 (`RaytracingTier 1.2`) - [ ] windows-intel VK (`VK_KHR_ray_tracing_pipeline`) - [x] macOS Metal (`supportsRaytracing`) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f4e85ca commit a446ce7

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"
@@ -574,6 +575,7 @@ struct InstanceDesc {
574575
uint32_t InstanceID = 0;
575576
uint8_t InstanceMask = 0xFF;
576577
uint32_t InstanceContributionToHitGroupIndex = 0;
578+
AccelerationStructureInstanceFlags Flags = InstanceFlagNone;
577579
};
578580

579581
struct TLASDesc {
@@ -850,6 +852,19 @@ template <> struct MappingTraits<offloadtest::ShaderBindingTableDesc> {
850852
static void mapping(IO &I, offloadtest::ShaderBindingTableDesc &S);
851853
};
852854

855+
template <>
856+
struct ScalarBitSetTraits<offloadtest::AccelerationStructureInstanceFlags> {
857+
static void bitset(IO &I,
858+
offloadtest::AccelerationStructureInstanceFlags &V) {
859+
#define BIT_CASE(Val) I.bitSetCase(V, #Val, offloadtest::Val)
860+
BIT_CASE(TriangleCullDisable);
861+
BIT_CASE(TriangleFrontCounterclockwise);
862+
BIT_CASE(ForceOpaque);
863+
BIT_CASE(ForceNonOpaque);
864+
#undef BIT_CASE
865+
}
866+
};
867+
853868
template <> struct ScalarEnumerationTraits<offloadtest::Rule> {
854869
static void enumeration(IO &I, offloadtest::Rule &V) {
855870
#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
@@ -3454,7 +3454,9 @@ llvm::Error DXComputeEncoder::batchBuildAS(llvm::ArrayRef<ASBuildItem> Items) {
34543454
NI.InstanceMask = Inst.InstanceMask;
34553455
NI.InstanceContributionToHitGroupIndex =
34563456
Inst.InstanceContributionToHitGroupIndex & 0xFFFFFFu;
3457-
NI.Flags = D3D12_RAYTRACING_INSTANCE_FLAG_NONE;
3457+
// Bits in AccelerationStructureInstanceFlags match
3458+
// D3D12_RAYTRACING_INSTANCE_FLAGS by design.
3459+
NI.Flags = static_cast<D3D12_RAYTRACING_INSTANCE_FLAGS>(Inst.Flags);
34583460
auto *BLASPtr = llvm::cast<DXAccelerationStructure>(Inst.BLAS);
34593461
NI.AccelerationStructure = BLASPtr->getGPUVirtualAddress();
34603462
Native.push_back(NI);

lib/API/Device.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ llvm::Error offloadtest::buildPipelineAccelerationStructures(
250250
Inst.InstanceMask = I.InstanceMask;
251251
Inst.InstanceContributionToHitGroupIndex =
252252
I.InstanceContributionToHitGroupIndex;
253+
Inst.Flags = I.Flags;
253254
Inst.BLAS = It->second;
254255
Req.Instances.push_back(Inst);
255256
}

lib/API/MTL/MTLDevice.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3249,7 +3249,10 @@ llvm::Error MTLComputeEncoder::batchBuildAS(llvm::ArrayRef<ASBuildItem> Items) {
32493249
for (int Row = 0; Row < 3; ++Row)
32503250
for (int Col = 0; Col < 4; ++Col)
32513251
D.transformationMatrix.columns[Col][Row] = Src.Transform[Row][Col];
3252-
D.options = MTL::AccelerationStructureInstanceOptionNone;
3252+
// Bits in AccelerationStructureInstanceFlags match
3253+
// MTLAccelerationStructureInstanceOptions by design.
3254+
D.options =
3255+
static_cast<MTL::AccelerationStructureInstanceOptions>(Src.Flags);
32533256
D.mask = Src.InstanceMask;
32543257
D.intersectionFunctionTableOffset = 0;
32553258
D.accelerationStructureIndex = InstanceASIdx[I];

lib/API/VK/Device.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4901,7 +4901,9 @@ llvm::Error VKComputeEncoder::batchBuildAS(llvm::ArrayRef<ASBuildItem> Items) {
49014901
NI.mask = Inst.InstanceMask;
49024902
NI.instanceShaderBindingTableRecordOffset =
49034903
Inst.InstanceContributionToHitGroupIndex & 0xFFFFFFu;
4904-
NI.flags = 0;
4904+
// Bits in AccelerationStructureInstanceFlags match
4905+
// VkGeometryInstanceFlagBitsKHR by design.
4906+
NI.flags = static_cast<VkGeometryInstanceFlagsKHR>(Inst.Flags);
49054907
auto *BLASPtr = llvm::cast<VulkanAccelerationStructure>(Inst.BLAS);
49064908
NI.accelerationStructureReference = BLASPtr->getDeviceAddress();
49074909
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)