From 459b5222511ce0eea17f5a43cb55f54bbaca7984 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Mon, 13 Nov 2023 11:19:44 +0100 Subject: [PATCH] rusticl/program: add debug option to validate internal spirvs Sometimes it's useful to validate SPIR-Vs we generate just to make sure they are valid. Signed-off-by: Karol Herbst Part-of: --- docs/envvars.rst | 1 + .../frontends/rusticl/core/platform.rs | 3 ++ src/gallium/frontends/rusticl/core/program.rs | 30 ++++++++++++++++--- .../rusticl/mesa/compiler/clc/spirv.rs | 9 ++++-- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/docs/envvars.rst b/docs/envvars.rst index 300f2cd40e1..920e2cecbc7 100644 --- a/docs/envvars.rst +++ b/docs/envvars.rst @@ -1064,6 +1064,7 @@ Rusticl environment variables - ``clc`` dumps all OpenCL C source being compiled - ``program`` dumps compilation logs to stderr - ``sync`` waits on the GPU to complete after every event + - ``validate`` validates any internally generated SPIR-Vs, e.g. through compiling OpenCL C code .. _clc-env-var: diff --git a/src/gallium/frontends/rusticl/core/platform.rs b/src/gallium/frontends/rusticl/core/platform.rs index 6e948e358c5..66fa219d444 100644 --- a/src/gallium/frontends/rusticl/core/platform.rs +++ b/src/gallium/frontends/rusticl/core/platform.rs @@ -21,6 +21,7 @@ pub struct PlatformDebug { pub clc: bool, pub program: bool, pub sync_every_event: bool, + pub validate_spirv: bool, } pub struct PlatformFeatures { @@ -64,6 +65,7 @@ static mut PLATFORM_DBG: PlatformDebug = PlatformDebug { clc: false, program: false, sync_every_event: false, + validate_spirv: false, }; static mut PLATFORM_FEATURES: PlatformFeatures = PlatformFeatures { fp16: false, @@ -79,6 +81,7 @@ fn load_env() { "clc" => debug.clc = true, "program" => debug.program = true, "sync" => debug.sync_every_event = true, + "validate" => debug.validate_spirv = true, "" => (), _ => eprintln!("Unknown RUSTICL_DEBUG flag found: {}", flag), } diff --git a/src/gallium/frontends/rusticl/core/program.rs b/src/gallium/frontends/rusticl/core/program.rs index 1f81df429bb..13e7f5b095c 100644 --- a/src/gallium/frontends/rusticl/core/program.rs +++ b/src/gallium/frontends/rusticl/core/program.rs @@ -608,13 +608,13 @@ impl Program { ) -> bool { let d = info.dev_build_mut(dev); + let val_options = clc_validator_options(dev); let (spirv, log) = match &self.src { ProgramSourceType::Il(spirv) => { - let options = clc_validator_options(dev); if Platform::dbg().allow_invalid_spirv { (Some(spirv.clone()), String::new()) } else { - spirv.clone_on_validate(&options) + spirv.clone_on_validate(&val_options) } } ProgramSourceType::Src(src) => { @@ -630,7 +630,7 @@ impl Program { eprintln!("source code:\n{src}"); } - spirv::SPIRVBin::from_clc( + let (spirv, msgs) = spirv::SPIRVBin::from_clc( src, &args, headers, @@ -638,7 +638,18 @@ impl Program { dev.cl_features(), &dev.spirv_extensions, dev.address_bits(), - ) + ); + + if Platform::dbg().validate_spirv { + if let Some(spirv) = spirv { + let (res, spirv_msgs) = spirv.validate(&val_options); + (res.then_some(spirv), format!("{}\n{}", msgs, spirv_msgs)) + } else { + (None, msgs) + } + } else { + (spirv, msgs) + } } // do nothing if we got a library or binary _ => { @@ -682,6 +693,17 @@ impl Program { .collect(); let (spirv, log) = spirv::SPIRVBin::link(&bins, lib); + let (spirv, log) = if Platform::dbg().validate_spirv { + if let Some(spirv) = spirv { + let val_options = clc_validator_options(d); + let (res, spirv_msgs) = spirv.validate(&val_options); + (res.then_some(spirv), format!("{}\n{}", log, spirv_msgs)) + } else { + (None, log) + } + } else { + (spirv, log) + }; let status; let bin_type; diff --git a/src/gallium/frontends/rusticl/mesa/compiler/clc/spirv.rs b/src/gallium/frontends/rusticl/mesa/compiler/clc/spirv.rs index 157065d6634..f347eaef0f5 100644 --- a/src/gallium/frontends/rusticl/mesa/compiler/clc/spirv.rs +++ b/src/gallium/frontends/rusticl/mesa/compiler/clc/spirv.rs @@ -206,12 +206,17 @@ impl SPIRVBin { (res, msgs.join("\n")) } - pub fn clone_on_validate(&self, options: &clc_validator_options) -> (Option, String) { + pub fn validate(&self, options: &clc_validator_options) -> (bool, String) { let mut msgs: Vec = Vec::new(); let logger = create_clc_logger(&mut msgs); let res = unsafe { clc_validate_spirv(&self.spirv, &logger, options) }; - (res.then(|| self.clone()), msgs.join("\n")) + (res, msgs.join("\n")) + } + + pub fn clone_on_validate(&self, options: &clc_validator_options) -> (Option, String) { + let (res, msgs) = self.validate(options); + (res.then(|| self.clone()), msgs) } fn kernel_infos(&self) -> &[clc_kernel_info] {