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 <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27204>
This commit is contained in:
Karol Herbst
2023-11-13 11:19:44 +01:00
committed by Marge Bot
parent 6e70699e24
commit 459b522251
4 changed files with 37 additions and 6 deletions

View File

@@ -1064,6 +1064,7 @@ Rusticl environment variables
- ``clc`` dumps all OpenCL C source being compiled - ``clc`` dumps all OpenCL C source being compiled
- ``program`` dumps compilation logs to stderr - ``program`` dumps compilation logs to stderr
- ``sync`` waits on the GPU to complete after every event - ``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: .. _clc-env-var:

View File

@@ -21,6 +21,7 @@ pub struct PlatformDebug {
pub clc: bool, pub clc: bool,
pub program: bool, pub program: bool,
pub sync_every_event: bool, pub sync_every_event: bool,
pub validate_spirv: bool,
} }
pub struct PlatformFeatures { pub struct PlatformFeatures {
@@ -64,6 +65,7 @@ static mut PLATFORM_DBG: PlatformDebug = PlatformDebug {
clc: false, clc: false,
program: false, program: false,
sync_every_event: false, sync_every_event: false,
validate_spirv: false,
}; };
static mut PLATFORM_FEATURES: PlatformFeatures = PlatformFeatures { static mut PLATFORM_FEATURES: PlatformFeatures = PlatformFeatures {
fp16: false, fp16: false,
@@ -79,6 +81,7 @@ fn load_env() {
"clc" => debug.clc = true, "clc" => debug.clc = true,
"program" => debug.program = true, "program" => debug.program = true,
"sync" => debug.sync_every_event = true, "sync" => debug.sync_every_event = true,
"validate" => debug.validate_spirv = true,
"" => (), "" => (),
_ => eprintln!("Unknown RUSTICL_DEBUG flag found: {}", flag), _ => eprintln!("Unknown RUSTICL_DEBUG flag found: {}", flag),
} }

View File

@@ -608,13 +608,13 @@ impl Program {
) -> bool { ) -> bool {
let d = info.dev_build_mut(dev); let d = info.dev_build_mut(dev);
let val_options = clc_validator_options(dev);
let (spirv, log) = match &self.src { let (spirv, log) = match &self.src {
ProgramSourceType::Il(spirv) => { ProgramSourceType::Il(spirv) => {
let options = clc_validator_options(dev);
if Platform::dbg().allow_invalid_spirv { if Platform::dbg().allow_invalid_spirv {
(Some(spirv.clone()), String::new()) (Some(spirv.clone()), String::new())
} else { } else {
spirv.clone_on_validate(&options) spirv.clone_on_validate(&val_options)
} }
} }
ProgramSourceType::Src(src) => { ProgramSourceType::Src(src) => {
@@ -630,7 +630,7 @@ impl Program {
eprintln!("source code:\n{src}"); eprintln!("source code:\n{src}");
} }
spirv::SPIRVBin::from_clc( let (spirv, msgs) = spirv::SPIRVBin::from_clc(
src, src,
&args, &args,
headers, headers,
@@ -638,7 +638,18 @@ impl Program {
dev.cl_features(), dev.cl_features(),
&dev.spirv_extensions, &dev.spirv_extensions,
dev.address_bits(), 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 // do nothing if we got a library or binary
_ => { _ => {
@@ -682,6 +693,17 @@ impl Program {
.collect(); .collect();
let (spirv, log) = spirv::SPIRVBin::link(&bins, lib); 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 status;
let bin_type; let bin_type;

View File

@@ -206,12 +206,17 @@ impl SPIRVBin {
(res, msgs.join("\n")) (res, msgs.join("\n"))
} }
pub fn clone_on_validate(&self, options: &clc_validator_options) -> (Option<Self>, String) { pub fn validate(&self, options: &clc_validator_options) -> (bool, String) {
let mut msgs: Vec<String> = Vec::new(); let mut msgs: Vec<String> = Vec::new();
let logger = create_clc_logger(&mut msgs); let logger = create_clc_logger(&mut msgs);
let res = unsafe { clc_validate_spirv(&self.spirv, &logger, options) }; 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<Self>, String) {
let (res, msgs) = self.validate(options);
(res.then(|| self.clone()), msgs)
} }
fn kernel_infos(&self) -> &[clc_kernel_info] { fn kernel_infos(&self) -> &[clc_kernel_info] {