mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 17:48:10 +02:00
rusticl/device: refactor Device::new
Adding a DeviceBase type will allow us to do pass in a proper spirv_caps object into SPIRVBin::get_lib_clc. Should also make device creation more flexible. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35439>
This commit is contained in:
parent
95eb537548
commit
3b2af3006e
1 changed files with 136 additions and 118 deletions
|
|
@ -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<CL_INVALID_DEVICE>,
|
||||
/// Contains basic stuff we need to partially initialize Device
|
||||
pub struct DeviceBase {
|
||||
pub screen: Arc<PipeScreen>,
|
||||
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<cl_name_version>,
|
||||
pub formats: HashMap<cl_image_format, HashMap<cl_mem_object_type, cl_mem_flags>>,
|
||||
pub lib_clc: NirShader,
|
||||
pub caps: DeviceCaps,
|
||||
helper_ctx: Mutex<PipeContext>,
|
||||
reusable_ctx: Mutex<Vec<PipeContext>>,
|
||||
}
|
||||
|
||||
pub struct Device {
|
||||
pub base: CLObjectBase<CL_INVALID_DEVICE>,
|
||||
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<Device> {
|
||||
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<Device> {
|
||||
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<Device> {
|
||||
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<Device> {
|
||||
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 _))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue