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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! # HAC
//!
//! Hardware Accelerated Computing API via the GPU, built on top of [wgpu](wgpu.rs/)
//! for achieving great portability.
//!
//! ## Example: Add arrays
//!
//! ```rust
//! use rand::Rng;
//!
//! // wgpu's default `max_workgroups_per_dimension`
//! // can be changed using `hac::Limits` on Context creation
//! const N: usize = 1 << 16 - 1;
//!
//! const KERNEL_SOURCE: &'static str = r#"
//! struct ComputeInput {
//! // wgsl builtin variables can be found in the following link
//! // https://www.w3.org/TR/WGSL/#builtin-values
//! @builtin(global_invocation_id) id: vec3<u32>,
//! }
//!
//! @group(0) @binding(0)
//! var<storage, read> a: array<f32>;
//! @group(0) @binding(1)
//! var<storage, read> b: array<f32>;
//! @group(0) @binding(2)
//! var<storage, read_write> c: array<f32>;
//!
//! @compute @workgroup_size(1)
//! fn main(input: ComputeInput) {
//! let i = input.id.x;
//! c[i] = a[i] + b[i];
//! }"#;
//!
//!
//! fn main() {
//! let context = hac::Context::new(&hac::ContextInfo::default());
//!
//! let mut rng = rand::thread_rng();
//!
//! let mut a = vec![0.0f32; N];
//! rng.fill(&mut a[..]);
//!
//! let mut b = vec![0.0f32; N];
//! rng.fill(&mut b[..]);
//!
//! let buf_a = context.buffer_from_slice(&a); // input
//! let buf_b = context.buffer_from_slice(&b); // input
//! let buf_c = context.buffer::<f32>(N as u64); // output
//!
//! let bind_group = context
//! .bind_group_descriptor()
//! .push_buffer(&buf_a, hac::BufferAccess::ReadOnly) // @binding(0)
//! .push_buffer(&buf_b, hac::BufferAccess::ReadOnly) // @binding(1)
//! .push_buffer(&buf_c, hac::BufferAccess::ReadWrite) // @binding(2)
//! .into_bind_group();
//!
//! let program = context.program_from_wgsl(KERNEL_SOURCE);
//!
//! let kernel = context.kernel(&hac::KernelInfo {
//! program: &program,
//! entry_point: "main",
//! bind_groups: &[&bind_group], // each index corresponds to the group
//! // each binding of `bind_group` is in @group(0)
//! push_constants_range: None, // requires the `PUSH_CONSTANTS` feature
//! });
//!
//! kernel.dispatch(hac::Range::d1(N as u32));
//!
//! let c = buf_c.read_to_vec(); // read result
//!
//! // check if the sums were performed correctly and print some results
//! (0..N).for_each(|i| assert!((a[i] + b[i] - c[i]).abs() <= f32::EPSILON));
//! (0..8).for_each(|i| println!("{:<11} + {:<11} = {}", a[i], b[i], c[i]));
//! }
//! ```
pub use ;
pub use cast_slice;
/// Handle of `wgpu::Device` and it's `wgpu::Queue`, atomically shared between
/// all structs that need it.
/// 3 dimensional range used to specify workgroup sizes when dispatching a kernel.