summaryrefslogtreecommitdiffstats
path: root/third_party/rust/metal/examples/mps
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/metal/examples/mps
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/metal/examples/mps')
-rw-r--r--third_party/rust/metal/examples/mps/main.rs148
-rw-r--r--third_party/rust/metal/examples/mps/shaders.metal26
-rw-r--r--third_party/rust/metal/examples/mps/shaders.metallibbin0 -> 14339 bytes
3 files changed, 174 insertions, 0 deletions
diff --git a/third_party/rust/metal/examples/mps/main.rs b/third_party/rust/metal/examples/mps/main.rs
new file mode 100644
index 0000000000..cc01b7a40d
--- /dev/null
+++ b/third_party/rust/metal/examples/mps/main.rs
@@ -0,0 +1,148 @@
+use metal::*;
+use std::ffi::c_void;
+use std::mem;
+
+#[repr(C)]
+struct Vertex {
+ xyz: [f32; 3],
+}
+
+type Ray = mps::MPSRayOriginMinDistanceDirectionMaxDistance;
+type Intersection = mps::MPSIntersectionDistancePrimitiveIndexCoordinates;
+
+// Original example taken from https://sergeyreznik.github.io/metal-ray-tracer/part-1/index.html
+fn main() {
+ let device = Device::system_default().expect("No device found");
+
+ let library_path =
+ std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("examples/mps/shaders.metallib");
+ let library = device
+ .new_library_with_file(library_path)
+ .expect("Failed to load shader library");
+
+ let generate_rays_pipeline = create_pipeline("generateRays", &library, &device);
+
+ let queue = device.new_command_queue();
+ let command_buffer = queue.new_command_buffer();
+
+ // Simple vertex/index buffer data
+
+ let vertices: [Vertex; 3] = [
+ Vertex {
+ xyz: [0.25, 0.25, 0.0],
+ },
+ Vertex {
+ xyz: [0.75, 0.25, 0.0],
+ },
+ Vertex {
+ xyz: [0.50, 0.75, 0.0],
+ },
+ ];
+
+ let vertex_stride = mem::size_of::<Vertex>();
+
+ let indices: [u32; 3] = [0, 1, 2];
+
+ // Vertex data should be stored in private or managed buffers on discrete GPU systems (AMD, NVIDIA).
+ // Private buffers are stored entirely in GPU memory and cannot be accessed by the CPU. Managed
+ // buffers maintain a copy in CPU memory and a copy in GPU memory.
+ let buffer_opts = MTLResourceOptions::StorageModeManaged;
+
+ let vertex_buffer = device.new_buffer_with_data(
+ vertices.as_ptr() as *const c_void,
+ (vertex_stride * vertices.len()) as u64,
+ buffer_opts,
+ );
+
+ let index_buffer = device.new_buffer_with_data(
+ indices.as_ptr() as *const c_void,
+ (mem::size_of::<u32>() * indices.len()) as u64,
+ buffer_opts,
+ );
+
+ // Build an acceleration structure using our vertex and index buffers containing the single triangle.
+ let acceleration_structure = mps::TriangleAccelerationStructure::from_device(&device)
+ .expect("Failed to create acceleration structure");
+
+ acceleration_structure.set_vertex_buffer(Some(&vertex_buffer));
+ acceleration_structure.set_vertex_stride(vertex_stride as u64);
+ acceleration_structure.set_index_buffer(Some(&index_buffer));
+ acceleration_structure.set_index_type(mps::MPSDataType::UInt32);
+ acceleration_structure.set_triangle_count(1);
+ acceleration_structure.set_usage(mps::MPSAccelerationStructureUsage::None);
+ acceleration_structure.rebuild();
+
+ let ray_intersector =
+ mps::RayIntersector::from_device(&device).expect("Failed to create ray intersector");
+
+ ray_intersector.set_ray_stride(mem::size_of::<Ray>() as u64);
+ ray_intersector.set_ray_data_type(mps::MPSRayDataType::OriginMinDistanceDirectionMaxDistance);
+ ray_intersector.set_intersection_stride(mem::size_of::<Intersection>() as u64);
+ ray_intersector.set_intersection_data_type(
+ mps::MPSIntersectionDataType::DistancePrimitiveIndexCoordinates,
+ );
+
+ // Create a buffer to hold generated rays and intersection results
+ let ray_count = 1024;
+ let ray_buffer = device.new_buffer(
+ (mem::size_of::<Ray>() * ray_count) as u64,
+ MTLResourceOptions::StorageModePrivate,
+ );
+
+ let intersection_buffer = device.new_buffer(
+ (mem::size_of::<Intersection>() * ray_count) as u64,
+ MTLResourceOptions::StorageModePrivate,
+ );
+
+ // Run the compute shader to generate rays
+ let encoder = command_buffer.new_compute_command_encoder();
+ encoder.set_buffer(0, Some(&ray_buffer), 0);
+ encoder.set_compute_pipeline_state(&generate_rays_pipeline);
+ encoder.dispatch_thread_groups(
+ MTLSize {
+ width: 4,
+ height: 4,
+ depth: 1,
+ },
+ MTLSize {
+ width: 8,
+ height: 8,
+ depth: 1,
+ },
+ );
+ encoder.end_encoding();
+
+ // Intersect rays with triangles inside acceleration structure
+ ray_intersector.encode_intersection_to_command_buffer(
+ &command_buffer,
+ mps::MPSIntersectionType::Nearest,
+ &ray_buffer,
+ 0,
+ &intersection_buffer,
+ 0,
+ ray_count as u64,
+ &acceleration_structure,
+ );
+
+ command_buffer.commit();
+ command_buffer.wait_until_completed();
+
+ println!("Done");
+}
+
+fn create_pipeline(func: &str, library: &LibraryRef, device: &DeviceRef) -> ComputePipelineState {
+ // Create compute pipelines will will execute code on the GPU
+ let compute_descriptor = ComputePipelineDescriptor::new();
+
+ // Set to YES to allow compiler to make certain optimizations
+ compute_descriptor.set_thread_group_size_is_multiple_of_thread_execution_width(true);
+
+ let function = library.get_function(func, None).unwrap();
+ compute_descriptor.set_compute_function(Some(&function));
+
+ let pipeline = device
+ .new_compute_pipeline_state(&compute_descriptor)
+ .unwrap();
+
+ pipeline
+}
diff --git a/third_party/rust/metal/examples/mps/shaders.metal b/third_party/rust/metal/examples/mps/shaders.metal
new file mode 100644
index 0000000000..d824d70d1b
--- /dev/null
+++ b/third_party/rust/metal/examples/mps/shaders.metal
@@ -0,0 +1,26 @@
+//
+// Created by Sergey Reznik on 9/15/18.
+// Copyright © 2018 Serhii Rieznik. All rights reserved.
+//
+
+// Taken from https://github.com/sergeyreznik/metal-ray-tracer/tree/part-1/source/Shaders
+// MIT License https://github.com/sergeyreznik/metal-ray-tracer/blob/part-1/LICENSE
+
+#include <MetalPerformanceShaders/MetalPerformanceShaders.h>
+
+using Ray = MPSRayOriginMinDistanceDirectionMaxDistance;
+using Intersection = MPSIntersectionDistancePrimitiveIndexCoordinates;
+
+kernel void generateRays(
+ device Ray* rays [[buffer(0)]],
+ uint2 coordinates [[thread_position_in_grid]],
+ uint2 size [[threads_per_grid]])
+{
+ float2 uv = float2(coordinates) / float2(size - 1);
+
+ uint rayIndex = coordinates.x + coordinates.y * size.x;
+ rays[rayIndex].origin = MPSPackedFloat3(uv.x, uv.y, -1.0);
+ rays[rayIndex].direction = MPSPackedFloat3(0.0, 0.0, 1.0);
+ rays[rayIndex].minDistance = 0.0f;
+ rays[rayIndex].maxDistance = 2.0f;
+}
diff --git a/third_party/rust/metal/examples/mps/shaders.metallib b/third_party/rust/metal/examples/mps/shaders.metallib
new file mode 100644
index 0000000000..2cecf7b837
--- /dev/null
+++ b/third_party/rust/metal/examples/mps/shaders.metallib
Binary files differ