Example #1
0
        public string GetExpression(AstOperand operand, ShaderConfig config, bool cbIndexable)
        {
            switch (operand.Type)
            {
            case OperandType.Argument:
                return(GetArgumentName(operand.Value));

            case OperandType.Attribute:
                return(GetAttributeName(operand, config));

            case OperandType.Constant:
                return(NumberFormatter.FormatInt(operand.Value));

            case OperandType.ConstantBuffer:
                return(GetConstantBufferName(operand.CbufSlot, operand.CbufOffset, config.Stage, cbIndexable));

            case OperandType.LocalVariable:
                return(_locals[operand]);

            case OperandType.Undefined:
                return(DefaultNames.UndefinedName);
            }

            throw new ArgumentException($"Invalid operand type \"{operand.Type}\".");
        }
Example #2
0
        public string DeclareLocal(AstOperand operand)
        {
            string name = $"{DefaultNames.LocalNamePrefix}_{_locals.Count}";

            _locals.Add(operand, name);

            return(name);
        }
Example #3
0
        public static string GetConstantBufferName(AstOperand cbuf, GalShaderType shaderType)
        {
            string ubName = GetUbName(shaderType, cbuf.CbufSlot);

            ubName += "[" + (cbuf.CbufOffset >> 2) + "]";

            return(ubName + "." + GetSwizzleMask(cbuf.CbufOffset & 3));
        }
Example #4
0
        private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo info)
        {
            Dictionary <string, AstTextureOperation> samplers = new Dictionary <string, AstTextureOperation>();

            foreach (AstTextureOperation texOp in info.Samplers.OrderBy(x => x.Handle))
            {
                string indexExpr = NumberFormatter.FormatInt(texOp.ArraySize);

                string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

                if (!samplers.TryAdd(samplerName, texOp))
                {
                    continue;
                }

                string samplerTypeName = GetSamplerTypeName(texOp.Type);

                context.AppendLine("uniform " + samplerTypeName + " " + samplerName + ";");
            }

            foreach (KeyValuePair <string, AstTextureOperation> kv in samplers)
            {
                string samplerName = kv.Key;

                AstTextureOperation texOp = kv.Value;

                TextureDescriptor desc;

                if ((texOp.Flags & TextureFlags.Bindless) != 0)
                {
                    AstOperand operand = texOp.GetSource(0) as AstOperand;

                    desc = new TextureDescriptor(samplerName, texOp.Type, operand.CbufSlot, operand.CbufOffset);

                    context.TextureDescriptors.Add(desc);
                }
                else if ((texOp.Type & SamplerType.Indexed) != 0)
                {
                    for (int index = 0; index < texOp.ArraySize; index++)
                    {
                        string indexExpr = NumberFormatter.FormatInt(index);

                        string indexedSamplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

                        desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Handle + index * 2);

                        context.TextureDescriptors.Add(desc);
                    }
                }
                else
                {
                    desc = new TextureDescriptor(samplerName, texOp.Type, texOp.Handle);

                    context.TextureDescriptors.Add(desc);
                }
            }
        }
Example #5
0
        private static VariableType GetOperandVarType(AstOperand operand)
        {
            if (operand.Type == OperandType.Attribute)
            {
                if (_builtInAttributes.TryGetValue(operand.Value & ~3, out BuiltInAttribute builtInAttr))
                {
                    return(builtInAttr.Type);
                }
            }

            return(OperandInfo.GetVarType(operand));
        }
Example #6
0
        public static string GetConstantBufferName(IAstNode slot, string offsetExpr, ShaderStage stage)
        {
            // Non-constant slots are not supported.
            // It is expected that upstream stages are never going to generate non-constant
            // slot access.
            AstOperand operand = (AstOperand)slot;

            string ubName = GetUbName(stage, operand.Value);

            string index0 = "[" + offsetExpr + " >> 2]";

            return(GetVec4Indexed(ubName + index0, offsetExpr + " & 3"));
        }
Example #7
0
 public string GetExpression(AstOperand operand, ShaderConfig config)
 {
     return(operand.Type switch
     {
         OperandType.Argument => GetArgumentName(operand.Value),
         OperandType.Attribute => GetAttributeName(operand.Value, config, perPatch: false),
         OperandType.AttributePerPatch => GetAttributeName(operand.Value, config, perPatch: true),
         OperandType.Constant => NumberFormatter.FormatInt(operand.Value),
         OperandType.ConstantBuffer => GetConstantBufferName(operand, config),
         OperandType.LocalVariable => _locals[operand],
         OperandType.Undefined => DefaultNames.UndefinedName,
         _ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
     });
Example #8
0
        public static string GetConstantBufferName(IAstNode slot, string offsetExpr, GalShaderType shaderType)
        {
            // Non-constant slots are not supported.
            // It is expected that upstream stages are never going to generate non-constant
            // slot access.
            AstOperand operand = (AstOperand)slot;

            string ubName = GetUbName(shaderType, operand.Value);

            string index0 = "[" + offsetExpr + " >> 4]";
            string index1 = "[" + offsetExpr + " >> 2 & 3]";

            return(ubName + index0 + index1);
        }
Example #9
0
        public int FindTextureDescriptorIndex(AstTextureOperation texOp)
        {
            AstOperand operand  = texOp.GetSource(0) as AstOperand;
            bool       bindless = (texOp.Flags & TextureFlags.Bindless) > 0;

            int cBufSlot   = bindless ? operand.CbufSlot : 0;
            int cBufOffset = bindless ? operand.CbufOffset : 0;

            return(TextureDescriptors.FindIndex(descriptor =>
                                                descriptor.Type == texOp.Type &&
                                                descriptor.HandleIndex == texOp.Handle &&
                                                descriptor.CbufSlot == cBufSlot &&
                                                descriptor.CbufOffset == cBufOffset));
        }
Example #10
0
        private int FindDescriptorIndex(List <TextureDescriptor> list, AstTextureOperation texOp)
        {
            AstOperand operand  = texOp.GetSource(0) as AstOperand;
            bool       bindless = (texOp.Flags & TextureFlags.Bindless) > 0;

            int cBufSlot   = bindless ? operand.CbufSlot : 0;
            int cBufOffset = bindless ? operand.CbufOffset : 0;

            return(list.FindIndex(descriptor =>
                                  descriptor.Type == texOp.Type &&
                                  descriptor.HandleIndex == texOp.Handle &&
                                  descriptor.Format == texOp.Format &&
                                  descriptor.CbufSlot == cBufSlot &&
                                  descriptor.CbufOffset == cBufOffset));
        }
Example #11
0
 public string GetExpression(AstOperand operand, ShaderConfig config)
 {
     return(operand.Type switch
     {
         OperandType.Argument => GetArgumentName(operand.Value),
         OperandType.Attribute => GetAttributeName(operand, config),
         OperandType.Constant => NumberFormatter.FormatInt(operand.Value),
         OperandType.ConstantBuffer => GetConstantBufferName(
             operand.CbufSlot,
             operand.CbufOffset,
             config.Stage,
             config.UsedFeatures.HasFlag(FeatureFlags.CbIndexing)),
         OperandType.LocalVariable => _locals[operand],
         OperandType.Undefined => DefaultNames.UndefinedName,
         _ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
     });
Example #12
0
        public static string Call(CodeGenContext context, AstOperation operation)
        {
            AstOperand funcId = (AstOperand)operation.GetSource(0);

            Debug.Assert(funcId.Type == OperandType.Constant);

            var function = context.GetFunction(funcId.Value);

            string[] args = new string[operation.SourcesCount - 1];

            for (int i = 0; i < args.Length; i++)
            {
                args[i] = GetSoureExpr(context, operation.GetSource(i + 1), function.GetArgumentType(i));
            }

            return($"{function.Name}({string.Join(", ", args)})");
        }
Example #13
0
        public static string GetSamplerName(GalShaderType shaderType, AstTextureOperation texOp)
        {
            string suffix;

            if ((texOp.Flags & TextureFlags.Bindless) != 0)
            {
                AstOperand operand = texOp.GetSource(0) as AstOperand;

                suffix = "_cb" + operand.CbufSlot + "_" + operand.CbufOffset;
            }
            else
            {
                suffix = (texOp.Handle - 8).ToString();
            }

            return(GetShaderStagePrefix(shaderType) + "_" + DefaultNames.SamplerNamePrefix + suffix);
        }
Example #14
0
        public static VariableType GetNodeDestType(CodeGenContext context, IAstNode node)
        {
            if (node is AstOperation operation)
            {
                // Load attribute basically just returns the attribute value.
                // Some built-in attributes may have different types, so we need
                // to return the type based on the attribute that is being read.
                if (operation.Inst == Instruction.LoadAttribute)
                {
                    return(GetOperandVarType((AstOperand)operation.GetSource(0)));
                }
                else if (operation.Inst == Instruction.Call)
                {
                    AstOperand funcId = (AstOperand)operation.GetSource(0);

                    Debug.Assert(funcId.Type == OperandType.Constant);

                    return(context.GetFunction(funcId.Value).ReturnType);
                }
                else if (operation is AstTextureOperation texOp &&
                         (texOp.Inst == Instruction.ImageLoad ||
                          texOp.Inst == Instruction.ImageStore))
                {
                    return(texOp.Format.GetComponentType());
                }

                return(GetDestVarType(operation.Inst));
            }
            else if (node is AstOperand operand)
            {
                if (operand.Type == OperandType.Argument)
                {
                    int argIndex = operand.Value;

                    return(context.CurrentFunction.GetArgumentType(argIndex));
                }

                return(GetOperandVarType(operand));
            }
            else
            {
                throw new ArgumentException($"Invalid node type \"{node?.GetType().Name ?? "null"}\".");
            }
        }
Example #15
0
        public static string GetSamplerName(ShaderStage stage, AstTextureOperation texOp, string indexExpr)
        {
            string suffix;

            if ((texOp.Flags & TextureFlags.Bindless) != 0)
            {
                AstOperand operand = texOp.GetSource(0) as AstOperand;

                suffix = "_cb" + operand.CbufSlot + "_" + operand.CbufOffset;
            }
            else
            {
                suffix = texOp.Handle.ToString("X");

                if ((texOp.Type & SamplerType.Indexed) != 0)
                {
                    suffix += $"a[{indexExpr}]";
                }
            }

            return(GetShaderStagePrefix(stage) + "_" + DefaultNames.SamplerNamePrefix + suffix);
        }
Example #16
0
        public string GetExpression(AstOperand operand, GalShaderType shaderType)
        {
            switch (operand.Type)
            {
            case OperandType.Attribute:
                return(GetAttributeName(operand, shaderType));

            case OperandType.Constant:
                return(NumberFormatter.FormatInt(operand.Value));

            case OperandType.ConstantBuffer:
                return(GetConstantBufferName(operand, shaderType));

            case OperandType.LocalVariable:
                return(_locals[operand]);

            case OperandType.Undefined:
                return(DefaultNames.UndefinedName);
            }

            throw new ArgumentException($"Invalid operand type \"{operand.Type}\".");
        }
Example #17
0
 public static string GetOutAttributeName(AstOperand attr, GalShaderType shaderType)
 {
     return(GetAttributeName(attr, shaderType, isOutAttr: true));
 }
Example #18
0
        public static string GetAttributeName(AstOperand attr, ShaderConfig config, bool isOutAttr = false, string indexExpr = "0")
        {
            int value = attr.Value;

            char swzMask = GetSwizzleMask((value >> 2) & 3);

            if (value >= AttributeConsts.UserAttributeBase && value < AttributeConsts.UserAttributeEnd)
            {
                value -= AttributeConsts.UserAttributeBase;

                string prefix = isOutAttr
                    ? DefaultNames.OAttributePrefix
                    : DefaultNames.IAttributePrefix;

                if ((config.Flags & TranslationFlags.Feedback) != 0)
                {
                    string name = $"{prefix}{(value >> 4)}_{swzMask}";

                    if (config.Stage == ShaderStage.Geometry && !isOutAttr)
                    {
                        name += $"[{indexExpr}]";
                    }

                    return(name);
                }
                else
                {
                    string name = $"{prefix}{(value >> 4)}";

                    if (config.Stage == ShaderStage.Geometry && !isOutAttr)
                    {
                        name += $"[{indexExpr}]";
                    }

                    return(name + '.' + swzMask);
                }
            }
            else
            {
                if (value >= AttributeConsts.FragmentOutputColorBase && value < AttributeConsts.FragmentOutputColorEnd)
                {
                    value -= AttributeConsts.FragmentOutputColorBase;

                    return($"{DefaultNames.OAttributePrefix}{(value >> 4)}.{swzMask}");
                }
                else if (_builtInAttributes.TryGetValue(value & ~3, out BuiltInAttribute builtInAttr))
                {
                    // TODO: There must be a better way to handle this...
                    if (config.Stage == ShaderStage.Fragment)
                    {
                        switch (value & ~3)
                        {
                        case AttributeConsts.PositionX: return("(gl_FragCoord.x / fp_renderScale[0])");

                        case AttributeConsts.PositionY: return("(gl_FragCoord.y / fp_renderScale[0])");

                        case AttributeConsts.PositionZ: return("gl_FragCoord.z");

                        case AttributeConsts.PositionW: return("gl_FragCoord.w");
                        }
                    }

                    string name = builtInAttr.Name;

                    if (config.Stage == ShaderStage.Geometry && (value & AttributeConsts.SpecialMask) == 0 && !isOutAttr)
                    {
                        name = $"gl_in[{indexExpr}].{name}";
                    }

                    return(name);
                }
            }

            // TODO: Warn about unknown built-in attribute.

            return(isOutAttr ? "// bad_attr0x" + value.ToString("X") : "0.0");
        }
Example #19
0
 public static string GetOutAttributeName(AstOperand attr, ShaderConfig config)
 {
     return(GetAttributeName(attr, config, isOutAttr: true));
 }
Example #20
0
        private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo info)
        {
            Dictionary <string, AstTextureOperation> samplers = new Dictionary <string, AstTextureOperation>();

            // Texture instructions other than TextureSample (like TextureSize)
            // may have incomplete sampler type information. In those cases,
            // we prefer instead the more accurate information from the
            // TextureSample instruction, if both are available.
            foreach (AstTextureOperation texOp in info.Samplers.OrderBy(x => x.Handle * 2 + (x.Inst == Instruction.TextureSample ? 0 : 1)))
            {
                string indexExpr = NumberFormatter.FormatInt(texOp.ArraySize);

                string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

                if (!samplers.TryAdd(samplerName, texOp))
                {
                    continue;
                }

                string samplerTypeName = GetSamplerTypeName(texOp.Type);

                context.AppendLine("uniform " + samplerTypeName + " " + samplerName + ";");
            }

            foreach (KeyValuePair <string, AstTextureOperation> kv in samplers)
            {
                string samplerName = kv.Key;

                AstTextureOperation texOp = kv.Value;

                TextureDescriptor desc;

                if ((texOp.Flags & TextureFlags.Bindless) != 0)
                {
                    AstOperand operand = texOp.GetSource(0) as AstOperand;

                    desc = new TextureDescriptor(samplerName, texOp.Type, operand.CbufSlot, operand.CbufOffset);

                    context.TextureDescriptors.Add(desc);
                }
                else if ((texOp.Type & SamplerType.Indexed) != 0)
                {
                    for (int index = 0; index < texOp.ArraySize; index++)
                    {
                        string indexExpr = NumberFormatter.FormatInt(index);

                        string indexedSamplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

                        desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Handle + index * 2);

                        context.TextureDescriptors.Add(desc);
                    }
                }
                else
                {
                    desc = new TextureDescriptor(samplerName, texOp.Type, texOp.Handle);

                    context.TextureDescriptors.Add(desc);
                }
            }
        }
Example #21
0
 public static string GetOutAttributeName(AstOperand attr, ShaderStage stage)
 {
     return(GetAttributeName(attr, stage, isOutAttr: true));
 }
Example #22
0
        private static string GetAttributeName(AstOperand attr, GalShaderType shaderType, bool isOutAttr = false)
        {
            int value = attr.Value;

            string swzMask = GetSwizzleMask((value >> 2) & 3);

            if (value >= AttributeConsts.UserAttributeBase &&
                value < AttributeConsts.UserAttributeEnd)
            {
                value -= AttributeConsts.UserAttributeBase;

                string prefix = isOutAttr
                    ? DefaultNames.OAttributePrefix
                    : DefaultNames.IAttributePrefix;

                string name = $"{prefix}{(value >> 4)}";

                if (shaderType == GalShaderType.Geometry && !isOutAttr)
                {
                    name += "[0]";
                }

                name += "." + swzMask;

                return(name);
            }
            else
            {
                if (value >= AttributeConsts.FragmentOutputColorBase &&
                    value < AttributeConsts.FragmentOutputColorEnd)
                {
                    value -= AttributeConsts.FragmentOutputColorBase;

                    return($"{DefaultNames.OAttributePrefix}{(value >> 4)}.{swzMask}");
                }
                else if (_builtInAttributes.TryGetValue(value & ~3, out BuiltInAttribute builtInAttr))
                {
                    // TODO: There must be a better way to handle this...
                    if (shaderType == GalShaderType.Fragment)
                    {
                        switch (value & ~3)
                        {
                        case AttributeConsts.PositionX: return("gl_FragCoord.x");

                        case AttributeConsts.PositionY: return("gl_FragCoord.y");

                        case AttributeConsts.PositionZ: return("gl_FragCoord.z");

                        case AttributeConsts.PositionW: return("1.0");
                        }
                    }

                    string name = builtInAttr.Name;

                    if (shaderType == GalShaderType.Geometry && !isOutAttr)
                    {
                        name = "gl_in[0]." + name;
                    }

                    return(name);
                }
            }

            // TODO: Warn about unknown built-in attribute.

            return(isOutAttr ? "// bad_attr0x" + value.ToString("X") : "0.0");
        }