Skip to content

Commit c1a4c59

Browse files
committed
implement custom shader request type
1 parent 62a1c13 commit c1a4c59

File tree

4 files changed

+158
-176
lines changed

4 files changed

+158
-176
lines changed

source/ShaderCompiler.cs

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -277,38 +277,18 @@ public readonly void ReadTexturePropertiesFromSPV(USpan<byte> fragmentBytes, Lis
277277
/// <summary>
278278
/// Converts the given UTF8 bytes from GLSL to SPIR-V.
279279
/// </summary>
280-
public readonly USpan<byte> GLSLToSPV(USpan<byte> bytes, ShaderStage shaderStage)
280+
public readonly USpan<byte> GLSLToSPV(USpan<byte> bytes, ShaderType type)
281281
{
282282
ThrowIfDisposed();
283+
ThrowIfUnknownType(type);
283284

284-
ShaderKind bytesFormat = default;
285-
if (shaderStage == ShaderStage.Fragment)
286-
{
287-
bytesFormat = ShaderKind.FragmentShader;
288-
}
289-
else if (shaderStage == ShaderStage.Vertex)
290-
{
291-
bytesFormat = ShaderKind.VertexShader;
292-
}
293-
else if (shaderStage == ShaderStage.Compute)
294-
{
295-
bytesFormat = ShaderKind.ComputeShader;
296-
}
297-
else if (shaderStage == ShaderStage.Geometry)
298-
{
299-
bytesFormat = ShaderKind.GeometryShader;
300-
}
301-
else
302-
{
303-
throw new Exception($"Unsupported shader stage {shaderStage}");
304-
}
305-
285+
ShaderKind bytesFormat = (ShaderKind)type;
306286
string entryPoint = "main";
307287
using BinaryWriter entryPointWriter = new(4);
308-
entryPointWriter.WriteUTF8Text(entryPoint);
288+
entryPointWriter.WriteUTF8(entryPoint);
309289
USpan<byte> emptyStringBytes = stackalloc byte[1];
310290
emptyStringBytes[0] = default;
311-
USpan<byte> entryPointBytes = entryPointWriter.GetBytes();
291+
USpan<byte> entryPointBytes = entryPointWriter.AsSpan();
312292
nint result = shaderc_compile_into_spv(pointer, (byte*)bytes.Address, bytes.Length, (int)bytesFormat, (byte*)emptyStringBytes.Address, (byte*)entryPointBytes.Address, options.address);
313293
uint count = (uint)shaderc_result_get_length(result);
314294
uint errorCount = (uint)shaderc_result_get_num_errors(result);
@@ -497,7 +477,16 @@ private static (Type type, byte size) GetRuntimeType(spvc_type type, uint vector
497477
break;
498478
}
499479

500-
throw new Exception("Unsupported type");
480+
throw new InvalidOperationException($"Unsupported value type `{baseType}`");
481+
}
482+
483+
[Conditional("DEBUG")]
484+
private static void ThrowIfUnknownType(ShaderType type)
485+
{
486+
if ((byte)type >= 4)
487+
{
488+
throw new InvalidOperationException($"Unsupported shader type `{type}`");
489+
}
501490
}
502491

503492
public readonly struct Options : IDisposable

source/Shaders.Systems.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
</ItemGroup>
2323

2424
<ItemGroup>
25+
<ProjectReference Include="..\..\data\core\Data.Core.csproj" />
2526
<ProjectReference Include="..\..\shaders\source\Shaders.csproj" />
2627
<ProjectReference Include="..\..\collections\source\Collections.csproj" />
2728
<ProjectReference Include="..\..\simulation\core\Simulation.Core.csproj" />
Lines changed: 121 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using Collections;
2-
using Data;
3-
using Data.Components;
2+
using Data.Messages;
43
using Shaders.Components;
54
using Simulation;
65
using System;
@@ -36,27 +35,36 @@ void ISystem.Start(in SystemContainer systemContainer, in World world)
3635

3736
void ISystem.Update(in SystemContainer systemContainer, in World world, in TimeSpan delta)
3837
{
39-
Schema schema = world.Schema;
4038
ComponentQuery<IsShaderRequest> requestQuery = new(world);
39+
Simulator simulator = systemContainer.simulator;
4140
foreach (var r in requestQuery)
4241
{
4342
ref IsShaderRequest request = ref r.component1;
44-
bool sourceChanged;
4543
Entity shader = new(world, r.entity);
46-
if (!shaderVersions.ContainsKey(shader))
44+
if (request.status == IsShaderRequest.Status.Submitted)
4745
{
48-
sourceChanged = true;
49-
}
50-
else
51-
{
52-
sourceChanged = shaderVersions[shader] != request.version;
46+
request.status = IsShaderRequest.Status.Loading;
47+
Trace.WriteLine($"Started searching data for shader `{shader}` with address `{request.address}`");
5348
}
5449

55-
if (sourceChanged)
50+
if (request.status == IsShaderRequest.Status.Loading)
5651
{
57-
if (TryLoadShader(shader, request, schema))
52+
IsShaderRequest dataRequest = request;
53+
if (TryLoadShader(shader, dataRequest, simulator))
54+
{
55+
Trace.WriteLine($"Shader `{shader}` has been loaded");
56+
57+
//todo: being done this way because reference to the request may have shifted
58+
world.SetComponent(r.entity, dataRequest.BecomeLoaded());
59+
}
60+
else
5861
{
59-
shaderVersions.AddOrSet(shader, request.version);
62+
request.duration += delta;
63+
if (request.duration >= request.timeout)
64+
{
65+
Trace.TraceError($"Shader `{shader}` could not be loaded");
66+
request.status = IsShaderRequest.Status.NotFound;
67+
}
6068
}
6169
}
6270
}
@@ -88,133 +96,116 @@ private readonly void PerformOperations(World world)
8896
}
8997
}
9098

91-
/// <summary>
92-
/// Updates the shader entity with up to date <see cref="ShaderUniformProperty"/>,
93-
/// <see cref="ShaderSamplerProperty"/>, and <see cref="ShaderVertexInputAttribute"/> collections.
94-
/// <para>Modifies the `byte` lists to contain SPV bytecode.</para>
95-
/// </summary>
96-
private readonly bool TryLoadShader(Entity shader, IsShaderRequest request, Schema schema)
99+
private readonly bool TryLoadShader(Entity shader, IsShaderRequest request, Simulator simulator)
97100
{
98-
World world = shader.GetWorld();
99-
DataRequest vertex = new(world, shader.GetReference(request.vertex));
100-
DataRequest fragment = new(world, shader.GetReference(request.fragment));
101-
while (!vertex.Is() || !fragment.Is())
101+
HandleDataRequest message = new(shader, request.address);
102+
if (simulator.TryHandleMessage(ref message))
102103
{
103-
Trace.WriteLine($"Waiting for shader request `{shader}` to have data available");
104-
//todo: fault: if data update performs after shader update, then this may never break, kinda scary
105-
//Console.WriteLine("hanging shaders");
106-
//Thread.Sleep(1);
107-
return false;
108-
}
109-
110-
Trace.WriteLine($"Starting shader compilation for `{shader}`");
111-
USpan<BinaryData> spvVertex = shaderCompiler.GLSLToSPV(vertex.Data, ShaderStage.Vertex).As<BinaryData>();
112-
USpan<BinaryData> spvFragment = shaderCompiler.GLSLToSPV(fragment.Data, ShaderStage.Fragment).As<BinaryData>();
113-
114-
Operation operation = new();
115-
Operation.SelectedEntity selectedEntity;
116-
ref IsShader component = ref shader.TryGetComponent<IsShader>(out bool contains);
117-
if (contains)
118-
{
119-
uint existingVertex = shader.GetReference(component.vertex);
120-
uint existingFragment = shader.GetReference(component.fragment);
121-
122-
selectedEntity = operation.SelectEntity(existingVertex);
123-
selectedEntity.ResizeArray<BinaryData>(spvVertex.Length, schema);
124-
selectedEntity.SetArrayElements(0, spvVertex, schema);
125-
126-
operation.ClearSelection();
127-
selectedEntity = operation.SelectEntity(existingFragment);
128-
selectedEntity.ResizeArray<BinaryData>(spvFragment.Length, schema);
129-
selectedEntity.SetArrayElements(0, spvFragment, schema);
130-
131-
operation.ClearSelection();
132-
selectedEntity = operation.SelectEntity(shader);
133-
selectedEntity.SetComponent(new IsShader(component.vertex, component.fragment, component.version + 1), schema);
134-
}
135-
else
136-
{
137-
selectedEntity = operation.CreateEntity();
138-
selectedEntity.CreateArray(spvVertex, schema);
139-
140-
selectedEntity = operation.CreateEntity();
141-
selectedEntity.CreateArray(spvFragment, schema);
142-
143-
operation.ClearSelection();
144-
selectedEntity = operation.SelectEntity(shader);
145-
selectedEntity.AddReferenceTowardsPreviouslyCreatedEntity(1); //for vertex
146-
selectedEntity.AddReferenceTowardsPreviouslyCreatedEntity(0); //for fragment
147-
148-
uint referenceCount = shader.GetReferenceCount();
149-
selectedEntity.AddComponent(new IsShader((rint)(referenceCount + 1), (rint)(referenceCount + 2)), schema);
150-
}
104+
if (message.loaded)
105+
{
106+
ShaderType type = request.type;
107+
Schema schema = shader.world.Schema;
108+
109+
Trace.WriteLine($"Loading shader data onto entity `{shader}`");
110+
USpan<byte> sourceBytes = message.Bytes;
111+
USpan<byte> shaderBytes = shaderCompiler.GLSLToSPV(sourceBytes, type);
112+
Operation operation = new();
113+
Operation.SelectedEntity selectedEntity = operation.SelectEntity(shader);
114+
if (shader.TryGetComponent(out IsShader component))
115+
{
116+
selectedEntity.SetComponent(component.IncrementVersion(), schema);
117+
}
118+
else
119+
{
120+
selectedEntity.AddComponent(new IsShader(0, type), schema);
121+
}
151122

152-
using List<ShaderPushConstant> pushConstants = new();
153-
using List<ShaderUniformProperty> uniformProperties = new();
154-
using List<ShaderUniformPropertyMember> uniformPropertyMembers = new();
155-
using List<ShaderSamplerProperty> textureProperties = new();
156-
using List<ShaderVertexInputAttribute> vertexInputAttributes = new();
123+
//set the shader bytes
124+
if (shader.ContainsArray<ShaderByte>())
125+
{
126+
selectedEntity.ResizeArray<ShaderByte>(shaderBytes.Length, schema);
127+
selectedEntity.SetArrayElements(0, shaderBytes.As<ShaderByte>(), schema);
128+
}
129+
else
130+
{
131+
selectedEntity.CreateArray(shaderBytes.As<ShaderByte>(), schema);
132+
}
157133

158-
//fill in shader data
159-
shaderCompiler.ReadPushConstantsFromSPV(spvVertex.As<byte>(), pushConstants);
160-
shaderCompiler.ReadUniformPropertiesFromSPV(spvVertex.As<byte>(), uniformProperties, uniformPropertyMembers);
161-
shaderCompiler.ReadTexturePropertiesFromSPV(spvFragment.As<byte>(), textureProperties);
162-
shaderCompiler.ReadVertexInputAttributesFromSPV(spvVertex.As<byte>(), vertexInputAttributes);
134+
//fill metadata
135+
using List<ShaderUniformPropertyMember> uniformPropertyMembers = new();
136+
using List<ShaderUniformProperty> uniformProperties = new();
137+
shaderCompiler.ReadUniformPropertiesFromSPV(shaderBytes, uniformProperties, uniformPropertyMembers);
163138

164-
//make sure lists for shader properties exists
165-
if (!shader.ContainsArray<ShaderPushConstant>())
166-
{
167-
selectedEntity.CreateArray(pushConstants.AsSpan(), schema);
168-
}
169-
else
170-
{
171-
selectedEntity.ResizeArray<ShaderPushConstant>(pushConstants.Count, schema);
172-
selectedEntity.SetArrayElements(0, pushConstants.AsSpan(), schema);
173-
}
139+
if (!shader.ContainsArray<ShaderUniformProperty>())
140+
{
141+
selectedEntity.CreateArray(uniformProperties.AsSpan(), schema);
142+
}
143+
else
144+
{
145+
selectedEntity.ResizeArray<ShaderUniformProperty>(uniformProperties.Count, schema);
146+
selectedEntity.SetArrayElements(0, uniformProperties.AsSpan(), schema);
147+
}
174148

175-
if (!shader.ContainsArray<ShaderUniformProperty>())
176-
{
177-
selectedEntity.CreateArray(uniformProperties.AsSpan(), schema);
178-
}
179-
else
180-
{
181-
selectedEntity.ResizeArray<ShaderUniformProperty>(uniformProperties.Count, schema);
182-
selectedEntity.SetArrayElements(0, uniformProperties.AsSpan(), schema);
183-
}
149+
if (!shader.ContainsArray<ShaderUniformPropertyMember>())
150+
{
151+
selectedEntity.CreateArray(uniformPropertyMembers.AsSpan(), schema);
152+
}
153+
else
154+
{
155+
selectedEntity.ResizeArray<ShaderUniformPropertyMember>(uniformPropertyMembers.Count, schema);
156+
selectedEntity.SetArrayElements(0, uniformPropertyMembers.AsSpan(), schema);
157+
}
184158

185-
if (!shader.ContainsArray<ShaderUniformPropertyMember>())
186-
{
187-
selectedEntity.CreateArray(uniformPropertyMembers.AsSpan(), schema);
188-
}
189-
else
190-
{
191-
selectedEntity.ResizeArray<ShaderUniformPropertyMember>(uniformPropertyMembers.Count, schema);
192-
selectedEntity.SetArrayElements(0, uniformPropertyMembers.AsSpan(), schema);
193-
}
159+
if (type == ShaderType.Vertex)
160+
{
161+
using List<ShaderPushConstant> pushConstants = new();
162+
using List<ShaderVertexInputAttribute> vertexInputAttributes = new();
163+
shaderCompiler.ReadPushConstantsFromSPV(shaderBytes, pushConstants);
164+
shaderCompiler.ReadVertexInputAttributesFromSPV(shaderBytes, vertexInputAttributes);
165+
166+
if (!shader.ContainsArray<ShaderPushConstant>())
167+
{
168+
selectedEntity.CreateArray(pushConstants.AsSpan(), schema);
169+
}
170+
else
171+
{
172+
selectedEntity.ResizeArray<ShaderPushConstant>(pushConstants.Count, schema);
173+
selectedEntity.SetArrayElements(0, pushConstants.AsSpan(), schema);
174+
}
175+
176+
if (!shader.ContainsArray<ShaderVertexInputAttribute>())
177+
{
178+
selectedEntity.CreateArray(vertexInputAttributes.AsSpan(), schema);
179+
}
180+
else
181+
{
182+
selectedEntity.ResizeArray<ShaderVertexInputAttribute>(vertexInputAttributes.Count, schema);
183+
selectedEntity.SetArrayElements(0, vertexInputAttributes.AsSpan(), schema);
184+
}
185+
}
194186

195-
if (!shader.ContainsArray<ShaderSamplerProperty>())
196-
{
197-
selectedEntity.CreateArray(textureProperties.AsSpan(), schema);
198-
}
199-
else
200-
{
201-
selectedEntity.ResizeArray<ShaderSamplerProperty>(textureProperties.Count, schema);
202-
selectedEntity.SetArrayElements(0, textureProperties.AsSpan(), schema);
203-
}
187+
if (type == ShaderType.Fragment)
188+
{
189+
using List<ShaderSamplerProperty> textureProperties = new();
190+
shaderCompiler.ReadTexturePropertiesFromSPV(shaderBytes, textureProperties);
191+
192+
if (!shader.ContainsArray<ShaderSamplerProperty>())
193+
{
194+
selectedEntity.CreateArray(textureProperties.AsSpan(), schema);
195+
}
196+
else
197+
{
198+
selectedEntity.ResizeArray<ShaderSamplerProperty>(textureProperties.Count, schema);
199+
selectedEntity.SetArrayElements(0, textureProperties.AsSpan(), schema);
200+
}
201+
}
204202

205-
if (!shader.ContainsArray<ShaderVertexInputAttribute>())
206-
{
207-
selectedEntity.CreateArray(vertexInputAttributes.AsSpan(), schema);
208-
}
209-
else
210-
{
211-
selectedEntity.ResizeArray<ShaderVertexInputAttribute>(vertexInputAttributes.Count, schema);
212-
selectedEntity.SetArrayElements(0, vertexInputAttributes.AsSpan(), schema);
203+
operations.Push(operation);
204+
return true;
205+
}
213206
}
214207

215-
operations.Push(operation);
216-
Trace.WriteLine($"Shader `{shader}` compiled with vertex `{vertex}` and fragment `{fragment}`");
217-
return true;
208+
return false;
218209
}
219210
}
220-
}
211+
}

0 commit comments

Comments
 (0)