示例#1
0
        public ShaderFunction CreateFunction(FunctionKey key)
        {
            ShaderFunction shaderFunction = new ShaderFunction();

            mFunctionMap.Add(key, shaderFunction);
            return(shaderFunction);
        }
示例#2
0
        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);
        }
示例#3
0
        public IShaderIR GetFunctionParameter(ShaderFunction shaderFunction, int paramIndex, CSharpSyntaxNode argument)
        {
            // Evaluate the expression
            var argumentOp = WalkAndGetResult(argument);

            return(GetFunctionParameter(shaderFunction, paramIndex, argumentOp));
        }
示例#4
0
 public void Visit(ShaderFunction function)
 {
     mReferencedFunctions.Add(function);
     Visit(function.mResultType);
     Visit(function.mParametersBlock);
     Visit(function.mBlocks);
 }
示例#5
0
 public virtual void Visit(ShaderFunction shaderFunction)
 {
     Visit(shaderFunction.mParametersBlock);
     foreach (var block in shaderFunction.mBlocks)
     {
         Visit(block);
     }
 }
示例#6
0
 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;
        }
示例#9
0
 void GenerateIds(ShaderFunction function)
 {
     GenerateIds(function.mResultType);
     GetId(function);
     GenerateIds(function.mParametersBlock);
     foreach (var block in function.mBlocks)
     {
         GenerateIds(block);
     }
 }
示例#10
0
        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;
                    }
                }
            }
        }
示例#11
0
        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);
        }
示例#12
0
        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);
        }
示例#13
0
        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);
        }
示例#14
0
        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);
        }
示例#15
0
        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);
        }
示例#16
0
 public void GenerateFunctionCall(ShaderFunction shaderFunction, IShaderIR selfOp, List <IShaderIR> arguments)
 {
     mFrontEnd.GenerateFunctionCall(shaderFunction, selfOp, arguments, mContext);
 }
示例#17
0
 public IShaderIR GetFunctionParameter(ShaderFunction shaderFunction, int paramIndex, IShaderIR argumentOp)
 {
     return(mFrontEnd.GetFunctionParameter(shaderFunction, paramIndex, argumentOp, mContext));
 }
示例#18
0
 //---------------------------------------------------------------Functions
 public bool AddFunction(FunctionKey key, ShaderFunction shaderFunction)
 {
     return(mFunctionMap.TryAdd(key, shaderFunction));
 }
示例#19
0
 public static string GenerateEntryPointFunctionName(FrontEndTranslator translator, ShaderType shaderType, ShaderFunction shaderFunction)
 {
     if (shaderFunction == null)
     {
         return("EntryPoint");
     }
     return(shaderFunction.mMeta.mName + "_EntryPoint");
 }
示例#20
0
        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);
        }
示例#21
0
 public override void Visit(ShaderFunction shaderFunction)
 {
     GetId(shaderFunction);
     base.Visit(shaderFunction);
 }
示例#22
0
 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);
 }