public static void AddGlobalVariables(FrontEndTranslator translator, ShaderEntryPointInfo entryPoint, EntryPointInterfaceInfo interfaceInfo) { foreach (var globalShaderField in interfaceInfo.GlobalFields) { entryPoint.mGlobalVariablesBlock.mLocalVariables.Add(globalShaderField.InstanceOp); } }
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); }
public static ShaderType ProcessSamplerType(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, AttributeData attribute) { var shaderType = translator.CreateType(typeSymbol, OpType.Sampler); shaderType.mStorageClass = StorageClass.UniformConstant; return(shaderType); }
public static void ConstructShaderType(FrontEndTranslator translator, ShaderType shaderType, FrontEndContext context) { var selfOp = translator.ConstructAndInitializeOpVariable(shaderType, context); selfOp.DebugInfo.Name = "self"; context.mThisOp = selfOp; }
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); }
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])); } } }
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); }
public virtual void Visit(FrontEndTranslator translator, CSharpCompilation compilation, List <SyntaxTree> trees, FrontEndContext context) { mFrontEnd = translator; mContext = context; mContext.mCurrentPass = this; VisitTrees(compilation, trees); }
ShaderType CreateFloatType(FrontEndTranslator translator, Type type, uint width) { var floatType = translator.CreatePrimitive(type, OpType.Float); floatType.mParameters.Add(translator.CreateConstantLiteral(width)); return(floatType); }
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); } } }
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); }); }
public ShaderOp GetFieldInstance(FrontEndTranslator translator, ShaderInterfaceField interfaceField, FrontEndContext context) { if (interfaceField.GetInstance == null) { return(null); } return(interfaceField.GetInstance(translator, interfaceField, context)); }
public static string GenerateEntryPointFunctionName(FrontEndTranslator translator, ShaderType shaderType, ShaderFunction shaderFunction) { if (shaderFunction == null) { return("EntryPoint"); } return(shaderFunction.mMeta.mName + "_EntryPoint"); }
public ShaderOp GetOwnerInstance(FrontEndTranslator translator, ShaderOp ownerOp, FrontEndContext context) { if (GetOwnerDelegate == null) { return(ownerOp); } return(GetOwnerDelegate(translator, this, ownerOp, context)); }
/// <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); }
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 }); }
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); }
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 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 }); }
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 }); }
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 }); }
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 }); }
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); }
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); }
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 })); }); }
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 })); }); }
/// <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); }