1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package shader
import "core:mem"
import "core:testing"
TRACKED_COMPUTE_SOURCE :: `
struct Params
count: uint
scale: float
end
struct DataBuffer
values: [64]float
end
@group(0) @binding(0) buffer params: Params
@group(0) @binding(1) buffer data: DataBuffer
@entry(compute)
@workgroup_size(64, 1, 1)
function main(@builtin(global_invocation_id) global_id: uvec3)
let idx = global_id.x
data.values[idx] = data.values[idx] * params.scale
end
`
@(test)
test_compile_result_destroy_releases_success_allocations :: proc(t: ^testing.T) {
track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)
track.bad_free_callback = mem.tracking_allocator_bad_free_callback_add_to_array
defer mem.tracking_allocator_destroy(&track)
allocator := mem.tracking_allocator(&track)
result := compile(TRACKED_COMPUTE_SOURCE, {
target = .WGSL,
stage = .Compute,
opt_level = .Basic,
}, "tracked_success.luma", allocator)
testing.expect(t, result.success)
testing.expect(t, len(result.output) > 0)
testing.expect(t, len(result.reflection.entry_points) > 0)
testing.expect(t, len(result.reflection.bindings) > 0)
destroy_compile_result(&result)
testing.expect_value(t, len(track.allocation_map), 0)
testing.expect_value(t, len(track.bad_free_array), 0)
}
@(test)
test_compile_result_destroy_releases_failure_allocations :: proc(t: ^testing.T) {
track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)
track.bad_free_callback = mem.tracking_allocator_bad_free_callback_add_to_array
defer mem.tracking_allocator_destroy(&track)
allocator := mem.tracking_allocator(&track)
result := compile("function main(\n", {
target = .WGSL,
stage = .Compute,
}, "tracked_failure.luma", allocator)
testing.expect(t, !result.success)
testing.expect(t, len(result.diagnostics) > 0)
testing.expect(t, len(result.diagnostics[0].message) > 0)
destroy_compile_result(&result)
testing.expect_value(t, len(track.allocation_map), 0)
testing.expect_value(t, len(track.bad_free_array), 0)
}
@(test)
test_compile_result_owned_across_repeated_compiles :: proc(t: ^testing.T) {
track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)
track.bad_free_callback = mem.tracking_allocator_bad_free_callback_add_to_array
defer mem.tracking_allocator_destroy(&track)
allocator := mem.tracking_allocator(&track)
first := compile(TRACKED_COMPUTE_SOURCE, {
target = .WGSL,
stage = .Compute,
opt_level = .Basic,
}, "first.luma", allocator)
second := compile("function main(\n", {
target = .WGSL,
stage = .Compute,
}, "second.luma", allocator)
testing.expect(t, first.success)
testing.expect(t, len(first.output) > 0)
testing.expect(t, len(first.reflection.entry_points) > 0)
testing.expect(t, !second.success)
testing.expect(t, len(second.diagnostics) > 0)
destroy_compile_result(&second)
destroy_compile_result(&first)
testing.expect_value(t, len(track.allocation_map), 0)
testing.expect_value(t, len(track.bad_free_array), 0)
}