rusticl: implement cl_khr_spirv_queries
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35439>
This commit is contained in:
@@ -836,6 +836,7 @@ Rusticl extensions that are not part of any OpenCL version:
|
||||
cl_khr_spirv_extended_debug_info not started
|
||||
cl_khr_spirv_linkonce_odr DONE
|
||||
cl_khr_spirv_no_integer_wrap_decoration DONE
|
||||
cl_khr_spirv_queries DONE
|
||||
cl_khr_srgb_image_writes not started
|
||||
cl_khr_subgroup_ballot not started
|
||||
cl_khr_subgroup_clustered_reduce not started
|
||||
|
||||
@@ -40,3 +40,4 @@ cl_khr_fp16 on asahi, freedreno, llvmpipe, panfrost, radeonsi and zink
|
||||
GL_ARB_shader_clock on panfrost/v6+
|
||||
VK_EXT_texture_compression_astc_hdr on panvk
|
||||
MSAA with 8 and 16 sample counts on panfrost
|
||||
cl_khr_spirv_queries
|
||||
|
||||
@@ -12,6 +12,7 @@ use rusticl_proc_macros::cl_entrypoint;
|
||||
use rusticl_proc_macros::cl_info_entrypoint;
|
||||
|
||||
use std::cmp::min;
|
||||
use std::ffi::c_char;
|
||||
use std::ffi::CStr;
|
||||
use std::mem::size_of;
|
||||
use std::ptr;
|
||||
@@ -279,6 +280,17 @@ unsafe impl CLInfo<cl_device_info> for cl_device_id {
|
||||
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_SPIRV_CAPABILITIES_KHR => {
|
||||
v.write_iter::<cl_uint>(dev.spirv_caps_vec.iter().map(|&cap| cap as _))
|
||||
}
|
||||
CL_DEVICE_SPIRV_EXTENDED_INSTRUCTION_SETS_KHR => {
|
||||
// use static memory as we hand out pointers to the values here.
|
||||
static instr_sets: [&CStr; 1] = [c"OpenCL.std"];
|
||||
v.write_iter::<*const c_char>(instr_sets.iter().map(|str| str.as_ptr()))
|
||||
}
|
||||
CL_DEVICE_SPIRV_EXTENSIONS_KHR => {
|
||||
v.write_iter::<*const c_char>(dev.spirv_extensions.iter().map(|str| str.as_ptr()))
|
||||
}
|
||||
CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS => v.write::<bool>(false),
|
||||
CL_DEVICE_SUB_GROUP_SIZES_INTEL => {
|
||||
if dev.subgroups_supported() {
|
||||
|
||||
@@ -382,6 +382,18 @@ impl<T> CLProp for *mut T {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CLProp for *const T {
|
||||
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>
|
||||
where
|
||||
T: CLProp + Copy + Default,
|
||||
|
||||
@@ -45,6 +45,8 @@ pub struct DeviceBase {
|
||||
pub embedded: bool,
|
||||
pub extension_string: String,
|
||||
pub extensions: Vec<cl_name_version>,
|
||||
pub spirv_caps: spirv_capabilities,
|
||||
pub spirv_caps_vec: Vec<SpvCapability>,
|
||||
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>>,
|
||||
@@ -575,6 +577,8 @@ impl DeviceBase {
|
||||
let mut exts_str: Vec<String> = Vec::new();
|
||||
let mut exts = Vec::new();
|
||||
let mut feats = Vec::new();
|
||||
let mut spirv_caps = spirv_capabilities::default();
|
||||
let mut spirv_caps_vec = Vec::new();
|
||||
let mut spirv_exts = Vec::new();
|
||||
let mut add_ext = |major, minor, patch, ext: &str| {
|
||||
exts.push(mk_cl_version_ext(major, minor, patch, ext));
|
||||
@@ -586,6 +590,12 @@ impl DeviceBase {
|
||||
let mut add_spirv = |ext| {
|
||||
spirv_exts.push(ext);
|
||||
};
|
||||
let mut add_cap = |cap: SpvCapability| {
|
||||
unsafe {
|
||||
spirv_capabilities_set(&mut spirv_caps, cap, true);
|
||||
}
|
||||
spirv_caps_vec.push(cap);
|
||||
};
|
||||
|
||||
// add extensions all drivers support for now
|
||||
add_ext(1, 0, 0, "cl_khr_byte_addressable_store");
|
||||
@@ -599,6 +609,7 @@ impl DeviceBase {
|
||||
add_ext(1, 0, 0, "cl_khr_local_int32_extended_atomics");
|
||||
add_ext(2, 0, 0, "cl_khr_integer_dot_product");
|
||||
add_ext(1, 0, 0, "cl_khr_spirv_no_integer_wrap_decoration");
|
||||
add_ext(1, 0, 0, "cl_khr_spirv_queries");
|
||||
add_ext(1, 0, 0, "cl_khr_suggested_local_work_size");
|
||||
|
||||
add_feat(2, 0, 0, "__opencl_c_integer_dot_product_input_4x8bit");
|
||||
@@ -614,16 +625,31 @@ impl DeviceBase {
|
||||
add_spirv(c"SPV_KHR_integer_dot_product");
|
||||
add_spirv(c"SPV_KHR_no_integer_wrap_decoration");
|
||||
|
||||
add_cap(SpvCapability::SpvCapabilityAddresses);
|
||||
add_cap(SpvCapability::SpvCapabilityDotProduct);
|
||||
add_cap(SpvCapability::SpvCapabilityDotProductInput4x8Bit);
|
||||
add_cap(SpvCapability::SpvCapabilityDotProductInput4x8BitPacked);
|
||||
add_cap(SpvCapability::SpvCapabilityExpectAssumeKHR);
|
||||
add_cap(SpvCapability::SpvCapabilityFloat16Buffer);
|
||||
add_cap(SpvCapability::SpvCapabilityInt8);
|
||||
add_cap(SpvCapability::SpvCapabilityInt16);
|
||||
add_cap(SpvCapability::SpvCapabilityLinkage);
|
||||
add_cap(SpvCapability::SpvCapabilityKernel);
|
||||
add_cap(SpvCapability::SpvCapabilityUniformDecoration);
|
||||
add_cap(SpvCapability::SpvCapabilityVector16);
|
||||
|
||||
if self.linkonce_supported() {
|
||||
add_ext(1, 0, 0, "cl_khr_spirv_linkonce_odr");
|
||||
add_spirv(c"SPV_KHR_linkonce_odr");
|
||||
}
|
||||
|
||||
if self.fp16_supported() {
|
||||
add_cap(SpvCapability::SpvCapabilityFloat16);
|
||||
add_ext(1, 0, 0, "cl_khr_fp16");
|
||||
}
|
||||
|
||||
if self.fp64_supported() {
|
||||
add_cap(SpvCapability::SpvCapabilityFloat64);
|
||||
add_ext(1, 0, 0, "cl_khr_fp64");
|
||||
add_feat(1, 0, 0, "__opencl_c_fp64");
|
||||
}
|
||||
@@ -637,10 +663,12 @@ impl DeviceBase {
|
||||
add_ext(1, 0, 0, "cles_khr_int64");
|
||||
};
|
||||
|
||||
add_cap(SpvCapability::SpvCapabilityInt64);
|
||||
add_feat(1, 0, 0, "__opencl_c_int64");
|
||||
}
|
||||
|
||||
if self.kernel_clock_supported() {
|
||||
add_cap(SpvCapability::SpvCapabilityShaderClockKHR);
|
||||
add_ext(1, 0, 0, "cl_khr_kernel_clock");
|
||||
add_feat(1, 0, 0, "__opencl_c_kernel_clock_scope_device");
|
||||
add_feat(1, 0, 0, "__opencl_c_kernel_clock_scope_sub_group");
|
||||
@@ -648,6 +676,12 @@ impl DeviceBase {
|
||||
}
|
||||
|
||||
if self.caps.has_images {
|
||||
add_cap(SpvCapability::SpvCapabilityImage1D);
|
||||
add_cap(SpvCapability::SpvCapabilityImageBasic);
|
||||
add_cap(SpvCapability::SpvCapabilityImageBuffer);
|
||||
add_cap(SpvCapability::SpvCapabilityLiteralSampler);
|
||||
add_cap(SpvCapability::SpvCapabilitySampled1D);
|
||||
add_cap(SpvCapability::SpvCapabilitySampledBuffer);
|
||||
add_feat(1, 0, 0, "__opencl_c_images");
|
||||
|
||||
if self.image2d_from_buffer_supported() {
|
||||
@@ -655,6 +689,7 @@ impl DeviceBase {
|
||||
}
|
||||
|
||||
if self.caps.has_rw_images {
|
||||
add_cap(SpvCapability::SpvCapabilityImageReadWrite);
|
||||
add_feat(1, 0, 0, "__opencl_c_read_write_images");
|
||||
}
|
||||
|
||||
@@ -680,6 +715,10 @@ impl DeviceBase {
|
||||
}
|
||||
|
||||
if self.subgroups_supported() {
|
||||
add_cap(SpvCapability::SpvCapabilityGroupNonUniformShuffle);
|
||||
add_cap(SpvCapability::SpvCapabilityGroupNonUniformShuffleRelative);
|
||||
add_cap(SpvCapability::SpvCapabilityGroups);
|
||||
add_cap(SpvCapability::SpvCapabilitySubgroupDispatch);
|
||||
// requires CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS
|
||||
//add_ext(1, 0, 0, "cl_khr_subgroups");
|
||||
add_feat(1, 0, 0, "__opencl_c_subgroups");
|
||||
@@ -688,6 +727,9 @@ impl DeviceBase {
|
||||
add_ext(1, 0, 0, "cl_khr_subgroup_shuffle");
|
||||
add_ext(1, 0, 0, "cl_khr_subgroup_shuffle_relative");
|
||||
if self.intel_subgroups_supported() {
|
||||
// add_cap(SpvCapability::SpvCapabilitySubgroupBufferBlockIOINTEL);
|
||||
// add_cap(SpvCapability::SpvCapabilitySubgroupImageBlockIOINTEL);
|
||||
add_cap(SpvCapability::SpvCapabilitySubgroupShuffleINTEL);
|
||||
add_ext(1, 0, 0, "cl_intel_required_subgroup_size");
|
||||
add_ext(1, 0, 0, "cl_intel_subgroups");
|
||||
add_spirv(c"SPV_INTEL_subgroups");
|
||||
@@ -705,6 +747,8 @@ impl DeviceBase {
|
||||
self.extensions = exts;
|
||||
self.clc_features = feats;
|
||||
self.extension_string = exts_str.join(" ");
|
||||
self.spirv_caps = spirv_caps;
|
||||
self.spirv_caps_vec = spirv_caps_vec;
|
||||
self.spirv_extensions = spirv_exts;
|
||||
}
|
||||
|
||||
@@ -1168,11 +1212,6 @@ impl Device {
|
||||
// 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),
|
||||
@@ -1184,6 +1223,8 @@ impl Device {
|
||||
embedded: false,
|
||||
extension_string: String::from(""),
|
||||
extensions: Vec::new(),
|
||||
spirv_caps: spirv_capabilities::default(),
|
||||
spirv_caps_vec: Vec::new(),
|
||||
spirv_extensions: Vec::new(),
|
||||
clc_features: Vec::new(),
|
||||
formats: HashMap::new(),
|
||||
@@ -1203,6 +1244,17 @@ impl Device {
|
||||
// now figure out what version we are
|
||||
dev_base.check_version();
|
||||
|
||||
// Libclc depends on a few caps which must always be enabled. At runtime we should never
|
||||
// actually pass relevant functionality down to drivers, so this should be fine.
|
||||
let mut spirv_caps = dev_base.spirv_caps;
|
||||
spirv_caps.Float64 = true;
|
||||
spirv_caps.Int64 = true;
|
||||
|
||||
let lib_clc = spirv::SPIRVBin::get_lib_clc(dev_base.screen(), &spirv_caps);
|
||||
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");
|
||||
}
|
||||
|
||||
Some(Device {
|
||||
base: CLObjectBase::new(RusticlTypes::Device),
|
||||
dev_base: dev_base,
|
||||
|
||||
@@ -216,6 +216,7 @@ impl ProgramBuild {
|
||||
kernel,
|
||||
d.screen
|
||||
.nir_shader_compiler_options(pipe_shader_type::PIPE_SHADER_COMPUTE),
|
||||
&d.spirv_caps,
|
||||
&d.lib_clc,
|
||||
&mut spec_constants,
|
||||
d.address_bits(),
|
||||
|
||||
@@ -277,33 +277,6 @@ impl SPIRVBin {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_spirv_capabilities() -> spirv_capabilities {
|
||||
spirv_capabilities {
|
||||
Addresses: true,
|
||||
Float16: true,
|
||||
Float16Buffer: true,
|
||||
Float64: true,
|
||||
GenericPointer: true,
|
||||
Groups: true,
|
||||
GroupNonUniformShuffle: true,
|
||||
GroupNonUniformShuffleRelative: true,
|
||||
Int8: true,
|
||||
Int16: true,
|
||||
Int64: true,
|
||||
Kernel: true,
|
||||
ImageBasic: true,
|
||||
ImageReadWrite: true,
|
||||
Linkage: true,
|
||||
LiteralSampler: true,
|
||||
SampledBuffer: true,
|
||||
Sampled1D: true,
|
||||
ShaderClockKHR: true,
|
||||
UniformDecoration: true,
|
||||
Vector16: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_spirv_options(
|
||||
library: bool,
|
||||
clc_shader: *const nir_shader,
|
||||
@@ -350,15 +323,15 @@ impl SPIRVBin {
|
||||
&self,
|
||||
entry_point: &str,
|
||||
nir_options: *const nir_shader_compiler_options,
|
||||
spirv_caps: &spirv_capabilities,
|
||||
libclc: &NirShader,
|
||||
spec_constants: &mut [nir_spirv_specialization],
|
||||
address_bits: u32,
|
||||
log: Option<&mut Vec<String>>,
|
||||
) -> Option<NirShader> {
|
||||
let c_entry = CString::new(entry_point.as_bytes()).unwrap();
|
||||
let spirv_caps = Self::get_spirv_capabilities();
|
||||
let spirv_options =
|
||||
Self::get_spirv_options(false, libclc.get_nir(), address_bits, &spirv_caps, log);
|
||||
Self::get_spirv_options(false, libclc.get_nir(), address_bits, spirv_caps, log);
|
||||
|
||||
let nir = unsafe {
|
||||
spirv_to_nir(
|
||||
@@ -376,12 +349,11 @@ impl SPIRVBin {
|
||||
NirShader::new(nir)
|
||||
}
|
||||
|
||||
pub fn get_lib_clc(screen: &PipeScreen) -> Option<NirShader> {
|
||||
pub fn get_lib_clc(screen: &PipeScreen, spirv_caps: &spirv_capabilities) -> Option<NirShader> {
|
||||
let nir_options = screen.nir_shader_compiler_options(pipe_shader_type::PIPE_SHADER_COMPUTE);
|
||||
let address_bits = screen.compute_caps().address_bits;
|
||||
let spirv_caps = Self::get_spirv_capabilities();
|
||||
let spirv_options =
|
||||
Self::get_spirv_options(false, ptr::null(), address_bits, &spirv_caps, None);
|
||||
Self::get_spirv_options(false, ptr::null(), address_bits, spirv_caps, None);
|
||||
let shader_cache = DiskCacheBorrowed::as_ptr(&screen.shader_cache());
|
||||
|
||||
NirShader::new(unsafe {
|
||||
|
||||
Reference in New Issue
Block a user