Skip to main content

06_resources_and_archives/common/
mod.rs

1#![allow(dead_code)]
2
3use apple_metal::{pixel_format, storage_mode, texture_usage, MetalBuffer, TextureDescriptor};
4use std::fs;
5use std::path::PathBuf;
6
7pub const COMPUTE_SRC: &str = r"
8#include <metal_stdlib>
9using namespace metal;
10
11struct Args {
12    device uint *buffer;
13    texture2d<float> texture;
14};
15
16kernel void increment(device uint *data [[buffer(0)]],
17                      uint gid [[thread_position_in_grid]]) {
18    if (gid < 4) {
19        data[gid] += 1;
20    }
21}
22
23kernel void use_args(constant Args &args [[buffer(0)]],
24                     uint gid [[thread_position_in_grid]]) {
25    if (gid == 0) {
26        args.buffer[0] = 7;
27    }
28}
29";
30
31pub const RENDER_SRC: &str = r"
32#include <metal_stdlib>
33using namespace metal;
34
35struct VertexOut {
36    float4 position [[position]];
37};
38
39vertex VertexOut fullscreen_vertex(uint vertex_id [[vertex_id]]) {
40    float2 positions[3] = {
41        float2(-1.0, -1.0),
42        float2( 3.0, -1.0),
43        float2(-1.0,  3.0)
44    };
45
46    VertexOut out;
47    out.position = float4(positions[vertex_id], 0.0, 1.0);
48    return out;
49}
50
51fragment float4 solid_fragment() {
52    return float4(0.2, 0.4, 0.8, 1.0);
53}
54";
55
56pub const DYNAMIC_LIB_SRC: &str = r"
57#include <metal_stdlib>
58using namespace metal;
59
60kernel void dynamic_noop(device uint *data [[buffer(0)]],
61                         uint gid [[thread_position_in_grid]]) {
62    if (gid == 0) {
63        data[gid] += 1;
64    }
65}
66";
67
68pub fn artifact_path(name: &str) -> PathBuf {
69    let mut dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
70    dir.push("target");
71    dir.push("apple-metal-example-artifacts");
72    fs::create_dir_all(&dir).expect("create example artifact dir");
73    let mut path = dir;
74    path.push(name);
75    let _ = fs::remove_file(&path);
76    path
77}
78
79pub fn write_u32_words(buffer: &MetalBuffer, data: &[u32]) {
80    let mut mapping = unsafe { buffer.map_write().expect("shared buffer mapping") };
81    assert!(mapping.len() >= core::mem::size_of_val(data));
82    for (bytes, value) in mapping.chunks_exact_mut(4).zip(data) {
83        bytes.copy_from_slice(&value.to_ne_bytes());
84    }
85    drop(mapping);
86}
87
88pub fn read_u32_words(buffer: &MetalBuffer, len: usize) -> Vec<u32> {
89    let mapping = unsafe { buffer.map_read().expect("shared buffer mapping") };
90    mapping
91        .chunks_exact(4)
92        .take(len)
93        .map(|bytes| u32::from_ne_bytes(bytes.try_into().expect("four-byte word")))
94        .collect()
95}
96
97pub const fn shared_render_target(width: usize, height: usize) -> TextureDescriptor {
98    let mut descriptor =
99        TextureDescriptor::render_target_2d(width, height, pixel_format::BGRA8UNORM);
100    descriptor.storage_mode = storage_mode::SHARED;
101    descriptor.usage = texture_usage::RENDER_TARGET | texture_usage::SHADER_READ;
102    descriptor
103}