mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 13:58:04 +02:00
rusticl: rework query APIs
The old way was quite annoying as it required to create a Vec to even get the size of the result causing needless computations. This also meant that copying into the result buffer always required to go through a byte Vec even though we could just do the copy directly. The main idea here is that instead of returning the result, we simply call into a write function giving us more flexibility here. Potentially this will also allow us to add overloads for Iterators or to even use closures in case the size calculation is cheaper than creating the value just to get the size. Reviewed-by: @LingMan Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32268>
This commit is contained in:
parent
6fd6de46dc
commit
008caff86d
10 changed files with 607 additions and 466 deletions
|
|
@ -15,41 +15,41 @@ use rusticl_proc_macros::cl_info_entrypoint;
|
|||
use std::ffi::c_char;
|
||||
use std::ffi::c_void;
|
||||
use std::mem::transmute;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
#[cl_info_entrypoint(clGetContextInfo)]
|
||||
impl CLInfo<cl_context_info> for cl_context {
|
||||
fn query(&self, q: cl_context_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_context_info> for cl_context {
|
||||
fn query(&self, q: cl_context_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let ctx = Context::ref_from_raw(*self)?;
|
||||
Ok(match q {
|
||||
CL_CONTEXT_DEVICES => cl_prop::<Vec<cl_device_id>>(
|
||||
match q {
|
||||
CL_CONTEXT_DEVICES => v.write::<Vec<cl_device_id>>(
|
||||
ctx.devs
|
||||
.iter()
|
||||
.map(|&d| cl_device_id::from_ptr(d))
|
||||
.collect(),
|
||||
),
|
||||
CL_CONTEXT_NUM_DEVICES => cl_prop::<cl_uint>(ctx.devs.len() as u32),
|
||||
CL_CONTEXT_PROPERTIES => cl_prop::<&Properties<cl_context_properties>>(&ctx.properties),
|
||||
CL_CONTEXT_REFERENCE_COUNT => cl_prop::<cl_uint>(Context::refcnt(*self)?),
|
||||
CL_CONTEXT_NUM_DEVICES => v.write::<cl_uint>(ctx.devs.len() as u32),
|
||||
// need to return None if no properties exist
|
||||
CL_CONTEXT_PROPERTIES => v.write::<&Properties<cl_context_properties>>(&ctx.properties),
|
||||
CL_CONTEXT_REFERENCE_COUNT => v.write::<cl_uint>(Context::refcnt(*self)?),
|
||||
// CL_INVALID_VALUE if param_name is not one of the supported values
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CLInfo<cl_gl_context_info> for GLCtxManager {
|
||||
fn query(&self, q: cl_gl_context_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_gl_context_info> for GLCtxManager {
|
||||
fn query(&self, q: cl_gl_context_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let info = self.interop_dev_info;
|
||||
|
||||
Ok(match q {
|
||||
match q {
|
||||
CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR => {
|
||||
let ptr = match get_dev_for_uuid(info.device_uuid) {
|
||||
Some(dev) => dev,
|
||||
None => ptr::null(),
|
||||
};
|
||||
cl_prop::<cl_device_id>(cl_device_id::from_ptr(ptr))
|
||||
v.write::<cl_device_id>(cl_device_id::from_ptr(ptr))
|
||||
}
|
||||
CL_DEVICES_FOR_GL_CONTEXT_KHR => {
|
||||
// TODO: support multiple devices
|
||||
|
|
@ -57,10 +57,10 @@ impl CLInfo<cl_gl_context_info> for GLCtxManager {
|
|||
.iter()
|
||||
.map(|&d| cl_device_id::from_ptr(d))
|
||||
.collect();
|
||||
cl_prop::<&Vec<cl_device_id>>(&devs)
|
||||
v.write::<Vec<cl_device_id>>(devs)
|
||||
}
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rusticl_proc_macros::cl_info_entrypoint;
|
|||
|
||||
use std::cmp::min;
|
||||
use std::ffi::CStr;
|
||||
use std::mem::{size_of, MaybeUninit};
|
||||
use std::mem::size_of;
|
||||
use std::ptr;
|
||||
|
||||
const SPIRV_SUPPORT_STRING: &CStr = c"SPIR-V_1.0 SPIR-V_1.1 SPIR-V_1.2 SPIR-V_1.3 SPIR-V_1.4";
|
||||
|
|
@ -27,38 +27,38 @@ const SPIRV_SUPPORT: [cl_name_version; 5] = [
|
|||
type ClDevIdpAccelProps = cl_device_integer_dot_product_acceleration_properties_khr;
|
||||
|
||||
#[cl_info_entrypoint(clGetDeviceInfo)]
|
||||
impl CLInfo<cl_device_info> for cl_device_id {
|
||||
fn query(&self, q: cl_device_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_device_info> for cl_device_id {
|
||||
fn query(&self, q: cl_device_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let dev = Device::ref_from_raw(*self)?;
|
||||
|
||||
// curses you CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR
|
||||
#[allow(non_upper_case_globals)]
|
||||
Ok(match q {
|
||||
CL_DEVICE_ADDRESS_BITS => cl_prop::<cl_uint>(dev.address_bits()),
|
||||
CL_DEVICE_ATOMIC_FENCE_CAPABILITIES => cl_prop::<cl_device_atomic_capabilities>(
|
||||
match q {
|
||||
CL_DEVICE_ADDRESS_BITS => v.write::<cl_uint>(dev.address_bits()),
|
||||
CL_DEVICE_ATOMIC_FENCE_CAPABILITIES => v.write::<cl_device_atomic_capabilities>(
|
||||
(CL_DEVICE_ATOMIC_ORDER_RELAXED
|
||||
| CL_DEVICE_ATOMIC_ORDER_ACQ_REL
|
||||
| CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP)
|
||||
as cl_device_atomic_capabilities,
|
||||
),
|
||||
CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES => cl_prop::<cl_device_atomic_capabilities>(
|
||||
CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES => v.write::<cl_device_atomic_capabilities>(
|
||||
(CL_DEVICE_ATOMIC_ORDER_RELAXED | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP)
|
||||
as cl_device_atomic_capabilities,
|
||||
),
|
||||
CL_DEVICE_AVAILABLE => cl_prop::<bool>(true),
|
||||
CL_DEVICE_BUILT_IN_KERNELS => cl_prop::<&CStr>(c""),
|
||||
CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION => cl_prop::<Vec<cl_name_version>>(Vec::new()),
|
||||
CL_DEVICE_COMPILER_AVAILABLE => cl_prop::<bool>(true),
|
||||
CL_DEVICE_AVAILABLE => v.write::<bool>(true),
|
||||
CL_DEVICE_BUILT_IN_KERNELS => v.write::<&CStr>(c""),
|
||||
CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION => v.write::<Vec<cl_name_version>>(Vec::new()),
|
||||
CL_DEVICE_COMPILER_AVAILABLE => v.write::<bool>(true),
|
||||
CL_DEVICE_CROSS_DEVICE_SHARED_MEM_CAPABILITIES_INTEL => {
|
||||
cl_prop::<cl_device_device_enqueue_capabilities>(0)
|
||||
v.write::<cl_device_device_enqueue_capabilities>(0)
|
||||
}
|
||||
CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES => {
|
||||
cl_prop::<cl_device_device_enqueue_capabilities>(0)
|
||||
v.write::<cl_device_device_enqueue_capabilities>(0)
|
||||
}
|
||||
CL_DEVICE_DEVICE_MEM_CAPABILITIES_INTEL => {
|
||||
cl_prop::<cl_device_unified_shared_memory_capabilities_intel>(0)
|
||||
v.write::<cl_device_unified_shared_memory_capabilities_intel>(0)
|
||||
}
|
||||
CL_DEVICE_DOUBLE_FP_CONFIG => cl_prop::<cl_device_fp_config>(
|
||||
CL_DEVICE_DOUBLE_FP_CONFIG => v.write::<cl_device_fp_config>(
|
||||
if dev.fp64_supported() {
|
||||
let mut fp64_config = CL_FP_FMA
|
||||
| CL_FP_ROUND_TO_NEAREST
|
||||
|
|
@ -75,20 +75,20 @@ impl CLInfo<cl_device_info> for cl_device_id {
|
|||
}
|
||||
.into(),
|
||||
),
|
||||
CL_DEVICE_ENDIAN_LITTLE => cl_prop::<bool>(dev.little_endian()),
|
||||
CL_DEVICE_ERROR_CORRECTION_SUPPORT => cl_prop::<bool>(false),
|
||||
CL_DEVICE_ENDIAN_LITTLE => v.write::<bool>(dev.little_endian()),
|
||||
CL_DEVICE_ERROR_CORRECTION_SUPPORT => v.write::<bool>(false),
|
||||
CL_DEVICE_EXECUTION_CAPABILITIES => {
|
||||
cl_prop::<cl_device_exec_capabilities>(CL_EXEC_KERNEL.into())
|
||||
v.write::<cl_device_exec_capabilities>(CL_EXEC_KERNEL.into())
|
||||
}
|
||||
CL_DEVICE_EXTENSIONS => cl_prop::<&str>(&dev.extension_string),
|
||||
CL_DEVICE_EXTENSIONS_WITH_VERSION => cl_prop::<&Vec<cl_name_version>>(&dev.extensions),
|
||||
CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT => cl_prop::<bool>(false),
|
||||
CL_DEVICE_GLOBAL_MEM_CACHE_TYPE => cl_prop::<cl_device_mem_cache_type>(CL_NONE),
|
||||
CL_DEVICE_GLOBAL_MEM_CACHE_SIZE => cl_prop::<cl_ulong>(0),
|
||||
CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_GLOBAL_MEM_SIZE => cl_prop::<cl_ulong>(dev.global_mem_size()),
|
||||
CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE => cl_prop::<usize>(0),
|
||||
CL_DEVICE_HALF_FP_CONFIG => cl_prop::<cl_device_fp_config>(
|
||||
CL_DEVICE_EXTENSIONS => v.write::<&str>(&dev.extension_string),
|
||||
CL_DEVICE_EXTENSIONS_WITH_VERSION => v.write::<&[cl_name_version]>(&dev.extensions),
|
||||
CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT => v.write::<bool>(false),
|
||||
CL_DEVICE_GLOBAL_MEM_CACHE_TYPE => v.write::<cl_device_mem_cache_type>(CL_NONE),
|
||||
CL_DEVICE_GLOBAL_MEM_CACHE_SIZE => v.write::<cl_ulong>(0),
|
||||
CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_GLOBAL_MEM_SIZE => v.write::<cl_ulong>(dev.global_mem_size()),
|
||||
CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE => v.write::<usize>(0),
|
||||
CL_DEVICE_HALF_FP_CONFIG => v.write::<cl_device_fp_config>(
|
||||
if dev.fp16_supported() {
|
||||
CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN
|
||||
} else {
|
||||
|
|
@ -97,32 +97,32 @@ impl CLInfo<cl_device_info> for cl_device_id {
|
|||
.into(),
|
||||
),
|
||||
CL_DEVICE_HOST_MEM_CAPABILITIES_INTEL => {
|
||||
cl_prop::<cl_device_unified_shared_memory_capabilities_intel>(0)
|
||||
v.write::<cl_device_unified_shared_memory_capabilities_intel>(0)
|
||||
}
|
||||
CL_DEVICE_HOST_UNIFIED_MEMORY => cl_prop::<bool>(dev.unified_memory()),
|
||||
CL_DEVICE_IL_VERSION => cl_prop::<&CStr>(SPIRV_SUPPORT_STRING),
|
||||
CL_DEVICE_ILS_WITH_VERSION => cl_prop::<Vec<cl_name_version>>(SPIRV_SUPPORT.to_vec()),
|
||||
CL_DEVICE_HOST_UNIFIED_MEMORY => v.write::<bool>(dev.unified_memory()),
|
||||
CL_DEVICE_IL_VERSION => v.write::<&CStr>(SPIRV_SUPPORT_STRING),
|
||||
CL_DEVICE_ILS_WITH_VERSION => v.write::<Vec<cl_name_version>>(SPIRV_SUPPORT.to_vec()),
|
||||
CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT => {
|
||||
cl_prop::<cl_uint>(dev.image_base_address_alignment())
|
||||
v.write::<cl_uint>(dev.image_base_address_alignment())
|
||||
}
|
||||
CL_DEVICE_IMAGE_MAX_ARRAY_SIZE => cl_prop::<usize>(dev.image_array_size()),
|
||||
CL_DEVICE_IMAGE_MAX_BUFFER_SIZE => cl_prop::<usize>(dev.image_buffer_max_size_pixels()),
|
||||
CL_DEVICE_IMAGE_PITCH_ALIGNMENT => cl_prop::<cl_uint>(dev.image_pitch_alignment()),
|
||||
CL_DEVICE_IMAGE_SUPPORT => cl_prop::<bool>(dev.caps.has_images),
|
||||
CL_DEVICE_IMAGE2D_MAX_HEIGHT => cl_prop::<usize>(dev.caps.image_2d_size as usize),
|
||||
CL_DEVICE_IMAGE2D_MAX_WIDTH => cl_prop::<usize>(dev.caps.image_2d_size as usize),
|
||||
CL_DEVICE_IMAGE3D_MAX_HEIGHT => cl_prop::<usize>(dev.image_3d_size()),
|
||||
CL_DEVICE_IMAGE3D_MAX_WIDTH => cl_prop::<usize>(dev.image_3d_size()),
|
||||
CL_DEVICE_IMAGE3D_MAX_DEPTH => cl_prop::<usize>(dev.image_3d_size()),
|
||||
CL_DEVICE_IMAGE_MAX_ARRAY_SIZE => v.write::<usize>(dev.image_array_size()),
|
||||
CL_DEVICE_IMAGE_MAX_BUFFER_SIZE => v.write::<usize>(dev.image_buffer_max_size_pixels()),
|
||||
CL_DEVICE_IMAGE_PITCH_ALIGNMENT => v.write::<cl_uint>(dev.image_pitch_alignment()),
|
||||
CL_DEVICE_IMAGE_SUPPORT => v.write::<bool>(dev.caps.has_images),
|
||||
CL_DEVICE_IMAGE2D_MAX_HEIGHT => v.write::<usize>(dev.caps.image_2d_size as usize),
|
||||
CL_DEVICE_IMAGE2D_MAX_WIDTH => v.write::<usize>(dev.caps.image_2d_size as usize),
|
||||
CL_DEVICE_IMAGE3D_MAX_HEIGHT => v.write::<usize>(dev.image_3d_size()),
|
||||
CL_DEVICE_IMAGE3D_MAX_WIDTH => v.write::<usize>(dev.image_3d_size()),
|
||||
CL_DEVICE_IMAGE3D_MAX_DEPTH => v.write::<usize>(dev.image_3d_size()),
|
||||
CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR => {
|
||||
cl_prop::<cl_device_integer_dot_product_capabilities_khr>(
|
||||
v.write::<cl_device_integer_dot_product_capabilities_khr>(
|
||||
(CL_DEVICE_INTEGER_DOT_PRODUCT_INPUT_4x8BIT_PACKED_KHR
|
||||
| CL_DEVICE_INTEGER_DOT_PRODUCT_INPUT_4x8BIT_KHR)
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR => {
|
||||
cl_prop::<ClDevIdpAccelProps>({
|
||||
CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR => v
|
||||
.write::<ClDevIdpAccelProps>({
|
||||
let pack = dev.pack_32_4x8_supported();
|
||||
let sdot = dev.sdot_4x8_supported() && pack;
|
||||
let udot = dev.udot_4x8_supported() && pack;
|
||||
|
|
@ -138,10 +138,9 @@ impl CLInfo<cl_device_info> for cl_device_id {
|
|||
udot_sat.into(),
|
||||
sudot_sat.into(),
|
||||
)
|
||||
})
|
||||
}
|
||||
}),
|
||||
CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR => {
|
||||
cl_prop::<ClDevIdpAccelProps>({
|
||||
v.write::<ClDevIdpAccelProps>({
|
||||
IdpAccelProps::new(
|
||||
dev.sdot_4x8_supported().into(),
|
||||
dev.udot_4x8_supported().into(),
|
||||
|
|
@ -154,137 +153,137 @@ impl CLInfo<cl_device_info> for cl_device_id {
|
|||
}
|
||||
|
||||
CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED => {
|
||||
cl_prop::<&CStr>(dev.screen().cl_cts_version())
|
||||
v.write::<&CStr>(dev.screen().cl_cts_version())
|
||||
}
|
||||
CL_DEVICE_LINKER_AVAILABLE => cl_prop::<bool>(true),
|
||||
CL_DEVICE_LOCAL_MEM_SIZE => cl_prop::<cl_ulong>(dev.local_mem_size()),
|
||||
CL_DEVICE_LINKER_AVAILABLE => v.write::<bool>(true),
|
||||
CL_DEVICE_LOCAL_MEM_SIZE => v.write::<cl_ulong>(dev.local_mem_size()),
|
||||
// TODO add query for CL_LOCAL vs CL_GLOBAL
|
||||
CL_DEVICE_LOCAL_MEM_TYPE => cl_prop::<cl_device_local_mem_type>(CL_GLOBAL),
|
||||
CL_DEVICE_LUID_KHR => cl_prop::<[cl_uchar; CL_LUID_SIZE_KHR as usize]>(
|
||||
CL_DEVICE_LOCAL_MEM_TYPE => v.write::<cl_device_local_mem_type>(CL_GLOBAL),
|
||||
CL_DEVICE_LUID_KHR => v.write::<[cl_uchar; CL_LUID_SIZE_KHR as usize]>(
|
||||
dev.screen().device_luid().unwrap_or_default(),
|
||||
),
|
||||
CL_DEVICE_LUID_VALID_KHR => {
|
||||
cl_prop::<cl_bool>(dev.screen().device_luid().is_some().into())
|
||||
v.write::<cl_bool>(dev.screen().device_luid().is_some().into())
|
||||
}
|
||||
CL_DEVICE_MAX_CLOCK_FREQUENCY => cl_prop::<cl_uint>(dev.max_clock_freq()),
|
||||
CL_DEVICE_MAX_COMPUTE_UNITS => cl_prop::<cl_uint>(dev.max_compute_units()),
|
||||
CL_DEVICE_MAX_CLOCK_FREQUENCY => v.write::<cl_uint>(dev.max_clock_freq()),
|
||||
CL_DEVICE_MAX_COMPUTE_UNITS => v.write::<cl_uint>(dev.max_compute_units()),
|
||||
// TODO atm implemented as mem_const
|
||||
CL_DEVICE_MAX_CONSTANT_ARGS => cl_prop::<cl_uint>(dev.const_max_count()),
|
||||
CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE => cl_prop::<cl_ulong>(dev.const_max_size()),
|
||||
CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE => cl_prop::<usize>(0),
|
||||
CL_DEVICE_MAX_MEM_ALLOC_SIZE => cl_prop::<cl_ulong>(dev.max_mem_alloc()),
|
||||
CL_DEVICE_MAX_NUM_SUB_GROUPS => cl_prop::<cl_uint>(if dev.subgroups_supported() {
|
||||
CL_DEVICE_MAX_CONSTANT_ARGS => v.write::<cl_uint>(dev.const_max_count()),
|
||||
CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE => v.write::<cl_ulong>(dev.const_max_size()),
|
||||
CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE => v.write::<usize>(0),
|
||||
CL_DEVICE_MAX_MEM_ALLOC_SIZE => v.write::<cl_ulong>(dev.max_mem_alloc()),
|
||||
CL_DEVICE_MAX_NUM_SUB_GROUPS => v.write::<cl_uint>(if dev.subgroups_supported() {
|
||||
dev.max_subgroups()
|
||||
} else {
|
||||
0
|
||||
}),
|
||||
CL_DEVICE_MAX_ON_DEVICE_EVENTS => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_MAX_ON_DEVICE_QUEUES => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_MAX_PARAMETER_SIZE => cl_prop::<usize>(dev.param_max_size()),
|
||||
CL_DEVICE_MAX_PIPE_ARGS => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_MAX_READ_IMAGE_ARGS => cl_prop::<cl_uint>(dev.caps.max_read_images),
|
||||
CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS => cl_prop::<cl_uint>(if dev.caps.has_rw_images {
|
||||
CL_DEVICE_MAX_ON_DEVICE_EVENTS => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_MAX_ON_DEVICE_QUEUES => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_MAX_PARAMETER_SIZE => v.write::<usize>(dev.param_max_size()),
|
||||
CL_DEVICE_MAX_PIPE_ARGS => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_MAX_READ_IMAGE_ARGS => v.write::<cl_uint>(dev.caps.max_read_images),
|
||||
CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS => v.write::<cl_uint>(if dev.caps.has_rw_images {
|
||||
dev.caps.max_write_images
|
||||
} else {
|
||||
0
|
||||
}),
|
||||
CL_DEVICE_MAX_SAMPLERS => cl_prop::<cl_uint>(dev.max_samplers()),
|
||||
CL_DEVICE_MAX_WORK_GROUP_SIZE => cl_prop::<usize>(dev.max_threads_per_block()),
|
||||
CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS => cl_prop::<cl_uint>(dev.max_grid_dimensions()),
|
||||
CL_DEVICE_MAX_WORK_ITEM_SIZES => cl_prop::<Vec<usize>>(dev.max_block_sizes()),
|
||||
CL_DEVICE_MAX_WRITE_IMAGE_ARGS => cl_prop::<cl_uint>(dev.caps.max_write_images),
|
||||
CL_DEVICE_MAX_SAMPLERS => v.write::<cl_uint>(dev.max_samplers()),
|
||||
CL_DEVICE_MAX_WORK_GROUP_SIZE => v.write::<usize>(dev.max_threads_per_block()),
|
||||
CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS => v.write::<cl_uint>(dev.max_grid_dimensions()),
|
||||
CL_DEVICE_MAX_WORK_ITEM_SIZES => v.write::<Vec<usize>>(dev.max_block_sizes()),
|
||||
CL_DEVICE_MAX_WRITE_IMAGE_ARGS => v.write::<cl_uint>(dev.caps.max_write_images),
|
||||
// TODO proper retrival from devices
|
||||
CL_DEVICE_MEM_BASE_ADDR_ALIGN => cl_prop::<cl_uint>(0x1000),
|
||||
CL_DEVICE_MEM_BASE_ADDR_ALIGN => v.write::<cl_uint>(0x1000),
|
||||
CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE => {
|
||||
cl_prop::<cl_uint>(16 * size_of::<cl_ulong>() as cl_uint)
|
||||
v.write::<cl_uint>(16 * size_of::<cl_ulong>() as cl_uint)
|
||||
}
|
||||
CL_DEVICE_NAME => cl_prop::<&CStr>(dev.screen().name()),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR => cl_prop::<cl_uint>(1),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE => cl_prop::<cl_uint>(dev.fp64_supported().into()),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT => cl_prop::<cl_uint>(1),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF => cl_prop::<cl_uint>(dev.fp16_supported().into()),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_INT => cl_prop::<cl_uint>(1),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG => cl_prop::<cl_uint>(1),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT => cl_prop::<cl_uint>(1),
|
||||
CL_DEVICE_NAME => v.write::<&CStr>(dev.screen().name()),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR => v.write::<cl_uint>(1),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE => v.write::<cl_uint>(dev.fp64_supported().into()),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT => v.write::<cl_uint>(1),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF => v.write::<cl_uint>(dev.fp16_supported().into()),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_INT => v.write::<cl_uint>(1),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG => v.write::<cl_uint>(1),
|
||||
CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT => v.write::<cl_uint>(1),
|
||||
CL_DEVICE_NODE_MASK_KHR => {
|
||||
cl_prop::<cl_uint>(dev.screen().device_node_mask().unwrap_or_default())
|
||||
v.write::<cl_uint>(dev.screen().device_node_mask().unwrap_or_default())
|
||||
}
|
||||
CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT => cl_prop::<bool>(false),
|
||||
CL_DEVICE_NUMERIC_VERSION => cl_prop::<cl_version>(dev.cl_version.into()),
|
||||
CL_DEVICE_OPENCL_C_ALL_VERSIONS => cl_prop::<&Vec<cl_name_version>>(&dev.clc_versions),
|
||||
CL_DEVICE_OPENCL_C_FEATURES => cl_prop::<&Vec<cl_name_version>>(&dev.clc_features),
|
||||
CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT => v.write::<bool>(false),
|
||||
CL_DEVICE_NUMERIC_VERSION => v.write::<cl_version>(dev.cl_version.into()),
|
||||
CL_DEVICE_OPENCL_C_ALL_VERSIONS => v.write::<&[cl_name_version]>(&dev.clc_versions),
|
||||
CL_DEVICE_OPENCL_C_FEATURES => v.write::<&[cl_name_version]>(&dev.clc_features),
|
||||
CL_DEVICE_OPENCL_C_NUMERIC_VERSION_KHR => {
|
||||
cl_prop::<cl_version_khr>(dev.clc_version.into())
|
||||
v.write::<cl_version_khr>(dev.clc_version.into())
|
||||
}
|
||||
CL_DEVICE_OPENCL_C_VERSION => {
|
||||
cl_prop::<&str>(&format!("OpenCL C {} ", dev.clc_version.api_str()))
|
||||
v.write::<&str>(&format!("OpenCL C {} ", dev.clc_version.api_str()))
|
||||
}
|
||||
// TODO subdevice support
|
||||
CL_DEVICE_PARENT_DEVICE => cl_prop::<cl_device_id>(cl_device_id::from_ptr(ptr::null())),
|
||||
CL_DEVICE_PARTITION_AFFINITY_DOMAIN => cl_prop::<cl_device_affinity_domain>(0),
|
||||
CL_DEVICE_PARTITION_MAX_SUB_DEVICES => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_PARTITION_PROPERTIES => cl_prop::<Vec<cl_device_partition_property>>(vec![0]),
|
||||
CL_DEVICE_PARTITION_TYPE => cl_prop::<Vec<cl_device_partition_property>>(Vec::new()),
|
||||
CL_DEVICE_PARENT_DEVICE => v.write::<cl_device_id>(cl_device_id::from_ptr(ptr::null())),
|
||||
CL_DEVICE_PARTITION_AFFINITY_DOMAIN => v.write::<cl_device_affinity_domain>(0),
|
||||
CL_DEVICE_PARTITION_MAX_SUB_DEVICES => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_PARTITION_PROPERTIES => v.write::<Vec<cl_device_partition_property>>(vec![0]),
|
||||
CL_DEVICE_PARTITION_TYPE => v.write::<Vec<cl_device_partition_property>>(Vec::new()),
|
||||
CL_DEVICE_PCI_BUS_INFO_KHR => {
|
||||
cl_prop::<cl_device_pci_bus_info_khr>(dev.pci_info().ok_or(CL_INVALID_VALUE)?)
|
||||
v.write::<cl_device_pci_bus_info_khr>(dev.pci_info().ok_or(CL_INVALID_VALUE)?)
|
||||
}
|
||||
CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_PIPE_MAX_PACKET_SIZE => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_PIPE_SUPPORT => cl_prop::<bool>(false),
|
||||
CL_DEVICE_PLATFORM => cl_prop::<cl_platform_id>(Platform::get().as_ptr()),
|
||||
CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_PREFERRED_INTEROP_USER_SYNC => cl_prop::<bool>(true),
|
||||
CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR => cl_prop::<cl_uint>(1),
|
||||
CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_PIPE_MAX_PACKET_SIZE => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_PIPE_SUPPORT => v.write::<bool>(false),
|
||||
CL_DEVICE_PLATFORM => v.write::<cl_platform_id>(Platform::get().as_ptr()),
|
||||
CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_PREFERRED_INTEROP_USER_SYNC => v.write::<bool>(true),
|
||||
CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR => v.write::<cl_uint>(1),
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE => {
|
||||
cl_prop::<cl_uint>(dev.fp64_supported().into())
|
||||
v.write::<cl_uint>(dev.fp64_supported().into())
|
||||
}
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT => cl_prop::<cl_uint>(1),
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT => v.write::<cl_uint>(1),
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF => {
|
||||
cl_prop::<cl_uint>(dev.fp16_supported().into())
|
||||
v.write::<cl_uint>(dev.fp16_supported().into())
|
||||
}
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT => cl_prop::<cl_uint>(1),
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG => cl_prop::<cl_uint>(1),
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT => cl_prop::<cl_uint>(1),
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT => v.write::<cl_uint>(1),
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG => v.write::<cl_uint>(1),
|
||||
CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT => v.write::<cl_uint>(1),
|
||||
CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_MULTIPLE => {
|
||||
cl_prop::<usize>(dev.subgroup_sizes()[0])
|
||||
v.write::<usize>(dev.subgroup_sizes()[0])
|
||||
}
|
||||
CL_DEVICE_PRINTF_BUFFER_SIZE => cl_prop::<usize>(dev.printf_buffer_size()),
|
||||
CL_DEVICE_PROFILE => cl_prop(if dev.embedded {
|
||||
CL_DEVICE_PRINTF_BUFFER_SIZE => v.write::<usize>(dev.printf_buffer_size()),
|
||||
CL_DEVICE_PROFILE => v.write::<&CStr>(if dev.embedded {
|
||||
c"EMBEDDED_PROFILE"
|
||||
} else {
|
||||
c"FULL_PROFILE"
|
||||
}),
|
||||
CL_DEVICE_PROFILING_TIMER_RESOLUTION => {
|
||||
cl_prop::<usize>(dev.caps.timer_resolution as usize)
|
||||
v.write::<usize>(dev.caps.timer_resolution as usize)
|
||||
}
|
||||
CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE => cl_prop::<cl_uint>(0),
|
||||
CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES => cl_prop::<cl_command_queue_properties>(0),
|
||||
CL_DEVICE_QUEUE_ON_HOST_PROPERTIES => cl_prop::<cl_command_queue_properties>(
|
||||
CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE => v.write::<cl_uint>(0),
|
||||
CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES => v.write::<cl_command_queue_properties>(0),
|
||||
CL_DEVICE_QUEUE_ON_HOST_PROPERTIES => v.write::<cl_command_queue_properties>(
|
||||
(CL_QUEUE_PROFILING_ENABLE | CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE).into(),
|
||||
),
|
||||
CL_DEVICE_REFERENCE_COUNT => cl_prop::<cl_uint>(1),
|
||||
CL_DEVICE_REFERENCE_COUNT => v.write::<cl_uint>(1),
|
||||
CL_DEVICE_SHARED_SYSTEM_MEM_CAPABILITIES_INTEL => {
|
||||
cl_prop::<cl_device_unified_shared_memory_capabilities_intel>(0)
|
||||
v.write::<cl_device_unified_shared_memory_capabilities_intel>(0)
|
||||
}
|
||||
CL_DEVICE_SINGLE_DEVICE_SHARED_MEM_CAPABILITIES_INTEL => {
|
||||
cl_prop::<cl_device_unified_shared_memory_capabilities_intel>(0)
|
||||
v.write::<cl_device_unified_shared_memory_capabilities_intel>(0)
|
||||
}
|
||||
CL_DEVICE_SINGLE_FP_CONFIG => cl_prop::<cl_device_fp_config>(
|
||||
CL_DEVICE_SINGLE_FP_CONFIG => v.write::<cl_device_fp_config>(
|
||||
(CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN) as cl_device_fp_config,
|
||||
),
|
||||
CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS => cl_prop::<bool>(false),
|
||||
CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS => v.write::<bool>(false),
|
||||
CL_DEVICE_SUB_GROUP_SIZES_INTEL => {
|
||||
cl_prop::<Vec<usize>>(if dev.subgroups_supported() {
|
||||
v.write::<Vec<usize>>(if dev.subgroups_supported() {
|
||||
dev.subgroup_sizes()
|
||||
} else {
|
||||
vec![0; 1]
|
||||
})
|
||||
}
|
||||
CL_DEVICE_SVM_CAPABILITIES | CL_DEVICE_SVM_CAPABILITIES_ARM => {
|
||||
cl_prop::<cl_device_svm_capabilities>(
|
||||
v.write::<cl_device_svm_capabilities>(
|
||||
if dev.svm_supported() {
|
||||
CL_DEVICE_SVM_COARSE_GRAIN_BUFFER
|
||||
| CL_DEVICE_SVM_FINE_GRAIN_BUFFER
|
||||
|
|
@ -295,22 +294,22 @@ impl CLInfo<cl_device_info> for cl_device_id {
|
|||
.into(),
|
||||
)
|
||||
}
|
||||
CL_DEVICE_TYPE => cl_prop::<cl_device_type>(dev.device_type(false)),
|
||||
CL_DEVICE_UUID_KHR => cl_prop::<[cl_uchar; CL_UUID_SIZE_KHR as usize]>(
|
||||
CL_DEVICE_TYPE => v.write::<cl_device_type>(dev.device_type(false)),
|
||||
CL_DEVICE_UUID_KHR => v.write::<[cl_uchar; CL_UUID_SIZE_KHR as usize]>(
|
||||
dev.screen().device_uuid().unwrap_or_default(),
|
||||
),
|
||||
CL_DEVICE_VENDOR => cl_prop::<&CStr>(dev.screen().device_vendor()),
|
||||
CL_DEVICE_VENDOR_ID => cl_prop::<cl_uint>(dev.vendor_id()),
|
||||
CL_DEVICE_VERSION => cl_prop::<&str>(&format!("OpenCL {} ", dev.cl_version.api_str())),
|
||||
CL_DRIVER_UUID_KHR => cl_prop::<[cl_char; CL_UUID_SIZE_KHR as usize]>(
|
||||
CL_DEVICE_VENDOR => v.write::<&CStr>(dev.screen().device_vendor()),
|
||||
CL_DEVICE_VENDOR_ID => v.write::<cl_uint>(dev.vendor_id()),
|
||||
CL_DEVICE_VERSION => v.write::<&str>(&format!("OpenCL {} ", dev.cl_version.api_str())),
|
||||
CL_DRIVER_UUID_KHR => v.write::<[cl_char; CL_UUID_SIZE_KHR as usize]>(
|
||||
dev.screen().driver_uuid().unwrap_or_default(),
|
||||
),
|
||||
CL_DRIVER_VERSION => cl_prop::<&CStr>(unsafe { CStr::from_ptr(mesa_version_string()) }),
|
||||
CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT => cl_prop::<bool>(false),
|
||||
CL_DRIVER_VERSION => v.write::<&CStr>(unsafe { CStr::from_ptr(mesa_version_string()) }),
|
||||
CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT => v.write::<bool>(false),
|
||||
// CL_INVALID_VALUE if param_name is not one of the supported values
|
||||
// CL_INVALID_VALUE [...] if param_name is a value that is available as an extension and the corresponding extension is not supported by the device.
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,20 +10,19 @@ use rusticl_proc_macros::cl_entrypoint;
|
|||
use rusticl_proc_macros::cl_info_entrypoint;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cl_info_entrypoint(clGetEventInfo)]
|
||||
impl CLInfo<cl_event_info> for cl_event {
|
||||
fn query(&self, q: cl_event_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_event_info> for cl_event {
|
||||
fn query(&self, q: cl_event_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let event = Event::ref_from_raw(*self)?;
|
||||
Ok(match *q {
|
||||
CL_EVENT_COMMAND_EXECUTION_STATUS => cl_prop::<cl_int>(event.status()),
|
||||
match *q {
|
||||
CL_EVENT_COMMAND_EXECUTION_STATUS => v.write::<cl_int>(event.status()),
|
||||
CL_EVENT_CONTEXT => {
|
||||
// Note we use as_ptr here which doesn't increase the reference count.
|
||||
let ptr = Arc::as_ptr(&event.context);
|
||||
cl_prop::<cl_context>(cl_context::from_ptr(ptr))
|
||||
v.write::<cl_context>(cl_context::from_ptr(ptr))
|
||||
}
|
||||
CL_EVENT_COMMAND_QUEUE => {
|
||||
let ptr = match event.queue.as_ref() {
|
||||
|
|
@ -31,33 +30,33 @@ impl CLInfo<cl_event_info> for cl_event {
|
|||
Some(queue) => Arc::as_ptr(queue),
|
||||
None => ptr::null_mut(),
|
||||
};
|
||||
cl_prop::<cl_command_queue>(cl_command_queue::from_ptr(ptr))
|
||||
v.write::<cl_command_queue>(cl_command_queue::from_ptr(ptr))
|
||||
}
|
||||
CL_EVENT_REFERENCE_COUNT => cl_prop::<cl_uint>(Event::refcnt(*self)?),
|
||||
CL_EVENT_COMMAND_TYPE => cl_prop::<cl_command_type>(event.cmd_type),
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
CL_EVENT_REFERENCE_COUNT => v.write::<cl_uint>(Event::refcnt(*self)?),
|
||||
CL_EVENT_COMMAND_TYPE => v.write::<cl_command_type>(event.cmd_type),
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cl_info_entrypoint(clGetEventProfilingInfo)]
|
||||
impl CLInfo<cl_profiling_info> for cl_event {
|
||||
fn query(&self, q: cl_profiling_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_profiling_info> for cl_event {
|
||||
fn query(&self, q: cl_profiling_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let event = Event::ref_from_raw(*self)?;
|
||||
if event.cmd_type == CL_COMMAND_USER {
|
||||
// CL_PROFILING_INFO_NOT_AVAILABLE [...] if event is a user event object.
|
||||
return Err(CL_PROFILING_INFO_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
Ok(match *q {
|
||||
CL_PROFILING_COMMAND_QUEUED => cl_prop::<cl_ulong>(event.get_time(EventTimes::Queued)),
|
||||
CL_PROFILING_COMMAND_SUBMIT => cl_prop::<cl_ulong>(event.get_time(EventTimes::Submit)),
|
||||
CL_PROFILING_COMMAND_START => cl_prop::<cl_ulong>(event.get_time(EventTimes::Start)),
|
||||
CL_PROFILING_COMMAND_END => cl_prop::<cl_ulong>(event.get_time(EventTimes::End)),
|
||||
match *q {
|
||||
CL_PROFILING_COMMAND_QUEUED => v.write::<cl_ulong>(event.get_time(EventTimes::Queued)),
|
||||
CL_PROFILING_COMMAND_SUBMIT => v.write::<cl_ulong>(event.get_time(EventTimes::Submit)),
|
||||
CL_PROFILING_COMMAND_START => v.write::<cl_ulong>(event.get_time(EventTimes::Start)),
|
||||
CL_PROFILING_COMMAND_END => v.write::<cl_ulong>(event.get_time(EventTimes::End)),
|
||||
// For now, we treat Complete the same as End
|
||||
CL_PROFILING_COMMAND_COMPLETE => cl_prop::<cl_ulong>(event.get_time(EventTimes::End)),
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
CL_PROFILING_COMMAND_COMPLETE => v.write::<cl_ulong>(event.get_time(EventTimes::End)),
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,38 +16,38 @@ use rusticl_proc_macros::cl_info_entrypoint;
|
|||
|
||||
use std::cmp;
|
||||
use std::ffi::CStr;
|
||||
use std::mem::{self, MaybeUninit};
|
||||
use std::mem;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cl_info_entrypoint(clGetKernelInfo)]
|
||||
impl CLInfo<cl_kernel_info> for cl_kernel {
|
||||
fn query(&self, q: cl_kernel_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_kernel_info> for cl_kernel {
|
||||
fn query(&self, q: cl_kernel_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let kernel = Kernel::ref_from_raw(*self)?;
|
||||
Ok(match q {
|
||||
CL_KERNEL_ATTRIBUTES => cl_prop::<&str>(&kernel.kernel_info.attributes_string),
|
||||
match q {
|
||||
CL_KERNEL_ATTRIBUTES => v.write::<&str>(&kernel.kernel_info.attributes_string),
|
||||
CL_KERNEL_CONTEXT => {
|
||||
let ptr = Arc::as_ptr(&kernel.prog.context);
|
||||
cl_prop::<cl_context>(cl_context::from_ptr(ptr))
|
||||
v.write::<cl_context>(cl_context::from_ptr(ptr))
|
||||
}
|
||||
CL_KERNEL_FUNCTION_NAME => cl_prop::<&str>(&kernel.name),
|
||||
CL_KERNEL_NUM_ARGS => cl_prop::<cl_uint>(kernel.kernel_info.args.len() as cl_uint),
|
||||
CL_KERNEL_FUNCTION_NAME => v.write::<&str>(&kernel.name),
|
||||
CL_KERNEL_NUM_ARGS => v.write::<cl_uint>(kernel.kernel_info.args.len() as cl_uint),
|
||||
CL_KERNEL_PROGRAM => {
|
||||
let ptr = Arc::as_ptr(&kernel.prog);
|
||||
cl_prop::<cl_program>(cl_program::from_ptr(ptr))
|
||||
v.write::<cl_program>(cl_program::from_ptr(ptr))
|
||||
}
|
||||
CL_KERNEL_REFERENCE_COUNT => cl_prop::<cl_uint>(Kernel::refcnt(*self)?),
|
||||
CL_KERNEL_REFERENCE_COUNT => v.write::<cl_uint>(Kernel::refcnt(*self)?),
|
||||
// CL_INVALID_VALUE if param_name is not one of the supported values
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cl_info_entrypoint(clGetKernelArgInfo)]
|
||||
impl CLInfoObj<cl_kernel_arg_info, cl_uint> for cl_kernel {
|
||||
fn query(&self, idx: cl_uint, q: cl_kernel_arg_info) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfoObj<cl_kernel_arg_info, cl_uint> for cl_kernel {
|
||||
fn query(&self, idx: cl_uint, q: cl_kernel_arg_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let kernel = Kernel::ref_from_raw(*self)?;
|
||||
|
||||
// CL_INVALID_ARG_INDEX if arg_index is not a valid argument index.
|
||||
|
|
@ -55,39 +55,40 @@ impl CLInfoObj<cl_kernel_arg_info, cl_uint> for cl_kernel {
|
|||
return Err(CL_INVALID_ARG_INDEX);
|
||||
}
|
||||
|
||||
Ok(match *q {
|
||||
match *q {
|
||||
CL_KERNEL_ARG_ACCESS_QUALIFIER => {
|
||||
cl_prop::<cl_kernel_arg_access_qualifier>(kernel.access_qualifier(idx))
|
||||
v.write::<cl_kernel_arg_access_qualifier>(kernel.access_qualifier(idx))
|
||||
}
|
||||
CL_KERNEL_ARG_ADDRESS_QUALIFIER => {
|
||||
cl_prop::<cl_kernel_arg_address_qualifier>(kernel.address_qualifier(idx))
|
||||
v.write::<cl_kernel_arg_address_qualifier>(kernel.address_qualifier(idx))
|
||||
}
|
||||
CL_KERNEL_ARG_NAME => cl_prop::<&CStr>(
|
||||
CL_KERNEL_ARG_NAME => v.write::<&CStr>(
|
||||
kernel
|
||||
.arg_name(idx)
|
||||
.ok_or(CL_KERNEL_ARG_INFO_NOT_AVAILABLE)?,
|
||||
),
|
||||
CL_KERNEL_ARG_TYPE_NAME => cl_prop::<&CStr>(
|
||||
CL_KERNEL_ARG_TYPE_NAME => v.write::<&CStr>(
|
||||
kernel
|
||||
.arg_type_name(idx)
|
||||
.ok_or(CL_KERNEL_ARG_INFO_NOT_AVAILABLE)?,
|
||||
),
|
||||
CL_KERNEL_ARG_TYPE_QUALIFIER => {
|
||||
cl_prop::<cl_kernel_arg_type_qualifier>(kernel.type_qualifier(idx))
|
||||
v.write::<cl_kernel_arg_type_qualifier>(kernel.type_qualifier(idx))
|
||||
}
|
||||
// CL_INVALID_VALUE if param_name is not one of the supported values
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cl_info_entrypoint(clGetKernelWorkGroupInfo)]
|
||||
impl CLInfoObj<cl_kernel_work_group_info, cl_device_id> for cl_kernel {
|
||||
unsafe impl CLInfoObj<cl_kernel_work_group_info, cl_device_id> for cl_kernel {
|
||||
fn query(
|
||||
&self,
|
||||
dev: cl_device_id,
|
||||
q: cl_kernel_work_group_info,
|
||||
) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
v: CLInfoValue,
|
||||
) -> CLResult<CLInfoRes> {
|
||||
let kernel = Kernel::ref_from_raw(*self)?;
|
||||
|
||||
// CL_INVALID_DEVICE [..] if device is NULL but there is more than one device associated with kernel.
|
||||
|
|
@ -106,21 +107,21 @@ impl CLInfoObj<cl_kernel_work_group_info, cl_device_id> for cl_kernel {
|
|||
return Err(CL_INVALID_DEVICE);
|
||||
}
|
||||
|
||||
Ok(match *q {
|
||||
CL_KERNEL_COMPILE_WORK_GROUP_SIZE => cl_prop::<[usize; 3]>(kernel.work_group_size()),
|
||||
CL_KERNEL_LOCAL_MEM_SIZE => cl_prop::<cl_ulong>(kernel.local_mem_size(dev)),
|
||||
match *q {
|
||||
CL_KERNEL_COMPILE_WORK_GROUP_SIZE => v.write::<[usize; 3]>(kernel.work_group_size()),
|
||||
CL_KERNEL_LOCAL_MEM_SIZE => v.write::<cl_ulong>(kernel.local_mem_size(dev)),
|
||||
CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE => {
|
||||
cl_prop::<usize>(kernel.preferred_simd_size(dev))
|
||||
v.write::<usize>(kernel.preferred_simd_size(dev))
|
||||
}
|
||||
CL_KERNEL_PRIVATE_MEM_SIZE => cl_prop::<cl_ulong>(kernel.priv_mem_size(dev)),
|
||||
CL_KERNEL_WORK_GROUP_SIZE => cl_prop::<usize>(kernel.max_threads_per_block(dev)),
|
||||
CL_KERNEL_PRIVATE_MEM_SIZE => v.write::<cl_ulong>(kernel.priv_mem_size(dev)),
|
||||
CL_KERNEL_WORK_GROUP_SIZE => v.write::<usize>(kernel.max_threads_per_block(dev)),
|
||||
// CL_INVALID_VALUE if param_name is not one of the supported values
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CLInfoObj<cl_kernel_sub_group_info, (cl_device_id, usize, *const c_void, usize)>
|
||||
unsafe impl CLInfoObj<cl_kernel_sub_group_info, (cl_device_id, usize, *const c_void, usize)>
|
||||
for cl_kernel
|
||||
{
|
||||
fn query(
|
||||
|
|
@ -132,7 +133,8 @@ impl CLInfoObj<cl_kernel_sub_group_info, (cl_device_id, usize, *const c_void, us
|
|||
usize,
|
||||
),
|
||||
q: cl_program_build_info,
|
||||
) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
v: CLInfoValue,
|
||||
) -> CLResult<CLInfoRes> {
|
||||
let kernel = Kernel::ref_from_raw(*self)?;
|
||||
|
||||
// CL_INVALID_DEVICE [..] if device is NULL but there is more than one device associated
|
||||
|
|
@ -183,12 +185,12 @@ impl CLInfoObj<cl_kernel_sub_group_info, (cl_device_id, usize, *const c_void, us
|
|||
_ => &[],
|
||||
};
|
||||
|
||||
Ok(match q {
|
||||
match q {
|
||||
CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE => {
|
||||
cl_prop::<usize>(kernel.subgroups_for_block(dev, input))
|
||||
v.write::<usize>(kernel.subgroups_for_block(dev, input))
|
||||
}
|
||||
CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE => {
|
||||
cl_prop::<usize>(kernel.subgroup_size_for_block(dev, input))
|
||||
v.write::<usize>(kernel.subgroup_size_for_block(dev, input))
|
||||
}
|
||||
CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT => {
|
||||
let subgroups = input[0];
|
||||
|
|
@ -211,7 +213,7 @@ impl CLInfoObj<cl_kernel_sub_group_info, (cl_device_id, usize, *const c_void, us
|
|||
}
|
||||
|
||||
res.truncate(output_value_size / usize_byte);
|
||||
cl_prop::<Vec<usize>>(res)
|
||||
v.write::<Vec<usize>>(res)
|
||||
}
|
||||
CL_KERNEL_MAX_NUM_SUB_GROUPS => {
|
||||
let threads = kernel.max_threads_per_block(dev);
|
||||
|
|
@ -222,13 +224,13 @@ impl CLInfoObj<cl_kernel_sub_group_info, (cl_device_id, usize, *const c_void, us
|
|||
result = cmp::max(result, threads / sgs);
|
||||
result = cmp::min(result, max_groups as usize);
|
||||
}
|
||||
cl_prop::<usize>(result)
|
||||
v.write::<usize>(result)
|
||||
}
|
||||
CL_KERNEL_COMPILE_NUM_SUB_GROUPS => cl_prop::<usize>(kernel.num_subgroups()),
|
||||
CL_KERNEL_COMPILE_SUB_GROUP_SIZE_INTEL => cl_prop::<usize>(kernel.subgroup_size()),
|
||||
CL_KERNEL_COMPILE_NUM_SUB_GROUPS => v.write::<usize>(kernel.num_subgroups()),
|
||||
CL_KERNEL_COMPILE_SUB_GROUP_SIZE_INTEL => v.write::<usize>(kernel.subgroup_size()),
|
||||
// CL_INVALID_VALUE if param_name is not one of the supported values
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -214,10 +214,10 @@ fn validate_matching_buffer_flags(mem: &MemBase, flags: cl_mem_flags) -> CLResul
|
|||
}
|
||||
|
||||
#[cl_info_entrypoint(clGetMemObjectInfo)]
|
||||
impl CLInfo<cl_mem_info> for cl_mem {
|
||||
fn query(&self, q: cl_mem_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_mem_info> for cl_mem {
|
||||
fn query(&self, q: cl_mem_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let mem = MemBase::ref_from_raw(*self)?;
|
||||
Ok(match *q {
|
||||
match *q {
|
||||
CL_MEM_ASSOCIATED_MEMOBJECT => {
|
||||
let ptr = match mem.parent.as_ref() {
|
||||
// Note we use as_ptr here which doesn't increase the reference count.
|
||||
|
|
@ -225,35 +225,35 @@ impl CLInfo<cl_mem_info> for cl_mem {
|
|||
Some(Mem::Image(image)) => cl_mem::from_ptr(Arc::as_ptr(image)),
|
||||
None => ptr::null_mut(),
|
||||
};
|
||||
cl_prop::<cl_mem>(ptr.cast())
|
||||
v.write::<cl_mem>(ptr.cast())
|
||||
}
|
||||
CL_MEM_CONTEXT => {
|
||||
// Note we use as_ptr here which doesn't increase the reference count.
|
||||
let ptr = Arc::as_ptr(&mem.context);
|
||||
cl_prop::<cl_context>(cl_context::from_ptr(ptr))
|
||||
v.write::<cl_context>(cl_context::from_ptr(ptr))
|
||||
}
|
||||
CL_MEM_FLAGS => cl_prop::<cl_mem_flags>(mem.flags),
|
||||
CL_MEM_FLAGS => v.write::<cl_mem_flags>(mem.flags),
|
||||
// TODO debugging feature
|
||||
CL_MEM_MAP_COUNT => cl_prop::<cl_uint>(0),
|
||||
CL_MEM_HOST_PTR => cl_prop::<*mut c_void>(mem.host_ptr()),
|
||||
CL_MEM_OFFSET => cl_prop::<usize>(if mem.is_buffer() {
|
||||
CL_MEM_MAP_COUNT => v.write::<cl_uint>(0),
|
||||
CL_MEM_HOST_PTR => v.write::<*mut c_void>(mem.host_ptr()),
|
||||
CL_MEM_OFFSET => v.write::<usize>(if mem.is_buffer() {
|
||||
Buffer::ref_from_raw(*self)?.offset
|
||||
} else {
|
||||
0
|
||||
}),
|
||||
CL_MEM_PROPERTIES => cl_prop::<&Vec<cl_mem_properties>>(&mem.props),
|
||||
CL_MEM_REFERENCE_COUNT => cl_prop::<cl_uint>(if mem.is_buffer() {
|
||||
CL_MEM_PROPERTIES => v.write::<&[cl_mem_properties]>(&mem.props),
|
||||
CL_MEM_REFERENCE_COUNT => v.write::<cl_uint>(if mem.is_buffer() {
|
||||
Buffer::refcnt(*self)?
|
||||
} else {
|
||||
Image::refcnt(*self)?
|
||||
}),
|
||||
CL_MEM_SIZE => cl_prop::<usize>(mem.size),
|
||||
CL_MEM_TYPE => cl_prop::<cl_mem_object_type>(mem.mem_type),
|
||||
CL_MEM_SIZE => v.write::<usize>(mem.size),
|
||||
CL_MEM_TYPE => v.write::<cl_mem_object_type>(mem.mem_type),
|
||||
CL_MEM_USES_SVM_POINTER | CL_MEM_USES_SVM_POINTER_ARM => {
|
||||
cl_prop::<cl_bool>(mem.is_svm().into())
|
||||
v.write::<cl_bool>(mem.is_svm().into())
|
||||
}
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -731,27 +731,27 @@ fn validate_buffer(
|
|||
}
|
||||
|
||||
#[cl_info_entrypoint(clGetImageInfo)]
|
||||
impl CLInfo<cl_image_info> for cl_mem {
|
||||
fn query(&self, q: cl_image_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_image_info> for cl_mem {
|
||||
fn query(&self, q: cl_image_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let mem = Image::ref_from_raw(*self)?;
|
||||
Ok(match *q {
|
||||
CL_IMAGE_ARRAY_SIZE => cl_prop::<usize>(mem.image_desc.image_array_size),
|
||||
CL_IMAGE_BUFFER => cl_prop::<cl_mem>(unsafe { mem.image_desc.anon_1.buffer }),
|
||||
CL_IMAGE_DEPTH => cl_prop::<usize>(mem.image_desc.image_depth),
|
||||
CL_IMAGE_ELEMENT_SIZE => cl_prop::<usize>(mem.image_elem_size.into()),
|
||||
CL_IMAGE_FORMAT => cl_prop::<cl_image_format>(mem.image_format),
|
||||
CL_IMAGE_HEIGHT => cl_prop::<usize>(mem.image_desc.image_height),
|
||||
CL_IMAGE_NUM_MIP_LEVELS => cl_prop::<cl_uint>(mem.image_desc.num_mip_levels),
|
||||
CL_IMAGE_NUM_SAMPLES => cl_prop::<cl_uint>(mem.image_desc.num_samples),
|
||||
CL_IMAGE_ROW_PITCH => cl_prop::<usize>(mem.image_desc.image_row_pitch),
|
||||
CL_IMAGE_SLICE_PITCH => cl_prop::<usize>(if mem.image_desc.dims() == 1 {
|
||||
match *q {
|
||||
CL_IMAGE_ARRAY_SIZE => v.write::<usize>(mem.image_desc.image_array_size),
|
||||
CL_IMAGE_BUFFER => v.write::<cl_mem>(unsafe { mem.image_desc.anon_1.buffer }),
|
||||
CL_IMAGE_DEPTH => v.write::<usize>(mem.image_desc.image_depth),
|
||||
CL_IMAGE_ELEMENT_SIZE => v.write::<usize>(mem.image_elem_size.into()),
|
||||
CL_IMAGE_FORMAT => v.write::<cl_image_format>(mem.image_format),
|
||||
CL_IMAGE_HEIGHT => v.write::<usize>(mem.image_desc.image_height),
|
||||
CL_IMAGE_NUM_MIP_LEVELS => v.write::<cl_uint>(mem.image_desc.num_mip_levels),
|
||||
CL_IMAGE_NUM_SAMPLES => v.write::<cl_uint>(mem.image_desc.num_samples),
|
||||
CL_IMAGE_ROW_PITCH => v.write::<usize>(mem.image_desc.image_row_pitch),
|
||||
CL_IMAGE_SLICE_PITCH => v.write::<usize>(if mem.image_desc.dims() == 1 {
|
||||
0
|
||||
} else {
|
||||
mem.image_desc.image_slice_pitch
|
||||
}),
|
||||
CL_IMAGE_WIDTH => cl_prop::<usize>(mem.image_desc.image_width),
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
CL_IMAGE_WIDTH => v.write::<usize>(mem.image_desc.image_width),
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -931,25 +931,25 @@ fn get_supported_image_formats(
|
|||
}
|
||||
|
||||
#[cl_info_entrypoint(clGetSamplerInfo)]
|
||||
impl CLInfo<cl_sampler_info> for cl_sampler {
|
||||
fn query(&self, q: cl_sampler_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_sampler_info> for cl_sampler {
|
||||
fn query(&self, q: cl_sampler_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let sampler = Sampler::ref_from_raw(*self)?;
|
||||
Ok(match q {
|
||||
CL_SAMPLER_ADDRESSING_MODE => cl_prop::<cl_addressing_mode>(sampler.addressing_mode),
|
||||
match q {
|
||||
CL_SAMPLER_ADDRESSING_MODE => v.write::<cl_addressing_mode>(sampler.addressing_mode),
|
||||
CL_SAMPLER_CONTEXT => {
|
||||
// Note we use as_ptr here which doesn't increase the reference count.
|
||||
let ptr = Arc::as_ptr(&sampler.context);
|
||||
cl_prop::<cl_context>(cl_context::from_ptr(ptr))
|
||||
v.write::<cl_context>(cl_context::from_ptr(ptr))
|
||||
}
|
||||
CL_SAMPLER_FILTER_MODE => cl_prop::<cl_filter_mode>(sampler.filter_mode),
|
||||
CL_SAMPLER_NORMALIZED_COORDS => cl_prop::<bool>(sampler.normalized_coords),
|
||||
CL_SAMPLER_REFERENCE_COUNT => cl_prop::<cl_uint>(Sampler::refcnt(*self)?),
|
||||
CL_SAMPLER_FILTER_MODE => v.write::<cl_filter_mode>(sampler.filter_mode),
|
||||
CL_SAMPLER_NORMALIZED_COORDS => v.write::<bool>(sampler.normalized_coords),
|
||||
CL_SAMPLER_REFERENCE_COUNT => v.write::<cl_uint>(Sampler::refcnt(*self)?),
|
||||
CL_SAMPLER_PROPERTIES => {
|
||||
cl_prop::<&Option<Properties<cl_sampler_properties>>>(&sampler.props)
|
||||
v.write::<Option<&Properties<cl_sampler_properties>>>(sampler.props.as_ref())
|
||||
}
|
||||
// CL_INVALID_VALUE if param_name is not one of the supported values
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2316,8 +2316,8 @@ fn enqueue_migrate_mem_objects(
|
|||
}
|
||||
|
||||
#[cl_info_entrypoint(clGetPipeInfo)]
|
||||
impl CLInfo<cl_pipe_info> for cl_mem {
|
||||
fn query(&self, _q: cl_pipe_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_pipe_info> for cl_mem {
|
||||
fn query(&self, _q: cl_pipe_info, _v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
// CL_INVALID_MEM_OBJECT if pipe is a not a valid pipe object.
|
||||
Err(CL_INVALID_MEM_OBJECT)
|
||||
}
|
||||
|
|
@ -3018,19 +3018,19 @@ fn create_pipe(
|
|||
}
|
||||
|
||||
#[cl_info_entrypoint(clGetGLTextureInfo)]
|
||||
impl CLInfo<cl_gl_texture_info> for cl_mem {
|
||||
fn query(&self, q: cl_gl_texture_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_gl_texture_info> for cl_mem {
|
||||
fn query(&self, q: cl_gl_texture_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let mem = MemBase::ref_from_raw(*self)?;
|
||||
Ok(match *q {
|
||||
CL_GL_MIPMAP_LEVEL => cl_prop::<cl_GLint>(0),
|
||||
CL_GL_TEXTURE_TARGET => cl_prop::<cl_GLenum>(
|
||||
match *q {
|
||||
CL_GL_MIPMAP_LEVEL => v.write::<cl_GLint>(0),
|
||||
CL_GL_TEXTURE_TARGET => v.write::<cl_GLenum>(
|
||||
mem.gl_obj
|
||||
.as_ref()
|
||||
.ok_or(CL_INVALID_GL_OBJECT)?
|
||||
.gl_object_target,
|
||||
),
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,29 +8,28 @@ use rusticl_opencl_gen::*;
|
|||
use rusticl_proc_macros::cl_entrypoint;
|
||||
use rusticl_proc_macros::cl_info_entrypoint;
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[cl_info_entrypoint(clGetPlatformInfo)]
|
||||
impl CLInfo<cl_platform_info> for cl_platform_id {
|
||||
fn query(&self, q: cl_platform_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_platform_info> for cl_platform_id {
|
||||
fn query(&self, q: cl_platform_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
self.get_ref()?;
|
||||
Ok(match q {
|
||||
// TODO spirv
|
||||
CL_PLATFORM_EXTENSIONS => cl_prop(PLATFORM_EXTENSION_STR),
|
||||
match q {
|
||||
CL_PLATFORM_EXTENSIONS => v.write::<&str>(PLATFORM_EXTENSION_STR),
|
||||
CL_PLATFORM_EXTENSIONS_WITH_VERSION => {
|
||||
cl_prop::<Vec<cl_name_version>>(PLATFORM_EXTENSIONS.to_vec())
|
||||
v.write::<Vec<cl_name_version>>(PLATFORM_EXTENSIONS.to_vec())
|
||||
}
|
||||
CL_PLATFORM_HOST_TIMER_RESOLUTION => cl_prop::<cl_ulong>(1),
|
||||
CL_PLATFORM_ICD_SUFFIX_KHR => cl_prop(c"MESA"),
|
||||
CL_PLATFORM_NAME => cl_prop(c"rusticl"),
|
||||
CL_PLATFORM_NUMERIC_VERSION => cl_prop::<cl_version>(CLVersion::Cl3_0 as u32),
|
||||
CL_PLATFORM_PROFILE => cl_prop(c"FULL_PROFILE"),
|
||||
CL_PLATFORM_VENDOR => cl_prop(c"Mesa/X.org"),
|
||||
CL_PLATFORM_HOST_TIMER_RESOLUTION => v.write::<cl_ulong>(1),
|
||||
CL_PLATFORM_ICD_SUFFIX_KHR => v.write::<&CStr>(c"MESA"),
|
||||
CL_PLATFORM_NAME => v.write::<&CStr>(c"rusticl"),
|
||||
CL_PLATFORM_NUMERIC_VERSION => v.write::<cl_version>(CLVersion::Cl3_0.into()),
|
||||
CL_PLATFORM_PROFILE => v.write::<&CStr>(c"FULL_PROFILE"),
|
||||
CL_PLATFORM_VENDOR => v.write::<&CStr>(c"Mesa/X.org"),
|
||||
// OpenCL<space><major_version.minor_version><space><platform-specific information>
|
||||
CL_PLATFORM_VERSION => cl_prop(c"OpenCL 3.0 "),
|
||||
CL_PLATFORM_VERSION => v.write::<&CStr>(c"OpenCL 3.0 "),
|
||||
// CL_INVALID_VALUE if param_name is not one of the supported values
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use rusticl_proc_macros::cl_info_entrypoint;
|
|||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::iter;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::os::raw::c_char;
|
||||
use std::ptr;
|
||||
|
|
@ -23,57 +22,70 @@ use std::slice;
|
|||
use std::sync::Arc;
|
||||
|
||||
#[cl_info_entrypoint(clGetProgramInfo)]
|
||||
impl CLInfo<cl_program_info> for cl_program {
|
||||
fn query(&self, q: cl_program_info, vals: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_program_info> for cl_program {
|
||||
fn query(&self, q: cl_program_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let prog = Program::ref_from_raw(*self)?;
|
||||
Ok(match q {
|
||||
CL_PROGRAM_BINARIES => cl_prop::<Vec<*mut u8>>(prog.binaries(vals)?),
|
||||
CL_PROGRAM_BINARY_SIZES => cl_prop::<Vec<usize>>(prog.bin_sizes()),
|
||||
match q {
|
||||
CL_PROGRAM_BINARIES => {
|
||||
let input = v.input::<*mut u8>()?;
|
||||
// SAFETY: Oer spec it contains an array of pointers to write the binaries to,
|
||||
// so we can assume the entire slice to be initialized.
|
||||
let input = unsafe { slice_assume_init_ref(input) };
|
||||
let bins = prog.binaries(input)?;
|
||||
v.write::<Vec<*mut u8>>(bins)
|
||||
}
|
||||
CL_PROGRAM_BINARY_SIZES => v.write::<Vec<usize>>(prog.bin_sizes()),
|
||||
CL_PROGRAM_CONTEXT => {
|
||||
// Note we use as_ptr here which doesn't increase the reference count.
|
||||
let ptr = Arc::as_ptr(&prog.context);
|
||||
cl_prop::<cl_context>(cl_context::from_ptr(ptr))
|
||||
v.write::<cl_context>(cl_context::from_ptr(ptr))
|
||||
}
|
||||
CL_PROGRAM_DEVICES => cl_prop::<Vec<cl_device_id>>(
|
||||
CL_PROGRAM_DEVICES => v.write::<Vec<cl_device_id>>(
|
||||
prog.devs
|
||||
.iter()
|
||||
.map(|&d| cl_device_id::from_ptr(d))
|
||||
.collect(),
|
||||
),
|
||||
CL_PROGRAM_IL => match &prog.src {
|
||||
ProgramSourceType::Il(il) => to_maybeuninit_vec(il.to_bin().to_vec()),
|
||||
CL_PROGRAM_IL => v.write::<Vec<u8>>(match &prog.src {
|
||||
ProgramSourceType::Il(il) => il.to_bin().to_vec(),
|
||||
_ => Vec::new(),
|
||||
},
|
||||
CL_PROGRAM_KERNEL_NAMES => cl_prop::<&str>(&*prog.build_info().kernels().join(";")),
|
||||
CL_PROGRAM_NUM_DEVICES => cl_prop::<cl_uint>(prog.devs.len() as cl_uint),
|
||||
CL_PROGRAM_NUM_KERNELS => cl_prop::<usize>(prog.build_info().kernels().len()),
|
||||
CL_PROGRAM_REFERENCE_COUNT => cl_prop::<cl_uint>(Program::refcnt(*self)?),
|
||||
CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT => cl_prop::<cl_bool>(CL_FALSE),
|
||||
CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT => cl_prop::<cl_bool>(CL_FALSE),
|
||||
CL_PROGRAM_SOURCE => match &prog.src {
|
||||
ProgramSourceType::Src(src) => cl_prop::<&CStr>(src.as_c_str()),
|
||||
_ => Vec::new(),
|
||||
},
|
||||
}),
|
||||
CL_PROGRAM_KERNEL_NAMES => v.write::<&str>(&prog.build_info().kernels().join(";")),
|
||||
CL_PROGRAM_NUM_DEVICES => v.write::<cl_uint>(prog.devs.len() as cl_uint),
|
||||
CL_PROGRAM_NUM_KERNELS => v.write::<usize>(prog.build_info().kernels().len()),
|
||||
CL_PROGRAM_REFERENCE_COUNT => v.write::<cl_uint>(Program::refcnt(*self)?),
|
||||
CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT => v.write::<cl_bool>(CL_FALSE),
|
||||
CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT => v.write::<cl_bool>(CL_FALSE),
|
||||
CL_PROGRAM_SOURCE => v.write::<&CStr>(match &prog.src {
|
||||
ProgramSourceType::Src(src) => src,
|
||||
// need to return a null string if no source is available.
|
||||
_ => c"",
|
||||
}),
|
||||
// CL_INVALID_VALUE if param_name is not one of the supported values
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cl_info_entrypoint(clGetProgramBuildInfo)]
|
||||
impl CLInfoObj<cl_program_build_info, cl_device_id> for cl_program {
|
||||
fn query(&self, d: cl_device_id, q: cl_program_build_info) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfoObj<cl_program_build_info, cl_device_id> for cl_program {
|
||||
fn query(
|
||||
&self,
|
||||
d: cl_device_id,
|
||||
q: cl_program_build_info,
|
||||
v: CLInfoValue,
|
||||
) -> CLResult<CLInfoRes> {
|
||||
let prog = Program::ref_from_raw(*self)?;
|
||||
let dev = Device::ref_from_raw(d)?;
|
||||
Ok(match q {
|
||||
CL_PROGRAM_BINARY_TYPE => cl_prop::<cl_program_binary_type>(prog.bin_type(dev)),
|
||||
CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE => cl_prop::<usize>(0),
|
||||
CL_PROGRAM_BUILD_LOG => cl_prop::<&str>(&prog.log(dev)),
|
||||
CL_PROGRAM_BUILD_OPTIONS => cl_prop::<&str>(&prog.options(dev)),
|
||||
CL_PROGRAM_BUILD_STATUS => cl_prop::<cl_build_status>(prog.status(dev)),
|
||||
match q {
|
||||
CL_PROGRAM_BINARY_TYPE => v.write::<cl_program_binary_type>(prog.bin_type(dev)),
|
||||
CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE => v.write::<usize>(0),
|
||||
CL_PROGRAM_BUILD_LOG => v.write::<&str>(&prog.log(dev)),
|
||||
CL_PROGRAM_BUILD_OPTIONS => v.write::<&str>(&prog.options(dev)),
|
||||
CL_PROGRAM_BUILD_STATUS => v.write::<cl_build_status>(prog.status(dev)),
|
||||
// CL_INVALID_VALUE if param_name is not one of the supported values
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,33 +11,32 @@ use rusticl_opencl_gen::*;
|
|||
use rusticl_proc_macros::cl_entrypoint;
|
||||
use rusticl_proc_macros::cl_info_entrypoint;
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cl_info_entrypoint(clGetCommandQueueInfo)]
|
||||
impl CLInfo<cl_command_queue_info> for cl_command_queue {
|
||||
fn query(&self, q: cl_command_queue_info, _: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>> {
|
||||
unsafe impl CLInfo<cl_command_queue_info> for cl_command_queue {
|
||||
fn query(&self, q: cl_command_queue_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||
let queue = Queue::ref_from_raw(*self)?;
|
||||
Ok(match q {
|
||||
match q {
|
||||
CL_QUEUE_CONTEXT => {
|
||||
// Note we use as_ptr here which doesn't increase the reference count.
|
||||
let ptr = Arc::as_ptr(&queue.context);
|
||||
cl_prop::<cl_context>(cl_context::from_ptr(ptr))
|
||||
v.write::<cl_context>(cl_context::from_ptr(ptr))
|
||||
}
|
||||
CL_QUEUE_DEVICE => cl_prop::<cl_device_id>(cl_device_id::from_ptr(queue.device)),
|
||||
CL_QUEUE_DEVICE_DEFAULT => cl_prop::<cl_command_queue>(ptr::null_mut()),
|
||||
CL_QUEUE_PROPERTIES => cl_prop::<cl_command_queue_properties>(queue.props),
|
||||
CL_QUEUE_DEVICE => v.write::<cl_device_id>(cl_device_id::from_ptr(queue.device)),
|
||||
CL_QUEUE_DEVICE_DEFAULT => v.write::<cl_command_queue>(ptr::null_mut()),
|
||||
CL_QUEUE_PROPERTIES => v.write::<cl_command_queue_properties>(queue.props),
|
||||
CL_QUEUE_PROPERTIES_ARRAY => {
|
||||
cl_prop::<&Option<Properties<cl_queue_properties>>>(&queue.props_v2)
|
||||
v.write::<Option<&Properties<cl_queue_properties>>>(queue.props_v2.as_ref())
|
||||
}
|
||||
CL_QUEUE_REFERENCE_COUNT => cl_prop::<cl_uint>(Queue::refcnt(*self)?),
|
||||
CL_QUEUE_REFERENCE_COUNT => v.write::<cl_uint>(Queue::refcnt(*self)?),
|
||||
// clGetCommandQueueInfo, passing CL_QUEUE_SIZE Returns CL_INVALID_COMMAND_QUEUE since
|
||||
// command_queue cannot be a valid device command-queue.
|
||||
CL_QUEUE_SIZE => return Err(CL_INVALID_COMMAND_QUEUE),
|
||||
CL_QUEUE_SIZE => Err(CL_INVALID_COMMAND_QUEUE),
|
||||
// CL_INVALID_VALUE if param_name is not one of the supported values
|
||||
_ => return Err(CL_INVALID_VALUE),
|
||||
})
|
||||
_ => Err(CL_INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,20 +4,157 @@ use crate::core::event::*;
|
|||
use crate::core::queue::*;
|
||||
|
||||
use mesa_rust_util::properties::Properties;
|
||||
use mesa_rust_util::ptr::CheckedPtr;
|
||||
use rusticl_opencl_gen::*;
|
||||
|
||||
use std::cmp;
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::mem::{size_of, MaybeUninit};
|
||||
use std::ffi::{c_void, CStr};
|
||||
use std::iter::zip;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ops::BitAnd;
|
||||
use std::slice;
|
||||
use std::sync::Arc;
|
||||
use std::{cmp, mem};
|
||||
|
||||
pub trait CLInfo<I> {
|
||||
fn query(&self, q: I, vals: &[u8]) -> CLResult<Vec<MaybeUninit<u8>>>;
|
||||
// TODO: use MaybeUninit::copy_from_slice once stable
|
||||
pub fn maybe_uninit_copy_from_slice<T>(this: &mut [MaybeUninit<T>], src: &[T])
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
// Assert this so we stick as close as possible to MaybeUninit::copy_from_slices behavior.
|
||||
debug_assert_eq!(this.len(), src.len());
|
||||
|
||||
for (dest, val) in zip(this, src) {
|
||||
*dest = MaybeUninit::new(*val);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use MaybeUninit::slice_assume_init_ref once stable
|
||||
pub const unsafe fn slice_assume_init_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] {
|
||||
// SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that
|
||||
// `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`.
|
||||
// The pointer obtained is valid since it refers to memory owned by `slice` which is a
|
||||
// reference and thus guaranteed to be valid for reads.
|
||||
unsafe { &*(slice as *const [_] as *const [T]) }
|
||||
}
|
||||
|
||||
/// Token to make sure that ClInfoValue::write is called
|
||||
pub struct CLInfoRes {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
/// A helper class to simplify implementing so called "info" APIs in OpenCL, e.g. `clGetDeviceInfo`.
|
||||
///
|
||||
/// Those APIs generally operate on opaque memory buffers and needs to be interpreted according to
|
||||
/// the specific query being made. The generic parameter to the input and write functions should
|
||||
/// always be explicitly specified.
|
||||
pub struct CLInfoValue<'a> {
|
||||
param_value: Option<&'a mut [MaybeUninit<u8>]>,
|
||||
param_value_size_ret: Option<&'a mut MaybeUninit<usize>>,
|
||||
}
|
||||
|
||||
impl<'a> CLInfoValue<'a> {
|
||||
/// # Safety
|
||||
/// `param_value` and `param_value_size_ret` need to be valid memory allocations or null.
|
||||
/// If `param_value` is not null it needs to point to an allocation of at least
|
||||
/// `param_value_size` bytes.
|
||||
unsafe fn new(
|
||||
param_value_size: usize,
|
||||
param_value: *mut c_void,
|
||||
param_value_size_ret: *mut usize,
|
||||
) -> CLResult<Self> {
|
||||
let param_value_size_ret: *mut MaybeUninit<usize> = param_value_size_ret.cast();
|
||||
let param_value = if !param_value.is_null() {
|
||||
Some(unsafe { cl_slice::from_raw_parts_mut(param_value.cast(), param_value_size)? })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
param_value: param_value,
|
||||
param_value_size_ret: unsafe { param_value_size_ret.as_mut() },
|
||||
})
|
||||
}
|
||||
|
||||
fn finish() -> CLInfoRes {
|
||||
CLInfoRes { _private: () }
|
||||
}
|
||||
|
||||
/// Used to read from the application provided data.
|
||||
pub fn input<T>(&self) -> CLResult<&[MaybeUninit<T>]> {
|
||||
if let Some(param_value) = &self.param_value {
|
||||
let count = param_value.len() / mem::size_of::<T>();
|
||||
unsafe { cl_slice::from_raw_parts(param_value.as_ptr().cast(), count) }
|
||||
} else {
|
||||
Ok(&[])
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes the passed in value according to the generic. It is important to pass in the same
|
||||
/// or compatible type as stated in the OpenCL specification.
|
||||
///
|
||||
/// It also verifies that if a buffer was provided by the application it's big enough to hold
|
||||
/// `t` and returns `Err(CL_INVALID_VALUE)` otherwise.
|
||||
///
|
||||
/// Type specific details:
|
||||
/// - Compatible with C arrays are `T` (if only one element is to be returned), `Vec<T>` or `&[T]`
|
||||
/// types.
|
||||
/// - Compatible with C strings are all basic Rust string types.
|
||||
/// - `bool`s are automatically converted to `cl_bool`.
|
||||
/// - For queries which can return no data, `Option<T>` can be used.
|
||||
/// - For C property arrays (0-terminated arrays of `T`) the
|
||||
/// [mesa_rust_util::properties::Properties] type can be used.
|
||||
///
|
||||
/// All types implementing [CLProp] are supported.
|
||||
pub fn write<T: CLProp>(self, t: T) -> CLResult<CLInfoRes> {
|
||||
let count = t.count();
|
||||
let bytes = count * mem::size_of::<T::Output>();
|
||||
|
||||
// param_value is a pointer to memory where the appropriate result being queried is
|
||||
// returned. If param_value is NULL, it is ignored.
|
||||
if let Some(param_value) = self.param_value {
|
||||
// CL_INVALID_VALUE [...] if size in bytes specified by param_value_size is < size of
|
||||
// return type as specified in the Context Attributes table and param_value is not a
|
||||
// NULL value.
|
||||
if param_value.len() < bytes {
|
||||
return Err(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
// SAFETY: Casting between types wrapped with MaybeUninit is fine, because it's up to
|
||||
// the caller to decide if it sound to read from it. Also the count passed in is
|
||||
// just the type adjusted size of the `param_value` slice.
|
||||
let out =
|
||||
unsafe { cl_slice::from_raw_parts_mut(param_value.as_mut_ptr().cast(), count)? };
|
||||
|
||||
t.write_to(out);
|
||||
}
|
||||
|
||||
// param_value_size_ret returns the actual size in bytes of data being queried by
|
||||
// param_name. If param_value_size_ret is NULL, it is ignored.
|
||||
if let Some(param_value_size_ret) = self.param_value_size_ret {
|
||||
param_value_size_ret.write(bytes);
|
||||
}
|
||||
|
||||
Ok(Self::finish())
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// This trait helps implementing various OpenCL Query APIs, however care have to be taken that the
|
||||
/// `query` implementation implements the corresponding query according to the OpenCL specification.
|
||||
///
|
||||
/// Queries which don't have a size known at compile time are expected to be called twice:
|
||||
/// 1. To ask the implementation of how much data will be returned. The application uses this
|
||||
/// to allocate enough memory to be passed into the next call.
|
||||
/// 2. To actually execute the query.
|
||||
/// This trait abstracts this pattern properly away to make it easier to implement it.
|
||||
///
|
||||
/// [CLInfoValue] contains helper functions to read and write data behind opaque buffers, the
|
||||
/// applications using those OpenCL queries expect the implementation to behave accordingly.
|
||||
///
|
||||
/// It is advised to explicitly specify the types of [CLInfoValue::input] and the various write
|
||||
/// helpers.
|
||||
pub unsafe trait CLInfo<I> {
|
||||
fn query(&self, q: I, v: CLInfoValue) -> CLResult<CLInfoRes>;
|
||||
|
||||
fn get_info(
|
||||
&self,
|
||||
|
|
@ -26,37 +163,18 @@ pub trait CLInfo<I> {
|
|||
param_value: *mut ::std::os::raw::c_void,
|
||||
param_value_size_ret: *mut usize,
|
||||
) -> CLResult<()> {
|
||||
let arr = if !param_value.is_null() && param_value_size != 0 {
|
||||
unsafe { slice::from_raw_parts(param_value.cast(), param_value_size) }
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
|
||||
let d = self.query(param_name, arr)?;
|
||||
let size: usize = d.len();
|
||||
|
||||
// CL_INVALID_VALUE [...] if size in bytes specified by param_value_size is < size of return
|
||||
// type as specified in the Context Attributes table and param_value is not a NULL value.
|
||||
if param_value_size < size && !param_value.is_null() {
|
||||
return Err(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
// param_value_size_ret returns the actual size in bytes of data being queried by param_name.
|
||||
// If param_value_size_ret is NULL, it is ignored.
|
||||
param_value_size_ret.write_checked(size);
|
||||
|
||||
// param_value is a pointer to memory where the appropriate result being queried is returned.
|
||||
// If param_value is NULL, it is ignored.
|
||||
unsafe {
|
||||
param_value.copy_checked(d.as_ptr().cast(), size);
|
||||
}
|
||||
|
||||
let value =
|
||||
unsafe { CLInfoValue::new(param_value_size, param_value, param_value_size_ret)? };
|
||||
self.query(param_name, value)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CLInfoObj<I, O> {
|
||||
fn query(&self, o: O, q: I) -> CLResult<Vec<MaybeUninit<u8>>>;
|
||||
/// # Safety
|
||||
///
|
||||
/// See [CLInfo]
|
||||
pub unsafe trait CLInfoObj<I, O> {
|
||||
fn query(&self, o: O, q: I, v: CLInfoValue) -> CLResult<CLInfoRes>;
|
||||
|
||||
fn get_info_obj(
|
||||
&self,
|
||||
|
|
@ -66,39 +184,35 @@ pub trait CLInfoObj<I, O> {
|
|||
param_value: *mut ::std::os::raw::c_void,
|
||||
param_value_size_ret: *mut usize,
|
||||
) -> CLResult<()> {
|
||||
let d = self.query(obj, param_name)?;
|
||||
let size: usize = d.len();
|
||||
|
||||
// CL_INVALID_VALUE [...] if size in bytes specified by param_value_size is < size of return
|
||||
// type as specified in the Context Attributes table and param_value is not a NULL value.
|
||||
if param_value_size < size && !param_value.is_null() {
|
||||
return Err(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
// param_value_size_ret returns the actual size in bytes of data being queried by param_name.
|
||||
// If param_value_size_ret is NULL, it is ignored.
|
||||
param_value_size_ret.write_checked(size);
|
||||
|
||||
// param_value is a pointer to memory where the appropriate result being queried is returned.
|
||||
// If param_value is NULL, it is ignored.
|
||||
unsafe {
|
||||
param_value.copy_checked(d.as_ptr().cast(), size);
|
||||
}
|
||||
|
||||
let value =
|
||||
unsafe { CLInfoValue::new(param_value_size, param_value, param_value_size_ret)? };
|
||||
self.query(obj, param_name, value)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait to be implemented for the [CLInfo] and [CLInfoObj].
|
||||
pub trait CLProp {
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>>;
|
||||
type Output: CLProp + Copy;
|
||||
|
||||
/// Returns the amount of `Self::Output` returned.
|
||||
fn count(&self) -> usize;
|
||||
|
||||
/// Called to write the value into the `out` buffer.
|
||||
fn write_to(&self, out: &mut [MaybeUninit<Self::Output>]);
|
||||
}
|
||||
|
||||
macro_rules! cl_prop_for_type {
|
||||
($ty: ty) => {
|
||||
impl CLProp for $ty {
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
unsafe { slice::from_raw_parts(std::ptr::from_ref(self).cast(), size_of::<Self>()) }
|
||||
.to_vec()
|
||||
type Output = Self;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn write_to(&self, out: &mut [MaybeUninit<Self>]) {
|
||||
out[0].write(*self);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -119,116 +233,142 @@ cl_prop_for_type!(cl_image_format);
|
|||
cl_prop_for_type!(cl_name_version);
|
||||
|
||||
impl CLProp for bool {
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
cl_prop::<cl_bool>(if *self { CL_TRUE } else { CL_FALSE })
|
||||
type Output = cl_bool;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn write_to(&self, out: &mut [MaybeUninit<cl_bool>]) {
|
||||
if *self { CL_TRUE } else { CL_FALSE }.write_to(out);
|
||||
}
|
||||
}
|
||||
|
||||
impl CLProp for &str {
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
to_maybeuninit_vec(
|
||||
CString::new(*self)
|
||||
.unwrap_or_default()
|
||||
.into_bytes_with_nul(),
|
||||
)
|
||||
type Output = u8;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
// we need one additional byte for the nul terminator
|
||||
self.len() + 1
|
||||
}
|
||||
|
||||
fn write_to(&self, out: &mut [MaybeUninit<u8>]) {
|
||||
let bytes = self.as_bytes();
|
||||
|
||||
maybe_uninit_copy_from_slice(&mut out[0..bytes.len()], bytes);
|
||||
out[bytes.len()].write(b'\0');
|
||||
}
|
||||
}
|
||||
|
||||
impl CLProp for &CStr {
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
to_maybeuninit_vec(self.to_bytes_with_nul().to_vec())
|
||||
type Output = u8;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
self.to_bytes_with_nul().len()
|
||||
}
|
||||
|
||||
fn write_to(&self, out: &mut [MaybeUninit<u8>]) {
|
||||
self.to_bytes_with_nul().write_to(out);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CLProp for Vec<T>
|
||||
where
|
||||
T: CLProp,
|
||||
T: CLProp + Copy,
|
||||
{
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
let mut res: Vec<MaybeUninit<u8>> = Vec::new();
|
||||
for i in self {
|
||||
res.append(&mut i.cl_vec())
|
||||
}
|
||||
res
|
||||
type Output = T;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write_to(&self, out: &mut [MaybeUninit<T>]) {
|
||||
self.as_slice().write_to(out);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CLProp for &T
|
||||
impl<T> CLProp for &[T]
|
||||
where
|
||||
T: CLProp,
|
||||
T: CLProp + Copy,
|
||||
{
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
T::cl_vec(self)
|
||||
}
|
||||
}
|
||||
type Output = T;
|
||||
|
||||
impl<T> CLProp for [T]
|
||||
where
|
||||
T: CLProp,
|
||||
{
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
let mut res: Vec<MaybeUninit<u8>> = Vec::new();
|
||||
for i in self {
|
||||
res.append(&mut i.cl_vec())
|
||||
}
|
||||
res
|
||||
fn count(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write_to(&self, out: &mut [MaybeUninit<T>]) {
|
||||
maybe_uninit_copy_from_slice(&mut out[0..self.len()], self);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const I: usize> CLProp for [T; I]
|
||||
where
|
||||
T: CLProp,
|
||||
T: CLProp + Copy,
|
||||
{
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
let mut res: Vec<MaybeUninit<u8>> = Vec::new();
|
||||
for i in self {
|
||||
res.append(&mut i.cl_vec())
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
type Output = Self;
|
||||
|
||||
impl<T> CLProp for *const T {
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
(*self as usize).cl_vec()
|
||||
fn count(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn write_to(&self, out: &mut [MaybeUninit<Self>]) {
|
||||
out[0].write(*self);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CLProp for *mut T {
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
(*self as usize).cl_vec()
|
||||
type Output = Self;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn write_to(&self, out: &mut [MaybeUninit<Self>]) {
|
||||
out[0].write(*self);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CLProp for Properties<T>
|
||||
impl<T> CLProp for &Properties<T>
|
||||
where
|
||||
T: CLProp + Default,
|
||||
T: CLProp + Copy + Default,
|
||||
{
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
let mut res: Vec<MaybeUninit<u8>> = Vec::new();
|
||||
for (k, v) in &self.props {
|
||||
res.append(&mut k.cl_vec());
|
||||
res.append(&mut v.cl_vec());
|
||||
type Output = T;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
// Properties are value pairs terminated with a 0 value.
|
||||
self.props.len() * 2 + 1
|
||||
}
|
||||
|
||||
fn write_to(&self, out: &mut [MaybeUninit<T>]) {
|
||||
for (idx, (k, v)) in self.props.iter().enumerate() {
|
||||
out[idx * 2].write(*k);
|
||||
out[idx * 2 + 1].write(*v);
|
||||
}
|
||||
res.append(&mut T::default().cl_vec());
|
||||
res
|
||||
|
||||
// need to terminate with a 0 value
|
||||
out[self.props.len() * 2].write(T::default());
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CLProp for Option<T>
|
||||
where
|
||||
T: CLProp,
|
||||
T: CLProp + Copy,
|
||||
{
|
||||
fn cl_vec(&self) -> Vec<MaybeUninit<u8>> {
|
||||
self.as_ref().map_or(Vec::new(), |v| v.cl_vec())
|
||||
}
|
||||
}
|
||||
type Output = T::Output;
|
||||
|
||||
pub fn cl_prop<T>(v: T) -> Vec<MaybeUninit<u8>>
|
||||
where
|
||||
T: CLProp + Sized,
|
||||
{
|
||||
v.cl_vec()
|
||||
fn count(&self) -> usize {
|
||||
match self {
|
||||
Some(val) => val.count(),
|
||||
None => 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn write_to(&self, out: &mut [MaybeUninit<T::Output>]) {
|
||||
if let Some(val) = self {
|
||||
val.write_to(out);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const CL_DEVICE_TYPES: u32 = CL_DEVICE_TYPE_ACCELERATOR
|
||||
|
|
@ -282,11 +422,6 @@ pub fn event_list_from_cl(
|
|||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn to_maybeuninit_vec<T: Copy>(v: Vec<T>) -> Vec<MaybeUninit<T>> {
|
||||
// In my tests the compiler was smart enough to turn this into a noop
|
||||
v.into_iter().map(MaybeUninit::new).collect()
|
||||
}
|
||||
|
||||
pub fn checked_compare(a: usize, o: cmp::Ordering, b: u64) -> bool {
|
||||
if usize::BITS > u64::BITS {
|
||||
a.cmp(&(b as usize)) == o
|
||||
|
|
|
|||
|
|
@ -477,21 +477,17 @@ impl Program {
|
|||
res
|
||||
}
|
||||
|
||||
pub fn binaries(&self, vals: &[u8]) -> CLResult<Vec<*mut u8>> {
|
||||
pub fn binaries(&self, ptrs: &[*mut u8]) -> CLResult<Vec<*mut u8>> {
|
||||
// if the application didn't provide any pointers, just return the length of devices
|
||||
if vals.is_empty() {
|
||||
if ptrs.is_empty() {
|
||||
return Ok(vec![std::ptr::null_mut(); self.devs.len()]);
|
||||
}
|
||||
|
||||
// vals is an array of pointers where we should write the device binaries into
|
||||
if vals.len() != self.devs.len() * size_of::<*const u8>() {
|
||||
// ptrs is an array of pointers where we should write the device binaries into
|
||||
if ptrs.len() < self.devs.len() {
|
||||
return Err(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
let ptrs: &[*mut u8] = unsafe {
|
||||
slice::from_raw_parts(vals.as_ptr().cast(), vals.len() / size_of::<*mut u8>())
|
||||
};
|
||||
|
||||
let lock = self.build_info();
|
||||
for (d, ptr) in self.devs.iter().zip(ptrs) {
|
||||
if ptr.is_null() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue