예제 #1
0
 public static void AddGlobalVariables(FrontEndTranslator translator, ShaderEntryPointInfo entryPoint, EntryPointInterfaceInfo interfaceInfo)
 {
     foreach (var globalShaderField in interfaceInfo.GlobalFields)
     {
         entryPoint.mGlobalVariablesBlock.mLocalVariables.Add(globalShaderField.InstanceOp);
     }
 }
예제 #2
0
        public static void ResolveVectorSwizzleGetter(FrontEndTranslator translator, FrontEndContext context, AttributeData attribute, ISymbol returnType, List <IShaderIR> arguments)
        {
            var swizzleElements = attribute.ConstructorArguments[0].Values;
            var self            = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, arguments[0]);
            var resultType      = translator.mCurrentLibrary.FindType(new TypeKey(returnType));

            // By default, assume the swizzle is 1 element (just a composite extract)
            var swizzleArgs = new List <IShaderIR>()
            {
                self
            };
            var opType = OpInstructionType.OpCompositeExtract;

            // If it's multiple elements, change this to a vector shuffle
            if (swizzleElements.Length != 1)
            {
                swizzleArgs.Add(self);
                opType = OpInstructionType.OpVectorShuffle;
            }
            // Add all elements to grab for the swizzle from the attribute
            foreach (var element in swizzleElements)
            {
                swizzleArgs.Add(translator.CreateConstantLiteral((UInt32)element.Value));
            }

            var op = translator.CreateOp(context.mCurrentBlock, opType, resultType, swizzleArgs);

            context.Push(op);
        }
예제 #3
0
        public static ShaderType ProcessSamplerType(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, AttributeData attribute)
        {
            var shaderType = translator.CreateType(typeSymbol, OpType.Sampler);

            shaderType.mStorageClass = StorageClass.UniformConstant;
            return(shaderType);
        }
예제 #4
0
        public static void ConstructShaderType(FrontEndTranslator translator, ShaderType shaderType, FrontEndContext context)
        {
            var selfOp = translator.ConstructAndInitializeOpVariable(shaderType, context);

            selfOp.DebugInfo.Name = "self";
            context.mThisOp       = selfOp;
        }
예제 #5
0
        static void ProcessCompositeConstructIntrinsic(FrontEndTranslator translator, ShaderType returnType, List <IShaderIR> arguments, FrontEndContext context)
        {
            // Extract how many elements this composite is made up of
            var compositeCountLiteral = returnType.mParameters[1] as ShaderConstantLiteral;
            var compositeCount        = (uint)compositeCountLiteral.mValue;

            var valueOps = new List <IShaderIR>();

            // If this is a splat constructor (only 1 arg) then splat the argument for each composite element
            if (arguments.Count == 1)
            {
                var splatArgument = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, arguments[0]);
                for (uint i = 0; i < compositeCount; ++i)
                {
                    valueOps.Add(splatArgument);
                }
            }
            // Otherwise, just copy all args over (@JoshD: Needs validation)
            else
            {
                foreach (var argument in arguments)
                {
                    valueOps.Add(translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, argument));
                }
            }
            var op = translator.CreateOp(context.mCurrentBlock, OpInstructionType.OpCompositeConstruct, returnType, valueOps);

            context.Push(op);
        }
예제 #6
0
        public static ShaderOp GenerateInterfaceStructAndOp(FrontEndTranslator translator, List <ShaderInterfaceField> interfaceFields, TypeName structName, string instanceName, StorageClass storageClass)
        {
            var interfaceStruct = translator.FindType(new TypeKey(structName));

            // Generate the interface struct if it doesn't already exist (uniform buffers already exist)
            if (interfaceStruct == null)
            {
                interfaceStruct = translator.CreateType(new TypeKey(structName), structName, OpType.Struct, null);
                foreach (var interfaceField in interfaceFields)
                {
                    interfaceStruct.mFields.Add(interfaceField.ShaderField);
                }
            }

            var opPointerType = translator.FindOrCreatePointerType(new TypeKey(structName), structName, storageClass);
            var op            = translator.CreateOp(OpInstructionType.OpVariable, opPointerType, null);

            ShaderInterfaceField.InstanceAccessDelegate fieldInstanceGetFunction = (FrontEndTranslator translator, ShaderInterfaceField interfaceField, FrontEndContext context) =>
            {
                return(translator.GenerateAccessChain(op, interfaceField.ShaderField.mMeta.mName, context));
            };

            foreach (var interfaceField in interfaceFields)
            {
                interfaceField.GetInstance = fieldInstanceGetFunction;
            }

            op.DebugInfo.Name = instanceName;
            return(op);
        }
        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);
        }
 static void WriteArguments(FrontEndTranslator translator, FrontEndContext context, List <IShaderIR> valueOps, ImageIntrinsicAttributeData intrinsicData, List <IShaderIR> arguments, int startIndex)
 {
     // If there's no operands location, then just write the arguments as is. It's only if there's a mask and location that we write this (since not all image ops have a mask).
     if (intrinsicData.OperandsLocation == -1)
     {
         for (var i = startIndex; i < arguments.Count; ++i)
         {
             valueOps.Add(translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, arguments[i]));
         }
     }
     // Otherwise, add all of the given arguments, but put the operands mask in-between based upon the specified location.
     // This location isn't consistent for all image functions so it became an exposed value.
     else
     {
         for (var i = startIndex; i < intrinsicData.OperandsLocation && i < arguments.Count; ++i)
         {
             valueOps.Add(translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, arguments[i]));
         }
         valueOps.Add(translator.CreateConstantLiteral((UInt32)intrinsicData.Operands));
         for (var i = intrinsicData.OperandsLocation; i < arguments.Count; ++i)
         {
             valueOps.Add(translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, arguments[i]));
         }
     }
 }
예제 #9
0
        public CoreShaderLibrary(FrontEndTranslator translator)
        {
            translator.mCurrentLibrary = this;

            // Create core primitive times first
            translator.CreatePrimitive(typeof(void), OpType.Void);
            translator.CreatePrimitive(typeof(bool), OpType.Bool);
            // Unsigned int must be first
            CreateIntType(translator, typeof(uint), 32, 0);
            CreateIntType(translator, typeof(int), 32, 1);
            var floatType = CreateFloatType(translator, typeof(float), 32);

            // @JoshD: Double requires special capabilities, re-add later.
            //CreateFloatType(frontEnd, typeof(double), 64);

            // Add some custom intrinsics for built-int types that
            AddPrimitiveIntrinsics(translator);
            AddPrimitiveOps(translator);
            AddCastIntrinsics(translator);

            // Compile the custom data types and functions we're adding
            // @JoshD: Fix path lookup
            var path       = Path.Combine("..", "Shader");
            var extensions = new HashSet <string> {
                ".cs"
            };
            var project = new ShaderProject();

            project.LoadProjectDirectory(path, extensions);
            var trees = new List <SyntaxTree>();

            SourceCompilation = project.Compile("Core", null, translator, out trees);
            project.Translate(SourceCompilation, trees, null, translator, this);
        }
예제 #10
0
 public virtual void Visit(FrontEndTranslator translator, CSharpCompilation compilation, List <SyntaxTree> trees, FrontEndContext context)
 {
     mFrontEnd             = translator;
     mContext              = context;
     mContext.mCurrentPass = this;
     VisitTrees(compilation, trees);
 }
예제 #11
0
        ShaderType CreateFloatType(FrontEndTranslator translator, Type type, uint width)
        {
            var floatType = translator.CreatePrimitive(type, OpType.Float);

            floatType.mParameters.Add(translator.CreateConstantLiteral(width));
            return(floatType);
        }
예제 #12
0
 public static void ProcessVectorSwizzle(FrontEndTranslator frontEnd, INamedTypeSymbol typeSymbol, ISymbol memberSymbol, AttributeData attribute)
 {
     if (memberSymbol is IFieldSymbol fieldSymbol)
     {
         ShaderLibrary.InstrinsicDelegate getterResolver = (FrontEndTranslator translator, List <IShaderIR> arguments, FrontEndContext context) =>
         {
             ResolveVectorSwizzleGetter(translator, context, attribute, fieldSymbol.Type, arguments);
         };
         ShaderLibrary.InstrinsicSetterDelegate setterResolver = (FrontEndTranslator translator, IShaderIR selfInstance, IShaderIR rhsIR, FrontEndContext context) =>
         {
             ResolveVectorSwizzleSetter(translator, context, attribute, fieldSymbol.Type, selfInstance, rhsIR);
         };
         frontEnd.mCurrentLibrary.CreateIntrinsicFunction(new FunctionKey(memberSymbol), getterResolver);
         frontEnd.mCurrentLibrary.CreateIntrinsicSetterFunction(new FunctionKey(fieldSymbol), setterResolver);
     }
     if (memberSymbol is IPropertySymbol propertySymbol)
     {
         ShaderLibrary.InstrinsicDelegate getterResolver = (FrontEndTranslator translator, List <IShaderIR> arguments, FrontEndContext context) =>
         {
             ResolveVectorSwizzleGetter(translator, context, attribute, propertySymbol.Type, arguments);
         };
         ShaderLibrary.InstrinsicSetterDelegate setterResolver = (FrontEndTranslator translator, IShaderIR selfInstance, IShaderIR rhsIR, FrontEndContext context) =>
         {
             ResolveVectorSwizzleSetter(translator, context, attribute, propertySymbol.Type, selfInstance, rhsIR);
         };
         if (propertySymbol.GetMethod != null)
         {
             frontEnd.mCurrentLibrary.CreateIntrinsicFunction(new FunctionKey(propertySymbol.GetMethod), getterResolver);
         }
         if (propertySymbol.SetMethod != null)
         {
             frontEnd.mCurrentLibrary.CreateIntrinsicSetterFunction(new FunctionKey(propertySymbol.SetMethod), setterResolver);
         }
     }
 }
예제 #13
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);
     });
 }
예제 #14
0
 public ShaderOp GetFieldInstance(FrontEndTranslator translator, ShaderInterfaceField interfaceField, FrontEndContext context)
 {
     if (interfaceField.GetInstance == null)
     {
         return(null);
     }
     return(interfaceField.GetInstance(translator, interfaceField, context));
 }
예제 #15
0
 public static string GenerateEntryPointFunctionName(FrontEndTranslator translator, ShaderType shaderType, ShaderFunction shaderFunction)
 {
     if (shaderFunction == null)
     {
         return("EntryPoint");
     }
     return(shaderFunction.mMeta.mName + "_EntryPoint");
 }
예제 #16
0
 public ShaderOp GetOwnerInstance(FrontEndTranslator translator, ShaderOp ownerOp, FrontEndContext context)
 {
     if (GetOwnerDelegate == null)
     {
         return(ownerOp);
     }
     return(GetOwnerDelegate(translator, this, ownerOp, context));
 }
예제 #17
0
 /// <summary>
 /// Creates a simple intrinsic function (one whos ops are just value types of the args one-for-one) callback for the given symbol information.
 /// </summary>
 static public void CreateSimpleIntrinsicFunction(FrontEndTranslator translator, FunctionKey functionKey, OpInstructionType opType, ShaderType returnType)
 {
     ShaderLibrary.InstrinsicDelegate callback = (FrontEndTranslator translator, List <IShaderIR> arguments, FrontEndContext context) =>
     {
         SimpleValueTypeIntrinsic(translator, context, opType, returnType, arguments);
     };
     translator.mCurrentLibrary.CreateIntrinsicFunction(functionKey, callback);
 }
        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);
        }
예제 #19
0
        public static void AddDecorationBlock(FrontEndTranslator translator, ShaderType shaderType, ShaderBlock decorationsBlock)
        {
            var decorationBlockLiteral = translator.CreateConstantLiteral((int)Spv.Decoration.DecorationBlock);

            translator.CreateOp(decorationsBlock, OpInstructionType.OpDecorate, null, new List <IShaderIR>()
            {
                shaderType, decorationBlockLiteral
            });
        }
예제 #20
0
        public static void DecorateUniforms(FrontEndTranslator translator, ShaderOp instanceOp, ShaderBlock decorationsBlock)
        {
            var instanceType = instanceOp.mResultType.GetDereferenceType();

            AddDecorationDescriptorSet(translator, instanceType, 0, decorationsBlock);
            AddDecorationBinding(translator, instanceType, 0, decorationsBlock);
            AddDecorationBlock(translator, instanceType, decorationsBlock);
            DecorateOffsets(translator, instanceType, decorationsBlock);
        }
예제 #21
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);
        }
예제 #22
0
        public static void AddDecorationLocation(FrontEndTranslator translator, ShaderOp instanceOp, int location, ShaderBlock decorationsBlock)
        {
            var decorationLocationLiteral = translator.CreateConstantLiteral((int)Spv.Decoration.DecorationLocation);
            var locationLiteral           = translator.CreateConstantLiteral(location);

            translator.CreateOp(decorationsBlock, OpInstructionType.OpDecorate, null, new List <IShaderIR>()
            {
                instanceOp, decorationLocationLiteral, locationLiteral
            });
        }
예제 #23
0
        public static void AddDecorationBuiltIn(FrontEndTranslator translator, ShaderOp instanceOp, Spv.BuiltIn builtInType, ShaderBlock decorationsBlock)
        {
            var decorationBuiltInLiteral = translator.CreateConstantLiteral((int)Spv.Decoration.DecorationBuiltIn);
            var builtInTypeLiteral       = translator.CreateConstantLiteral((int)builtInType);

            translator.CreateOp(decorationsBlock, OpInstructionType.OpDecorate, null, new List <IShaderIR>()
            {
                instanceOp, decorationBuiltInLiteral, builtInTypeLiteral
            });
        }
예제 #24
0
        public static void AddDecorationDescriptorSet(FrontEndTranslator translator, IShaderIR ir, int descriptorSetId, ShaderBlock decorationsBlock)
        {
            var decorationBindingLiteral = translator.CreateConstantLiteral((int)Spv.Decoration.DecorationDescriptorSet);
            var descriptorSetIdLiteral   = translator.CreateConstantLiteral(descriptorSetId);

            translator.CreateOp(decorationsBlock, OpInstructionType.OpDecorate, null, new List <IShaderIR>()
            {
                ir, decorationBindingLiteral, descriptorSetIdLiteral
            });
        }
예제 #25
0
        public static void AddDecorationMemberMatrixMajor(FrontEndTranslator translator, ShaderType shaderType, int fieldIndex, Spv.Decoration decoration, ShaderBlock decorationsBlock)
        {
            var decorationOffsetLiteral = translator.CreateConstantLiteral((int)decoration);
            var fieldIndexLiteral       = translator.CreateConstantLiteral(fieldIndex);

            translator.CreateOp(decorationsBlock, OpInstructionType.OpMemberDecorate, null, new List <IShaderIR>()
            {
                shaderType, fieldIndexLiteral, decorationOffsetLiteral
            });
        }
예제 #26
0
        public static ShaderType ProcessFloatType(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, AttributeData attribute)
        {
            var width = (UInt32)attribute.ConstructorArguments[0].Value;

            var shaderType = translator.CreateType(typeSymbol, OpType.Float);

            shaderType.mParameters.Add(translator.CreateConstantLiteral(width));

            return(shaderType);
        }
예제 #27
0
        static public void CreateCompositeConstructIntrinsic(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, IMethodSymbol methodSymbol, AttributeData attribute)
        {
            var shaderReturnType = translator.FindType(new TypeKey(typeSymbol));

            ShaderLibrary.InstrinsicDelegate callback = (FrontEndTranslator translator, List <IShaderIR> arguments, FrontEndContext context) =>
            {
                ProcessCompositeConstructIntrinsic(translator, shaderReturnType, arguments, context);
            };
            translator.mCurrentLibrary.CreateIntrinsicFunction(new FunctionKey(methodSymbol), callback);
        }
예제 #28
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
         }));
     });
 }
예제 #29
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
         }));
     });
 }
예제 #30
0
        /// <summary>
        /// Creates a simple intrinsic type (one whos ops are just value types of the args one-for-one) callback for the given symbol information from the provided attribute.
        /// </summary>
        static public void CreateSimpleIntrinsicType(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, IMethodSymbol methodSymbol, AttributeData attribute)
        {
            var opTypeStr        = attribute.ConstructorArguments[0].Value.ToString();
            var opType           = (OpInstructionType)Enum.Parse(typeof(OpInstructionType), opTypeStr, true);
            var shaderReturnType = translator.FindType(new TypeKey(methodSymbol.ReturnType));

            ShaderLibrary.InstrinsicDelegate callback = (FrontEndTranslator translator, List <IShaderIR> arguments, FrontEndContext context) =>
            {
                SimpleValueTypeIntrinsic(translator, context, opType, shaderReturnType, arguments);
            };
            translator.mCurrentLibrary.CreateIntrinsicFunction(new FunctionKey(methodSymbol), callback);
        }