aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/IoMap.cs
blob: 7b4e14ff09817b7761f641d3cff895da3a3cc86f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation;
using System;
using static Spv.Specification;

namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{
    static class IoMap
    {
        // At least 16 attributes are guaranteed by the spec.
        private const int MaxAttributes = 16;

        public static (BuiltIn, AggregateType) GetSpirvBuiltIn(IoVariable ioVariable)
        {
            return ioVariable switch
            {
                IoVariable.BaseInstance => (BuiltIn.BaseInstance, AggregateType.S32),
                IoVariable.BaseVertex => (BuiltIn.BaseVertex, AggregateType.S32),
                IoVariable.ClipDistance => (BuiltIn.ClipDistance, AggregateType.Array | AggregateType.FP32),
                IoVariable.CtaId => (BuiltIn.WorkgroupId, AggregateType.Vector3 | AggregateType.U32),
                IoVariable.DrawIndex => (BuiltIn.DrawIndex, AggregateType.S32),
                IoVariable.FragmentCoord => (BuiltIn.FragCoord, AggregateType.Vector4 | AggregateType.FP32),
                IoVariable.FragmentOutputDepth => (BuiltIn.FragDepth, AggregateType.FP32),
                IoVariable.FrontFacing => (BuiltIn.FrontFacing, AggregateType.Bool),
                IoVariable.GlobalId => (BuiltIn.GlobalInvocationId, AggregateType.Vector3 | AggregateType.U32),
                IoVariable.InstanceId => (BuiltIn.InstanceId, AggregateType.S32),
                IoVariable.InstanceIndex => (BuiltIn.InstanceIndex, AggregateType.S32),
                IoVariable.InvocationId => (BuiltIn.InvocationId, AggregateType.S32),
                IoVariable.Layer => (BuiltIn.Layer, AggregateType.S32),
                IoVariable.PatchVertices => (BuiltIn.PatchVertices, AggregateType.S32),
                IoVariable.PointCoord => (BuiltIn.PointCoord, AggregateType.Vector2 | AggregateType.FP32),
                IoVariable.PointSize => (BuiltIn.PointSize, AggregateType.FP32),
                IoVariable.Position => (BuiltIn.Position, AggregateType.Vector4 | AggregateType.FP32),
                IoVariable.PrimitiveId => (BuiltIn.PrimitiveId, AggregateType.S32),
                IoVariable.SubgroupEqMask => (BuiltIn.SubgroupEqMask, AggregateType.Vector4 | AggregateType.U32),
                IoVariable.SubgroupGeMask => (BuiltIn.SubgroupGeMask, AggregateType.Vector4 | AggregateType.U32),
                IoVariable.SubgroupGtMask => (BuiltIn.SubgroupGtMask, AggregateType.Vector4 | AggregateType.U32),
                IoVariable.SubgroupLaneId => (BuiltIn.SubgroupLocalInvocationId, AggregateType.U32),
                IoVariable.SubgroupLeMask => (BuiltIn.SubgroupLeMask, AggregateType.Vector4 | AggregateType.U32),
                IoVariable.SubgroupLtMask => (BuiltIn.SubgroupLtMask, AggregateType.Vector4 | AggregateType.U32),
                IoVariable.TessellationCoord => (BuiltIn.TessCoord, AggregateType.Vector3 | AggregateType.FP32),
                IoVariable.TessellationLevelInner => (BuiltIn.TessLevelInner, AggregateType.Array | AggregateType.FP32),
                IoVariable.TessellationLevelOuter => (BuiltIn.TessLevelOuter, AggregateType.Array | AggregateType.FP32),
                IoVariable.ThreadId => (BuiltIn.LocalInvocationId, AggregateType.Vector3 | AggregateType.U32),
                IoVariable.ThreadKill => (BuiltIn.HelperInvocation, AggregateType.Bool),
                IoVariable.VertexId => (BuiltIn.VertexId, AggregateType.S32),
                IoVariable.VertexIndex => (BuiltIn.VertexIndex, AggregateType.S32),
                IoVariable.ViewportIndex => (BuiltIn.ViewportIndex, AggregateType.S32),
                IoVariable.ViewportMask => (BuiltIn.ViewportMaskNV, AggregateType.Array | AggregateType.S32),
                _ => (default, AggregateType.Invalid),
            };
        }

        public static int GetSpirvBuiltInArrayLength(IoVariable ioVariable)
        {
            return ioVariable switch
            {
                IoVariable.ClipDistance => 8,
                IoVariable.TessellationLevelInner => 2,
                IoVariable.TessellationLevelOuter => 4,
                IoVariable.ViewportMask => 1,
                IoVariable.UserDefined => MaxAttributes,
                _ => 1,
            };
        }

        public static bool IsPerVertex(IoVariable ioVariable, ShaderStage stage, bool isOutput)
        {
            switch (ioVariable)
            {
                case IoVariable.Layer:
                case IoVariable.ViewportIndex:
                case IoVariable.PointSize:
                case IoVariable.Position:
                case IoVariable.UserDefined:
                case IoVariable.ClipDistance:
                case IoVariable.PointCoord:
                case IoVariable.ViewportMask:
                    return !isOutput &&
                           stage is ShaderStage.TessellationControl or ShaderStage.TessellationEvaluation or ShaderStage.Geometry;
            }

            return false;
        }

        public static bool IsPerVertexBuiltIn(IoVariable ioVariable)
        {
            switch (ioVariable)
            {
                case IoVariable.Position:
                case IoVariable.PointSize:
                case IoVariable.ClipDistance:
                    return true;
            }

            return false;
        }

        public static bool IsPerVertexArrayBuiltIn(StorageKind storageKind, ShaderStage stage)
        {
            if (storageKind == StorageKind.Output)
            {
                return stage == ShaderStage.TessellationControl;
            }
            else
            {
                return stage == ShaderStage.TessellationControl ||
                       stage == ShaderStage.TessellationEvaluation ||
                       stage == ShaderStage.Geometry;
            }
        }

        public static int GetPerVertexStructFieldIndex(IoVariable ioVariable)
        {
            return ioVariable switch
            {
                IoVariable.Position => 0,
                IoVariable.PointSize => 1,
                IoVariable.ClipDistance => 2,
                _ => throw new ArgumentException($"Invalid built-in variable {ioVariable}.")
            };
        }
    }
}