Skip to content

Commit ab93f53

Browse files
[Core] Add partial support for compute shaders;
1 parent 2232eba commit ab93f53

File tree

11 files changed

+354
-138
lines changed

11 files changed

+354
-138
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Type Compute
2+
3+
Begin Parameters
4+
5+
WOBuffer<vec4> myBuffer : 0
6+
7+
End Parameters
8+
9+
Begin Compute
10+
11+
#define GROUP_SIZE 512
12+
13+
NUM_THREADS(GROUP_SIZE, 1, 1)
14+
void main()
15+
{
16+
myBuffer[gl_GlobalInvocationID.x] = vec4(1.0, 2.0, 3.0, 4.0);
17+
}
18+
19+
End Compute
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"guid": "1af8332a-0203-44ba-9811-47312c5d9b13",
3+
"typeName": "Staple.Internal.Shader"
4+
}

Engine/Core/MessagePackGenerated/MessagePackGenerated.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3960,9 +3960,10 @@ public void Serialize(ref global::MessagePack.MessagePackWriter writer, global::
39603960
}
39613961

39623962
global::MessagePack.IFormatterResolver formatterResolver = options.Resolver;
3963-
writer.WriteArrayHeader(2);
3963+
writer.WriteArrayHeader(3);
39643964
formatterResolver.GetFormatterWithVerify<string>().Serialize(ref writer, value.name, options);
39653965
formatterResolver.GetFormatterWithVerify<global::Staple.Internal.ShaderUniformType>().Serialize(ref writer, value.type, options);
3966+
writer.Write(value.slot);
39663967
}
39673968

39683969
public global::Staple.Internal.ShaderUniform Deserialize(ref global::MessagePack.MessagePackReader reader, global::MessagePack.MessagePackSerializerOptions options)
@@ -3987,6 +3988,9 @@ public void Serialize(ref global::MessagePack.MessagePackWriter writer, global::
39873988
case 1:
39883989
____result.type = formatterResolver.GetFormatterWithVerify<global::Staple.Internal.ShaderUniformType>().Deserialize(ref reader, options);
39893990
break;
3991+
case 2:
3992+
____result.slot = reader.ReadInt32();
3993+
break;
39903994
default:
39913995
reader.Skip();
39923996
break;

Engine/Core/Serialization/Shader/SerializableShader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,5 @@ public class SerializableShader
4242
public ShaderMetadata metadata;
4343

4444
[Key(1)]
45-
public Dictionary<string, SerializableShaderData> data = new();
45+
public Dictionary<string, SerializableShaderData> data = [];
4646
}

Engine/Core/Serialization/Shader/ShaderMetadata.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ public enum ShaderUniformType
1919
Color,
2020
Texture,
2121
Matrix3x3,
22-
Matrix4x4
22+
Matrix4x4,
23+
ReadOnlyBuffer,
24+
WriteOnlyBuffer,
25+
ReadWriteBuffer,
2326
}
2427

2528
[MessagePackObject]
@@ -30,6 +33,9 @@ public class ShaderUniform
3033

3134
[Key(1)]
3235
public ShaderUniformType type;
36+
37+
[Key(2)]
38+
public int slot;
3339
}
3440

3541
[MessagePackObject]

Engine/StapleToolingTests/ShaderParserTests.cs

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,7 @@ End Compute
8383
Assert.That(fragment, Is.Not.Null);
8484
Assert.That(fragment.content, Is.EqualTo("fragment A\nfragment B"));
8585

86-
Assert.That(compute, Is.Not.Null);
87-
Assert.That(compute.content, Is.EqualTo("compute A\ncompute B"));
86+
Assert.That(compute, Is.Null);
8887
}
8988

9089
[Test]
@@ -165,6 +164,79 @@ End Compute
165164
Assert.That(fragment, Is.Not.Null);
166165
Assert.That(fragment.content, Is.EqualTo("fragment A\nfragment B"));
167166

167+
Assert.That(compute, Is.Null);
168+
}
169+
170+
[Test]
171+
public void TestParseBuffers()
172+
{
173+
var shader = $$"""
174+
Type Compute
175+
176+
Variants A, B, C
177+
178+
Begin Parameters
179+
varying vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0)
180+
varying vec2 v_texcoord1 : TEXCOORD1
181+
uniform vec2 v_texcoord2
182+
ROBuffer<vec4> myBuffer:0
183+
End Parameters
184+
185+
Begin Vertex
186+
$input v_texcoord0
187+
$output v_texcoord1, v_texcoord2
188+
vertex A
189+
vertex B
190+
End Vertex
191+
192+
Begin Fragment
193+
fragment A
194+
fragment B
195+
End Fragment
196+
197+
Begin Compute
198+
compute A
199+
compute B
200+
End Compute
201+
""";
202+
203+
Assert.IsTrue(ShaderParser.Parse(shader, out var type, out var blend, out var parameters, out var variants,
204+
out var vertex, out var fragment, out var compute));
205+
206+
Assert.That(type, Is.EqualTo(ShaderType.Compute));
207+
208+
Assert.That(variants.Count, Is.EqualTo(0));
209+
210+
Assert.That(blend, Is.Null);
211+
212+
Assert.That(parameters.Count, Is.EqualTo(4));
213+
214+
Assert.That(parameters[0].type, Is.EqualTo("varying"));
215+
Assert.That(parameters[0].dataType, Is.EqualTo("vec2"));
216+
Assert.That(parameters[0].name, Is.EqualTo("v_texcoord0"));
217+
Assert.That(parameters[0].attribute, Is.EqualTo("TEXCOORD0"));
218+
Assert.That(parameters[0].initializer, Is.EqualTo("vec2(0.0, 0.0)"));
219+
220+
Assert.That(parameters[1].type, Is.EqualTo("varying"));
221+
Assert.That(parameters[1].dataType, Is.EqualTo("vec2"));
222+
Assert.That(parameters[1].name, Is.EqualTo("v_texcoord1"));
223+
Assert.That(parameters[1].attribute, Is.EqualTo("TEXCOORD1"));
224+
Assert.That(parameters[1].initializer, Is.Null);
225+
226+
Assert.That(parameters[2].type, Is.EqualTo("uniform"));
227+
Assert.That(parameters[2].dataType, Is.EqualTo("vec2"));
228+
Assert.That(parameters[2].name, Is.EqualTo("v_texcoord2"));
229+
Assert.That(parameters[2].attribute, Is.Null);
230+
Assert.That(parameters[2].initializer, Is.Null);
231+
232+
Assert.That(parameters[3].type, Is.EqualTo("ROBuffer"));
233+
Assert.That(parameters[3].dataType, Is.EqualTo("vec4"));
234+
Assert.That(parameters[3].name, Is.EqualTo("myBuffer"));
235+
Assert.That(parameters[3].attribute, Is.Null);
236+
Assert.That(parameters[3].initializer, Is.EqualTo("0"));
237+
238+
Assert.That(vertex, Is.Null);
239+
168240
Assert.That(compute, Is.Not.Null);
169241
Assert.That(compute.content, Is.EqualTo("compute A\ncompute B"));
170242
}

Engine/Tooling/ShaderParser.cs

Lines changed: 71 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public class Parameter
2020
public class ShaderPiece
2121
{
2222
public string content;
23-
public List<string> inputs = new();
24-
public List<string> outputs = new();
23+
public List<string> inputs = [];
24+
public List<string> outputs = [];
2525
}
2626

2727
private static Regex typeRegex = TypeRegex();
@@ -34,10 +34,14 @@ public class ShaderPiece
3434
private static Regex outputRegex = OutputRegex();
3535
private static Regex blendRegex = BlendRegex();
3636
private static Regex variantsRegex = VariantsRegex();
37+
private static Regex bufferRegex = BufferRegex();
3738

3839
[GeneratedRegex("(varying|uniform) (\\w+) (\\w+)(([ ]*)\\:([ ]*)(\\w+))?(([ ]*)\\=([ ]*)(.*))?")]
3940
private static partial Regex ParameterRegex();
4041

42+
[GeneratedRegex("(ROBuffer|RWBuffer|WOBuffer)\\<(\\w+)\\>([ ]*)(\\w+)([ ]*)\\:([ ]*)([0-9]+)")]
43+
private static partial Regex BufferRegex();
44+
4145
[GeneratedRegex("Begin Vertex((.|\\n)*)End Vertex")]
4246
private static partial Regex VertexRegex();
4347

@@ -84,28 +88,36 @@ public static bool Parse(string source, out ShaderType type, out (BlendMode, Ble
8488
return false;
8589
}
8690

87-
var variantsMatch = variantsRegex.Match(source);
88-
89-
if (variantsMatch != null && variantsMatch.Length > 0)
90-
{
91-
variants = variantsMatch.Groups[1].Value.Split(",").Select(x => x.Trim()).ToList();
92-
}
93-
else
91+
if(type == ShaderType.VertexFragment)
9492
{
95-
variants = [];
96-
}
93+
var variantsMatch = variantsRegex.Match(source);
9794

98-
var blendMatch = blendRegex.Match(source);
95+
if (variantsMatch != null && variantsMatch.Length > 0)
96+
{
97+
variants = variantsMatch.Groups[1].Value.Split(",").Select(x => x.Trim()).ToList();
98+
}
99+
else
100+
{
101+
variants = [];
102+
}
99103

100-
if(blendMatch == null ||
101-
Enum.TryParse<BlendMode>(blendMatch.Groups[1].Value, true, out var from) == false ||
102-
Enum.TryParse<BlendMode>(blendMatch.Groups[2].Value, true, out var to) == false)
103-
{
104-
blendMode = default;
104+
var blendMatch = blendRegex.Match(source);
105+
106+
if (blendMatch == null ||
107+
Enum.TryParse<BlendMode>(blendMatch.Groups[1].Value, true, out var from) == false ||
108+
Enum.TryParse<BlendMode>(blendMatch.Groups[2].Value, true, out var to) == false)
109+
{
110+
blendMode = default;
111+
}
112+
else
113+
{
114+
blendMode = (from, to);
115+
}
105116
}
106117
else
107118
{
108-
blendMode = (from, to);
119+
variants = [];
120+
blendMode = default;
109121
}
110122

111123
var parametersMatch = parametersRegex.Match(source);
@@ -115,6 +127,7 @@ public static bool Parse(string source, out ShaderType type, out (BlendMode, Ble
115127
var content = parametersMatch.Groups[1].Value;
116128

117129
var parameterMatches = parameterRegex.Matches(content);
130+
var bufferMatches = bufferRegex.Matches(content);
118131

119132
var parameterList = new List<Parameter>();
120133

@@ -142,6 +155,32 @@ public static bool Parse(string source, out ShaderType type, out (BlendMode, Ble
142155
parameterList.Add(parameter);
143156
}
144157

158+
foreach(Match match in bufferMatches)
159+
{
160+
if(int.TryParse(match.Groups[7].Value.Trim(), out var bufferIndex) == false)
161+
{
162+
type = default;
163+
parameters = default;
164+
variants = [];
165+
vertex = default;
166+
fragment = default;
167+
compute = default;
168+
blendMode = default;
169+
170+
return false;
171+
}
172+
173+
var parameter = new Parameter
174+
{
175+
type = match.Groups[1].Value.Trim(),
176+
dataType = match.Groups[2].Value.Trim(),
177+
name = match.Groups[4].Value.Trim(),
178+
initializer = bufferIndex.ToString(),
179+
};
180+
181+
parameterList.Add(parameter);
182+
}
183+
145184
parameters = parameterList.ToArray();
146185
}
147186
else
@@ -195,9 +234,20 @@ void HandleContent(Regex regex, out ShaderPiece piece)
195234
}
196235
}
197236

198-
HandleContent(vertexRegex, out vertex);
199-
HandleContent(fragmentRegex, out fragment);
200-
HandleContent(computeRegex, out compute);
237+
if(type == ShaderType.VertexFragment)
238+
{
239+
HandleContent(vertexRegex, out vertex);
240+
HandleContent(fragmentRegex, out fragment);
241+
242+
compute = default;
243+
}
244+
else
245+
{
246+
HandleContent(computeRegex, out compute);
247+
248+
vertex = default;
249+
fragment = default;
250+
}
201251

202252
return true;
203253
}

Engine/TypeRegistration/TypeCacheRegistrationGenerator.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,14 @@ public void Execute(GeneratorExecutionContext context)
5454
var source = $@"// <auto-generated />
5555
using System;
5656
using System.Runtime.InteropServices;
57-
using Staple.Internal;
5857
5958
namespace StapleCodeGeneration
6059
{{
6160
public static class TypeCacheRegistration
6261
{{
6362
public static void RegisterAll()
6463
{{
65-
TypeCache.Clear();
64+
Staple.Internal.TypeCache.Clear();
6665
";
6766

6867
var types = new HashSet<string>();
@@ -344,7 +343,7 @@ void Name(INamespaceSymbol s)
344343
if (componentTypes.Contains(type) && constructibleTypes.Contains(type))
345344
{
346345
source += $@"
347-
TypeCache.RegisterType(typeof({type}),
346+
Staple.Internal.TypeCache.RegisterType(typeof({type}),
348347
{sizeofSnippet}
349348
{constructorSnippet}
350349
new()
@@ -359,7 +358,7 @@ void Name(INamespaceSymbol s)
359358
else
360359
{
361360
source += $@"
362-
TypeCache.RegisterType(typeof({type}),
361+
Staple.Internal.TypeCache.RegisterType(typeof({type}),
363362
{sizeofSnippet}
364363
{constructorSnippet}
365364
null);

0 commit comments

Comments
 (0)