fn shader_entry_stub(
        &self,
        entry_func: SpirvValue,
        hir_params: &[Param<'_>],
        name: String,
        execution_model: ExecutionModel,
    ) {
        let void = SpirvType::Void.def(self);
        let fn_void_void = SpirvType::Function {
            return_type: void,
            arguments: vec![],
        }
        .def(self);
        let (entry_func_return, entry_func_args) = match self.lookup_type(entry_func.ty) {
            SpirvType::Function {
                return_type,
                arguments,
            } => (return_type, arguments),
            other => self.tcx.sess.fatal(&format!(
                "Invalid entry_stub type: {}",
                other.debug(entry_func.ty, self)
            )),
        };
        let mut emit = self.emit_global();
        let mut decoration_locations = HashMap::new();
        // Create OpVariables before OpFunction so they're global instead of local vars.
        let arguments = entry_func_args
            .iter()
            .zip(hir_params)
            .map(|(&arg, hir_param)| {
                let storage_class = match self.lookup_type(arg) {
                    SpirvType::Pointer { storage_class, .. } => storage_class,
                    other => self.tcx.sess.fatal(&format!(
                        "Invalid entry arg type {}",
                        other.debug(arg, self)
                    )),
                };
                let mut has_location = match storage_class {
                    StorageClass::Input | StorageClass::Output | StorageClass::UniformConstant => {
                        true
                    }
                    _ => false,
                };
                // Note: this *declares* the variable too.
                let variable = emit.variable(arg, None, storage_class, None);
                for attr in hir_param.attrs {
                    if let Some(SpirvAttribute::Builtin(builtin)) = parse_attr(self, attr) {
                        emit.decorate(
                            variable,
                            Decoration::BuiltIn,
                            std::iter::once(Operand::BuiltIn(builtin)),
                        );
                        has_location = false;
                    }
                }
                // Assign locations from left to right, incrementing each storage class
                // individually.
                // TODO: Is this right for UniformConstant? Do they share locations with
                // input/outpus?
                if has_location {
                    let location = decoration_locations
                        .entry(storage_class)
                        .or_insert_with(|| 0);
                    emit.decorate(
                        variable,
                        Decoration::Location,
                        std::iter::once(Operand::LiteralInt32(*location)),
                    );
                    *location += 1;
                }
                variable
            })
            .collect::<Vec<_>>();
        let fn_id = emit
            .begin_function(void, None, FunctionControl::NONE, fn_void_void)
            .unwrap();
        emit.begin_block(None).unwrap();
        emit.function_call(
            entry_func_return,
            None,
            entry_func.def,
            arguments.iter().copied(),
        )
        .unwrap();
        emit.ret().unwrap();
        emit.end_function().unwrap();

        let interface = arguments;
        emit.entry_point(execution_model, fn_id, name, interface);
        if execution_model == ExecutionModel::Fragment {
            // TODO: Make this configurable.
            emit.execution_mode(fn_id, ExecutionMode::OriginUpperLeft, &[]);
        }
    }
// Entry points declare their "interface" (all uniforms, inputs, outputs, etc.) as parameters. spir-v uses globals
// to declare the interface. So, we need to generate a lil stub for the "real" main that collects all those global
// variables and calls the user-defined main function.
Entry points declare their "interface" (all uniforms, inputs, outputs, etc.) as parameters. spir-v uses globals
to declare the interface. So, we need to generate a lil stub for the "real" main that collects all those global
variables and calls the user-defined main function.
Entry points declare their " interface " ( all uniforms inputs outputs etc . ) as parameters . spir - v uses globals to declare the interface . So we need to generate a lil stub for the " real " main that collects all those global variables and calls the user - defined main function .
fn shader_entry_stub(
        &self,
        entry_func: SpirvValue,
        hir_params: &[Param<'_>],
        name: String,
        execution_model: ExecutionModel,
    ) {
        let void = SpirvType::Void.def(self);
        let fn_void_void = SpirvType::Function {
            return_type: void,
            arguments: vec![],
        }
        .def(self);
        let (entry_func_return, entry_func_args) = match self.lookup_type(entry_func.ty) {
            SpirvType::Function {
                return_type,
                arguments,
            } => (return_type, arguments),
            other => self.tcx.sess.fatal(&format!(
                "Invalid entry_stub type: {}",
                other.debug(entry_func.ty, self)
            )),
        };
        let mut emit = self.emit_global();
        let mut decoration_locations = HashMap::new();
        // Create OpVariables before OpFunction so they're global instead of local vars.
        let arguments = entry_func_args
            .iter()
            .zip(hir_params)
            .map(|(&arg, hir_param)| {
                let storage_class = match self.lookup_type(arg) {
                    SpirvType::Pointer { storage_class, .. } => storage_class,
                    other => self.tcx.sess.fatal(&format!(
                        "Invalid entry arg type {}",
                        other.debug(arg, self)
                    )),
                };
                let mut has_location = match storage_class {
                    StorageClass::Input | StorageClass::Output | StorageClass::UniformConstant => {
                        true
                    }
                    _ => false,
                };
                // Note: this *declares* the variable too.
                let variable = emit.variable(arg, None, storage_class, None);
                for attr in hir_param.attrs {
                    if let Some(SpirvAttribute::Builtin(builtin)) = parse_attr(self, attr) {
                        emit.decorate(
                            variable,
                            Decoration::BuiltIn,
                            std::iter::once(Operand::BuiltIn(builtin)),
                        );
                        has_location = false;
                    }
                }
                // Assign locations from left to right, incrementing each storage class
                // individually.
                // TODO: Is this right for UniformConstant? Do they share locations with
                // input/outpus?
                if has_location {
                    let location = decoration_locations
                        .entry(storage_class)
                        .or_insert_with(|| 0);
                    emit.decorate(
                        variable,
                        Decoration::Location,
                        std::iter::once(Operand::LiteralInt32(*location)),
                    );
                    *location += 1;
                }
                variable
            })
            .collect::<Vec<_>>();
        let fn_id = emit
            .begin_function(void, None, FunctionControl::NONE, fn_void_void)
            .unwrap();
        emit.begin_block(None).unwrap();
        emit.function_call(
            entry_func_return,
            None,
            entry_func.def,
            arguments.iter().copied(),
        )
        .unwrap();
        emit.ret().unwrap();
        emit.end_function().unwrap();
        let interface = arguments;
        emit.entry_point(execution_model, fn_id, name, interface);
        if execution_model == ExecutionModel::Fragment {
            // TODO: Make this configurable.
            emit.execution_mode(fn_id, ExecutionMode::OriginUpperLeft, &[]);
        }
    }
fn shader_entry_stub ( & self , entry_func : SpirvValue , hir_params : & [ Param < ' _ > ] , name : String , execution_model : ExecutionModel , ) { let void = SpirvType :: Void . def ( self ) ; let fn_void_void = SpirvType :: Function { return_type : void , arguments : vec ! [ ] , } . def ( self ) ; let ( entry_func_return , entry_func_args ) = match self . lookup_type ( entry_func . ty ) { SpirvType :: Function { return_type , arguments , } => ( return_type , arguments ) , other => self . tcx . sess . fatal ( & format ! ( " " other debug ( entry_func ty self ) ) ) , } ; let mut emit = self . emit_global ( ) ; let mut decoration_locations = HashMap :: new ( ) ; // Create OpVariables before OpFunction so they're global instead of local vars. let arguments = entry_func_args . iter ( ) . zip ( hir_params ) . map ( | ( & arg , hir_param ) | { let storage_class = match self . lookup_type ( arg ) { SpirvType :: Pointer { storage_class , .. } => storage_class , other => self . tcx . sess . fatal ( & format ! ( " " other debug ( arg self ) ) ) , } ; let mut has_location = match storage_class { StorageClass :: Input | StorageClass :: Output | StorageClass :: UniformConstant => { true } _ => false , } ; // Note: this *declares* the variable too. let variable = emit . variable ( arg , None , storage_class , None ) ; for attr in hir_param . attrs { if let Some ( SpirvAttribute :: Builtin ( builtin ) ) = parse_attr ( self , attr ) { emit . decorate ( variable , Decoration :: BuiltIn , std :: iter :: once ( Operand :: BuiltIn ( builtin ) ) , ) ; has_location = false ; } } // Assign locations from left to right, incrementing each storage class // individually. // TODO: Is this right for UniformConstant? Do they share locations with // input/outpus? if has_location { let location = decoration_locations . entry ( storage_class ) . or_insert_with ( | | 0 ) ; emit . decorate ( variable , Decoration :: Location , std :: iter :: once ( Operand :: LiteralInt32 ( * location ) ) , ) ; * location += 1 ; } variable } ) . collect :: < Vec < _ > > ( ) ; let fn_id = emit . begin_function ( void , None , FunctionControl :: NONE , fn_void_void ) . unwrap ( ) ; emit . begin_block ( None ) . unwrap ( ) ; emit . function_call ( entry_func_return , None , entry_func . def , arguments . iter ( ) . copied ( ) , ) . unwrap ( ) ; emit . ret ( ) . unwrap ( ) ; emit . end_function ( ) . unwrap ( ) ; let interface = arguments ; emit . entry_point ( execution_model , fn_id , name , interface ) ; if execution_model == ExecutionModel :: Fragment { // TODO: Make this configurable. emit . execution_mode ( fn_id , ExecutionMode :: OriginUpperLeft , & [ ] ) ; } }
Entry points declare their "interface" (all uniforms, inputs, outputs, etc.)
Entry points declare their " interface " ( all uniforms inputs outputs etc . )
&self
entry_func
SpirvValue
hir_params
&[Param<'_>]
name
String
execution_model
ExecutionModel
&self
entry_func
SpirvValue
hir_params
&[Param<'_>]
name
String
execution_model
ExecutionModel