### Build and Enqueue OpenCL Kernel with Arguments Source: https://context7.com/cogciprocate/ocl/llms.txt Demonstrates building an OpenCL kernel with both named and positional arguments, setting arguments, and enqueuing the kernel for execution. Ensure all necessary OpenCL setup (Platform, Device, Context, Program, Queue) is completed before building the kernel. ```rust use ocl::{Buffer, Context, Device, Kernel, Platform, Program, Queue}; fn main() -> ocl::Result<()> { let src = r##" __kernel void multiply_by_scalar( __private float const coeff, __global float const* const src, __global float* const res) { uint const idx = get_global_id(0); res[idx] = src[idx] * coeff; } "##; let platform = Platform::default(); let device = Device::first(platform)?; let context = Context::builder().platform(platform).devices(device).build()?; let program = Program::builder().src(src).devices(device).build(&context)?; let queue = Queue::new(&context, device, None)?; let source = Buffer::::builder().queue(queue.clone()).len(1024) .fill_val(2.0f32).build()?; let result: Buffer = Buffer::builder().queue(queue.clone()).len(1024).build()?; // Build kernel with one named argument and two positional: let kernel = Kernel::builder() .program(&program) .name("multiply_by_scalar") .queue(queue.clone()) .global_work_size(1024) .arg(5.0f32) // coeff (index 0) .arg(None::<&Buffer>) // src placeholder (index 1) .arg_named("res", None::<&Buffer>) .build()?; // Set arguments before enqueueing: kernel.set_arg(1, &source)?; kernel.set_arg("res", &result)?; // Override work dimensions per-enqueue, wait on/create events: let mut event = ocl::Event::empty(); unsafe { kernel.cmd() .global_work_size(1024) .enew(&mut event) .enq()?; } event.wait_for()?; let mut out = vec![0.0f32; 1024]; result.read(&mut out).enq()?; assert_eq!(out[0], 10.0); // 2.0 * 5.0 println!("result[0] = {}", out[0]); Ok(()) } ``` -------------------------------- ### Trivial OpenCL Kernel Example Source: https://github.com/cogciprocate/ocl/blob/master/README.md Demonstrates a basic OpenCL kernel for adding a scalar to a buffer. Requires an OpenCL library to be installed. The kernel is built, arguments are set, and the operation is enqueued. The modified buffer is then read back and a value is printed. ```rust extern crate ocl; use ocl::ProQue; fn trivial() -> ocl::Result<()> { let src = r#"__kernel void add(__global float* buffer, float scalar) { buffer[get_global_id(0)] += scalar; }"#; let pro_que = ProQue::builder() .src(src) .dims(1 << 20) .build()?; let buffer = pro_que.create_buffer::()?; let kernel = pro_que.kernel_builder("add") .arg(&buffer) .arg(10.0f32) .build()?; unsafe { kernel.enq()? }; let mut vec = vec![0.0f32; buffer.len()]; buffer.read(&mut vec).enq()?; println!("The value at index [{}] is now '{}'!", 200007, vec[200007]); Ok(()) } ``` -------------------------------- ### Trivial OpenCL Kernel Example in Rust Source: https://github.com/cogciprocate/ocl/blob/master/ocl/README.md Demonstrates a basic OpenCL kernel for adding a scalar to a buffer using `ocl::ProQue`. Ensure an OpenCL library is installed on your platform. ```rust extern crate ocl; use ocl::ProQue; fn trivial() -> ocl::Result<()> { let src = r##"__kernel void add(__global float* buffer, float scalar) { buffer[get_global_id(0)] += scalar; }"##; let pro_que = ProQue::builder() .src(src) .dims(1 << 20) .build()?; let buffer = pro_que.create_buffer::()?; let kernel = pro_que.kernel_builder("add") .arg(&buffer) .arg(10.0f32) .build()?; unsafe { kernel.enq()? }; let mut vec = vec![0.0f32; buffer.len()]; buffer.read(&mut vec).enq()?; println!("The value at index [{}] is now '{}'!", 200007, vec[200007]); Ok(()) } ``` -------------------------------- ### Create and Use 2D Image Buffer in OpenCL Source: https://context7.com/cogciprocate/ocl/llms.txt Shows how to create a 2D image buffer with specified format, dimensions, and queue. Includes writing pixel data and reading it back. Requires OpenCL setup. ```rust use ocl::{Context, Device, Image, Platform, Queue, Sampler}; use ocl::core::{ImageFormat, ImageChannelOrder, ImageChannelDataType, MemObjectType}; fn main() -> ocl::Result<()> { let platform = Platform::default(); let device = Device::first(platform)?; let context = Context::builder().platform(platform).devices(device).build()?; let queue = Queue::new(&context, device, None)?; // Create a 256x256 RGBA u8 image: let image = Image::::builder() .channel_order(ImageChannelOrder::Rgba) .channel_data_type(ImageChannelDataType::UnormInt8) .image_type(MemObjectType::Image2d) .dims((256, 256)) .queue(queue.clone()) .build()?; // Create a default sampler: let _sampler = Sampler::with_defaults(&context)?; // Write pixel data to the image: let pixels = vec![128u8; 256 * 256 * 4]; // RGBA image.cmd().write(&pixels).enq()?; // Read back: let mut readback = vec![0u8; 256 * 256 * 4]; image.cmd().read(&mut readback).enq()?; println!("Image dims: {:?}", image.dims()); println!("First pixel R channel: {}", readback[0]); Ok(()) } ``` -------------------------------- ### Low-Level OpenCL API for Buffer Operations Source: https://context7.com/cogciprocate/ocl/llms.txt Demonstrates using the `ocl::core` module for direct OpenCL C API bindings. This example creates a context, program, kernel, and buffer, then enqueues a kernel to modify buffer data. Requires careful handling of unsafe blocks. ```rust use ocl::{core, flags}; use ocl::builders::ContextProperties; use ocl::enums::ArgVal; use std::ffi::CString; fn main() -> ocl::core::Result<()> { let src = r#" __kernel void add(__global float* buffer, float scalar) { buffer[get_global_id(0)] += scalar; } "#; // Enumerate platforms and pick first device: let platform_id = core::default_platform()?; let device_ids = core::get_device_ids(&platform_id, None, None)?; let device_id = device_ids[0]; // Create context, program, queue: let ctx_props = ContextProperties::new().platform(platform_id); let context = core::create_context(Some(&ctx_props), &[device_id], None, None)?; let src_cstring = CString::new(src)?; let program = core::create_program_with_source(&context, &[src_cstring])?; core::build_program(&program, Some(&[device_id]), &CString::new("")?, None, None)?; let queue = core::create_command_queue(&context, &device_id, None)?; let dims = [1 << 20usize, 1, 1]; // Allocate buffer with host data: let mut vec = vec![0.0f32; dims[0]]; let buffer = unsafe { core::create_buffer(&context, flags::MEM_READ_WRITE | flags::MEM_COPY_HOST_PTR, dims[0], Some(&vec))? }; // Create and configure kernel, then enqueue: let kernel = core::create_kernel(&program, "add")?; core::set_kernel_arg(&kernel, 0, ArgVal::mem(&buffer))?; core::set_kernel_arg(&kernel, 1, ArgVal::scalar(&10.0f32))?; unsafe { core::enqueue_kernel(&queue, &kernel, 1, None, &dims, None, None::, None::<&mut core::Event>)?; } // Read results: unsafe { core::enqueue_read_buffer(&queue, &buffer, true, 0, &mut vec, None::, None::<&mut core::Event>)?; } println!("vec[0] = {}", vec[0]); // 10.0 Ok(()) } ``` -------------------------------- ### Async GPU Buffer Read into RwVec Source: https://context7.com/cogciprocate/ocl/llms.txt Utilizes `RwVec` for safe, asynchronous sharing of data between CPU and GPU. This example enqueues a kernel to increment buffer elements and then asynchronously reads the results into an `RwVec`, resolving the future to access the updated data. ```rust use ocl::{RwVec, Buffer, ProQue}; use ocl::flags::MemFlags; fn main() -> ocl::Result<()> { let src = r#" __kernel void increment(__global int* data) { data[get_global_id(0)] += 1; } "#; let pq = ProQue::builder().src(src).dims(64).build()?; // Create a shared host-side vec: let rw_vec = RwVec::::new(); // Build a buffer that writes into the RwVec asynchronously: let buffer = Buffer::::builder() .queue(pq.queue().clone()) .flags(MemFlags::new().read_write().alloc_host_ptr()) .len(64) .build()?; let kernel = pq.kernel_builder("increment").arg(&buffer).build()?; unsafe { kernel.enq()? }; // Enqueue an async read into the RwVec (returns a Future): let future_guard = buffer.read(rw_vec.clone()).enq_async()?; // Resolve the future (blocks until complete): use futures::Future; let guard = future_guard.wait()?; println!("rw_vec[0] = {}", guard[0]); // 1 Ok(()) } ``` -------------------------------- ### Kernel Building and Execution Source: https://context7.com/cogciprocate/ocl/llms.txt Demonstrates how to build an OpenCL kernel, set its arguments (positionally and by name), and enqueue it for execution with explicit event handling. ```APIDOC ## Kernel::builder() ### Description Builds a new `Kernel` object, allowing for argument configuration before execution. ### Method `Kernel::builder()` ### Parameters None directly on builder, arguments are set via chained methods. ### Usage ```rust let kernel = Kernel::builder() .program(&program) .name("kernel_name") .queue(queue.clone()) .global_work_size(1024) .arg(arg1) .arg_named("arg_name", arg2) .build()?; ``` ## Kernel::set_arg() ### Description Sets or updates a kernel argument by its index or name. ### Method `kernel.set_arg(index_or_name, argument)` ### Parameters - **index_or_name** (usize or str) - The index or name of the argument to set. - **argument** (&T) - The argument value to set. ### Usage ```rust kernel.set_arg(1, &source)?; // Set argument at index 1 kernel.set_arg("res", &result)?; // Set argument named "res" ``` ## Kernel::cmd() ### Description Returns a command builder for enqueuing the kernel with advanced options. ### Method `kernel.cmd()` ### Usage ```rust kernel.cmd().global_work_size(1024).enew(&mut event).enq()?; ``` ## Kernel::enq() (unsafe) ### Description Enqueues the kernel for execution. This is an unsafe operation. ### Method `unsafe { kernel.enq() }` ### Usage ```rust unsafe { kernel.enq()?; } ``` ``` -------------------------------- ### Platform: List and Select OpenCL Platforms Source: https://context7.com/cogciprocate/ocl/llms.txt Discover available OpenCL implementations using Platform::list(). Select a platform using Platform::default() or Platform::first(). ```rust use ocl::Platform; fn main() -> ocl::Result<()> { let platforms = Platform::list(); println!("Found {} platform(s):", platforms.len()); for platform in &platforms { println!( " Name: {}, Vendor: {}, Version: {}", platform.name()?, platform.vendor()?, platform.version()?, ); } // Get the first platform without relying on env vars: let first = Platform::first()?; println!("First platform: {}", first.name()?); Ok(()) } ``` -------------------------------- ### ProQue: All-in-One Context, Program, Queue, and Dims Source: https://context7.com/cogciprocate/ocl/llms.txt Use ProQue for a simplified entry point to OCL, wrapping context, program, queue, and dimensions. Configure via a fluent builder and directly create buffers and kernels. ```rust use ocl::ProQue; fn main() -> ocl::Result<()> { let src = r##" __kernel void add(__global float* buffer, float scalar) { buffer[get_global_id(0)] += scalar; } "##; // Build context + program + queue + dims in one step: let pro_que = ProQue::builder() .src(src) .dims(1 << 20) // 1,048,576 work items .build()?; // Create a zero-initialized device buffer sized to ProQue dims: let buffer = pro_que.create_buffer::()?; // Build the kernel, wiring arguments positionally: let kernel = pro_que.kernel_builder("add") .arg(&buffer) .arg(10.0f32) .build()?; // Enqueue the kernel (unsafe because GPU code is inherently untrusted): unsafe { kernel.enq()? }; // Read results back into a host Vec: let mut vec = vec![0.0f32; buffer.len()]; buffer.read(&mut vec).enq()?; println!("Value at index 200007: {}", vec[200007]); // Output: Value at index 200007: 10 Ok(()) } ``` -------------------------------- ### Device: Query and Select OpenCL Devices Source: https://context7.com/cogciprocate/ocl/llms.txt Enumerate devices on a platform using Device::list_all() or select specific devices using Device::list_select() with DeviceSpecifier. ```rust use ocl::{Device, Platform}; fn main() -> ocl::Result<()> { let platform = Platform::default(); // List all devices on the platform: let devices = Device::list_all(&platform)?; for device in &devices { println!( "Device: {} | Vendor: {} | Max WG Size: {}", device.name()?, device.vendor()?, device.max_wg_size()?, ); } // Select the first device: let device = Device::first(platform)?; // Or specify by type (GPU preferred): use ocl::DeviceType; let gpu_devices = Device::list_select(&platform, Some(DeviceType::GPU), None)?; println!("GPU devices: {}", gpu_devices.len()); Ok(()) } ``` -------------------------------- ### Event and EventList Synchronization Source: https://context7.com/cogciprocate/ocl/llms.txt Illustrates how to use `Event` and `EventList` for fine-grained synchronization of OpenCL commands, including capturing events and creating dependencies. ```APIDOC ## Event::empty() ### Description Creates an empty `Event` object that can be populated when a command is enqueued. ### Method `Event::empty()` ### Usage ```rust let mut event = Event::empty(); ``` ## Event::set_callback() ### Description Attaches a callback function to be executed when the event completes. This is an unsafe operation. ### Method `unsafe { event.set_callback(callback_fn, user_data) }` ### Parameters - **callback_fn** (*mut c_void) - A function pointer to the callback. - **user_data** (*mut c_void) - User-defined data to pass to the callback. ### Usage ```rust unsafe { ev.set_callback(on_complete, std::ptr::null_mut())? } ``` ## EventList::new() ### Description Creates a new empty `EventList` to store multiple events. ### Method `EventList::new()` ### Usage ```rust let mut kernel_events = EventList::new(); ``` ## EventList::wait_for() ### Description Blocks the current thread until all events in the `EventList` have completed. ### Method `kernel_events.wait_for()?` ### Usage ```rust kernel_events.wait_for()?; ``` ## EventList::clear_completed() ### Description Removes all completed events from the `EventList`. ### Method `kernel_events.clear_completed()?` ### Usage ```rust kernel_events.clear_completed()?; ``` ## CommandBuilder::ewait() ### Description Specifies that the command should wait for the given event(s) to complete before execution. ### Method `command_builder.ewait(event_or_event_list)` ### Parameters - **event_or_event_list** (Event or EventList) - The event(s) to wait for. ### Usage ```rust kernel.cmd().ewait(&write_event).enew(&mut kernel_events).enq()?; ``` ## CommandBuilder::enew() ### Description Captures the completion event of the enqueued command. Can be a single `Event` or an `EventList`. ### Method `command_builder.enew(event_target)` ### Parameters - **event_target** (Event or EventList) - The target to capture the event into. ### Usage ```rust .enew(&mut event) .enew(&mut kernel_events) ``` ``` -------------------------------- ### Buffer Creation with Flags and Data Source: https://github.com/cogciprocate/ocl/blob/master/RELEASES.md Use Buffer::builder() for constructing buffers with specified flags, dimensions, and host data. This is the recommended approach over the unstable Buffer::new(). ```rust Buffer::builder() .queue(queue) .flags(flags) .dims(dims) .host_data(&data) .build() ``` -------------------------------- ### Synchronize OpenCL Commands with Events Source: https://context7.com/cogciprocate/ocl/llms.txt Illustrates using `Event` and `EventList` for fine-grained synchronization between OpenCL commands. Events can be captured during enqueueing and used to establish dependencies for subsequent commands. Callbacks can be attached to events for post-execution actions. ```rust use ocl::{Buffer, Event, EventList, ProQue}; fn main() -> ocl::Result<()> { let src = r##" __kernel void add(__global float* buf, float val) { buf[get_global_id(0)] += val; } "##; let pq = ProQue::builder().src(src).dims(1024).build()?; let buffer = pq.create_buffer::()?; let kernel = pq.kernel_builder("add").arg(&buffer).arg(1.0f32).build()?; // Capture a single event: let mut write_event = Event::empty(); let data = vec![0.0f32; 1024]; buffer.write(&data).enew(&mut write_event).enq()?; // Capture kernel events in a list, wait on the write event: let mut kernel_events = EventList::new(); unsafe { kernel.cmd() .ewait(&write_event) .enew(&mut kernel_events) .enq()?; } // Wait for all kernel events to complete: kernel_events.wait_for()?; kernel_events.clear_completed()?; // Attach a callback to an event (advanced, requires unsafe): use ocl::ffi::{c_void, cl_event, cl_int}; extern "C" fn on_complete(_event: cl_event, _status: cl_int, _data: *mut c_void) { println!("Command completed!"); } let last = kernel_events.last(); if let Some(ev) = last { unsafe { ev.set_callback(on_complete, std::ptr::null_mut())? }; } pq.queue().finish()?; Ok(()) } ``` -------------------------------- ### OpenGL Interoperability with OpenCL Source: https://context7.com/cogciprocate/ocl/llms.txt Demonstrates how to create an OpenCL context sharing resources with an active OpenGL context. This allows acquiring and releasing OpenGL buffer objects for use in OpenCL kernels. ```rust // Cargo.toml: ocl-interop = "0.1" // // First create and activate an OpenGL context, then: fn gl_interop_example() -> ocl::Result<()> { // Create an OpenCL context tied to the current OpenGL context: let context = ocl_interop::get_context()?; // Build program and queue from this shared context: let device = ocl::Device::first(ocl::Platform::default())?; let queue = ocl::Queue::new(&context, device, None)?; // Wrap an existing OpenGL VBO (gl_buffer_id) as an OpenCL buffer: let gl_buffer_id: u32 = 42; // from glGenBuffers let cl_buffer = ocl::Buffer::::from_gl_buffer(&queue, None, gl_buffer_id)?; // Acquire exclusive OpenCL access: cl_buffer.cmd().gl_acquire().enq()?; // ... run kernels against cl_buffer ... // Release back to OpenGL: cl_buffer.cmd().gl_release().enq()?; queue.finish()?; Ok(()) } ``` -------------------------------- ### Multi-Queue Usage for Concurrent OpenCL Kernels Source: https://context7.com/cogciprocate/ocl/llms.txt Illustrates how to create and utilize multiple OpenCL queues for concurrent submission of kernels. This pattern is useful for maximizing device utilization in data-parallel applications. ```rust use ocl::{Buffer, Context, Device, Kernel, Platform, Program, Queue}; use std::thread; fn main() -> ocl::Result<()> { let src = r#"__kernel void add(__global float* buffer, float addend) { buffer[get_global_id(0)] += addend; }"#; let platform = Platform::default(); let device = Device::first(platform)?; let context = Context::builder().platform(platform).devices(device).build()?; let program = Program::builder().src(src).devices(device).build(&context)?; // Create multiple queues for concurrent submission: let queues: Vec = (0..4) .map(|_| Queue::new(&context, device, None)) .collect::>()?; let mut handles = vec![]; for queue in queues { let program = program.clone(); let handle = thread::spawn(move || -> ocl::Result { let buffer = Buffer::::builder() .queue(queue.clone()) .len(1024) .build()?; let kernel = Kernel::builder() .program(&program) .name("add") .queue(queue.clone()) .global_work_size(1024) .arg(&buffer) .arg(1.0f32) .build()?; unsafe { kernel.enq()? }; let mut vec = vec![0.0f32; 1024]; buffer.read(&mut vec).enq()?; Ok(format!("vec[0] = {}", vec[0])) }); handles.push(handle); } for h in handles { println!("{}", h.join().unwrap()?); } Ok(()) } ``` -------------------------------- ### Update Kernel Creation in ocl Source: https://github.com/cogciprocate/ocl/blob/master/RELEASES.md Instructions for updating kernel creation syntax from older versions to newer ones, involving changes to `ProQue::create_kernel` and `Kernel::new`. ```regex ProQue::create_kernel\(([^\]+)\) --> ProQue::kernel_builder(\1) ``` ```regex Kernel::new\(([^,]+, [^\]+)\) --> Kernel::builder().name(\1).program(\2) ``` -------------------------------- ### Kernel Creation and Queue Assignment Source: https://github.com/cogciprocate/ocl/blob/master/RELEASES.md Instantiate kernels using Kernel::new() and assign a queue using the .queue() method. This replaces the older method of passing the queue directly during kernel creation. ```rust Kernel::new("kernel_name", &program)?.queue(queue) ``` -------------------------------- ### Create OpenCL Command Queue Source: https://context7.com/cogciprocate/ocl/llms.txt Dispatches commands (kernel executions, buffer reads/writes) to a device. Use `finish()` to block until all commands complete, or `flush()` to flush the queue without blocking. Supports profiling. ```rust use ocl::{Context, Device, Platform, Queue}; use ocl::core::QUEUE_PROFILING_ENABLE; fn main() -> ocl::Result<()> { let platform = Platform::default(); let device = Device::first(platform)?; let context = Context::builder() .platform(platform) .devices(device) .build()?; // Standard queue: let queue = Queue::new(&context, device, None)?; // Queue with profiling enabled (for timing commands): let profiling_queue = Queue::new( &context, device, Some(QUEUE_PROFILING_ENABLE), )?; // Wait for all previously-enqueued commands to complete: queue.finish()?; println!("Queue on device: {}", queue.device().name()?); Ok(()) } ``` -------------------------------- ### Create OpenCL Context with OpenGL Interop Source: https://github.com/cogciprocate/ocl/blob/master/ocl-interop/README.md Creates an OpenCL context that supports OpenGL interoperability. This function automatically selects the first available GPU device supporting OpenGL interop. For more control, manual device selection and context creation might be necessary. ```rust // First, create an OpenGL context and make sure it is active... // Next, Create an OpenCL context with the interop enabled: (NOTE: // `::get_context` will return the first available GPU device on your that // supports OpenGL interop on your system -- you may need to choose a device // and create the context manually instead if this does not work): let context = ocl_interop::get_context()?; ``` -------------------------------- ### Add ocl-interop Dependency Source: https://github.com/cogciprocate/ocl/blob/master/ocl-interop/README.md Add the ocl-interop crate to your Cargo.toml file to include the necessary functionality. ```toml ocl-interop = "0.1" ``` -------------------------------- ### Compile OpenCL Kernel Source Source: https://context7.com/cogciprocate/ocl/llms.txt Compiles OpenCL C source code for one or more devices. Use `Program::builder()` to supply source strings, source files, or binary blobs. Supports building from inline source. ```rust use ocl::{Context, Device, Platform, Program}; fn main() -> ocl::Result<()> { let platform = Platform::default(); let device = Device::first(platform)?; let context = Context::builder() .platform(platform) .devices(device) .build()?; let src = r#" __kernel void multiply(__global float* buffer, float coeff) { buffer[get_global_id(0)] *= coeff; } "#; // Build from inline source: let program = Program::builder() .src(src) .devices(device) .build(&context)?; // Build from a source file: // let program = Program::builder() // .src_file("kernels/mykernel.cl") // .devices(device) // .build(&context)?; use ocl::core::ProgramInfo; println!("Kernel names: {}", program.info(ProgramInfo::KernelNames)?); Ok(()) } ``` -------------------------------- ### Add Cargo.toml Dependency Source: https://github.com/cogciprocate/ocl/blob/master/README.md Add the ocl crate as a dependency in your Cargo.toml file. ```toml [dependencies] ocl = "0.19" ``` -------------------------------- ### Update Kernel Argument Handling in OCL Source: https://github.com/cogciprocate/ocl/blob/master/RELEASES.md Demonstrates the updated method for setting kernel arguments using `ArgVal` enum and `set_kernel_arg`. Scalar and vector types must now be passed as references. ```rust let kernel = core::create_kernel(&program, "multiply")?; core::set_kernel_arg(&kernel, 0, ArgVal::scalar(&10.0f32))?; core::set_kernel_arg(&kernel, 1, ArgVal::mem(&buffer))?; ``` -------------------------------- ### Create OpenCL Buffer from OpenGL Buffer Source: https://github.com/cogciprocate/ocl/blob/master/ocl-interop/README.md Creates an OpenCL buffer object from an existing OpenGL buffer object. Ensure the OpenGL context is active and the buffer is properly created before calling this. ```rust // Later, after creating an OpenGL buffer... // Create an OpenCL buffer from an OpenGL buffer: let cl_buffer = ocl::Buffer::::from_gl_buffer(&queue, None, gl_buffer)?; ``` -------------------------------- ### Create and Share OpenCL Context Source: https://context7.com/cogciprocate/ocl/llms.txt Manages the association between the host application and one or more OpenCL devices. A context can be freely cloned and shared across threads. ```rust use ocl::{Context, Device, Platform}; fn main() -> ocl::Result<()> { let platform = Platform::default(); let device = Device::first(platform)?; let context = Context::builder() .platform(platform) .devices(device) .build()?; println!("Context: {}", context); // Access devices associated with this context: for dev in context.devices() { println!(" Device: {}", dev.name()?); } Ok(()) } ``` -------------------------------- ### Declare ocl_interop Crate Source: https://github.com/cogciprocate/ocl/blob/master/ocl-interop/README.md Declare the ocl_interop crate in your crate root (lib.rs or main.rs) to make its features available. ```rust extern crate ocl_interop; ``` -------------------------------- ### Allocate and Transfer Device Memory with Buffer Source: https://context7.com/cogciprocate/ocl/llms.txt Manages data on the OpenCL device. Use `Buffer::builder()` for full control over memory flags, initial data, and queue. Supports read, write, fill, and copy operations. ```rust use ocl::{Buffer, Context, Device, Platform, Queue, flags}; fn main() -> ocl::Result<()> { let platform = Platform::default(); let device = Device::first(platform)?; let context = Context::builder() .platform(platform) .devices(device) .build()?; let queue = Queue::new(&context, device, None)?; // Allocate a read-write buffer of 1024 floats, initialized from host data: let host_data: Vec = (0..1024).map(|i| i as f32).collect(); let buffer = Buffer::::builder() .queue(queue.clone()) .flags(flags::MEM_READ_WRITE) .len(1024) .copy_host_slice(&host_data) .build()?; // Write new values to the buffer: let new_data: Vec = vec![42.0f32; 1024]; buffer.write(&new_data).enq()?; // Read back into a host Vec: let mut result = vec![0.0f32; buffer.len()]; buffer.read(&mut result).enq()?; assert_eq!(result[0], 42.0); // Fill the entire buffer with a single value: buffer.cmd().fill(7.0f32, None).enq()?; // Copy buffer to another: let dst_buffer = Buffer::::builder() .queue(queue.clone()) .len(1024) .build()?; buffer.copy(&dst_buffer, None, None).enq()?; println!("Buffer length: {}", buffer.len()); Ok(()) } ``` -------------------------------- ### Wrap Kernel Enqueue Calls in unsafe Block Source: https://github.com/cogciprocate/ocl/blob/master/RELEASES.md Demonstrates the necessary change to make kernel enqueue calls safe by wrapping them in an `unsafe` block, as `Kernel::enq` and `KernelCmd::enq` are now unsafe. ```rust kernel.enq().unwrap(); ``` ```rust unsafe { kernel.enq().unwrap(); } ``` -------------------------------- ### Acquire and Release OpenCL Buffer for OpenGL Source: https://github.com/cogciprocate/ocl/blob/master/ocl-interop/README.md Acquires an OpenCL buffer, making it usable by OpenGL, and subsequently releases it. This is crucial for managing access to shared resources between OpenCL and OpenGL operations. ```rust // Acquire the buffer, making it usable: cl_buffer.cmd().gl_acquire().enq()?; // Use the buffer... // Release the acquisition: cl_buffer.cmd().gl_release().enq()?; ``` -------------------------------- ### Declare External Crate Source: https://github.com/cogciprocate/ocl/blob/master/README.md Declare the ocl crate in your crate root (lib.rs or main.rs) using extern crate. ```rust extern crate ocl; ``` -------------------------------- ### Specify Full Type for None Arguments in Kernel::set_arg_img_named Source: https://github.com/cogciprocate/ocl/blob/master/RELEASES.md When calling kernel argument declaration functions with a `None` variant, you must now specify the full type of the image, buffer, or sub-buffer. This ensures type safety and clarity in argument passing. ```rust ```.arg_buf_named::("buf", None)``` ``` ```rust ```.arg_buf_named("buf", None::>)``` ``` ```rust ```.arg_buf_named::>("buf", None)``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.