Skip to content

Commit 3024d64

Browse files
committed
[Vulkan] Implement initial support for sparse resources
This commit introduces the ability to create and test sparse resources in the Vulkan backend. Key changes: - **Vulkan Backend**: Updated the Vulkan implementation to support sparse binding and residency for buffers. - **Test Infrastructure**: Enhanced test/lit.cfg.py to automatically detect and expose all boolean Vulkan features from api-query as lit features. This enables tests to use REQUIRE for specific hardware capabilities like sparseBinding and sparseResidencyBuffer. - **New Tests**: Added a suite of feature tests in test/Feature/Sparse/ to verify sparse resource behavior across different buffer types, including residency checks and partially mapped resource loads. This provides the necessary framework to validate sparse resource handling and residency behavior in HLSL-to-Vulkan pipelines.
1 parent 9cdb2b0 commit 3024d64

File tree

8 files changed

+698
-41
lines changed

8 files changed

+698
-41
lines changed

lib/API/VK/Device.cpp

Lines changed: 237 additions & 41 deletions
Large diffs are not rendered by default.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#--- source.hlsl
2+
RWByteAddressBuffer X : register(u0);
3+
RWStructuredBuffer<int> Out : register(u1);
4+
5+
[numthreads(1,1,1)]
6+
void main() {
7+
// Index 0: Offset 0.
8+
Out[0] = X.Load(0);
9+
10+
// Offset 128000: Second tile.
11+
Out[1] = X.Load(128000);
12+
}
13+
14+
//--- pipeline.yaml
15+
---
16+
17+
Shaders:
18+
- Stage: Compute
19+
Entry: main
20+
DispatchSize: [1, 1, 1]
21+
Buffers:
22+
- Name: X
23+
Format: Int32
24+
Stride: 4
25+
FillSize: 131072
26+
FillValue: 9001
27+
- Name: Out
28+
Format: Int32
29+
Stride: 4
30+
FillSize: 8
31+
FillValue: 0
32+
- Name: ExpectedOut
33+
Format: Int32
34+
Stride: 4
35+
Data: [9001, 0]
36+
37+
Results:
38+
- Result: Test
39+
Rule: BufferExact
40+
Actual: Out
41+
Expected: ExpectedOut
42+
43+
DescriptorSets:
44+
- Resources:
45+
- Name: X
46+
Kind: RWByteAddressBuffer
47+
IsReserved: true
48+
DirectXBinding:
49+
Register: 0
50+
Space: 0
51+
VulkanBinding:
52+
Binding: 0
53+
TilesMapped: 1
54+
- Name: Out
55+
Kind: RWStructuredBuffer
56+
DirectXBinding:
57+
Register: 1
58+
Space: 0
59+
VulkanBinding:
60+
Binding: 1
61+
#--- end
62+
63+
# REQUIRES: !Vulkan || sparseBinding
64+
# REQUIRES: !Vulkan || sparseResidencyBuffer
65+
66+
# XFAIL: Clang
67+
68+
# RUN: split-file %s %t
69+
# RUN: %dxc_target -T cs_6_5 -Fo %t.o %t/source.hlsl
70+
# RUN: %offloader %t/pipeline.yaml %t.o | FileCheck %s
71+
72+
# CHECK: - Name: Out
73+
# CHECK-NEXT: Format: Int32
74+
# CHECK-NEXT: Stride: 4
75+
# CHECK-NEXT: Data: [ 9001, 0 ]
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#--- source.hlsl
2+
RWStructuredBuffer<int> X : register(u0);
3+
RWStructuredBuffer<int> Out : register(u1);
4+
5+
[numthreads(1,1,1)]
6+
void main() {
7+
// Index 0: Guaranteed to be in the first mapped tile.
8+
Out[0] = X[0];
9+
10+
// Index 32000: 32000 * 4 bytes = 128,000 bytes.
11+
// If tile size is 64KB (65536 bytes), this is in the second tile (offset 65536+).
12+
// This should return 0 because it is unmapped.
13+
Out[1] = X[32000];
14+
}
15+
16+
//--- pipeline.yaml
17+
---
18+
19+
Shaders:
20+
- Stage: Compute
21+
Entry: main
22+
DispatchSize: [1, 1, 1]
23+
Buffers:
24+
- Name: X
25+
Format: Int32
26+
Stride: 4
27+
FillSize: 131072 # 128KB total bytes (32768 elements)
28+
FillValue: 9001
29+
- Name: Out
30+
Format: Int32
31+
Stride: 4
32+
FillSize: 8
33+
FillValue: 0
34+
- Name: ExpectedOut
35+
Format: Int32
36+
Stride: 4
37+
Data: [9001, 0]
38+
39+
Results:
40+
- Result: Test
41+
Rule: BufferExact
42+
Actual: Out
43+
Expected: ExpectedOut
44+
45+
DescriptorSets:
46+
- Resources:
47+
- Name: X
48+
Kind: RWStructuredBuffer
49+
IsReserved: true
50+
DirectXBinding:
51+
Register: 0
52+
Space: 0
53+
VulkanBinding:
54+
Binding: 0
55+
TilesMapped: 1
56+
- Name: Out
57+
Kind: RWStructuredBuffer
58+
DirectXBinding:
59+
Register: 1
60+
Space: 0
61+
VulkanBinding:
62+
Binding: 1
63+
#--- end
64+
65+
# REQUIRES: !Vulkan || sparseBinding
66+
# REQUIRES: !Vulkan || sparseResidencyBuffer
67+
# REQUIRES: !Vulkan || residencyNonResidentStrict
68+
69+
# RUN: split-file %s %t
70+
# RUN: %dxc_target -T cs_6_5 -Fo %t.o %t/source.hlsl
71+
# RUN: %offloader %t/pipeline.yaml %t.o | FileCheck %s
72+
73+
# CHECK: - Name: Out
74+
# CHECK-NEXT: Format: Int32
75+
# CHECK-NEXT: Stride: 4
76+
# CHECK-NEXT: Data: [ 9001, 0 ]
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#--- source.hlsl
2+
RWBuffer<int> X : register(u0);
3+
RWStructuredBuffer<int> Out : register(u1);
4+
5+
[numthreads(1,1,1)]
6+
void main() {
7+
// Index 0: Guaranteed to be in the first mapped tile.
8+
Out[0] = X[0];
9+
10+
// Index 32000: 32000 * 4 bytes = 128,000 bytes.
11+
// If tile size is 64KB (65536 bytes), this is in the second tile (offset 65536+).
12+
// This should return 0 since it is unmapped.
13+
Out[1] = X[32000];
14+
}
15+
16+
//--- pipeline.yaml
17+
---
18+
19+
Shaders:
20+
- Stage: Compute
21+
Entry: main
22+
DispatchSize: [1, 1, 1]
23+
Buffers:
24+
- Name: X
25+
Format: Int32
26+
Stride: 4
27+
FillSize: 131072 # 128KB total bytes (32768 elements)
28+
FillValue: 9001
29+
- Name: Out
30+
Format: Int32
31+
Stride: 4
32+
FillSize: 8
33+
FillValue: 0
34+
- Name: ExpectedOut
35+
Format: Int32
36+
Stride: 4
37+
Data: [9001, 0]
38+
39+
Results:
40+
- Result: Test
41+
Rule: BufferExact
42+
Actual: Out
43+
Expected: ExpectedOut
44+
45+
DescriptorSets:
46+
- Resources:
47+
- Name: X
48+
Kind: RWBuffer
49+
IsReserved: true
50+
DirectXBinding:
51+
Register: 0
52+
Space: 0
53+
VulkanBinding:
54+
Binding: 0
55+
TilesMapped: 1
56+
- Name: Out
57+
Kind: RWStructuredBuffer
58+
DirectXBinding:
59+
Register: 1
60+
Space: 0
61+
VulkanBinding:
62+
Binding: 1
63+
#--- end
64+
65+
# REQUIRES: !Vulkan || sparseBinding
66+
# REQUIRES: !Vulkan || sparseResidencyBuffer
67+
# REQUIRES: !Vulkan || residencyNonResidentStrict
68+
69+
# RUN: split-file %s %t
70+
71+
# RUN: %dxc_target -T cs_6_5 -Fo %t.o %t/source.hlsl
72+
73+
# RUN: %offloader %t/pipeline.yaml %t.o | FileCheck %s
74+
75+
76+
77+
# CHECK: - Name: Out
78+
79+
# CHECK-NEXT: Format: Int32
80+
81+
# CHECK-NEXT: Stride: 4
82+
83+
# CHECK-NEXT: Data: [ 9001, 0 ]
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#--- source.hlsl
2+
Buffer<int4> X : register(t0);
3+
4+
RWStructuredBuffer<int> Out : register(u1);
5+
6+
[numthreads(1,1,1)]
7+
void main() {
8+
int4 Result;
9+
10+
// Index 0: Tile 0 of X. Mapped.
11+
Result = X.Load(0);
12+
Out[0] = Result.x;
13+
14+
// Index 5000: Tile 1 of X. Unmapped.
15+
Result = X.Load(5000);
16+
Out[1] = Result.x;
17+
}
18+
19+
//--- pipeline.yaml
20+
---
21+
22+
Shaders:
23+
- Stage: Compute
24+
Entry: main
25+
DispatchSize: [1, 1, 1]
26+
Buffers:
27+
- Name: X
28+
Format: Int32
29+
Channels: 4
30+
FillSize: 131072 # 128KB
31+
FillValue: 9001
32+
- Name: Out
33+
Format: Int32
34+
Stride: 4
35+
FillSize: 8
36+
DescriptorSets:
37+
- Resources:
38+
- Name: X
39+
Kind: Buffer
40+
IsReserved: true
41+
DirectXBinding:
42+
Register: 0
43+
Space: 0
44+
VulkanBinding:
45+
Binding: 0
46+
TilesMapped: 1
47+
- Name: Out
48+
Kind: RWStructuredBuffer
49+
DirectXBinding:
50+
Register: 1
51+
Space: 0
52+
VulkanBinding:
53+
Binding: 1
54+
#--- end
55+
56+
# REQUIRES: !Vulkan || sparseBinding
57+
# REQUIRES: !Vulkan || sparseResidencyBuffer
58+
# REQUIRES: !Vulkan || residencyNonResidentStrict
59+
60+
# RUN: split-file %s %t
61+
# RUN: %dxc_target -T cs_6_5 -Fo %t.o %t/source.hlsl
62+
# RUN: %offloader %t/pipeline.yaml %t.o | FileCheck %s
63+
64+
# CHECK: - Name: Out
65+
# CHECK-NEXT: Format: Int32
66+
# CHECK-NEXT: Stride: 4
67+
# CHECK-NEXT: Data: [ 9001, 0 ]
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#--- source.hlsl
2+
Buffer<int4> X : register(t0);
3+
RWStructuredBuffer<int> Out : register(u1);
4+
5+
[numthreads(1,1,1)]
6+
void main() {
7+
// Index 0: Tile 0. Mapped.
8+
Out[0] = X.Load(0).x;
9+
// Index 5000: Tile 1 (offset 80000). Mapped (TilesMapped: 2 = 128KB).
10+
Out[1] = X.Load(5000).x;
11+
}
12+
13+
//--- pipeline.yaml
14+
---
15+
16+
Shaders:
17+
- Stage: Compute
18+
Entry: main
19+
DispatchSize: [1, 1, 1]
20+
Buffers:
21+
- Name: X
22+
Format: Int32
23+
Channels: 4
24+
FillSize: 131072
25+
FillValue: 9001
26+
- Name: Out
27+
Format: Int32
28+
Stride: 4
29+
FillSize: 8
30+
DescriptorSets:
31+
- Resources:
32+
- Name: X
33+
Kind: Buffer
34+
IsReserved: true
35+
DirectXBinding:
36+
Register: 0
37+
Space: 0
38+
VulkanBinding:
39+
Binding: 0
40+
TilesMapped: 2
41+
- Name: Out
42+
Kind: RWStructuredBuffer
43+
DirectXBinding:
44+
Register: 1
45+
Space: 0
46+
VulkanBinding:
47+
Binding: 1
48+
#--- end
49+
50+
# REQUIRES: !Vulkan || sparseBinding
51+
# REQUIRES: !Vulkan || sparseResidencyBuffer
52+
53+
# RUN: split-file %s %t
54+
# RUN: %dxc_target -T cs_6_5 -Fo %t.o %t/source.hlsl
55+
# RUN: %offloader %t/pipeline.yaml %t.o | FileCheck %s
56+
57+
# CHECK: - Name: Out
58+
# CHECK-NEXT: Format: Int32
59+
# CHECK-NEXT: Stride: 4
60+
# CHECK-NEXT: Data: [ 9001, 9001 ]

0 commit comments

Comments
 (0)