rusticl/program: allow dumping compilation logs through RUSTICL_DEBUG
authorKarol Herbst <kherbst@redhat.com>
Tue, 4 Apr 2023 00:41:45 +0000 (02:41 +0200)
committerMarge Bot <emma+marge@anholt.net>
Thu, 13 Apr 2023 02:54:21 +0000 (02:54 +0000)
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22280>

docs/envvars.rst
src/gallium/frontends/rusticl/api/program.rs
src/gallium/frontends/rusticl/core/platform.rs
src/gallium/frontends/rusticl/core/program.rs
src/gallium/frontends/rusticl/mesa/compiler/clc/spirv.rs

index 78f2ec4..b2c0ba7 100644 (file)
@@ -893,6 +893,12 @@ Rusticl environment variables
    -  ``RUSTICL_ENABLE=iris:1,radeonsi:0,2`` (enables second iris and first
       and third radeonsi device)
 
+.. envvar:: RUSTICL_DEBUG
+
+   a comma-separated list of debug channels to enable.
+
+   - ``program`` dumps compilation logs to stderr
+
 Nine frontend environment variables
 -----------------------------------
 
index daa2180..ce8c11c 100644 (file)
@@ -2,6 +2,7 @@ use crate::api::icd::*;
 use crate::api::types::*;
 use crate::api::util::*;
 use crate::core::device::*;
+use crate::core::platform::*;
 use crate::core::program::*;
 
 use mesa_rust::compiler::clc::*;
@@ -270,8 +271,8 @@ pub fn build_program(
 
     // CL_BUILD_PROGRAM_FAILURE if there is a failure to build the program executable. This error
     // will be returned if clBuildProgram does not return until the build has completed.
-    for dev in devs {
-        res &= p.build(&dev, c_string_to_string(options));
+    for dev in &devs {
+        res &= p.build(dev, c_string_to_string(options));
     }
 
     call_cb(pfn_notify, program, user_data);
@@ -284,6 +285,11 @@ pub fn build_program(
     if res {
         Ok(())
     } else {
+        if Platform::get().debug.program {
+            for dev in &devs {
+                eprintln!("{}", p.log(dev));
+            }
+        }
         Err(CL_BUILD_PROGRAM_FAILURE)
     }
 }
@@ -337,8 +343,8 @@ pub fn compile_program(
 
     // CL_COMPILE_PROGRAM_FAILURE if there is a failure to compile the program source. This error
     // will be returned if clCompileProgram does not return until the compile has completed.
-    for dev in devs {
-        res &= p.compile(&dev, c_string_to_string(options), &headers);
+    for dev in &devs {
+        res &= p.compile(dev, c_string_to_string(options), &headers);
     }
 
     call_cb(pfn_notify, program, user_data);
@@ -349,6 +355,11 @@ pub fn compile_program(
     if res {
         Ok(())
     } else {
+        if Platform::get().debug.program {
+            for dev in &devs {
+                eprintln!("{}", p.log(dev));
+            }
+        }
         Err(CL_COMPILE_PROGRAM_FAILURE)
     }
 }
index 661d39d..41e77a1 100644 (file)
@@ -6,6 +6,7 @@ use crate::core::version::*;
 use mesa_rust_gen::*;
 use rusticl_opencl_gen::*;
 
+use std::env;
 use std::sync::Arc;
 use std::sync::Once;
 
@@ -14,6 +15,11 @@ pub struct Platform {
     dispatch: &'static cl_icd_dispatch,
     pub extensions: [cl_name_version; 2],
     pub devs: Vec<Arc<Device>>,
+    pub debug: PlatformDebug,
+}
+
+pub struct PlatformDebug {
+    pub program: bool,
 }
 
 static PLATFORM_ONCE: Once = Once::new();
@@ -24,6 +30,7 @@ static mut PLATFORM: Platform = Platform {
         mk_cl_version_ext(1, 0, 0, "cl_khr_il_program"),
     ],
     devs: Vec::new(),
+    debug: PlatformDebug { program: false },
 };
 
 impl Platform {
@@ -44,6 +51,14 @@ impl Platform {
         }
 
         self.devs.extend(Device::all());
+        if let Ok(debug_flags) = env::var("RUSTICL_DEBUG") {
+            for flag in debug_flags.split(',') {
+                match flag {
+                    "program" => self.debug.program = true,
+                    _ => eprintln!("Unknown RUSTICL_DEBUG flag found: {}", flag),
+                }
+            }
+        }
     }
 }
 
index 60bb813..926be65 100644 (file)
@@ -1,6 +1,7 @@
 use crate::api::icd::*;
 use crate::core::context::*;
 use crate::core::device::*;
+use crate::core::platform::Platform;
 use crate::impl_cl_type_trait;
 
 use mesa_rust::compiler::clc::*;
@@ -595,18 +596,25 @@ impl Program {
 
         let info = Self::dev_build_info(&mut lock, d);
         assert_eq!(info.status, CL_BUILD_SUCCESS as cl_build_status);
-        info.spirv
-            .as_ref()
-            .unwrap()
-            .to_nir(
-                kernel,
-                d.screen
-                    .nir_shader_compiler_options(pipe_shader_type::PIPE_SHADER_COMPUTE),
-                &d.lib_clc,
-                &mut spec_constants,
-                d.address_bits(),
-            )
-            .unwrap()
+
+        let mut log = Platform::get().debug.program.then(Vec::new);
+        let nir = info.spirv.as_ref().unwrap().to_nir(
+            kernel,
+            d.screen
+                .nir_shader_compiler_options(pipe_shader_type::PIPE_SHADER_COMPUTE),
+            &d.lib_clc,
+            &mut spec_constants,
+            d.address_bits(),
+            log.as_mut(),
+        );
+
+        if let Some(log) = log {
+            for line in log {
+                eprintln!("{}", line);
+            }
+        };
+
+        nir.unwrap()
     }
 
     pub fn is_binary(&self) -> bool {
index b957b37..8626a3a 100644 (file)
@@ -37,11 +37,24 @@ pub struct CLCHeader<'a> {
     pub source: &'a CString,
 }
 
-unsafe extern "C" fn msg_callback(data: *mut std::ffi::c_void, msg: *const c_char) {
+unsafe fn callback_impl(data: *mut c_void, msg: *const c_char) {
     let msgs = (data as *mut Vec<String>).as_mut().expect("");
     msgs.push(c_string_to_string(msg));
 }
 
+unsafe extern "C" fn spirv_msg_callback(data: *mut c_void, msg: *const c_char) {
+    callback_impl(data, msg);
+}
+
+unsafe extern "C" fn spirv_to_nir_msg_callback(
+    data: *mut c_void,
+    _dbg_level: mesa_rust_gen::nir_spirv_debug_level,
+    _offset: usize,
+    msg: *const c_char,
+) {
+    callback_impl(data, msg);
+}
+
 impl SPIRVBin {
     pub fn from_clc(
         source: &CString,
@@ -102,8 +115,8 @@ impl SPIRVBin {
         let mut msgs: Vec<String> = Vec::new();
         let logger = clc_logger {
             priv_: &mut msgs as *mut Vec<String> as *mut c_void,
-            error: Some(msg_callback),
-            warning: Some(msg_callback),
+            error: Some(spirv_msg_callback),
+            warning: Some(spirv_msg_callback),
         };
         let mut out = clc_binary::default();
 
@@ -143,8 +156,8 @@ impl SPIRVBin {
         let mut msgs: Vec<String> = Vec::new();
         let logger = clc_logger {
             priv_: &mut msgs as *mut Vec<String> as *mut c_void,
-            error: Some(msg_callback),
-            warning: Some(msg_callback),
+            error: Some(spirv_msg_callback),
+            warning: Some(spirv_msg_callback),
         };
 
         let mut out = clc_binary::default();
@@ -256,6 +269,7 @@ impl SPIRVBin {
         library: bool,
         clc_shader: *const nir_shader,
         address_bits: u32,
+        log: Option<&mut Vec<String>>,
     ) -> spirv_to_nir_options {
         let global_addr_format;
         let offset_addr_format;
@@ -268,6 +282,11 @@ impl SPIRVBin {
             offset_addr_format = nir_address_format::nir_address_format_32bit_offset_as_64bit;
         }
 
+        let debug = log.map(|log| spirv_to_nir_options__bindgen_ty_1 {
+            func: Some(spirv_to_nir_msg_callback),
+            private_data: (log as *mut Vec<String>).cast(),
+        });
+
         spirv_to_nir_options {
             create_library: library,
             environment: nir_spirv_execution_environment::NIR_SPIRV_OPENCL,
@@ -295,9 +314,8 @@ impl SPIRVBin {
             global_addr_format: global_addr_format,
             shared_addr_format: offset_addr_format,
             temp_addr_format: offset_addr_format,
+            debug: debug.unwrap_or_default(),
 
-            // default
-            debug: spirv_to_nir_options__bindgen_ty_1::default(),
             ..Default::default()
         }
     }
@@ -309,9 +327,10 @@ impl SPIRVBin {
         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_options = Self::get_spirv_options(false, libclc.get_nir(), address_bits);
+        let spirv_options = Self::get_spirv_options(false, libclc.get_nir(), address_bits, log);
 
         let nir = unsafe {
             spirv_to_nir(
@@ -332,7 +351,7 @@ impl SPIRVBin {
     pub fn get_lib_clc(screen: &PipeScreen) -> Option<NirShader> {
         let nir_options = screen.nir_shader_compiler_options(pipe_shader_type::PIPE_SHADER_COMPUTE);
         let address_bits = screen.compute_param(pipe_compute_cap::PIPE_COMPUTE_CAP_ADDRESS_BITS);
-        let spirv_options = Self::get_spirv_options(true, ptr::null(), address_bits);
+        let spirv_options = Self::get_spirv_options(true, ptr::null(), address_bits, None);
         let shader_cache = DiskCacheBorrowed::as_ptr(&screen.shader_cache());
 
         NirShader::new(unsafe {