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}.")
};
}
}
}
|