Skip to content

Commit 2d582b2

Browse files
committed
[naga] Process overrides selectively for the active entry point
This adds an argument to `process_overrides` to specify the desired entry point, and then modifies override processing to tolerate missing overrides if (and hopefully only if) they are not used by that entry point. During that processing, lists are constructed of the functions, globals, and entry points that cannot be used due to missing overrides. The MSL backend is changed to skip over those items while writing. - [ ] update the other backends - [ ] make save_overrides_resolved a bit nicer - [ ] add some more tests
1 parent 50eb207 commit 2d582b2

26 files changed

+960
-222
lines changed

naga-cli/src/bin/naga.rs

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,8 @@ fn write_output(
686686
params: &Parameters,
687687
output_path: &str,
688688
) -> anyhow::Result<()> {
689+
use naga::back::pipeline_constants::ProcessOverridesOutput;
690+
689691
match Path::new(&output_path)
690692
.extension()
691693
.ok_or(CliError("Output filename has no extension"))?
@@ -717,9 +719,14 @@ fn write_output(
717719
succeed, and it failed in a previous step",
718720
))?;
719721

720-
let (module, info) =
721-
naga::back::pipeline_constants::process_overrides(module, info, &params.overrides)
722-
.unwrap_pretty();
722+
let ProcessOverridesOutput { module, info, .. } =
723+
naga::back::pipeline_constants::process_overrides(
724+
module,
725+
info,
726+
None,
727+
&params.overrides,
728+
)
729+
.unwrap_pretty();
723730

724731
let pipeline_options = msl::PipelineOptions::default();
725732
let (msl, _) =
@@ -751,9 +758,17 @@ fn write_output(
751758
succeed, and it failed in a previous step",
752759
))?;
753760

754-
let (module, info) =
755-
naga::back::pipeline_constants::process_overrides(module, info, &params.overrides)
756-
.unwrap_pretty();
761+
let naga::back::pipeline_constants::ProcessOverridesOutput {
762+
module,
763+
info,
764+
unresolved: _,
765+
} = naga::back::pipeline_constants::process_overrides(
766+
module,
767+
info,
768+
None,
769+
&params.overrides,
770+
)
771+
.unwrap_pretty();
757772

758773
let spv =
759774
spv::write_vec(&module, &info, &params.spv_out, pipeline_options).unwrap_pretty();
@@ -788,9 +803,17 @@ fn write_output(
788803
succeed, and it failed in a previous step",
789804
))?;
790805

791-
let (module, info) =
792-
naga::back::pipeline_constants::process_overrides(module, info, &params.overrides)
793-
.unwrap_pretty();
806+
let naga::back::pipeline_constants::ProcessOverridesOutput {
807+
module,
808+
info,
809+
unresolved: _,
810+
} = naga::back::pipeline_constants::process_overrides(
811+
module,
812+
info,
813+
None,
814+
&params.overrides,
815+
)
816+
.unwrap_pretty();
794817

795818
let mut buffer = String::new();
796819
let mut writer = glsl::Writer::new(
@@ -819,9 +842,17 @@ fn write_output(
819842
succeed, and it failed in a previous step",
820843
))?;
821844

822-
let (module, info) =
823-
naga::back::pipeline_constants::process_overrides(module, info, &params.overrides)
824-
.unwrap_pretty();
845+
let naga::back::pipeline_constants::ProcessOverridesOutput {
846+
module,
847+
info,
848+
unresolved: _,
849+
} = naga::back::pipeline_constants::process_overrides(
850+
module,
851+
info,
852+
None,
853+
&params.overrides,
854+
)
855+
.unwrap_pretty();
825856

826857
let mut buffer = String::new();
827858
let pipeline_options = Default::default();

naga/src/back/msl/mod.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@ use alloc::{
5252
};
5353
use core::fmt::{Error as FmtError, Write};
5454

55-
use crate::{arena::Handle, ir, proc::index, valid::ModuleInfo};
55+
use crate::{
56+
arena::Handle,
57+
ir,
58+
proc::index,
59+
valid::{ModuleInfo, UnresolvedOverrides},
60+
};
5661

5762
mod keywords;
5863
pub mod sampler;
@@ -431,6 +436,14 @@ pub struct PipelineOptions {
431436
/// point is not found, an error will be thrown while writing.
432437
pub entry_point: Option<(ir::ShaderStage, String)>,
433438

439+
/// Information about unresolved overrides.
440+
///
441+
/// This struct is returned by `process_overrides`. It tells the writer
442+
/// which items to omit from the output because they are not used and refer
443+
/// to overrides that were not resolved to a concrete value.
444+
#[cfg_attr(feature = "serialize", serde(skip))]
445+
pub unresolved_overrides: UnresolvedOverrides,
446+
434447
/// Allow `BuiltIn::PointSize` and inject it if doesn't exist.
435448
///
436449
/// Metal doesn't like this for non-point primitive topologies and requires it for

naga/src/back/msl/writer.rs

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ use crate::{
2121
proc::{
2222
self,
2323
index::{self, BoundsCheck},
24-
NameKey, TypeResolution,
24+
NameKey, ResolveArraySizeError, TypeResolution,
2525
},
26-
valid, FastHashMap, FastHashSet,
26+
valid::{self, UnresolvedOverrides},
27+
FastHashMap, FastHashSet,
2728
};
2829

2930
#[cfg(test)]
@@ -436,6 +437,7 @@ pub struct Writer<W> {
436437
/// Set of (struct type, struct field index) denoting which fields require
437438
/// padding inserted **before** them (i.e. between fields at index - 1 and index)
438439
struct_member_pads: FastHashSet<(Handle<crate::Type>, u32)>,
440+
unresolved_overrides: Option<UnresolvedOverrides>,
439441
}
440442

441443
impl crate::Scalar {
@@ -775,6 +777,7 @@ impl<W: Write> Writer<W> {
775777
#[cfg(test)]
776778
put_block_stack_pointers: Default::default(),
777779
struct_member_pads: FastHashSet::default(),
780+
unresolved_overrides: None,
778781
}
779782
}
780783

@@ -4032,6 +4035,7 @@ impl<W: Write> Writer<W> {
40324035
);
40334036
self.wrapped_functions.clear();
40344037
self.struct_member_pads.clear();
4038+
self.unresolved_overrides = Some(pipeline_options.unresolved_overrides.clone());
40354039

40364040
writeln!(
40374041
self.out,
@@ -4216,8 +4220,20 @@ impl<W: Write> Writer<W> {
42164220
first_time: false,
42174221
};
42184222

4219-
match size.resolve(module.to_ctx())? {
4220-
proc::IndexableLength::Known(size) => {
4223+
match size.resolve(module.to_ctx()) {
4224+
Err(ResolveArraySizeError::NonConstArrayLength) => {
4225+
// The array size was never resolved. This _should_
4226+
// be because it is an override expression and the
4227+
// type is not needed for the entry point being
4228+
// written.
4229+
// TODO: do we want to assemble `UnresolvedOverrides.types` to make this safer?
4230+
// (And if so, do we also want to validate that those types are truly unused?)
4231+
continue;
4232+
}
4233+
Err(err @ ResolveArraySizeError::ExpectedPositiveArrayLength) => {
4234+
return Err(err.into());
4235+
}
4236+
Ok(proc::IndexableLength::Known(size)) => {
42214237
writeln!(self.out, "struct {name} {{")?;
42224238
writeln!(
42234239
self.out,
@@ -4229,7 +4245,7 @@ impl<W: Write> Writer<W> {
42294245
)?;
42304246
writeln!(self.out, "}};")?;
42314247
}
4232-
proc::IndexableLength::Dynamic => {
4248+
Ok(proc::IndexableLength::Dynamic) => {
42334249
writeln!(self.out, "typedef {base_name} {name}[1];")?;
42344250
}
42354251
}
@@ -5757,6 +5773,17 @@ template <typename A>
57575773
fun_handle
57585774
);
57595775

5776+
if self
5777+
.unresolved_overrides
5778+
.as_ref()
5779+
.unwrap()
5780+
.functions
5781+
.contains_key(&fun_handle)
5782+
{
5783+
log::trace!("skipping due to unresolved overrides");
5784+
continue;
5785+
}
5786+
57605787
let ctx = back::FunctionCtx {
57615788
ty: back::FunctionType::Function(fun_handle),
57625789
info: &mod_info[fun_handle],
@@ -5880,6 +5907,19 @@ template <typename A>
58805907
};
58815908

58825909
for ep_index in ep_range {
5910+
if self
5911+
.unresolved_overrides
5912+
.as_ref()
5913+
.unwrap()
5914+
.entry_points
5915+
.contains_key(&ep_index)
5916+
{
5917+
log::error!(
5918+
"must write the same entry point that was passed to `process_overrides`"
5919+
);
5920+
return Err(Error::Override);
5921+
}
5922+
58835923
let ep = &module.entry_points[ep_index];
58845924
let fun = &ep.function;
58855925
let fun_info = mod_info.get_entry_point(ep_index);
@@ -6288,7 +6328,15 @@ template <typename A>
62886328
// within the entry point.
62896329
for (handle, var) in module.global_variables.iter() {
62906330
let usage = fun_info[handle];
6291-
if usage.is_empty() || var.space == crate::AddressSpace::Private {
6331+
if usage.is_empty()
6332+
|| var.space == crate::AddressSpace::Private
6333+
|| self
6334+
.unresolved_overrides
6335+
.as_ref()
6336+
.unwrap()
6337+
.global_variables
6338+
.contains_key(&handle)
6339+
{
62926340
continue;
62936341
}
62946342

0 commit comments

Comments
 (0)