ShaderType CreateIntType(FrontEndTranslator translator, Type type, uint width, uint signedness) { var floatType = translator.CreatePrimitive(type, OpType.Int); floatType.mParameters.Add(translator.CreateConstantLiteral(width)); floatType.mParameters.Add(translator.CreateConstantLiteral(signedness)); return(floatType); }
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 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 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 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 ShaderType ProcessIntegerType(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, AttributeData attribute) { var width = (UInt32)attribute.ConstructorArguments[0].Value; var signed = (bool)attribute.ConstructorArguments[1].Value; var shaderType = translator.CreateType(typeSymbol, OpType.Int); shaderType.mParameters.Add(translator.CreateConstantLiteral(width)); var signedness = translator.CreateConstantLiteral <uint>(signed ? 1u : 0u); shaderType.mParameters.Add(signedness); return(shaderType); }
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 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 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 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); }
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 ShaderType ProcessVectorType(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, AttributeData attribute) { var componentType = translator.FindType(new TypeKey(attribute.ConstructorArguments[0].Value as ISymbol)); var componentCount = (UInt32)attribute.ConstructorArguments[1].Value; var shaderType = translator.CreateType(typeSymbol, OpType.Vector); shaderType.mParameters.Add(componentType); shaderType.mParameters.Add(translator.CreateConstantLiteral(componentCount)); ProcessVectorDefaultConstructor(translator, typeSymbol, shaderType); return(shaderType); }
/// <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); }
public void GenerateLoopHeaderBlock(ShaderBlock headerBlock, ShaderBlock branchTarget, ShaderBlock mergeBlock, ShaderBlock continueBlock, FrontEndContext context) { // Mark the header block as a loop block (so we emit the LoopMerge instruction) headerBlock.mBlockType = BlockType.Loop; // Being a LoopMerge requires setting the merge and continue points headerBlock.mMergePoint = mergeBlock; headerBlock.mContinuePoint = continueBlock; var loopControlMask = mFrontEnd.CreateConstantLiteral <uint>((uint)Spv.LoopControlMask.LoopControlMaskNone); mFrontEnd.CreateOp(headerBlock, OpInstructionType.OpLoopMerge, null, new List <IShaderIR> { mergeBlock, continueBlock, loopControlMask }); // The header always jumps to the branch target (typically a continue) mFrontEnd.CreateOp(headerBlock, OpInstructionType.OpBranch, null, new List <IShaderIR> { branchTarget }); }
public static ShaderType ProcessMatrixType(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, AttributeData attribute) { ShaderType columnType = null; UInt32 columnCount = 0; if (!ValidateMatrixPrimitive(translator, typeSymbol, attribute, out columnType, out columnCount)) { return(null); } var shaderType = translator.CreateType(typeSymbol, OpType.Matrix); shaderType.mParameters.Add(columnType); shaderType.mParameters.Add(translator.CreateConstantLiteral(columnCount)); RegisterMatrixConstructors(translator, typeSymbol, shaderType, columnType, columnCount); return(shaderType); }
public static void ResolveVectorSwizzleSetter(FrontEndTranslator translator, FrontEndContext context, AttributeData attribute, ISymbol returnType, IShaderIR selfInstance, IShaderIR rhsIR) { var swizzleElements = attribute.ConstructorArguments[0].Values; var selfValue = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, selfInstance); var selfValueType = selfValue.mResultType.GetDereferenceType(); var componentCount = (UInt32)(selfValueType.mParameters[1] as ShaderConstantLiteral).mValue; var rhs = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, rhsIR); // If we're setting just a single element, then do an access chain and to set that element if (swizzleElements.Length == 1) { // Find what element we're setting var constantLiteral = translator.CreateConstantLiteral((UInt32)swizzleElements[0].Value); var memberIndexConstant = translator.CreateConstantOp(translator.FindType(typeof(uint)), constantLiteral); // Lookup the result type var resultType = translator.mCurrentLibrary.FindType(new TypeKey(returnType)); resultType = resultType.FindPointerType(selfValue.mResultType.mStorageClass); // Build the access chain to the element var memberVariableOp = translator.CreateOp(context.mCurrentBlock, OpInstructionType.OpAccessChain, resultType, new List <IShaderIR> { selfInstance, memberIndexConstant }); // Then set this back to the lhs side translator.CreateStoreOp(context.mCurrentBlock, memberVariableOp, rhs); } // Otherwise construct a new vector and set it over else { var swizzleArgs = new List <IShaderIR>() { selfValue, rhs }; // Build up a set of what element indices were in the swizzle var elementSet = new HashSet <UInt32>(); foreach (var element in swizzleElements) { elementSet.Add((UInt32)element.Value); } // Foreach element in the new vector, choose if we take it from the rhs or the lhs. If the element index is in the swizzle ops, // then take the next element from rhs, otherwise take the same index from lhs. var rhsElementIndex = 0u; for (uint element = 0; element < componentCount; ++element) { if (elementSet.Contains(element)) { swizzleArgs.Add(translator.CreateConstantLiteral(componentCount + rhsElementIndex)); ++rhsElementIndex; } else { swizzleArgs.Add(translator.CreateConstantLiteral(element)); } } // To build the setter, first create the new vector from components in the lhs/rhs as appropriate. var op = translator.CreateOp(context.mCurrentBlock, OpInstructionType.OpVectorShuffle, selfValueType, swizzleArgs); // Then set this back to the lhs side translator.CreateStoreOp(context.mCurrentBlock, selfInstance, op); } }
public static ShaderType ProcessImageType(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, AttributeData attribute) { ShaderType sampledType = null; Shader.ImageDimension dimension = Shader.ImageDimension.Dim2D; Shader.ImageDepthMode depthMode = Shader.ImageDepthMode.None; Shader.ImageArrayedMode arrayedMode = Shader.ImageArrayedMode.None; Shader.ImageMultiSampledMode multiSampledMode = Shader.ImageMultiSampledMode.SingleSampled; Shader.ImageSampledMode sampledMode = Shader.ImageSampledMode.Sampling; Shader.ImageFormat imageFormat = Shader.ImageFormat.Unknown; // Load all constructor args by type. foreach (var argument in attribute.ConstructorArguments) { var argName = TypeAliases.GetTypeName(argument.Type); if (argName == TypeAliases.GetTypeName <Type>()) { sampledType = translator.FindType(new TypeKey(argument.Value as ITypeSymbol)); } else if (argName == TypeAliases.GetTypeName <Shader.ImageDimension>()) { dimension = (Shader.ImageDimension)argument.Value; } else if (argName == TypeAliases.GetTypeName <Shader.ImageDepthMode>()) { depthMode = (Shader.ImageDepthMode)argument.Value; } else if (argName == TypeAliases.GetTypeName <Shader.ImageArrayedMode>()) { arrayedMode = (Shader.ImageArrayedMode)argument.Value; } else if (argName == TypeAliases.GetTypeName <Shader.ImageMultiSampledMode>()) { multiSampledMode = (Shader.ImageMultiSampledMode)argument.Value; } else if (argName == TypeAliases.GetTypeName <Shader.ImageSampledMode>()) { sampledMode = (Shader.ImageSampledMode)argument.Value; } else if (argName == TypeAliases.GetTypeName <Shader.ImageFormat>()) { imageFormat = (Shader.ImageFormat)argument.Value; } } // Handle named arguments foreach (var pair in attribute.NamedArguments) { if (pair.Key == "SampledType") { sampledType = translator.FindType(new TypeKey(pair.Value.Value as ITypeSymbol)); } else if (pair.Key == "Dimension") { dimension = (Shader.ImageDimension)pair.Value.Value; } else if (pair.Key == "DepthMode") { depthMode = (Shader.ImageDepthMode)pair.Value.Value; } else if (pair.Key == "ArrayedMode") { arrayedMode = (Shader.ImageArrayedMode)pair.Value.Value; } else if (pair.Key == "MultiSampledMode") { multiSampledMode = (Shader.ImageMultiSampledMode)pair.Value.Value; } else if (pair.Key == "SampledMode") { sampledMode = (Shader.ImageSampledMode)pair.Value.Value; } else if (pair.Key == "ImageFormat") { imageFormat = (Shader.ImageFormat)pair.Value.Value; } } // Validate input type. SpirV spec says: "Sampled Type is the type of the components that result // from sampling or reading from this image type. Must be ascalar numerical type or OpTypeVoid" if (sampledType == null || (sampledType.mBaseType != OpType.Bool && sampledType.mBaseType != OpType.Int && sampledType.mBaseType != OpType.Float && sampledType.mBaseType != OpType.Void)) { throw new Exception(); } var shaderType = translator.CreateType(typeSymbol, OpType.Image); shaderType.mParameters.Add(sampledType); shaderType.mParameters.Add(translator.CreateConstantLiteral((UInt32)dimension)); shaderType.mParameters.Add(translator.CreateConstantLiteral((UInt32)depthMode)); shaderType.mParameters.Add(translator.CreateConstantLiteral((UInt32)arrayedMode)); shaderType.mParameters.Add(translator.CreateConstantLiteral((UInt32)multiSampledMode)); shaderType.mParameters.Add(translator.CreateConstantLiteral((UInt32)sampledMode)); shaderType.mParameters.Add(translator.CreateConstantLiteral((UInt32)imageFormat)); shaderType.mStorageClass = StorageClass.UniformConstant; return(shaderType); }