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);
        }
Esempio n. 2
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);
        }
Esempio n. 3
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);
        }
Esempio n. 4
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);
        }
        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);
        }
Esempio n. 6
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
            });
        }
Esempio n. 7
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
            });
        }
Esempio n. 8
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
            });
        }
Esempio n. 9
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);
        }
Esempio n. 10
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
            });
        }
Esempio n. 11
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
         }));
     });
 }
Esempio n. 12
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
            });
        }
Esempio n. 13
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
         }));
     });
 }
        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);
        }
Esempio n. 15
0
        /// <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);
        }
Esempio n. 16
0
 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;
     }
 }
Esempio n. 17
0
 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);
 }
Esempio n. 18
0
        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;
            }
        }
Esempio n. 19
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);
        }
Esempio n. 20
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);
        }
Esempio n. 21
0
        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);
        }
Esempio n. 22
0
        /// <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);
        }
Esempio n. 23
0
        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);
        }
Esempio n. 24
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
         }));
     });
 }
Esempio n. 25
0
        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);
            }
        }
Esempio n. 26
0
 public ShaderOp CreateOp(OpInstructionType opType, ShaderType resultType, List <IShaderIR> arguments)
 {
     return(mFrontEnd.CreateOp(opType, resultType, arguments));
 }