Skip to content

Commit

Permalink
v6.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
SkillfulElectro authored Sep 20, 2024
1 parent cb3a2c7 commit 5f59eb2
Show file tree
Hide file tree
Showing 8 changed files with 1,751 additions and 129 deletions.
1,395 changes: 1,395 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "EMCompute"
version = "5.0.0"
version = "6.0.0"
edition = "2021"
authors = ["ElectroMutex"]
description = "fast , simple and cross-platform parallel computing library"
Expand All @@ -14,7 +14,7 @@ categories = ["concurrency"]

[lib]
name = "EMCompute"
crate-type = ["cdylib"]
crate-type = ["cdylib" , "lib"]

[dependencies]
wgpu = "22.1.0"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ int main() {
- since version 3.0.0 caching method changed and is controled by setting_cache_index , if you set it to negative values which set_kernel_default_config function does ; api will allocate new gpu resources , so if you have used a config before you must keep track of it unless you want to go out of memory
- since version 4.0.0 structures of CKernel changed , kernel code and configs must be registered before using compute function . for seeing changes in details refer to https://github.com/SkillfulElectro/EMCompute/tree/main/header_files and read the comments on them or https://docs.rs/EMCompute/latest/EMCompute/
- since version 5.0.0 not much changes happened , you only must uint8_t** to data field of DataBinder
- since version 6.0.0 its possible to choose the device manually by setting gpu_index_in_backend_group field of GPUComputingConfig , if its negative , it will be set automatically . and you can get the lists of corresponding backend using get_computing_gpu_infos function , it will return GPUDevices and for freeing it from C you must use free_gpu_devices_infos . more infos -> https://docs.rs/EMCompute/latest/EMCompute/


## Contribution
Expand Down
4 changes: 2 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
extern crate cbindgen;
use std::env;

fn main(){
// Generate the header file using cbindgen
fn main() {
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let mut config: cbindgen::Config = Default::default();
config.language = cbindgen::Language::C;
Expand Down Expand Up @@ -95,3 +94,4 @@ SOFTWARE.*/"#.to_string());
.unwrap()
.write_to_file("target/EMCompute.hpp");
}

100 changes: 100 additions & 0 deletions src/configuration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#[repr(C)]
#[derive(Clone , Debug)]
/// computing backends of the api
pub enum GPUComputingBackend {
/// targets all of the backends
all = 0 ,
/// default backend
default_backend = 1 ,
/// Supported on Windows, Linux/Android, and macOS/iOS via Vulkan Portability (with the Vulkan feature enabled)
vulkan = 2,
/// Supported on Linux/Android, the web through webassembly via WebGL, and Windows and macOS/iOS via ANGLE
opengl = 3 ,
/// MacOS & iOS only
metal = 4 ,
/// Windows +10 only
direct_x12 = 5,
/// browser WebGPU
webgpu = 6 ,
/// targets VULKAN METALDX12 BROWSER_WEBGPU
highest_support = 7 ,
/// targets OpenGL backend
lowest_support = 8 ,
}

#[repr(C)]
#[derive(Clone , Debug)]
/// this enum is used to tell to API
/// to setup GPU resources based on power saving rules or
/// not
pub enum GPUPowerSettings {
/// power and performance does not matter
none = 0 ,
/// choose based on the power saving rules
LowPower = 1 ,
/// performance is more important
HighPerformance = 2 ,
}

#[repr(C)]
#[derive(Clone , Debug)]
/// this settings used to tell gpu pre information about
/// our work
pub enum GPUMemorySettings {
/// our app needs to me more performant instead being
/// cable of allocating too much memory on gpu side
prefer_performance = 0 ,
/// our app will need to allocate memory on gpu side
prefer_memory = 1 ,
/// if you set this , you have to set customize.gpu_memory_custom
/// this variable will be used for memory allocation in gpu
/// it sets min and max of memory you need in gpu side
custom_memory = 3 ,
}

#[repr(C)]
#[derive(Clone , Debug)]
/// this enum affects speed of the api
/// by setting how much gpu resources
/// are needed directly , if you take
/// too much which your hardware cannot
/// provide , panic happens
pub enum GPUSpeedSettings {
/// the lowest resources , supported on all backends
lowest_speed = 0 ,
/// low resources , supported on all backends expect webgl2
/// which our api does not aim to support for now
low_speed = 1 ,
/// the default
default_speed = 2 ,
/// will be supported in next versions , for now it is equal to
/// low_speed
custom_speed = 3 ,
}

#[repr(C)]
#[derive(Debug, Clone)]
/// as config field you have to provide GPUComputingConfig which
/// represent settings which you wanted
pub struct GPUComputingConfig {
/// set backend which you want
pub backend : GPUComputingBackend ,
/// set power settings which meets your needs
pub power : GPUPowerSettings ,
/// set speed settings which matches your needs
pub speed : GPUSpeedSettings ,
/// tell to gpu about your memory usage
pub memory : GPUMemorySettings ,
/// Optional Setting : if you know index of
/// your prefered gpu device in the list
/// gpu devices with the same backend , you can
/// set it , to API gets resources from
/// that gpu and use it for computing task
/// ```text
/// get_computing_gpu_infos function can be used to get list of them
/// free_gpu_devices_infos function must be used from C side of the program to deallocate
/// recived gpu infos , in Rust RAII will take care of it
/// ```
/// if it sets to negative value , API will automatically choose the gpu device
pub gpu_index_in_backend_group : i64 ,
}
185 changes: 185 additions & 0 deletions src/gpu_device.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
use crate::c_char;

use crate::
{GPUComputingBackend ,
GPUPowerSettings ,
GPUSpeedSettings ,
GPUMemorySettings ,
GPUComputingConfig};



#[repr(C)]
#[derive(Clone , Debug)]
/// Computing devices types
pub enum GPUDeviceType {
Other = 0,
IntegratedGpu = 1,
DiscreteGpu = 2,
VirtualGpu = 3,
Cpu = 4,
}

impl From<wgpu::DeviceType> for GPUDeviceType {
fn from(item : wgpu::DeviceType) -> Self {
match item {
wgpu::DeviceType::Other => GPUDeviceType::Other ,
wgpu::DeviceType::IntegratedGpu => GPUDeviceType::IntegratedGpu ,
wgpu::DeviceType::DiscreteGpu => GPUDeviceType::DiscreteGpu ,
wgpu::DeviceType::VirtualGpu => GPUDeviceType::VirtualGpu ,
wgpu::DeviceType::Cpu => GPUDeviceType::Cpu ,
}
}
}

#[repr(C)]
#[derive(Clone , Debug)]
/// this struct is used for storing information about
/// each device
pub struct GPUDeviceInfo {
/// name of the device
pub name: *const c_char,
/// vendor ID of the device
pub vendor: u32,
/// device id of the device
pub device: u32,
/// type of the device , GPUDeviceType
pub device_type: GPUDeviceType,
/// driver name
pub driver: *const c_char,
/// driver information
pub driver_info: *const c_char,
/// corresponding GPUComputingBackend
pub backend: GPUComputingBackend,
}

impl Drop for GPUDeviceInfo {
fn drop(&mut self){
unsafe {
let name = std::ffi::CString::from_raw(self.name as *mut c_char);
let driver = std::ffi::CString::from_raw(self.driver as *mut c_char);
let driver_info = std::ffi::CString::from_raw(self.driver_info as *mut c_char);
}
}
}

#[repr(C)]
#[derive(Clone , Debug)]
/// this function stores an dynamic array of GPUDeviceInfo with len ,
/// it must be freed with free_gpu_devices_infos function after usage
pub struct GPUDevices {
/// len of the dyn array
pub len : usize ,
/// pointer to the GPUDeviceInfo array
pub infos : *mut GPUDeviceInfo ,
}

// Rust RAII
impl Drop for GPUDevices {
fn drop(&mut self) {
unsafe {
let _tmp_vec = Vec::from_raw_parts(self.infos , self.len , self.len);
}
}
}

fn wgpu_backend_to_gpucomputingbackend(backend : wgpu::Backend) -> GPUComputingBackend {
match backend {
wgpu::Backend::Vulkan => {
GPUComputingBackend::vulkan
},
wgpu::Backend::Gl => {
GPUComputingBackend::opengl
},
wgpu::Backend::Empty => {
GPUComputingBackend::default_backend
},
wgpu::Backend::Metal => {
GPUComputingBackend::metal
},
wgpu::Backend::Dx12 => {
GPUComputingBackend::direct_x12
},
wgpu::Backend::BrowserWebGpu => {
GPUComputingBackend::webgpu
},
}
}

#[no_mangle]
/// this function returns GPUDevices of passed GPUComputingBackend
pub extern "C" fn get_computing_gpu_infos(backend : GPUComputingBackend) -> GPUDevices {

let backender = match backend {
GPUComputingBackend::vulkan => {
wgpu::Backends::VULKAN
},
GPUComputingBackend::opengl => {
wgpu::Backends::GL
},
GPUComputingBackend::all => {
wgpu::Backends::all()
},
GPUComputingBackend::default_backend => {
wgpu::Backends::default()
},
GPUComputingBackend::metal => {
wgpu::Backends::METAL
},
GPUComputingBackend::direct_x12 => {
wgpu::Backends::DX12
},
GPUComputingBackend::highest_support => {
wgpu::Backends::PRIMARY
},
GPUComputingBackend::lowest_support => {
wgpu::Backends::SECONDARY
},
GPUComputingBackend::webgpu => {
wgpu::Backends::BROWSER_WEBGPU
},
};

let instance = wgpu::Instance::new(wgpu::InstanceDescriptor{
backends : backender ,
..Default::default()
});

let adapters = instance.enumerate_adapters(backender);
let mut devices_keeper : Vec<GPUDeviceInfo> = Vec::new();
for adapter in adapters {
let info = adapter.get_info();
let name = std::ffi::CString::new(info.name).unwrap();
let driver = std::ffi::CString::new(info.driver).unwrap();
let driver_info = std::ffi::CString::new(info.driver_info).unwrap();
devices_keeper.push(GPUDeviceInfo{
vendor : info.vendor ,
device : info.device ,
name : name.into_raw() ,
driver : driver.into_raw() ,
driver_info : driver_info.into_raw() ,
device_type : GPUDeviceType::from(info.device_type) ,
backend : wgpu_backend_to_gpucomputingbackend(info.backend) ,
});

}

let len = devices_keeper.len();
let ptr = devices_keeper.as_ptr();
std::mem::forget(devices_keeper);
GPUDevices {
len : len ,
infos : ptr as *mut GPUDeviceInfo ,
}
}

#[no_mangle]
/// this function is used for deallocating GPUDevices type from C side
pub extern "C" fn free_gpu_devices_infos(devices : *mut GPUDevices) {

unsafe {
let mut devices = &mut *devices;
let tmp_vec = Vec::from_raw_parts(devices.infos , devices.len , devices.len);
}
/**/
}
Loading

0 comments on commit 5f59eb2

Please sign in to comment.