diff --git a/src/gallium/frontends/rusticl/core/device.rs b/src/gallium/frontends/rusticl/core/device.rs index 4cd2343be82..9a08ed594e5 100644 --- a/src/gallium/frontends/rusticl/core/device.rs +++ b/src/gallium/frontends/rusticl/core/device.rs @@ -29,13 +29,14 @@ use std::ffi::CStr; use std::fmt::Debug; use std::mem::transmute; use std::num::NonZeroU64; +use std::ops::Deref; use std::os::raw::*; use std::sync::Arc; use std::sync::Mutex; use std::sync::MutexGuard; -pub struct Device { - pub base: CLObjectBase, +/// Contains basic stuff we need to partially initialize Device +pub struct DeviceBase { pub screen: Arc, pub cl_version: CLVersion, pub clc_version: CLVersion, @@ -47,12 +48,25 @@ pub struct Device { pub spirv_extensions: Vec<&'static CStr>, pub clc_features: Vec, pub formats: HashMap>, - pub lib_clc: NirShader, pub caps: DeviceCaps, helper_ctx: Mutex, reusable_ctx: Mutex>, } +pub struct Device { + pub base: CLObjectBase, + dev_base: DeviceBase, + pub lib_clc: NirShader, +} + +impl Deref for Device { + type Target = DeviceBase; + + fn deref(&self) -> &Self::Target { + &self.dev_base + } +} + #[derive(Default)] pub struct DeviceCaps { pub has_3d_image_writes: bool, @@ -236,62 +250,7 @@ impl HelperContextWrapper for HelperContext<'_> { impl_cl_type_trait_base!(cl_device_id, Device, [Device], CL_INVALID_DEVICE); -impl Device { - fn new(screen: PipeScreen) -> Option { - if !Self::check_valid(&screen) { - return None; - } - - let screen = Arc::new(screen); - // Create before loading libclc as llvmpipe only creates the shader cache with the first - // context being created. - let helper_ctx = screen.create_context()?; - let lib_clc = spirv::SPIRVBin::get_lib_clc(&screen); - if lib_clc.is_none() { - eprintln!("Libclc failed to load. Please make sure it is installed and provides spirv-mesa3d-.spv and/or spirv64-mesa3d-.spv"); - } - - let mut d = Self { - caps: DeviceCaps::new(&screen), - base: CLObjectBase::new(RusticlTypes::Device), - helper_ctx: Mutex::new(helper_ctx), - screen: screen, - cl_version: CLVersion::Cl3_0, - clc_version: CLVersion::Cl3_0, - clc_versions: Vec::new(), - device_type: 0, - embedded: false, - extension_string: String::from(""), - extensions: Vec::new(), - spirv_extensions: Vec::new(), - clc_features: Vec::new(), - formats: HashMap::new(), - lib_clc: lib_clc?, - reusable_ctx: Mutex::new(Vec::new()), - }; - - // check if we are embedded or full profile first - d.embedded = d.check_embedded_profile(); - - d.set_device_type(); - - d.fill_format_tables(); - - // query supported extensions - d.fill_extensions(); - - // now figure out what version we are - d.check_version(); - - Some(d) - } - - /// Converts a temporary reference to a static if and only if this device lives inside static - /// memory. - pub fn to_static(&self) -> Option<&'static Self> { - devs().iter().find(|&dev| self == dev) - } - +impl DeviceBase { fn fill_format_tables(&mut self) { // no need to do this if we don't support images if !self.caps.has_images { @@ -424,29 +383,6 @@ impl Device { } } - fn check_valid(screen: &PipeScreen) -> bool { - if !screen.caps().compute - || screen - .shader_caps(pipe_shader_type::PIPE_SHADER_COMPUTE) - .supported_irs - & (1 << (pipe_shader_ir::PIPE_SHADER_IR_NIR as i32)) - == 0 - { - return false; - } - - // CL_DEVICE_MAX_PARAMETER_SIZE - // For this minimum value, only a maximum of 128 arguments can be passed to a kernel - if screen - .shader_caps(pipe_shader_type::PIPE_SHADER_COMPUTE) - .max_const_buffer0_size - < 128 - { - return false; - } - true - } - fn check_custom(&self) -> bool { // Max size of memory object allocation in bytes. The minimum value is // max(min(1024 × 1024 × 1024, 1/4th of CL_DEVICE_GLOBAL_MEM_SIZE), 32 × 1024 × 1024) @@ -777,42 +713,6 @@ impl Device { .shader_caps(pipe_shader_type::PIPE_SHADER_COMPUTE) } - pub fn all() -> Vec { - let mut devs: Vec<_> = load_screens().filter_map(Device::new).collect(); - - // Pick a default device. One must be the default one no matter what. And custom devices can - // only be that one if they are the only devices available. - // - // The entry with the highest value will be the default device. - let default = devs.iter_mut().max_by_key(|dev| { - let mut val = if dev.device_type == CL_DEVICE_TYPE_CUSTOM { - // needs to be small enough so it's always going to be the smallest value - -100 - } else if dev.device_type == CL_DEVICE_TYPE_CPU { - 0 - } else if dev.unified_memory() { - // we give unified memory devices max priority, because we don't want to spin up the - // discrete GPU on laptops by default. - 100 - } else { - 10 - }; - - // we deprioritize zink for now. - if dev.screen.driver_name() == c"zink" { - val -= 1; - } - - val - }); - - if let Some(default) = default { - default.device_type |= CL_DEVICE_TYPE_DEFAULT; - } - - devs - } - pub fn address_bits(&self) -> cl_uint { self.screen.compute_caps().address_bits } @@ -1258,6 +1158,124 @@ impl Device { } } +impl Device { + fn new(screen: PipeScreen) -> Option { + if !Self::check_valid(&screen) { + return None; + } + + let screen = Arc::new(screen); + // Create before loading libclc as llvmpipe only creates the shader cache with the first + // context being created. + let helper_ctx = screen.create_context()?; + let lib_clc = spirv::SPIRVBin::get_lib_clc(&screen); + if lib_clc.is_none() { + eprintln!("Libclc failed to load. Please make sure it is installed and provides spirv-mesa3d-.spv and/or spirv64-mesa3d-.spv"); + } + + let mut dev_base = DeviceBase { + caps: DeviceCaps::new(&screen), + helper_ctx: Mutex::new(helper_ctx), + screen: screen, + cl_version: CLVersion::Cl3_0, + clc_version: CLVersion::Cl3_0, + clc_versions: Vec::new(), + device_type: 0, + embedded: false, + extension_string: String::from(""), + extensions: Vec::new(), + spirv_extensions: Vec::new(), + clc_features: Vec::new(), + formats: HashMap::new(), + reusable_ctx: Mutex::new(Vec::new()), + }; + + // check if we are embedded or full profile first + dev_base.embedded = dev_base.check_embedded_profile(); + + dev_base.set_device_type(); + + dev_base.fill_format_tables(); + + // query supported extensions + dev_base.fill_extensions(); + + // now figure out what version we are + dev_base.check_version(); + + Some(Device { + base: CLObjectBase::new(RusticlTypes::Device), + dev_base: dev_base, + lib_clc: lib_clc?, + }) + } + + pub fn all() -> Vec { + let mut devs: Vec<_> = load_screens().filter_map(Device::new).collect(); + + // Pick a default device. One must be the default one no matter what. And custom devices can + // only be that one if they are the only devices available. + // + // The entry with the highest value will be the default device. + let default = devs.iter_mut().max_by_key(|dev| { + let mut val = if dev.device_type == CL_DEVICE_TYPE_CUSTOM { + // needs to be small enough so it's always going to be the smallest value + -100 + } else if dev.device_type == CL_DEVICE_TYPE_CPU { + 0 + } else if dev.unified_memory() { + // we give unified memory devices max priority, because we don't want to spin up the + // discrete GPU on laptops by default. + 100 + } else { + 10 + }; + + // we deprioritize zink for now. + if dev.screen.driver_name() == c"zink" { + val -= 1; + } + + val + }); + + if let Some(default) = default { + default.dev_base.device_type |= CL_DEVICE_TYPE_DEFAULT; + } + + devs + } + + fn check_valid(screen: &PipeScreen) -> bool { + if !screen.caps().compute + || screen + .shader_caps(pipe_shader_type::PIPE_SHADER_COMPUTE) + .supported_irs + & (1 << (pipe_shader_ir::PIPE_SHADER_IR_NIR as i32)) + == 0 + { + return false; + } + + // CL_DEVICE_MAX_PARAMETER_SIZE + // For this minimum value, only a maximum of 128 arguments can be passed to a kernel + if screen + .shader_caps(pipe_shader_type::PIPE_SHADER_COMPUTE) + .max_const_buffer0_size + < 128 + { + return false; + } + true + } + + /// Converts a temporary reference to a static if and only if this device lives inside static + /// memory. + pub fn to_static(&self) -> Option<&'static Self> { + devs().iter().find(|&dev| self == dev) + } +} + impl Debug for Device { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct(&format!("Device@{:?}", self as *const _))