Cache reserved keywords (#7338)

This commit is contained in:
Connor Fitzgerald 2025-03-18 14:26:45 -04:00 committed by GitHub
parent 5ac906645b
commit da7deb4381
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 106 additions and 16 deletions

View File

@ -1,3 +1,7 @@
use std::sync::LazyLock;
use hashbrown::HashSet;
pub const RESERVED_KEYWORDS: &[&str] = &[
//
// GLSL 4.6 keywords, from https://github.com/KhronosGroup/OpenGL-Registry/blob/d00e11dc1a1ffba581d633f21f70202051248d5c/specs/gl/GLSLangSpec.4.60.html#L2004-L2322
@ -490,3 +494,16 @@ pub const RESERVED_KEYWORDS: &[&str] = &[
super::FREXP_FUNCTION,
super::FIRST_INSTANCE_BINDING,
];
/// The above set of reserved keywords, turned into a cached HashSet. This saves
/// significant time during [`Namer::reset`](crate::proc::Namer::reset).
///
/// See <https://github.com/gfx-rs/wgpu/pull/7338> for benchmarks.
pub static RESERVED_KEYWORD_SET: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
let mut set = HashSet::default();
set.reserve(RESERVED_KEYWORDS.len());
for &word in RESERVED_KEYWORDS {
set.insert(word);
}
set
});

View File

@ -629,8 +629,7 @@ impl<'a, W: Write> Writer<'a, W> {
let mut namer = proc::Namer::default();
namer.reset(
module,
keywords::RESERVED_KEYWORDS,
&[],
&keywords::RESERVED_KEYWORD_SET,
&[],
&[
"gl_", // all GL built-in variables

View File

@ -1,3 +1,7 @@
use std::sync::LazyLock;
use hashbrown::HashSet;
// When compiling with FXC without strict mode, these keywords are actually case insensitive.
// If you compile with strict mode and specify a different casing like "Pass" instead in an identifier, FXC will give this error:
// "error X3086: alternate cases for 'pass' are deprecated in strict mode"
@ -912,6 +916,22 @@ pub const TYPES: &[&str] = &{
res
};
/// The above set of reserved keywords, turned into a cached HashSet. This saves
/// significant time during [`Namer::reset`](crate::proc::Namer::reset).
///
/// See <https://github.com/gfx-rs/wgpu/pull/7338> for benchmarks.
pub static RESERVED_SET: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
let mut set = HashSet::default();
set.reserve(RESERVED.len() + TYPES.len());
for &word in RESERVED {
set.insert(word);
}
for &word in TYPES {
set.insert(word);
}
set
});
pub const RESERVED_PREFIXES: &[&str] = &[
"__dynamic_buffer_offsets",
super::help::IMAGE_STORAGE_LOAD_SCALAR_WRAPPER,

View File

@ -140,8 +140,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
self.names.clear();
self.namer.reset(
module,
super::keywords::RESERVED,
super::keywords::TYPES,
&super::keywords::RESERVED_SET,
super::keywords::RESERVED_CASE_INSENSITIVE,
super::keywords::RESERVED_PREFIXES,
&mut self.names,

View File

@ -1,3 +1,7 @@
use std::sync::LazyLock;
use hashbrown::HashSet;
// MSLS - Metal Shading Language Specification:
// https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
//
@ -347,3 +351,16 @@ pub const RESERVED: &[&str] = &[
super::writer::NEG_FUNCTION,
super::writer::ARGUMENT_BUFFER_WRAPPER_STRUCT,
];
/// The above set of reserved keywords, turned into a cached HashSet. This saves
/// significant time during [`Namer::reset`](crate::proc::Namer::reset).
///
/// See <https://github.com/gfx-rs/wgpu/pull/7338> for benchmarks.
pub static RESERVED_SET: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
let mut set = HashSet::default();
set.reserve(RESERVED.len());
for &word in RESERVED {
set.insert(word);
}
set
});

View File

@ -3798,8 +3798,7 @@ impl<W: Write> Writer<W> {
self.names.clear();
self.namer.reset(
module,
super::keywords::RESERVED,
&[],
&super::keywords::RESERVED_SET,
&[],
&[CLAMPED_LOD_LOAD_PREFIX],
&mut self.names,

View File

@ -99,10 +99,9 @@ impl<W: Write> Writer<W> {
self.names.clear();
self.namer.reset(
module,
crate::keywords::wgsl::RESERVED,
&crate::keywords::wgsl::RESERVED_SET,
// an identifier must not start with two underscore
&[],
&[],
&["__", "_naga"],
&mut self.names,
);

View File

@ -4,6 +4,10 @@ Keywords for [WGSL][wgsl] (WebGPU Shading Language).
[wgsl]: https://gpuweb.github.io/gpuweb/wgsl.html
*/
use std::sync::LazyLock;
use hashbrown::HashSet;
// https://gpuweb.github.io/gpuweb/wgsl/#keyword-summary
// last sync: https://github.com/gpuweb/gpuweb/blob/39f2321f547c8f0b7f473cf1d47fba30b1691303/wgsl/index.bs
pub const RESERVED: &[&str] = &[
@ -229,3 +233,16 @@ pub const RESERVED: &[&str] = &[
"writeonly",
"yield",
];
/// The above set of reserved keywords, turned into a cached HashSet. This saves
/// significant time during [`Namer::reset`](crate::proc::Namer::reset).
///
/// See <https://github.com/gfx-rs/wgpu/pull/7338> for benchmarks.
pub static RESERVED_SET: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
let mut set = HashSet::default();
set.reserve(RESERVED.len());
for &word in RESERVED {
set.insert(word);
}
set
});

View File

@ -251,7 +251,18 @@ An override expression can be evaluated at pipeline creation time.
)]
#![no_std]
#[cfg(any(test, spv_out, feature = "spv-in", feature = "wgsl-in"))]
#[cfg(any(
test,
spv_out,
// Need OnceLock
hlsl_out,
msl_out,
wgsl_out,
feature = "spv-in",
feature = "wgsl-in"
))]
extern crate std;
extern crate alloc;

View File

@ -5,6 +5,7 @@ use alloc::{
vec::Vec,
};
use core::hash::{Hash, Hasher};
use hashbrown::HashSet;
use crate::{arena::Handle, FastHashMap, FastHashSet};
@ -27,15 +28,29 @@ pub enum NameKey {
/// This processor assigns names to all the things in a module
/// that may need identifiers in a textual backend.
#[derive(Default)]
pub struct Namer {
/// The last numeric suffix used for each base name. Zero means "no suffix".
unique: FastHashMap<String, u32>,
keywords: FastHashSet<&'static str>,
keywords: &'static HashSet<&'static str>,
keywords_case_insensitive: FastHashSet<AsciiUniCase<&'static str>>,
reserved_prefixes: Vec<&'static str>,
}
#[cfg(any(wgsl_out, glsl_out, msl_out, hlsl_out, test))]
impl Default for Namer {
fn default() -> Self {
use std::sync::LazyLock;
static DEFAULT_KEYWORDS: LazyLock<HashSet<&'static str>> = LazyLock::new(HashSet::default);
Self {
unique: Default::default(),
keywords: &DEFAULT_KEYWORDS,
keywords_case_insensitive: Default::default(),
reserved_prefixes: Default::default(),
}
}
}
impl Namer {
/// Return a form of `string` suitable for use as the base of an identifier.
///
@ -157,8 +172,7 @@ impl Namer {
pub fn reset(
&mut self,
module: &crate::Module,
reserved_keywords: &[&'static str],
extra_reserved_keywords: &[&'static str],
reserved_keywords: &'static HashSet<&'static str>,
reserved_keywords_case_insensitive: &[&'static str],
reserved_prefixes: &[&'static str],
output: &mut FastHashMap<NameKey, String>,
@ -167,9 +181,7 @@ impl Namer {
self.reserved_prefixes.extend(reserved_prefixes.iter());
self.unique.clear();
self.keywords.clear();
self.keywords.extend(reserved_keywords.iter());
self.keywords.extend(extra_reserved_keywords.iter());
self.keywords = reserved_keywords;
debug_assert!(reserved_keywords_case_insensitive
.iter()