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 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); }
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); }
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 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 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 }); }
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 })); }); }
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 }); }
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 })); }); }
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); }
/// <summary> /// Does a simple intrinsic (one where all ops are value types). /// </summary> static void SimpleValueTypeIntrinsic(FrontEndTranslator translator, FrontEndContext context, OpInstructionType opType, ShaderType returnType, List <IShaderIR> arguments) { var valueOps = new List <IShaderIR>(); foreach (var argument in arguments) { valueOps.Add(translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, argument)); } var op = translator.CreateOp(context.mCurrentBlock, opType, returnType, valueOps); context.Push(op); }
public static void GenerateInterfaceGlobalFields(FrontEndTranslator translator, List <ShaderInterfaceField> interfaceFields, string structName, string instanceName, StorageClass storageClass) { foreach (var interfaceField in interfaceFields) { var fieldPointerType = translator.FindOrCreatePointerType(interfaceField.ShaderField.mType, storageClass); var fieldOp = translator.CreateOp(OpInstructionType.OpVariable, fieldPointerType, null); ShaderInterfaceField.InstanceAccessDelegate fieldInstanceGetFunction = (FrontEndTranslator translator, ShaderInterfaceField interfaceField, FrontEndContext context) => { return(fieldOp); }; fieldOp.DebugInfo.Name = interfaceField.ShaderField.DebugInfo.Name; interfaceField.GetInstance = fieldInstanceGetFunction; } }
static public void CreateArraySetType(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, IMethodSymbol methodSymbol, AttributeData attribute) { // Do an access chain to get the element and then store the value inside the pointer ShaderLibrary.InstrinsicDelegate callback = (FrontEndTranslator translator, List <IShaderIR> arguments, FrontEndContext context) => { var selfOp = arguments[0]; var indexOp = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, arguments[1]); var valueOp = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, arguments[2]); var pointerType = valueOp.mResultType.FindPointerType(StorageClass.Function); var accessChainOp = translator.CreateOp(context.mCurrentBlock, OpInstructionType.OpAccessChain, pointerType, new List <IShaderIR> { selfOp, indexOp }); translator.CreateStoreOp(context.mCurrentBlock, accessChainOp, valueOp); }; translator.mCurrentLibrary.CreateIntrinsicFunction(new FunctionKey(methodSymbol), callback); }
public static void GenerateHardwareBuiltIns(FrontEndTranslator translator, ShaderInterfaceSet interfaceSet, StorageClass storageClass, ShaderBlock declarationBlock, ShaderBlock decorationsBlock) { foreach (var builtInInterfaceField in interfaceSet) { var pointerType = translator.FindOrCreatePointerType(builtInInterfaceField.ShaderField.mType, storageClass); var fieldInstanceOp = translator.CreateOp(OpInstructionType.OpVariable, pointerType, null); declarationBlock.mLocalVariables.Add(fieldInstanceOp); Decorations.AddDecorationBuiltIn(translator, fieldInstanceOp, builtInInterfaceField.BuiltInType, decorationsBlock); ShaderInterfaceField.InstanceAccessDelegate fieldInstanceGetFunction = (FrontEndTranslator translator, ShaderInterfaceField interfaceField, FrontEndContext context) => { return(fieldInstanceOp); }; builtInInterfaceField.GetInstance = fieldInstanceGetFunction; } }
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); }
/// <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 static void ResolveVectorDefaultConstructor(FrontEndTranslator translator, FrontEndContext context, ShaderType vectorType) { var componentType = vectorType.mParameters[0] as ShaderType; var componentCount = (UInt32)(vectorType.mParameters[1] 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); }
/// <summary> /// Creates an intrinsic to retrieve an element from an array. This unfortunately has to use OpAccessChain because the other /// instruction requires an integer literal, but OpAccessChain returns a pointer (which isn't exposed). This function will return the element as a value type. /// </summary> static public void CreateArrayGetType(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, IMethodSymbol methodSymbol, AttributeData attribute) { var shaderReturnType = translator.FindType(new TypeKey(methodSymbol.ReturnType)); var pointerReturnType = shaderReturnType.FindPointerType(StorageClass.Function); ShaderLibrary.InstrinsicDelegate callback = (FrontEndTranslator translator, List <IShaderIR> arguments, FrontEndContext context) => { var selfOp = arguments[0]; var indexOp = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, arguments[1]); var accessChainOp = translator.CreateOp(context.mCurrentBlock, OpInstructionType.OpAccessChain, pointerReturnType, new List <IShaderIR> { selfOp, indexOp }); // Always convert the pointer to a value type var returnOp = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, accessChainOp); context.Push(returnOp); }; translator.mCurrentLibrary.CreateIntrinsicFunction(new FunctionKey(methodSymbol), callback); }
public static void ResolveMatrixDefaultConstructor(FrontEndTranslator translator, FrontEndContext context, ShaderType vectorType) { var componentType = vectorType.mParameters[0] as ShaderType; var componentCount = (UInt32)(vectorType.mParameters[1] as ShaderConstantLiteral).mValue; // This direct call to the vector resolver is less than ideal, but works for now VectorResolvers.ResolveVectorDefaultConstructor(translator, context, componentType); var zeroConstant = context.Pop(); 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); }
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 })); }); }
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 ShaderOp CreateOp(OpInstructionType opType, ShaderType resultType, List <IShaderIR> arguments) { return(mFrontEnd.CreateOp(opType, resultType, arguments)); }