Skip to content

Commit 5f58a7f

Browse files
authored
Add the particle life use case test (#87)
* Add the particle life use case test * Undo the hack to avoid lerp with a scalar weight
1 parent c3cf2a4 commit 5f58a7f

File tree

1 file changed

+363
-0
lines changed

1 file changed

+363
-0
lines changed

test/UseCase/particle-life.test

Lines changed: 363 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,363 @@
1+
#--- particle-life.hlsl
2+
#define ROOT_SIGNATURE \
3+
"RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)," \
4+
"CBV(b0)," \
5+
"SRV(t0)," \
6+
"SRV(t1)," \
7+
"UAV(u0)," \
8+
"UAV(u1)"
9+
10+
11+
[[vk::binding(0)]]
12+
cbuffer CONSTANTS : register(b0) {
13+
uint ParticleTypeMax;
14+
uint NumParticles;
15+
float2 WorldSize;
16+
float Friction;
17+
float ForceMultipler;
18+
}
19+
20+
struct Rule {
21+
float force;
22+
float min_distance;
23+
float max_distance;
24+
};
25+
26+
struct Particle {
27+
float2 position;
28+
float2 velocity;
29+
uint type;
30+
};
31+
32+
struct Vertex {
33+
float2 position;
34+
uint color;
35+
};
36+
37+
[[vk::binding(1)]]
38+
StructuredBuffer<Rule> Rules : register(t0);
39+
[[vk::binding(2)]]
40+
StructuredBuffer<Particle> OldParticles : register(t1);
41+
[[vk::binding(3)]]
42+
RWStructuredBuffer<Particle> NewParticles : register(u0);
43+
[[vk::binding(4)]]
44+
RWStructuredBuffer<Vertex> Vertices : register(u1);
45+
46+
47+
float3 particle_type_to_color(uint type);
48+
uint float_to_abgr(float3 rgb);
49+
50+
51+
[numthreads(32, 1, 1)]
52+
void main(uint3 dispatch_thread_id : SV_DispatchThreadID) {
53+
uint particle_id = dispatch_thread_id.x;
54+
55+
Particle particle = OldParticles[particle_id];
56+
57+
// Accumulate forces
58+
float2 force = float2(0,0);
59+
float hit = 0;
60+
61+
for (uint i = 0; i < NumParticles; ++i) {
62+
if (i == particle_id)
63+
continue;
64+
65+
Particle other_particle = OldParticles[i];
66+
67+
Rule rule = Rules[particle.type * ParticleTypeMax + other_particle.type];
68+
69+
float2 direction = other_particle.position - particle.position;
70+
71+
// wrapping
72+
if (direction.x > WorldSize.x * 0.5f)
73+
direction.x -= WorldSize.x;
74+
if (direction.x < WorldSize.x * -0.5f)
75+
direction.x += WorldSize.x;
76+
if (direction.y > WorldSize.y * 0.5f)
77+
direction.y -= WorldSize.y;
78+
if (direction.y < WorldSize.y * -0.5f)
79+
direction.y += WorldSize.y;
80+
81+
// apply rule
82+
float distance = length(direction);
83+
direction = normalize(direction);
84+
85+
if (distance < rule.min_distance) {
86+
float repulsive_amount = abs(rule.force) * (1.0f - (distance / rule.min_distance)) * -3.0f;
87+
force += direction * repulsive_amount;
88+
}
89+
90+
if (distance < rule.max_distance) {
91+
float attract_amount = rule.force * (1.0f - (distance / rule.max_distance));
92+
force += direction * attract_amount;
93+
hit += 0.01f;
94+
}
95+
}
96+
97+
float2 velocity = particle.velocity;
98+
velocity += force * ForceMultipler;
99+
velocity *= Friction;
100+
101+
particle.position = particle.position + velocity;
102+
103+
if (particle.position.x < 0)
104+
particle.position.x += WorldSize.x;
105+
106+
if (particle.position.x > WorldSize.x)
107+
particle.position.x -= WorldSize.x;
108+
109+
if (particle.position.y < 0)
110+
particle.position.y += WorldSize.y;
111+
112+
if (particle.position.y > WorldSize.y)
113+
particle.position.y -= WorldSize.y;
114+
115+
116+
particle.velocity = velocity;
117+
118+
Vertices[particle_id].position = particle.position;
119+
120+
float3 color = particle_type_to_color(particle.type);
121+
122+
color = lerp(color, color * 0.1f, 1-saturate(hit));
123+
124+
Vertices[particle_id].color = float_to_abgr(color);
125+
126+
NewParticles[particle_id] = particle;
127+
}
128+
129+
130+
131+
// from https://chilliant.com/rgb2hsv.html
132+
float3 hue2rgb(float H) {
133+
float R = abs(H * 6 - 3) - 1;
134+
float G = 2 - abs(H * 6 - 2);
135+
float B = 2 - abs(H * 6 - 4);
136+
return saturate(float3(R,G,B));
137+
}
138+
139+
float3 particle_type_to_color(uint type) {
140+
float hue = (float)type / float(ParticleTypeMax);
141+
return hue2rgb(hue);
142+
}
143+
144+
uint float_to_abgr(float3 rgb) {
145+
rgb *= 255.0;
146+
147+
uint r = rgb.x;
148+
uint g = rgb.y;
149+
uint b = rgb.z;
150+
uint a = 255;
151+
152+
return (a << 24) | (b << 16) | (g << 8) | r;
153+
}
154+
//--- particle-life.yaml
155+
---
156+
Shaders:
157+
- Stage: Compute
158+
Entry: main
159+
DispatchSize: [32, 1, 1]
160+
Buffers:
161+
- Name: CONSTANTS
162+
Format: Int32
163+
Data: [
164+
2, # ParticleTypeMax
165+
32, # NumParticles
166+
576, # Width
167+
432, # Height
168+
1063675494, # Friction (0.9f)
169+
1028443341, # Force Multiplier (0.05f)
170+
]
171+
- Name: Rules
172+
Format: Float32
173+
Stride: 12
174+
Data: [
175+
# Values found via PIX capture.
176+
0.668609, 36.0982, 126.076,
177+
0.777813, 47.3667, 153.301,
178+
0.580675, 36.4385, 223.18,
179+
-0.4252, 49.3721, 268.325,
180+
]
181+
- Name: OldParticles
182+
Format: Float32
183+
Stride: 20
184+
Data: [
185+
# Values found via PIX capture.
186+
# Note: 1.40129846E-45f == 0x00000001
187+
0.696739, 142.038651, 0, 0, 0,
188+
291.907013, 399.526642, 0, 0, 1.40129846E-45,
189+
175.601410, 275.703766, 0, 0, 1.40129846E-45,
190+
568.259949, 49.678871, 0, 0, 0,
191+
403.012360, 364.514069, 0, 0, 0,
192+
543.165344, 129.993225, 0, 0, 1.40129846E-45,
193+
72.757988, 416.646820, 0, 0, 0,
194+
131.410492, 240.978271, 0, 0, 1.40129846E-45,
195+
97.691116, 348.687927, 0, 0, 1.40129846E-45,
196+
400.843658, 79.489296, 0, 0, 1.40129846E-45,
197+
17.295982, 21.020313, 0, 0, 1.40129846E-45,
198+
43.010857, 110.249710, 0, 0, 1.40129846E-45,
199+
120.579689, 289.477570, 0, 0, 0,
200+
525.788818, 62.932449, 0, 0, 0,
201+
174.842529, 259.451721, 0, 0, 1.40129846E-45,
202+
149.797974, 192.973465, 0, 0, 0,
203+
384.795868, 0.964359, 0, 0, 0,
204+
364.804382, 424.608429, 0, 0, 0,
205+
197.151855, 327.236420, 0, 0, 0,
206+
248.257019, 395.461426, 0, 0, 1.40129846E-45,
207+
137.357452, 154.307480, 0, 0, 0,
208+
249.463043, 268.753845, 0, 0, 1.40129846E-45,
209+
208.790161, 427.462463, 0, 0, 0,
210+
326.137054, 65.707703, 0, 0, 1.40129846E-45,
211+
104.155403, 329.894623, 0, 0, 1.40129846E-45,
212+
551.543274, 30.785648, 0, 0, 0,
213+
467.292267, 431.669495, 0, 0, 0,
214+
257.305725, 28.127918, 0, 0, 0,
215+
52.601646, 55.992886, 0, 0, 0,
216+
202.340485, 285.560913, 0, 0, 1.40129846E-45,
217+
320.065735, 225.830231, 0, 0, 0,
218+
538.903625, 321.111237, 0, 0, 0,
219+
]
220+
- Name: NewParticles
221+
Format: Float32
222+
Stride: 20
223+
ZeroInitSize: 640
224+
- Name: ExpectedParticles
225+
Format: Float32
226+
Stride: 20
227+
Data: [
228+
0.719183, 142.013, 0.0224437, -0.0260402, 0,
229+
291.965, 399.553, 0.0578723, 0.0264942, 1.4013e-45,
230+
175.561, 275.738, -0.0406105, 0.0342286, 1.4013e-45,
231+
568.239, 49.7021, -0.0212302, 0.023205, 0,
232+
403.003, 364.533, -0.00957608, 0.0192838, 0,
233+
543.176, 129.952, 0.0105071, -0.0414064, 1.4013e-45,
234+
72.7691, 416.616, 0.0111061, -0.0304487, 0,
235+
131.376, 240.927, -0.034767, -0.0512624, 1.4013e-45,
236+
97.6543, 348.763, -0.0368595, 0.0750704, 1.4013e-45,
237+
400.861, 79.4692, 0.0170616, -0.0201277, 1.4013e-45,
238+
17.3085, 21.0374, 0.0125516, 0.0170663, 1.4013e-45,
239+
43.0106, 110.25, -0.000270761, 4.26963e-05, 1.4013e-45,
240+
120.643, 289.471, 0.0629655, -0.00696298, 0,
241+
525.819, 62.9302, 0.0298929, -0.00222033, 0,
242+
174.816, 259.361, -0.0265245, -0.0912027, 1.4013e-45,
243+
149.799, 193.026, 0.00128695, 0.0527595, 0,
244+
384.789, 0.99188, -0.00676379, 0.0275205, 0,
245+
364.793, 424.59, -0.0112163, -0.0181641, 0,
246+
197.127, 327.186, -0.025348, -0.0508726, 0,
247+
248.25, 395.497, -0.00664204, 0.0360285, 1.4013e-45,
248+
137.358, 154.353, 0.000708882, 0.0458239, 0,
249+
249.506, 268.737, 0.043196, -0.0167597, 1.4013e-45,
250+
208.817, 427.431, 0.0266717, -0.0318986, 0,
251+
326.12, 65.6863, -0.0165907, -0.0213587, 1.4013e-45,
252+
104.15, 329.865, -0.00585696, -0.0293124, 1.4013e-45,
253+
551.528, 30.8113, -0.015763, 0.0257023, 0,
254+
467.281, 431.663, -0.0110225, -0.00609188, 0,
255+
257.321, 28.1362, 0.0151884, 0.008258, 0,
256+
52.5778, 56.0035, -0.0238628, 0.0106606, 0,
257+
202.387, 285.595, 0.0461606, 0.0336835, 1.4013e-45,
258+
320.047, 225.841, -0.0191667, 0.0108352, 0,
259+
538.904, 321.111, 0, 0, 0
260+
]
261+
- Name: Vertices
262+
Format: Float32
263+
Stride: 12
264+
ZeroInitSize: 384
265+
- Name: ExpectedVertices
266+
Format: Float32
267+
Stride: 20
268+
Data: [
269+
0.719183, 142.013, -1.70142e+38,
270+
291.965, 399.553, -2.52875e+38,
271+
175.561, 275.738, -2.58213e+38,
272+
568.239, 49.7021, -1.70142e+38,
273+
403.003, 364.533, -1.70142e+38,
274+
543.176, 129.952, -2.24852e+38,
275+
72.7691, 416.616, -1.70142e+38,
276+
131.376, 240.927, -2.64885e+38,
277+
97.6543, 348.763, -2.48872e+38,
278+
400.861, 79.4692, -2.31525e+38,
279+
17.3085, 21.0374, -2.22184e+38,
280+
43.0106, 110.25, -2.43534e+38,
281+
120.643, 289.471, -1.70142e+38,
282+
525.819, 62.9302, -1.70142e+38,
283+
174.816, 259.361, -2.58213e+38,
284+
149.799, 193.026, -1.70142e+38,
285+
384.789, 0.99188, -1.70142e+38,
286+
364.793, 424.59, -1.70142e+38,
287+
197.127, 327.186, -1.70142e+38,
288+
248.25, 395.497, -2.52875e+38,
289+
137.358, 154.353, -1.70142e+38,
290+
249.506, 268.737, -2.62216e+38,
291+
208.817, 427.431, -1.70142e+38,
292+
326.12, 65.6863, -2.43534e+38,
293+
104.15, 329.865, -2.52875e+38,
294+
551.528, 30.8113, -1.70142e+38,
295+
467.281, 431.663, -1.70142e+38,
296+
257.321, 28.1362, -1.70142e+38,
297+
52.5778, 56.0035, -1.70142e+38,
298+
202.387, 285.595, -2.62216e+38,
299+
320.047, 225.841, -1.70142e+38,
300+
538.904, 321.111, -1.70142e+38
301+
]
302+
Results:
303+
- Result: CheckNewParticles
304+
Rule: BufferFuzzy
305+
ULPT: 1000
306+
Actual: NewParticles
307+
Expected: ExpectedParticles
308+
- Result: CheckVertices
309+
Rule: BufferFuzzy
310+
ULPT: 1000
311+
Actual: Vertices
312+
Expected: ExpectedVertices
313+
DescriptorSets:
314+
- Resources:
315+
- Name: CONSTANTS
316+
Kind: ConstantBuffer
317+
DirectXBinding:
318+
Register: 0
319+
Space: 0
320+
VulkanBinding:
321+
Binding: 0
322+
- Name: Rules
323+
Kind: StructuredBuffer
324+
DirectXBinding:
325+
Register: 0
326+
Space: 0
327+
VulkanBinding:
328+
Binding: 1
329+
- Name: OldParticles
330+
Kind: StructuredBuffer
331+
DirectXBinding:
332+
Register: 1
333+
Space: 0
334+
VulkanBinding:
335+
Binding: 2
336+
- Name: NewParticles
337+
Kind: RWStructuredBuffer
338+
DirectXBinding:
339+
Register: 0
340+
Space: 0
341+
VulkanBinding:
342+
Binding: 3
343+
- Name: Vertices
344+
Kind: RWStructuredBuffer
345+
DirectXBinding:
346+
Register: 1
347+
Space: 0
348+
VulkanBinding:
349+
Binding: 4
350+
...
351+
#--- end
352+
353+
# UNSUPPORTED: Clang-Vulkan
354+
355+
# CBuffer bindings seem to be broken under metal
356+
# https://github.com/llvm-beanz/offload-test-suite/issues/55
357+
# UNSUPPORTED: Metal
358+
359+
# RUN: split-file %s %t
360+
# RUN: %if !Vulkan %{ %dxc_target -T cs_6_0 -Fo %t.o %t/particle-life.hlsl %}
361+
# RUN: %if Vulkan %{ %dxc_target -T cs_6_0 -fspv-target-env=vulkan1.3 -fvk-use-scalar-layout -Fo %t.o %t/particle-life.hlsl %}
362+
# TODO: Specify -rootsig-define ROOT_SIGNATURE
363+
# RUN: %offloader %t/particle-life.yaml %t.o

0 commit comments

Comments
 (0)