///|
fn copy_shader_def_values(
defs : Map[String, ShaderDefValue],
) -> Map[String, ShaderDefValue] {
let copied : Map[String, ShaderDefValue] = Map([])
for entry in defs.iter() {
let (name, value) = entry
copied.set(name, value)
}
copied
}
///|
fn copy_import_definitions(
imports : Array[ImportDefinition],
) -> Array[ImportDefinition] {
let copied : Array[ImportDefinition] = []
for import_definition in imports {
copied.push(import_definition)
}
copied
}
///|
fn copy_wgsl_immediate_specializations(
specializations : Array[WgslImmediateSpecialization],
) -> Array[WgslImmediateSpecialization] {
let copied : Array[WgslImmediateSpecialization] = []
for specialization in specializations {
copied.push(
WgslImmediateSpecialization(
specialization.rel_path,
specialization.global_name,
copy_shader_def_values(specialization.field_values),
),
)
}
copied
}
///|
fn serialize_wgsl_import_definition(
import_definition : ImportDefinition,
) -> String {
let import_path = import_definition.import_path.trim().to_owned()
if import_path == "" {
return ""
}
let items : Array[String] = []
for item in import_definition.items {
let trimmed_item = item.trim().to_owned()
if trimmed_item != "" {
items.push(trimmed_item)
}
}
if items.length() == 0 {
"#import \{import_path}"
} else {
let item_list = items.join(", ")
"#import \{import_path} \{item_list}"
}
}
///|
fn prepend_wgsl_additional_imports(
source : String,
additional_imports : Array[ImportDefinition],
) -> String {
let lines : Array[String] = []
for import_definition in additional_imports {
let line = serialize_wgsl_import_definition(import_definition)
if line != "" {
lines.push(line)
}
}
if lines.length() == 0 {
return source
}
let import_block = lines.join("\n")
"\{import_block}\n\{source}"
}
///|
fn copy_bool_defs(defs : Map[String, Bool]) -> Map[String, Bool] {
let copied : Map[String, Bool] = Map([])
for entry in defs.iter() {
let (name, value) = entry
copied.set(name, value)
}
copied
}
///|
fn copy_value_defs(
defs : Map[String, ShaderDefValue],
) -> Map[String, ShaderDefValue] {
let copied : Map[String, ShaderDefValue] = Map([])
for entry in defs.iter() {
let (name, value) = entry
copied.set(name, value)
}
copied
}
///|
fn merge_shader_def_value_into_compose_defs(
defines : Map[String, Bool],
value_defines : Map[String, ShaderDefValue],
shader_defs : Map[String, ShaderDefValue],
name : String,
value : ShaderDefValue,
) -> Unit {
shader_defs.set(name, value)
match value {
Bool(flag) => defines.set(name, flag)
Int(_) | UInt(_) | Raw(_) => value_defines.set(name, value)
}
}
///|
fn set_strings_to_array(values : @set.Set[String]) -> Array[String] {
let out : Array[String] = []
for value in values.iter() {
out.push(value)
}
out.sort()
out
}
///|
priv struct WgslComposeSemanticFacts {
declarations : Array[String]
global_variables : Array[String]
references : Array[WgslReferencePath]
reference_keys : @set.Set[String]
unqualified_reference_names : @set.Set[String]
}
///|
priv struct WgslComposeSymbolTable {
assigned_final_names : WgslComposeFinalNameTable
emitted_final_names : WgslComposeFinalNameTable
virtual_override_final_names : Array[WgslVirtualOverrideFinalNameBinding]
local_import_final_names : Array[WgslLocalImportFinalNameBinding]
local_spelling_final_names : Array[WgslLocalSpellingFinalNameBinding]
source_origins : Array[WgslSourceOriginEntry]
import_arena_events : Array[WgslComposeImportArenaEvent]
}
///|
priv struct WgslComposeSession {
defines : Map[String, Bool]
value_defines : Map[String, ShaderDefValue]
modules : Map[String, String]
redirects : Array[WgslSymbolRedirect]
additional_imports : Array[ImportDefinition]
immediate_specializations : Array[WgslImmediateSpecialization]
global_alias_bindings : WgslComposeBindingSet
redirect_match_counts : Map[String, Int32]
visited : @set.Set[String]
graph_planned_requests : @set.Set[String]
graph_planning_rel_paths : Array[String]
mut graph_execution_complete : Bool
mut emitted_virtual_functions : Bool
symbols : WgslComposeSymbolTable
link_graph : WgslComposeLinkGraph
semantic_facts : Map[String, WgslComposeSemanticFacts]
directive_scans : Map[String, Array[WgslDirectiveScanItem]]
importless_sources : Map[String, String]
directive_import_targets : Map[String, Array[WgslImportTarget]]
directive_single_import_targets : Map[String, Array[WgslImportTarget]]
semantic_reference_first_starts : Map[String, Map[String, Int32]]
source_local_shader_defs : Map[String, Map[String, ShaderDefValue]]
source_cache_ids : Map[String, Int32]
mut next_source_cache_id : Int32
processed_modules : Map[String, WgslProcessedComposeModule]
selected_import_candidate_rel_paths : Map[String, String]
import_request_plans : Map[String, Array[WgslImportRequest]]
emitted_item_import_requests : Map[String, Array[WgslImportRequest]]
active_rel_paths : Array[String]
}
///|
fn WgslComposeSession::source_cache_id(
self : WgslComposeSession,
source : String,
) -> Int32 {
match self.source_cache_ids.get(source) {
Some(id) => id
None => {
let id = self.next_source_cache_id
self.next_source_cache_id = id + 1
self.source_cache_ids.set(source, id)
id
}
}
}
///|
priv struct WgslProcessedComposeModule {
raw_source : String
active_defs : WgslActiveComposeDefs
prepared : WgslPreparedComposeSource
mut unit : WgslTranslationUnit?
mut declarations_by_name : Map[String, WgslGlobalDecl]?
mut declaration_summaries : Map[String, WgslProcessedDeclarationSummary]?
mut declaration_names : Array[String]?
mut item_extractor : WgslModuleItemExtractor?
item_extractions : Map[String, WgslModuleItemExtraction]
mut naga_pull_ranks : Map[String, Int32]?
mut source_decl_ranks : Map[String, Int32]?
mut virtual_override_targets : Array[String]?
mut has_override_function : Bool?
mut has_virtual_function : Bool?
}
///|
priv enum WgslProcessedDeclarationKind {
SummaryType
SummaryConstant
SummaryOverride
SummaryGlobalVariable
SummaryFunction
} derive(Eq)
///|
priv struct WgslProcessedDeclarationSummary {
kind : WgslProcessedDeclarationKind
has_resource_binding : Bool
}
///|
priv enum WgslComposeBindingScope {
QualifiedAliasBinding
UnqualifiedItemBinding
} derive(Eq)
///|
priv struct WgslComposeBinding {
reference_path : WgslReferencePath
target : WgslComposeSymbolTarget
scope : WgslComposeBindingScope
alias_name : String
key : String
}
///|
priv struct WgslComposeSymbolTarget {
identity : WgslComposeSymbolIdentity
identity_key : String
final_name : String
}
///|
priv struct WgslComposeBindingSet {
bindings : Array[WgslComposeBinding]
keys : @set.Set[String]
}
///|
priv struct WgslVirtualOverrideFinalNameBinding {
raw_target_name : String
rel_path : String
target_name : String
override_name : String
}
///|
priv struct WgslLocalImportFinalNameBinding {
rel_path : String
source_name : String
final_name : String
}
///|
priv struct WgslLocalSpellingFinalNameBinding {
visible_rel_path : String
symbol_rel_path : String
source_name : String
final_name : String
}
///|
priv struct WgslVirtualOverrideFinalNameKey {
text : String
}
///|
priv struct WgslLocalImportFinalNameKey {
text : String
}
///|
priv struct WgslLocalSpellingFinalNameKey {
text : String
}
///|
priv struct WgslLiveBindingPlan {
bindings : Array[WgslLiveSymbolBinding]
}
///|
priv struct WgslLiveSymbolBinding {
reference_path : WgslReferencePath
target : WgslComposeSymbolTarget
scope : WgslComposeBindingScope
alias_name : String
}
///|
fn WgslComposeSymbolTable::WgslComposeSymbolTable() -> WgslComposeSymbolTable {
{
assigned_final_names: WgslComposeFinalNameTable(),
emitted_final_names: WgslComposeFinalNameTable(),
virtual_override_final_names: [],
local_import_final_names: [],
local_spelling_final_names: [],
source_origins: [],
import_arena_events: [],
}
}
///|
fn WgslLiveBindingPlan::WgslLiveBindingPlan() -> WgslLiveBindingPlan {
{ bindings: [], }
}
///|
fn WgslLiveBindingPlan::push(
self : WgslLiveBindingPlan,
binding : WgslLiveSymbolBinding,
) -> Unit {
self.bindings.push(binding)
}
///|
fn wgsl_live_binding_conflict_message(
existing : WgslLiveSymbolBinding,
binding : WgslLiveSymbolBinding,
) -> String {
let existing_identity = existing.target.identity_key
let binding_identity = binding.target.identity_key
let scope = if binding.alias_name == "" {
binding.scope.label()
} else {
"\{binding.scope.label()} alias \{binding.alias_name}"
}
"\{binding.reference_path.text()} in \{scope}: \{existing_identity} -> \{existing.target.final_name} conflicts with \{binding_identity} -> \{binding.target.final_name}"
}
///|
fn WgslLiveBindingPlan::first_conflict(self : WgslLiveBindingPlan) -> String? {
for i in 0.. WgslReferenceRewritePlan {
let plan = WgslReferenceRewritePlan()
for binding in self.bindings {
plan.add_symbol_reference_binding(
binding.target.identity,
binding.reference_path,
binding.target.final_name,
)
}
for binding in session.symbols.virtual_override_final_names {
match WgslReferencePath::from_text(binding.raw_target_name) {
Some(reference_path) =>
plan.add_symbol_reference_binding(
WgslComposeSymbolIdentity(binding.rel_path, binding.raw_target_name),
reference_path,
binding.target_name,
)
None => ()
}
plan.add_virtual_override_binding(
binding.raw_target_name,
binding.target_name,
binding.override_name,
)
}
plan
}
///|
fn WgslComposeBindingSet::WgslComposeBindingSet() -> WgslComposeBindingSet {
{ bindings: [], keys: Set([]), }
}
///|
fn WgslComposeBindingScope::label(self : WgslComposeBindingScope) -> String {
match self {
QualifiedAliasBinding => "qualified"
UnqualifiedItemBinding => "unqualified"
}
}
///|
fn WgslComposeSymbolTarget::WgslComposeSymbolTarget(
identity : WgslComposeSymbolIdentity,
final_name : String,
) -> WgslComposeSymbolTarget {
{
identity,
identity_key: identity.key(),
final_name: final_name.trim().to_owned(),
}
}
///|
fn WgslComposeBinding::WgslComposeBinding(
reference_path : WgslReferencePath,
target : WgslComposeSymbolTarget,
scope : WgslComposeBindingScope,
alias_name : String,
) -> WgslComposeBinding {
let alias_name = alias_name.trim().to_owned()
let key = "\{scope.label()}|\{reference_path.text()}|\{target.final_name}|\{alias_name}|\{target.identity_key}"
{ reference_path, target, scope, alias_name, key, }
}
///|
fn WgslComposeBinding::for_alias_symbol(
rel_path : String,
alias_name : String,
original_name : String,
final_name : String,
scope : WgslComposeBindingScope,
) -> WgslComposeBinding? {
let identity = WgslComposeSymbolIdentity(rel_path, original_name)
match WgslReferencePath::from_text("\{alias_name}::\{original_name}") {
Some(reference_path) =>
Some(
WgslComposeBinding(
reference_path,
WgslComposeSymbolTarget(identity, final_name),
scope,
alias_name,
),
)
None => None
}
}
///|
fn WgslComposeBinding::for_unqualified_symbol(
rel_path : String,
original_name : String,
final_name : String,
scope : WgslComposeBindingScope,
) -> WgslComposeBinding? {
let identity = WgslComposeSymbolIdentity(rel_path, original_name)
match WgslReferencePath::from_text(original_name) {
Some(reference_path) =>
Some(
WgslComposeBinding(
reference_path,
WgslComposeSymbolTarget(identity, final_name),
scope,
"",
),
)
None => None
}
}
///|
fn WgslComposeBinding::as_unqualified_binding(
self : WgslComposeBinding,
reference_name : String,
) -> WgslComposeBinding? {
match WgslReferencePath::from_text(reference_name) {
Some(reference_path) =>
Some(
WgslComposeBinding(
reference_path,
self.target,
UnqualifiedItemBinding,
self.alias_name,
),
)
None => None
}
}
///|
fn WgslComposeBinding::with_target(
self : WgslComposeBinding,
target : WgslComposeSymbolTarget,
) -> WgslComposeBinding {
WgslComposeBinding(self.reference_path, target, self.scope, self.alias_name)
}
///|
fn WgslComposeBinding::to_live_binding(
self : WgslComposeBinding,
target : WgslComposeSymbolTarget,
) -> WgslLiveSymbolBinding {
{
reference_path: self.reference_path,
target,
scope: self.scope,
alias_name: self.alias_name,
}
}
///|
fn WgslComposeBindingSet::push(
self : WgslComposeBindingSet,
binding : WgslComposeBinding,
) -> Unit {
if binding.target.final_name == "" {
return
}
let key = binding.key
if self.keys.contains(key) {
return
}
self.keys.add(key)
self.bindings.push(binding)
}
///|
fn WgslComposeBindingSet::has_unqualified_local_name(
self : WgslComposeBindingSet,
name : String,
) -> Bool {
for binding in self.bindings {
if binding.scope == UnqualifiedItemBinding &&
binding.alias_name == "" &&
binding.reference_path.text() == name &&
binding.target.final_name == name {
return true
}
}
false
}
///|
fn WgslComposeBindingSet::has_unqualified_reference_name(
self : WgslComposeBindingSet,
name : String,
) -> Bool {
for binding in self.bindings {
if binding.scope == UnqualifiedItemBinding &&
binding.alias_name == "" &&
binding.reference_path.text() == name {
return true
}
}
false
}
///|
fn WgslVirtualOverrideFinalNameKey::WgslVirtualOverrideFinalNameKey(
binding : WgslVirtualOverrideFinalNameBinding,
) -> WgslVirtualOverrideFinalNameKey {
{
text: "\{binding.raw_target_name}|\{binding.rel_path}|\{binding.target_name}|\{binding.override_name}",
}
}
///|
fn WgslVirtualOverrideFinalNameKey::text(
self : WgslVirtualOverrideFinalNameKey,
) -> String {
self.text
}
///|
fn WgslLocalImportFinalNameKey::WgslLocalImportFinalNameKey(
binding : WgslLocalImportFinalNameBinding,
) -> WgslLocalImportFinalNameKey {
{ text: "\{binding.rel_path}|\{binding.source_name}|\{binding.final_name}", }
}
///|
fn WgslLocalImportFinalNameKey::text(
self : WgslLocalImportFinalNameKey,
) -> String {
self.text
}
///|
fn WgslLocalSpellingFinalNameKey::WgslLocalSpellingFinalNameKey(
binding : WgslLocalSpellingFinalNameBinding,
) -> WgslLocalSpellingFinalNameKey {
{
text: "\{binding.visible_rel_path}|\{binding.symbol_rel_path}|\{binding.source_name}|\{binding.final_name}",
}
}
///|
fn WgslLocalSpellingFinalNameKey::text(
self : WgslLocalSpellingFinalNameKey,
) -> String {
self.text
}
///|
fn WgslComposeSession::record_virtual_override_final_name(
self : WgslComposeSession,
raw_target_name : String,
rel_path : String,
target_name : String,
override_name : String,
) -> Unit {
let binding = WgslVirtualOverrideFinalNameBinding::{
raw_target_name,
rel_path,
target_name,
override_name,
}
let key = WgslVirtualOverrideFinalNameKey(binding).text()
for existing in self.symbols.virtual_override_final_names {
if WgslVirtualOverrideFinalNameKey(existing).text() == key {
return
}
}
self.symbols.virtual_override_final_names.push(binding)
}
///|
fn WgslComposeSession::record_local_import_final_name(
self : WgslComposeSession,
rel_path : String,
source_name : String,
final_name : String,
) -> Unit {
let rel_path = normalize_shader_rel_path(rel_path)
let source_name = source_name.trim().to_owned()
let final_name = final_name.trim().to_owned()
if rel_path == "" ||
source_name == "" ||
final_name == "" ||
source_name == final_name {
return
}
let binding = WgslLocalImportFinalNameBinding::{
rel_path,
source_name,
final_name,
}
let key = WgslLocalImportFinalNameKey(binding).text()
for existing in self.symbols.local_import_final_names {
if WgslLocalImportFinalNameKey(existing).text() == key {
return
}
}
self.symbols.local_import_final_names.push(binding)
}
///|
fn WgslComposeSession::record_local_spelling_final_name(
self : WgslComposeSession,
visible_rel_path : String,
symbol_rel_path : String,
source_name : String,
final_name : String,
) -> Unit {
let visible_rel_path = normalize_shader_rel_path(visible_rel_path)
let symbol_rel_path = normalize_shader_rel_path(symbol_rel_path)
let source_name = source_name.trim().to_owned()
let final_name = final_name.trim().to_owned()
if visible_rel_path == "" ||
symbol_rel_path == "" ||
source_name == "" ||
source_name == final_name {
return
}
let binding = WgslLocalSpellingFinalNameBinding::{
visible_rel_path,
symbol_rel_path,
source_name,
final_name,
}
let key = WgslLocalSpellingFinalNameKey(binding).text()
for existing in self.symbols.local_spelling_final_names {
if WgslLocalSpellingFinalNameKey(existing).text() == key {
return
}
}
self.symbols.local_spelling_final_names.push(binding)
}
///|
fn WgslComposeSession::record_canonical_final_name(
self : WgslComposeSession,
identity : WgslComposeSymbolIdentity,
final_name : String,
) -> Unit {
self.symbols.emitted_final_names.canonical_set(identity, final_name)
self.link_graph.record_reachable_symbol(identity)
}
///|
fn WgslComposeSession::assign_canonical_final_name(
self : WgslComposeSession,
identity : WgslComposeSymbolIdentity,
final_name : String,
) -> Unit {
self.symbols.assigned_final_names.canonical_set(identity, final_name)
self.link_graph.record_reachable_symbol(identity)
}
///|
fn WgslComposeSession::assigned_canonical_final_name(
self : WgslComposeSession,
identity : WgslComposeSymbolIdentity,
) -> String? {
self.symbols.assigned_final_names.canonical_get(identity)
}
///|
fn WgslComposeSession::assign_alias_final_name(
self : WgslComposeSession,
identity : WgslComposeAliasSymbolIdentity,
final_name : String,
) -> Unit {
self.symbols.assigned_final_names.canonical_set(identity.symbol(), final_name)
self.symbols.assigned_final_names.alias_set(identity, final_name)
self.link_graph.record_reachable_symbol(identity.symbol())
}
///|
fn WgslComposeSession::record_canonical_final_name_if_absent(
self : WgslComposeSession,
identity : WgslComposeSymbolIdentity,
final_name : String,
) -> Unit {
if self.symbols.emitted_final_names.canonical_get(identity) is None {
self.record_canonical_final_name(identity, final_name)
}
}
///|
fn WgslComposeSession::record_alias_final_name(
self : WgslComposeSession,
identity : WgslComposeAliasSymbolIdentity,
final_name : String,
) -> Unit {
self.symbols.emitted_final_names.alias_set(identity, final_name)
self.link_graph.record_reachable_symbol(identity.symbol())
}
///|
fn WgslComposeSession::record_alias_final_name_if_absent(
self : WgslComposeSession,
identity : WgslComposeAliasSymbolIdentity,
final_name : String,
) -> Unit {
if self.symbols.emitted_final_names.alias_get(identity) is None {
self.record_alias_final_name(identity, final_name)
}
}
///|
priv struct WgslActiveComposeDefs {
defines : Map[String, Bool]
value_defines : Map[String, ShaderDefValue]
shader_defs : Map[String, ShaderDefValue]
mut cache_text : String?
}
///|
fn composable_module_name_from_descriptor(
desc : ComposableModuleDescriptor,
metadata_name : String?,
) -> String raise ComposerError {
match desc.as_name {
Some(as_name) => {
let trimmed = as_name.trim().to_owned()
if trimmed == "" {
raise NoModuleName(desc.file_path)
}
trimmed
}
None =>
match metadata_name {
Some(name) if name.trim() != "" => name.trim().to_owned()
_ => raise NoModuleName(desc.file_path)
}
}
}
///|
fn composable_module_registry_rel_path(
desc : ComposableModuleDescriptor,
module_name : String,
) -> String {
let normalized_file_path = normalize_shader_rel_path(desc.file_path)
if normalized_file_path != "" {
return normalized_file_path
}
default_shader_rel_path_for_module_path(module_name)
}