summaryrefslogtreecommitdiffstats
path: root/third_party/rust/metal/examples/shader-dylib
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/metal/examples/shader-dylib
parentInitial commit. (diff)
downloadfirefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz
firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/metal/examples/shader-dylib')
-rw-r--r--third_party/rust/metal/examples/shader-dylib/main.rs177
-rw-r--r--third_party/rust/metal/examples/shader-dylib/test_dylib.metal8
-rw-r--r--third_party/rust/metal/examples/shader-dylib/test_shader.metal14
3 files changed, 199 insertions, 0 deletions
diff --git a/third_party/rust/metal/examples/shader-dylib/main.rs b/third_party/rust/metal/examples/shader-dylib/main.rs
new file mode 100644
index 0000000000..b713e20e06
--- /dev/null
+++ b/third_party/rust/metal/examples/shader-dylib/main.rs
@@ -0,0 +1,177 @@
+use cocoa::{appkit::NSView, base::id as cocoa_id};
+use core_graphics_types::geometry::CGSize;
+
+use metal::*;
+use objc::{rc::autoreleasepool, runtime::YES};
+
+use winit::{
+ event::{Event, WindowEvent},
+ event_loop::ControlFlow,
+ platform::macos::WindowExtMacOS,
+};
+
+use std::mem;
+
+struct App {
+ pub device: Device,
+ pub command_queue: CommandQueue,
+ pub layer: MetalLayer,
+ pub image_fill_cps: ComputePipelineState,
+ pub width: u32,
+ pub height: u32,
+}
+
+fn select_device() -> Option<Device> {
+ let devices = Device::all();
+ for device in devices {
+ if device.supports_dynamic_libraries() {
+ return Some(device);
+ }
+ }
+
+ None
+}
+
+impl App {
+ fn new(window: &winit::window::Window) -> Self {
+ let device = select_device().expect("no device found that supports dynamic libraries");
+ let command_queue = device.new_command_queue();
+
+ let layer = MetalLayer::new();
+ layer.set_device(&device);
+ layer.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
+ layer.set_presents_with_transaction(false);
+ layer.set_framebuffer_only(false);
+ unsafe {
+ let view = window.ns_view() as cocoa_id;
+ view.setWantsLayer(YES);
+ view.setLayer(mem::transmute(layer.as_ref()));
+ }
+ let draw_size = window.inner_size();
+ layer.set_drawable_size(CGSize::new(draw_size.width as f64, draw_size.height as f64));
+
+ // compile dynamic lib shader
+ let dylib_src_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
+ .join("examples/shader-dylib/test_dylib.metal");
+ let install_path =
+ std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("target/test_dylib.metallib");
+
+ let dylib_src = std::fs::read_to_string(dylib_src_path).expect("bad shit");
+ let opts = metal::CompileOptions::new();
+ opts.set_library_type(MTLLibraryType::Dynamic);
+ opts.set_install_name(install_path.to_str().unwrap());
+
+ let lib = device
+ .new_library_with_source(dylib_src.as_str(), &opts)
+ .unwrap();
+
+ // create dylib
+ let dylib = device.new_dynamic_library(&lib).unwrap();
+ dylib.set_label("test_dylib");
+
+ // optional: serialize binary blob that can be loaded later
+ let blob_url = String::from("file://") + install_path.to_str().unwrap();
+ let url = URL::new_with_string(&blob_url);
+ dylib.serialize_to_url(&url).unwrap();
+
+ // create shader that links with dylib
+ let shader_src_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
+ .join("examples/shader-dylib/test_shader.metal");
+
+ let shader_src = std::fs::read_to_string(shader_src_path).expect("bad shit");
+ let opts = metal::CompileOptions::new();
+ // add dynamic library to link with
+ let libraries = [dylib.as_ref()];
+ opts.set_libraries(&libraries);
+
+ // compile
+ let shader_lib = device
+ .new_library_with_source(shader_src.as_str(), &opts)
+ .unwrap();
+
+ let func = shader_lib.get_function("test_kernel", None).unwrap();
+
+ // create pipeline state
+ // linking occurs here
+ let image_fill_cps = device
+ .new_compute_pipeline_state_with_function(&func)
+ .unwrap();
+
+ Self {
+ device,
+ command_queue,
+ layer,
+ image_fill_cps,
+ width: draw_size.width,
+ height: draw_size.height,
+ }
+ }
+
+ fn resize(&mut self, width: u32, height: u32) {
+ self.layer
+ .set_drawable_size(CGSize::new(width as f64, height as f64));
+ self.width = width;
+ self.height = height;
+ }
+
+ fn draw(&self) {
+ let drawable = match self.layer.next_drawable() {
+ Some(drawable) => drawable,
+ None => return,
+ };
+
+ let w = self.image_fill_cps.thread_execution_width();
+ let h = self.image_fill_cps.max_total_threads_per_threadgroup() / w;
+ let threads_per_threadgroup = MTLSize::new(w, h, 1);
+ let threads_per_grid = MTLSize::new(self.width as _, self.height as _, 1);
+
+ let command_buffer = self.command_queue.new_command_buffer();
+
+ {
+ let encoder = command_buffer.new_compute_command_encoder();
+ encoder.set_compute_pipeline_state(&self.image_fill_cps);
+ encoder.set_texture(0, Some(&drawable.texture()));
+ encoder.dispatch_threads(threads_per_grid, threads_per_threadgroup);
+ encoder.end_encoding();
+ }
+
+ command_buffer.present_drawable(&drawable);
+ command_buffer.commit();
+ }
+}
+
+fn main() {
+ let events_loop = winit::event_loop::EventLoop::new();
+ let size = winit::dpi::LogicalSize::new(800, 600);
+
+ let window = winit::window::WindowBuilder::new()
+ .with_inner_size(size)
+ .with_title("Metal Shader Dylib Example".to_string())
+ .build(&events_loop)
+ .unwrap();
+
+ let mut app = App::new(&window);
+
+ events_loop.run(move |event, _, control_flow| {
+ autoreleasepool(|| {
+ *control_flow = ControlFlow::Poll;
+
+ match event {
+ Event::WindowEvent { event, .. } => match event {
+ WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
+ WindowEvent::Resized(size) => {
+ app.resize(size.width, size.height);
+ }
+ _ => (),
+ },
+ Event::MainEventsCleared => {
+ window.request_redraw();
+ }
+ Event::RedrawRequested(_) => {
+ app.draw();
+ }
+ _ => {}
+ }
+ });
+ });
+}
diff --git a/third_party/rust/metal/examples/shader-dylib/test_dylib.metal b/third_party/rust/metal/examples/shader-dylib/test_dylib.metal
new file mode 100644
index 0000000000..5faa4a803a
--- /dev/null
+++ b/third_party/rust/metal/examples/shader-dylib/test_dylib.metal
@@ -0,0 +1,8 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+float4 get_color_test(float4 inColor)
+{
+ return float4(inColor.r, inColor.g, inColor.b, 0);
+}
diff --git a/third_party/rust/metal/examples/shader-dylib/test_shader.metal b/third_party/rust/metal/examples/shader-dylib/test_shader.metal
new file mode 100644
index 0000000000..38203a64a5
--- /dev/null
+++ b/third_party/rust/metal/examples/shader-dylib/test_shader.metal
@@ -0,0 +1,14 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+extern float4 get_color_test(float4 inColor);
+
+kernel void test_kernel(
+ texture2d<float, access::write> image [[texture(0)]],
+ uint2 coordinates [[thread_position_in_grid]],
+ uint2 size [[threads_per_grid]])
+{
+ float2 uv = float2(coordinates) / float2(size - 1);
+ image.write(get_color_test(float4(uv, 0.0, 1.0)), coordinates);
+}