Beispiel #1
0
        public static ImageIntrinsicAttributeData Parse(AttributeData attribute, int defaultOperandsLocation = -1)
        {
            if (attribute.ConstructorArguments.Length == 0)
            {
                return(null);
            }

            ImageIntrinsicAttributeData result = new ImageIntrinsicAttributeData();

            result.OperandsLocation = defaultOperandsLocation;
            // Load the attribute params if they exist. Note: This isn't really safe, but works for now.
            foreach (var attributeParam in attribute.ConstructorArguments)
            {
                var argName = TypeAliases.GetTypeName(attributeParam.Type);
                if (argName == TypeAliases.GetTypeName <string>())
                {
                    result.OpType = (OpInstructionType)Enum.Parse(typeof(OpInstructionType), attributeParam.Value as string, true);
                }
                else if (argName == TypeAliases.GetTypeName <Shader.ImageOperands>())
                {
                    result.Operands = (Shader.ImageOperands)attributeParam.Value;
                }
                else if (argName == TypeAliases.GetTypeName <UInt32>())
                {
                    result.OperandsLocation = (int)(UInt32)attributeParam.Value;
                }
            }
            // Also try to resolve any named parameter arguments
            foreach (var pair in attribute.NamedArguments)
            {
                if (pair.Key == "OpName")
                {
                    result.OpType = (OpInstructionType)Enum.Parse(typeof(OpInstructionType), pair.Value.Value as string, true);
                }
                else if (pair.Key == "Operands")
                {
                    result.Operands = (Shader.ImageOperands)pair.Value.Value;
                }
                else if (pair.Key == "OperandsLocation")
                {
                    result.OperandsLocation = (int)pair.Value.Value;
                }
            }
            return(result);
        }
        static public void CreateSampledImageIntrinsicFunction(FrontEndTranslator translator, INamedTypeSymbol typeSymbol, IMethodSymbol methodSymbol, AttributeData attribute)
        {
            var intrinsicData = ImageIntrinsicAttributeData.Parse(attribute);

            if (intrinsicData == null)
            {
                throw new Exception("Failed to parse attribute");
            }

            var shaderReturnType = translator.FindType(new TypeKey(methodSymbol.ReturnType));

            ShaderLibrary.InstrinsicDelegate callback = null;

            var param0Type = translator.FindType(new TypeKey(methodSymbol.Parameters[0].Type));

            if (param0Type.mBaseType == OpType.SampledImage)
            {
                callback = (FrontEndTranslator translator, List <IShaderIR> arguments, FrontEndContext context) =>
                {
                    SampledImageValueTypeIntrinsic(translator, context, intrinsicData, shaderReturnType, arguments);
                };
            }
            else if (param0Type.mBaseType == OpType.Image)
            {
                var param1Type = translator.FindType(new TypeKey(methodSymbol.Parameters[1].Type));
                if (param1Type.mBaseType == OpType.Sampler)
                {
                    callback = (FrontEndTranslator translator, List <IShaderIR> arguments, FrontEndContext context) =>
                    {
                        SplitSampledImageValueTypeIntrinsic(translator, context, intrinsicData, shaderReturnType, arguments);
                    };
                }
            }

            if (callback == null)
            {
                throw new Exception("Failed to parse attribute");
            }

            translator.mCurrentLibrary.CreateIntrinsicFunction(new FunctionKey(methodSymbol), callback);
        }
 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]));
         }
     }
 }
        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 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);
        }
        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);
        }