Exemple #1
0
 public ShaderOp CastUIntToInt(ShaderType resultType, IShaderIR expressionOp, FrontEndContext context)
 {
     return(SimpleCast(resultType, OpInstructionType.OpBitcast, expressionOp, context));
 }
        static void SplitSampledImageValueTypeIntrinsic(FrontEndTranslator translator, FrontEndContext context, ImageIntrinsicAttributeData intrinsicData, ShaderType returnType, List <IShaderIR> arguments)
        {
            var valueOps = new List <IShaderIR>();

            var imageParam   = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, arguments[0]);
            var samplerParam = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, arguments[1]);

            // Try and generate a sampled image type for this image. If we do create a new type that wasn't necessary that's fine because it'll be de-duped in the binary backend.
            var sampledImageTypeStr = new TypeName {
                Name = "GeneratedSampledImage_" + imageParam.mResultType.ToString()
            };
            var sampledImageType = translator.FindType(new TypeKey(sampledImageTypeStr));

            if (sampledImageType == null)
            {
                sampledImageType = translator.CreateType(new TypeKey(sampledImageTypeStr), sampledImageTypeStr, OpType.SampledImage, null);
                sampledImageType.mParameters.Add(imageParam.mResultType.GetDereferenceType());
            }

            // Combine the image and sampler together into a sampled image. This is a bit annoying, but a sampled image
            // can't be stored into a variable so this has to be a temporary. Use this combined sampled image in place of the first two args to the intrinsics.
            var sampledImageOp = translator.CreateOp(context.mCurrentBlock, OpInstructionType.OpSampledImage, sampledImageType, new List <IShaderIR>()
            {
                imageParam, samplerParam
            });

            valueOps.Add(sampledImageOp);
            WriteArguments(translator, context, valueOps, intrinsicData, arguments, 2);
            var op = translator.CreateOp(context.mCurrentBlock, intrinsicData.OpType, returnType, valueOps);

            context.Push(op);
        }
Exemple #3
0
        public static ShaderFunction GenerateFunction_ShaderTypeParam(FrontEndTranslator translator, ShaderType shaderType, string functionName, out ShaderOp thisOp)
        {
            var library     = translator.mCurrentLibrary;
            var voidType    = library.FindType(new TypeKey(typeof(void)));
            var thisType    = shaderType.FindPointerType(StorageClass.Function);
            var fnArgsTypes = new List <ShaderType>()
            {
                thisType
            };

            var function = translator.CreateFunctionAndType(shaderType, voidType, functionName, null, fnArgsTypes);

            thisOp = translator.CreateOp(function.mParametersBlock, OpInstructionType.OpFunctionParameter, thisType, null);
            thisOp.DebugInfo.Name = "self";
            function.mBlocks.Add(new ShaderBlock());
            return(function);
        }
Exemple #4
0
 public static void ProcessVectorDefaultConstructor(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, ShaderType shaderType)
 {
     ShaderLibrary.InstrinsicDelegate defaultConstructorResolver = (FrontEndTranslator translator, List <IShaderIR> arguments, FrontEndContext context) =>
     {
         ResolveVectorDefaultConstructor(translator, context, shaderType);
     };
     foreach (var constructor in typeSymbol.Constructors)
     {
         if (constructor.Parameters.Length == 0 && constructor.IsImplicitlyDeclared)
         {
             translator.mCurrentLibrary.CreateIntrinsicFunction(new FunctionKey(constructor), defaultConstructorResolver);
         }
     }
 }
Exemple #5
0
 public override void Visit(ShaderType shaderType)
 {
     GetId(shaderType);
     base.Visit(shaderType);
 }
Exemple #6
0
 void AddSimpleValueTypeUnaryOp(FrontEndTranslator translator, ShaderType resultType, string opToken, ShaderType operandType, OpInstructionType instructionType)
 {
     CreateUnaryOpIntrinsic(new UnaryOpKey(opToken, operandType), (IShaderIR operandIR, FrontEndContext context) =>
     {
         var operandValueOp = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, operandIR);
         return(translator.CreateOp(context.mCurrentBlock, instructionType, resultType, new List <IShaderIR> {
             operandValueOp
         }));
     });
 }
Exemple #7
0
 void LogicOrAndOp(FrontEndTranslator translator, ShaderType resultType, ShaderType lhsType, string opToken, ShaderType rhsType, OpInstructionType instructionType, bool isOr)
 {
     CreateComplexBinaryOpIntrinsic(new BinaryOpKey(lhsType, opToken, rhsType), (SyntaxNode lhsExpression, SyntaxNode rhsExpression, FrontEndContext context) =>
     {
         LogicalOrAnd(lhsExpression, rhsExpression, context, isOr);
         return(context.Pop() as ShaderOp);
     });
 }
Exemple #8
0
 public ConstantOpKey(ShaderType shaderType, object value)
 {
     mType  = shaderType;
     mValue = value;
     Validate();
 }
Exemple #9
0
 public ConstantOpKey(ShaderConstantLiteral constant)
 {
     mType  = constant.mType;
     mValue = constant.mValue;
     Validate();
 }
Exemple #10
0
        //---------------------------------------------------------------Casting
        public void AddCastIntrinsics(ShaderType castToType, ShaderType castFromType, CastDelegate castDelegate)
        {
            var tuple = new Tuple <ShaderType, ShaderType>(castToType, castFromType);

            CastIntrinsics.Add(tuple, castDelegate);
        }
Exemple #11
0
 //---------------------------------------------------------------Types
 public bool AddType(TypeKey key, ShaderType shaderType)
 {
     return(mTypeMap.TryAdd(key, shaderType));
 }
        static void CombinedSampledImageValueTypeIntrinsic(FrontEndTranslator translator, FrontEndContext context, ImageIntrinsicAttributeData intrinsicData, ShaderType returnType, List <IShaderIR> arguments)
        {
            var valueOps = new List <IShaderIR>();

            var sampledImageParam = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, arguments[0]);
            var sampledImageType  = sampledImageParam.mResultType;
            var imageType         = sampledImageType.mParameters[0] as ShaderType;

            // Pull the image out of the sampled image.
            var imageOp = translator.CreateOp(context.mCurrentBlock, OpInstructionType.OpImage, imageType, new List <IShaderIR>()
            {
                sampledImageParam
            });

            valueOps.Add(imageOp);
            WriteArguments(translator, context, valueOps, intrinsicData, arguments, 1);
            var op = translator.CreateOp(context.mCurrentBlock, intrinsicData.OpType, returnType, valueOps);

            context.Push(op);
        }
Exemple #13
0
 public ShaderOp CastFloatToUInt(ShaderType resultType, IShaderIR expressionOp, FrontEndContext context)
 {
     return(SimpleCast(resultType, OpInstructionType.OpConvertFToU, expressionOp, context));
 }
Exemple #14
0
        public ShaderOp CastFloatToBool(ShaderType resultType, IShaderIR expressionOp, FrontEndContext context)
        {
            var constantOp = CreateConstantOp <float>(0.0f);

            return(SimpleCompareCast(resultType, OpInstructionType.OpFOrdNotEqual, expressionOp, constantOp, context));
        }
        public void CreateDummyEntryPoint(TypeDependencyCollector typeCollector, ShaderLibrary library, FrontEndTranslator frontEnd, ShaderType shaderType)
        {
            var context = new FrontEndContext();

            context.mCurrentType = shaderType;

            if (shaderType.mEntryPoints.Count != 0)
            {
                return;
            }

            ShaderEntryPointInfo entryPoint = null;

            if (shaderType.mFragmentType == FragmentType.Pixel || shaderType.mFragmentType == FragmentType.None)
            {
                entryPoint = EntryPointGeneration.GeneratePixel(frontEnd, shaderType, null);
            }
            else if (shaderType.mFragmentType == FragmentType.Vertex)
            {
                entryPoint = EntryPointGeneration.GenerateVertex(frontEnd, shaderType, null);
            }

            typeCollector.Visit(entryPoint);
        }
Exemple #16
0
 public TypeKey(ShaderType shaderType)
 {
     mKey = shaderType.mMeta.mName;
 }
Exemple #17
0
        /// <summary>
        /// Does a simple extension intrinsic (one where all ops are value types).
        /// </summary>
        static void ResolveSimpleExtensionIntrinsic(FrontEndTranslator translator, FrontEndContext context, string extensionName, int extOpType, ShaderType returnType, List <IShaderIR> arguments)
        {
            var extensionImportOp = translator.mCurrentLibrary.GetOrCreateExtensionLibraryImport(extensionName);
            var extOpTypeOp       = translator.CreateConstantLiteral(extOpType);

            var valueOps = new List <IShaderIR>();

            valueOps.Add(extensionImportOp);
            valueOps.Add(extOpTypeOp);
            foreach (var argument in arguments)
            {
                valueOps.Add(translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, argument));
            }
            var op = translator.CreateOp(context.mCurrentBlock, OpInstructionType.OpExtInst, returnType, valueOps);

            context.Push(op);
        }
Exemple #18
0
 public UnaryOpKey(string opToken, ShaderType operandType)
 {
     OpToken     = opToken;
     OperandType = operandType;
 }
Exemple #19
0
 void AddSimpleValueTypeBinaryOp(FrontEndTranslator translator, ShaderType resultType, ShaderType lhsType, string opToken, ShaderType rhsType, OpInstructionType instructionType)
 {
     CreateBinaryOpIntrinsic(new BinaryOpKey(lhsType, opToken, rhsType), (IShaderIR lhsExpression, IShaderIR rhsExpression, FrontEndContext context) =>
     {
         var lhsValueOp = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, lhsExpression);
         var rhsValueOp = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, rhsExpression);
         return(translator.CreateOp(context.mCurrentBlock, instructionType, resultType, new List <IShaderIR> {
             lhsValueOp, rhsValueOp
         }));
     });
 }
Exemple #20
0
 public BinaryOpKey(ShaderType leftType, string opToken, ShaderType rightType)
 {
     LeftType  = leftType;
     OpToken   = opToken;
     RightType = rightType;
 }
Exemple #21
0
 void IncDecOp(FrontEndTranslator translator, ShaderType resultType, string opToken, ShaderType operandType, OpInstructionType instructionType)
 {
     CreateUnaryOpIntrinsic(new UnaryOpKey(opToken, operandType), (IShaderIR operandIR, FrontEndContext context) =>
     {
         var operandValueOp      = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, operandIR);
         IShaderIR oneConstantOp = null;
         if (resultType.mBaseType == OpType.Int)
         {
             oneConstantOp = translator.CreateConstantOp(operandType, 1);
         }
         else if (resultType.mBaseType == OpType.Float)
         {
             oneConstantOp = translator.CreateConstantOp(operandType, 1.0f);
         }
         return(translator.CreateOp(context.mCurrentBlock, instructionType, resultType, new List <IShaderIR> {
             operandValueOp, oneConstantOp
         }));
     });
 }
        void WriteTypeDeclaration(ShaderType type, HashSet <UInt32> visitedTypeIds)
        {
            // Handle types existing more than once (for primitive deduping)
            var id = GetId(type);

            if (visitedTypeIds.Contains(id))
            {
                return;
            }
            visitedTypeIds.Add(id);

            if (type.mBaseType == OpType.Void)
            {
                mWriter.WriteInstruction(2, Spv.Op.OpTypeVoid, GetId(type));
            }
            else if (type.mBaseType == OpType.Bool)
            {
                mWriter.WriteInstruction(2, Spv.Op.OpTypeBool, GetId(type));
            }
            else if (type.mBaseType == OpType.Int)
            {
                mWriter.WriteInstruction(4, Spv.Op.OpTypeInt, GetId(type));
                WriteArgs(type.mParameters);
            }
            else if (type.mBaseType == OpType.Float)
            {
                mWriter.WriteInstruction(3, Spv.Op.OpTypeFloat, GetId(type));
                WriteArgs(type.mParameters);
            }
            else if (type.mBaseType == OpType.Vector)
            {
                mWriter.WriteInstruction(4, Spv.Op.OpTypeVector, GetId(type));
                WriteArgs(type.mParameters);
            }
            else if (type.mBaseType == OpType.Matrix)
            {
                mWriter.WriteInstruction(4, Spv.Op.OpTypeMatrix, GetId(type));
                WriteArgs(type.mParameters);
            }
            else if (type.mBaseType == OpType.Pointer)
            {
                var dereferenceType = type.GetDereferenceType();
                if (dereferenceType.mBaseType != OpType.Function)
                {
                    var storageClass = ConvertStorageClass(type.mStorageClass);
                    mWriter.WriteInstruction(4, Spv.Op.OpTypePointer, GetId(type), (UInt32)storageClass, GetId(dereferenceType));
                }
            }
            else if (type.mBaseType == OpType.Array)
            {
                mWriter.WriteInstruction(4, Spv.Op.OpTypeArray, GetId(type));
                WriteArgs(type.mParameters);
            }
            else if (type.mBaseType == OpType.Struct)
            {
                UInt16 instructionSize = (UInt16)(2 + type.mFields.Count);
                mWriter.WriteInstruction(instructionSize, Spv.Op.OpTypeStruct, GetId(type));
                foreach (var field in type.mFields)
                {
                    mWriter.Write(GetId(field.mType));
                }
            }
            else if (type.mBaseType == OpType.Sampler)
            {
                UInt16 instructionSize = (UInt16)2;
                mWriter.WriteInstruction(instructionSize, Spv.Op.OpTypeSampler, GetId(type));
            }
            else if (type.mBaseType == OpType.Image)
            {
                UInt16 instructionSize = (UInt16)9;
                mWriter.WriteInstruction(instructionSize, Spv.Op.OpTypeImage, GetId(type));
                WriteArgs(type.mParameters);
            }
            else if (type.mBaseType == OpType.SampledImage)
            {
                UInt16 instructionSize = (UInt16)3;
                mWriter.WriteInstruction(instructionSize, Spv.Op.OpTypeSampledImage, GetId(type));
                WriteArgs(type.mParameters);
            }
            else if (type.mBaseType == OpType.Function)
            {
                var instructionSize = 2 + type.mParameters.Count;
                mWriter.WriteInstruction((UInt16)(instructionSize), Spv.Op.OpTypeFunction, GetId(type));
                WriteArgs(type.mParameters);
            }
            else
            {
                throw new Exception();
            }
        }
Exemple #23
0
        public static void ResolveVectorDefaultConstructor(FrontEndTranslator translator, FrontEndContext context, ShaderType vectorType)
        {
            var componentType  = vectorType.mParameters[0] as ShaderType;
            var componentOp    = vectorType.mParameters[1] as ShaderOp;
            var componentCount = (UInt32)(componentOp.mParameters[0] as ShaderConstantLiteral).mValue;

            var zeroConstantLiteral = translator.CreateConstantLiteralZero(componentType);
            var zeroConstant        = translator.CreateConstantOp(componentType, zeroConstantLiteral);

            var constructorArgs = new List <IShaderIR>();

            for (var i = 0; i < componentCount; ++i)
            {
                constructorArgs.Add(zeroConstant);
            }
            var op = translator.CreateOp(context.mCurrentBlock, OpInstructionType.OpCompositeConstruct, vectorType, constructorArgs);

            context.Push(op);
        }
Exemple #24
0
        public static EntryPointFunction GenerateSpirVEntryPointFunction(FrontEndTranslator translator, ShaderType shaderType, string entryPointFnName)
        {
            EntryPointFunction entryPointFunction = new EntryPointFunction();

            var library  = translator.mCurrentLibrary;
            var voidType = library.FindType(new TypeKey(typeof(void)));

            entryPointFunction.ShaderFunction = translator.CreateFunctionAndType(shaderType, voidType, entryPointFnName, null, null);
            entryPointFunction.ShaderFunction.mBlocks.Add(new ShaderBlock());
            entryPointFunction.Context = new FrontEndContext();
            entryPointFunction.Context.mCurrentType     = shaderType;
            entryPointFunction.Context.mCurrentFunction = entryPointFunction.ShaderFunction;
            entryPointFunction.Context.mCurrentBlock    = entryPointFunction.ShaderFunction.mBlocks[0];

            return(entryPointFunction);
        }
        static void SampledImageValueTypeIntrinsic(FrontEndTranslator translator, FrontEndContext context, ImageIntrinsicAttributeData intrinsicData, ShaderType returnType, List <IShaderIR> arguments)
        {
            var valueOps = new List <IShaderIR>();

            WriteArguments(translator, context, valueOps, intrinsicData, arguments, 0);
            var op = translator.CreateOp(context.mCurrentBlock, intrinsicData.OpType, returnType, valueOps);

            context.Push(op);
        }
Exemple #26
0
        public static void CreateGlobalVariableInitializeFunction(FrontEndTranslator translator, ShaderType shaderType, ShaderEntryPointInfo entryPoint, EntryPointInterfaceInfo interfaceInfo, FrontEndContext context)
        {
            // First check if any global variables that need the variable initialization function exist. If not then don't emit anything.
            bool globalVariablesExist = false;

            foreach (var globalField in interfaceInfo.GlobalFields)
            {
                if (globalField.InitialValue != null)
                {
                    globalVariablesExist = true;
                }
            }
            if (!globalVariablesExist)
            {
                return;
            }

            var library            = translator.mCurrentLibrary;
            var voidType           = library.FindType(new TypeKey(typeof(void)));
            var initGlobalFunction = translator.CreateFunctionAndType(shaderType, voidType, "InitGlobals", null, null);

            initGlobalFunction.mBlocks.Add(new ShaderBlock());
            entryPoint.mGlobalsInitializationFunction = initGlobalFunction;

            // Add the store op for each global variable
            context.mCurrentFunction = initGlobalFunction;
            context.mCurrentBlock    = initGlobalFunction.mBlocks[0];
            foreach (var globalField in interfaceInfo.GlobalFields)
            {
                if (globalField.InitialValue != null)
                {
                    translator.CreateStoreOp(context.mCurrentBlock, globalField.InstanceOp, globalField.InitialValue);
                }
            }
            translator.FixupBlockTerminators(context.mCurrentFunction);
        }
Exemple #27
0
 public static string GenerateEntryPointFunctionName(FrontEndTranslator translator, ShaderType shaderType, ShaderFunction shaderFunction)
 {
     if (shaderFunction == null)
     {
         return("EntryPoint");
     }
     return(shaderFunction.mMeta.mName + "_EntryPoint");
 }
Exemple #28
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);
        }
Exemple #29
0
        public static EntryPointFunction GenerateEntryPointCopyFunction(FrontEndTranslator translator, ShaderType shaderType, string functionName)
        {
            ShaderOp thisOp         = null;
            var      shaderFunction = GenerateFunction_ShaderTypeParam(translator, shaderType, functionName, out thisOp);
            var      context        = new FrontEndContext();

            context.mCurrentBlock    = shaderFunction.mBlocks[0];
            context.mCurrentFunction = shaderFunction;

            var entryPointFunction = new EntryPointFunction();

            entryPointFunction.Context              = context;
            entryPointFunction.ShaderFunction       = shaderFunction;
            entryPointFunction.ShaderTypeInstanceOp = thisOp;
            return(entryPointFunction);
        }
Exemple #30
0
 public ShaderOp CastUnsignedConvert(ShaderType resultType, IShaderIR expressionOp, FrontEndContext context)
 {
     return(SimpleCast(resultType, OpInstructionType.OpUConvert, expressionOp, context));
 }