diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/rust/metal/examples/mps | |
parent | Initial commit. (diff) | |
download | firefox-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.rs | 148 | ||||
-rw-r--r-- | third_party/rust/metal/examples/mps/shaders.metal | 26 | ||||
-rw-r--r-- | third_party/rust/metal/examples/mps/shaders.metallib | bin | 0 -> 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 Binary files differnew file mode 100644 index 0000000000..2cecf7b837 --- /dev/null +++ b/third_party/rust/metal/examples/mps/shaders.metallib |