06_resources_and_archives/common/
mod.rs1#![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}