public ShaderFunction CreateFunction(FunctionKey key) { ShaderFunction shaderFunction = new ShaderFunction(); mFunctionMap.Add(key, shaderFunction); return(shaderFunction); }
public ShaderOp GenerateFunctionCall(ShaderFunction shaderFunction, IShaderIR selfOp, List <IShaderIR> arguments, FrontEndContext context) { var argumentOps = new List <IShaderIR>(); argumentOps.Add(shaderFunction); if (!shaderFunction.IsStatic || selfOp != null) { argumentOps.Add(selfOp); } if (arguments != null) { for (var i = 0; i < arguments.Count; ++i) { var argument = arguments[i]; var paramIR = GetFunctionParameter(shaderFunction, i, argument, context); argumentOps.Add(paramIR); } } var fnShaderReturnType = shaderFunction.GetReturnType(); var functionCallOp = CreateOp(context.mCurrentBlock, OpInstructionType.OpFunctionCall, fnShaderReturnType, argumentOps); return(functionCallOp); }
public IShaderIR GetFunctionParameter(ShaderFunction shaderFunction, int paramIndex, CSharpSyntaxNode argument) { // Evaluate the expression var argumentOp = WalkAndGetResult(argument); return(GetFunctionParameter(shaderFunction, paramIndex, argumentOp)); }
public void Visit(ShaderFunction function) { mReferencedFunctions.Add(function); Visit(function.mResultType); Visit(function.mParametersBlock); Visit(function.mBlocks); }
public virtual void Visit(ShaderFunction shaderFunction) { Visit(shaderFunction.mParametersBlock); foreach (var block in shaderFunction.mBlocks) { Visit(block); } }
public ShaderOp TryGenerateFunctionCall(ShaderFunction shaderFunction, IShaderIR selfOp, List <IShaderIR> arguments, FrontEndContext context) { if (shaderFunction == null) { return(null); } return(GenerateFunctionCall(shaderFunction, selfOp, arguments, context)); }
void WriteDebugInstructions(ShaderFunction function) { WriteDebugName(function, function.DebugInfo.Name); WriteDebugInstructions(function.mParametersBlock); foreach (var block in function.mBlocks) { WriteDebugInstructions(block); } }
public void VisitMethod(CSharpSyntaxNode node, ShaderFunction shaderFunction) { var fnSymbol = mFrontEnd.mSemanticModel.GetDeclaredSymbol(node) as IMethodSymbol; // Handle intrinsics. If we have a resolver for a special handler then call that and return. if (SpecialResolvers.TryProcessIntrinsicMethod(mFrontEnd, fnSymbol)) { return; } // Add the current function as the active one and the parameter mContext.mCurrentFunction = shaderFunction; // Start writing out the parameters (so the parameter block is the active one) mContext.mCurrentBlock = shaderFunction.mParametersBlock; // Add the 'this' op if it exists if (!fnSymbol.IsStatic) { var selfType = mContext.mCurrentType; var thisType = selfType.FindPointerType(StorageClass.Function); var selfOp = CreateOp(mContext.mCurrentBlock, OpInstructionType.OpFunctionParameter, thisType, null); selfOp.DebugInfo.Name = "self"; mContext.mThisOp = selfOp; } // Add the function parameter ops foreach (var parameter in fnSymbol.Parameters) { var parameterType = FindParameterType(mFrontEnd.mCurrentLibrary.FindType(new TypeKey(parameter.Type)), parameter); var paramOp = CreateOp(mContext.mCurrentBlock, OpInstructionType.OpFunctionParameter, parameterType, null); // Extract the debug info. We can't get this from the node because the node isn't always a method with arguments. // // If this is a get/set then the arguments are implicit and there's no location to look at. if (parameter.Locations != null && parameter.Locations.Length != 0) { paramOp.DebugInfo.Location = parameter.Locations[0]; } paramOp.DebugInfo.Name = parameter.Name; // Also map parameter symbols in this scope to their ops so we can look them up later when visiting identifiers mContext.mSymbolToIRMap.Add(parameter, paramOp); } // Now set the body as the current scope and visit the function var firstBlock = new ShaderBlock(); shaderFunction.mBlocks.Add(firstBlock); mContext.mCurrentBlock = firstBlock; mCommonPass.Visit(node); // SpirV has some special rules about returns. Make sure to address these by fixing up missing terminators or removing extra functions. mFrontEnd.FixupBlockTerminators(shaderFunction); // Clear the function out of the current context mContext.mThisOp = null; mContext.mCurrentBlock = null; mContext.mCurrentFunction = null; }
void GenerateIds(ShaderFunction function) { GenerateIds(function.mResultType); GetId(function); GenerateIds(function.mParametersBlock); foreach (var block in function.mBlocks) { GenerateIds(block); } }
public void FixupBlockTerminators(ShaderFunction shaderFunction) { if (shaderFunction.mBlocks.Count == 0) { shaderFunction.mBlocks.Add(new ShaderBlock()); } var lastBlock = shaderFunction.mBlocks[shaderFunction.mBlocks.Count - 1]; if (lastBlock.mTerminatorOp == null) { if (shaderFunction.GetReturnType() != FindType(typeof(void))) { lastBlock.mTerminatorOp = CreateOp(lastBlock, OpInstructionType.OpUnreachable, null, null); } else { lastBlock.mTerminatorOp = CreateOp(lastBlock, OpInstructionType.OpReturn, null, null); } } foreach (var block in shaderFunction.mBlocks) { if (block.mTerminatorOp == null) { continue; } for (var i = 0; i < block.mOps.Count; ++i) { var op = block.mOps[i] as ShaderOp; if (op != null && (op.mOpType == OpInstructionType.OpReturn || op.mOpType == OpInstructionType.OpReturnValue || op.mOpType == OpInstructionType.OpBranch || op.mOpType == OpInstructionType.OpBranchConditional || op.mOpType == OpInstructionType.OpKill || op.mOpType == OpInstructionType.OpSwitch)) { var nextOpIndex = i + 1; block.mOps.RemoveRange(nextOpIndex, block.mOps.Count - nextOpIndex); break; } } } }
public ShaderFunction CreateFunction(ShaderType owningType, ShaderType returnType, string name, ShaderType thisType, List <ShaderType> args) { var shaderFunction = new ShaderFunction(); shaderFunction.mMeta = new ShaderFunctionMeta(); shaderFunction.mMeta.mName = name; shaderFunction.DebugInfo.Name = name; shaderFunction.mParameters.Add(returnType); if (thisType != null) { shaderFunction.mParameters.Add(thisType); } if (args != null) { shaderFunction.mParameters.AddRange(args); } owningType.mFunctions.Add(shaderFunction); return(shaderFunction); }
public ShaderFunction CreateFunctionAndType(ShaderType owningType, ShaderType returnType, string name, ShaderType thisType, List <ShaderType> args) { var shaderFunction = new ShaderFunction(); shaderFunction.mMeta.mName = name; shaderFunction.DebugInfo.Name = GenerateDebugFunctionName(owningType, name); shaderFunction.mResultType = FindOrCreateFunctionType(returnType, thisType, args); shaderFunction.mParameters.Add(returnType); if (thisType != null) { shaderFunction.mParameters.Add(thisType); } if (args != null) { shaderFunction.mParameters.AddRange(args); } shaderFunction.mMeta.IsStatic = shaderFunction.IsStatic = (thisType == null); owningType.mFunctions.Add(shaderFunction); return(shaderFunction); }
public void GenerateFunctionCall(ShaderFunction shaderFunction, IShaderIR selfOp, List <CSharpSyntaxNode> arguments) { var argumentOps = new List <IShaderIR>(); argumentOps.Add(shaderFunction); if (!shaderFunction.IsStatic) { argumentOps.Add(selfOp); } for (var i = 0; i < arguments.Count; ++i) { var argument = arguments[i]; var paramIR = GetFunctionParameter(shaderFunction, i, argument); argumentOps.Add(paramIR); } var fnShaderReturnType = shaderFunction.GetReturnType(); var functionCallOp = mFrontEnd.CreateOp(mContext.mCurrentBlock, OpInstructionType.OpFunctionCall, fnShaderReturnType, argumentOps); mContext.Push(functionCallOp); }
public IShaderIR GetFunctionParameter(ShaderFunction shaderFunction, int paramIndex, IShaderIR argumentOp, FrontEndContext context) { // Handle if the parameter types don't match (e.g. handle out params and whatnot) var paramType = shaderFunction.GetExplicitParameterType(paramIndex); // If the function expects a pointer if (paramType.mBaseType == OpType.Pointer) { // If this isn't already a pointer then throw an exception. This might be valid, but has to be thought more about. // With C# I think it'll always be a pointer when you pass something in to an out/ref param. var op = argumentOp as ShaderOp; if (op.mResultType != paramType) { throw new Exception(); } } // If this is a pointer but the function expects a value type then deref if necessary else { argumentOp = GetOrGenerateValueTypeFromIR(context.mCurrentBlock, argumentOp); } return(argumentOp); }
public static ShaderEntryPointInfo GeneratePixel(FrontEndTranslator translator, ShaderType shaderType, ShaderFunction function) { var entryPoint = new ShaderEntryPointInfo(); var context = new FrontEndContext(); context.mCurrentType = shaderType; var interfaceInfo = new EntryPointInterfaceInfo(); EntryPointGenerationShared.CollectInterface(translator, shaderType, interfaceInfo); // Build inputs block EntryPointGenerationShared.GenerateHardwareBuiltIns(translator, interfaceInfo.HardwareBuiltInInputs, StorageClass.Input, entryPoint.mInterfaceVariables, entryPoint.mDecorations); InputDeclarations.GenerateInputStruct(translator, shaderType, interfaceInfo.StageInputs, entryPoint.mInterfaceVariables, entryPoint.mDecorations); EntryPointGenerationShared.GenerateHardwareBuiltIns(translator, interfaceInfo.HardwareBuiltInOutputs, StorageClass.Output, entryPoint.mInterfaceVariables, entryPoint.mDecorations); OutputDeclarations.GenerateOutputFields(translator, shaderType, interfaceInfo.StageOutputs, entryPoint.mInterfaceVariables, entryPoint.mDecorations); UniformDeclarations.DeclareUniformBuffers(translator, interfaceInfo.UniformBuffers, entryPoint.mInterfaceVariables, entryPoint.mDecorations); UniformDeclarations.DeclareUniformConstants(translator, interfaceInfo.ConstantUniforms, entryPoint.mDecorations); // Create the functions required to run an entry point string entryPointName = EntryPointGenerationShared.GenerateEntryPointFunctionName(translator, shaderType, function); CreateGlobalVariableInitializeFunction(translator, shaderType, entryPoint, interfaceInfo, context); InputDeclarations.GenerateCopyInputsFunction(translator, shaderType, entryPoint, interfaceInfo); OutputDeclarations.GenerateCopyOutputsFunction(translator, shaderType, entryPoint, interfaceInfo); var entryPointFunction = GenerateSpirVEntryPointFunction(translator, shaderType, entryPointName); // Generate the entry point function body translator.TryGenerateFunctionCall(entryPoint.mGlobalsInitializationFunction, null, null, entryPointFunction.Context); EntryPointGenerationShared.ConstructShaderType(translator, shaderType, entryPointFunction.Context); var entryPointThisOp = entryPointFunction.Context.mThisOp; translator.TryGenerateFunctionCall(interfaceInfo.CopyInputsFunction.ShaderFunction, entryPointThisOp, null, entryPointFunction.Context); translator.TryGenerateFunctionCall(function, entryPointThisOp, null, entryPointFunction.Context); translator.TryGenerateFunctionCall(interfaceInfo.CopyOutputsFunction.ShaderFunction, entryPointThisOp, null, entryPointFunction.Context); translator.FixupBlockTerminators(entryPointFunction.ShaderFunction); // Make sure all global variables are added to the interface of the entry point AddGlobalVariables(translator, entryPoint, interfaceInfo); entryPoint.mEntryPointFunction = entryPointFunction.ShaderFunction; entryPoint.mStageType = shaderType.mFragmentType; shaderType.mEntryPoints.Add(entryPoint); EntryPointGenerationShared.AddExecutionMode(translator, entryPoint, entryPoint.mEntryPointFunction, Spv.ExecutionMode.ExecutionModeOriginUpperLeft); return(entryPoint); }
public void GenerateFunctionCall(ShaderFunction shaderFunction, IShaderIR selfOp, List <IShaderIR> arguments) { mFrontEnd.GenerateFunctionCall(shaderFunction, selfOp, arguments, mContext); }
public IShaderIR GetFunctionParameter(ShaderFunction shaderFunction, int paramIndex, IShaderIR argumentOp) { return(mFrontEnd.GetFunctionParameter(shaderFunction, paramIndex, argumentOp, mContext)); }
//---------------------------------------------------------------Functions public bool AddFunction(FunctionKey key, ShaderFunction shaderFunction) { return(mFunctionMap.TryAdd(key, shaderFunction)); }
public static string GenerateEntryPointFunctionName(FrontEndTranslator translator, ShaderType shaderType, ShaderFunction shaderFunction) { if (shaderFunction == null) { return("EntryPoint"); } return(shaderFunction.mMeta.mName + "_EntryPoint"); }
public static void AddExecutionMode(FrontEndTranslator translator, ShaderEntryPointInfo entryPointInfo, ShaderFunction entryPointFn, Spv.ExecutionMode executionMode) { var library = translator.mCurrentLibrary; var executionModeLiteral = translator.CreateConstantLiteral(library.FindType(new TypeKey(typeof(int))), ((int)executionMode).ToString()); var executionModeOp = translator.CreateOp(OpInstructionType.OpExecutionMode, null, new List <IShaderIR> { entryPointFn, executionModeLiteral }); entryPointInfo.mExecutionModesBlock.mOps.Add(executionModeOp); }
public override void Visit(ShaderFunction shaderFunction) { GetId(shaderFunction); base.Visit(shaderFunction); }
public static ShaderEntryPointInfo Generate(FrontEndTranslator translator, ShaderType shaderType, ShaderFunction function) { if (shaderType.mFragmentType == FragmentType.Vertex) { return(GenerateVertex(translator, shaderType, function)); } else if (shaderType.mFragmentType == FragmentType.Pixel) { return(GeneratePixel(translator, shaderType, function)); } return(null); }