mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 21:01:52 +00:00
Handle EngineBuffers, Preview Names and variable editor types for materials
This commit is contained in:
@@ -9,12 +9,14 @@ namespace GlitchyEditor.Assets.Editors;
|
|||||||
|
|
||||||
class MaterialEditor
|
class MaterialEditor
|
||||||
{
|
{
|
||||||
public static void ShowEditor(AssetFile assetFile)
|
public static bool ShowEditor(AssetFile assetFile)
|
||||||
{
|
{
|
||||||
|
bool isDirty = false;
|
||||||
|
|
||||||
let material = assetFile.LoadedAsset as Material;
|
let material = assetFile.LoadedAsset as Material;
|
||||||
|
|
||||||
if (material == null)
|
if (material == null)
|
||||||
return;
|
return isDirty;
|
||||||
|
|
||||||
ImGui.PropertyTableStartNewProperty("Base Material");
|
ImGui.PropertyTableStartNewProperty("Base Material");
|
||||||
|
|
||||||
@@ -30,8 +32,15 @@ class MaterialEditor
|
|||||||
ImGui.PropertyTableStartNewRow();
|
ImGui.PropertyTableStartNewRow();
|
||||||
if (ImGui.CollapsingHeader("Parameters", .DefaultOpen | .AllowOverlap | .Framed | .SpanFullWidth | .SpanAllColumns))
|
if (ImGui.CollapsingHeader("Parameters", .DefaultOpen | .AllowOverlap | .Framed | .SpanFullWidth | .SpanAllColumns))
|
||||||
{
|
{
|
||||||
|
String prettyVariableName = scope .();
|
||||||
for (let (variableName, bufferVariable) in material.Variables)
|
for (let (variableName, bufferVariable) in material.Variables)
|
||||||
{
|
{
|
||||||
|
// Don't show engine buffer variables
|
||||||
|
if (!bufferVariable.ConstantBuffer.EngineBufferName.IsEmpty)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.PushID(variableName);
|
ImGui.PushID(variableName);
|
||||||
|
|
||||||
ImGui.PropertyTableStartNewRow();
|
ImGui.PropertyTableStartNewRow();
|
||||||
@@ -47,12 +56,54 @@ class MaterialEditor
|
|||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
StringView displayName = variableName;
|
StringView displayName = bufferVariable.PreviewName;
|
||||||
|
|
||||||
|
if (displayName.IsEmpty)
|
||||||
|
{
|
||||||
|
ToPrettyName(variableName, prettyVariableName);
|
||||||
|
displayName = prettyVariableName;
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.PropertyTableName(displayName);
|
ImGui.PropertyTableName(displayName);
|
||||||
|
|
||||||
// TODO: Somehow pass display name and type from imported shader to here!
|
// TODO: Somehow pass display name and type from imported shader to here!
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
|
|
||||||
|
switch (bufferVariable.EditorTypeName)
|
||||||
|
{
|
||||||
|
case "Color", "ColorHDR":
|
||||||
|
if (bufferVariable.ElementType != .Float || bufferVariable.Rows != 1 ||
|
||||||
|
bufferVariable.Columns < 3)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.ColorEditFlags flags = .None;
|
||||||
|
|
||||||
|
if (_ == "ColorHDR")
|
||||||
|
{
|
||||||
|
flags |= .HDR | .Float;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufferVariable.Columns == 3)
|
||||||
|
{
|
||||||
|
material.GetVariable<float3>(bufferVariable.Name, var value);
|
||||||
|
if (ImGui.ColorEdit3("", ref *(float[3]*)&value, flags))
|
||||||
|
material.SetVariable(bufferVariable.Name, value);
|
||||||
|
}
|
||||||
|
else if (bufferVariable.Columns == 4)
|
||||||
|
{
|
||||||
|
material.GetVariable<float4>(bufferVariable.Name, var value);
|
||||||
|
if (ImGui.ColorEdit4("", ref *(float[4]*)&value, flags))
|
||||||
|
material.SetVariable(bufferVariable.Name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled)
|
||||||
|
{
|
||||||
switch (bufferVariable.ElementType)
|
switch (bufferVariable.ElementType)
|
||||||
{
|
{
|
||||||
case .Float:
|
case .Float:
|
||||||
@@ -89,6 +140,7 @@ class MaterialEditor
|
|||||||
default:
|
default:
|
||||||
ImGui.TextUnformatted(scope $"Element Type {_} not supported");
|
ImGui.TextUnformatted(scope $"Element Type {_} not supported");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
|
|
||||||
@@ -99,6 +151,7 @@ class MaterialEditor
|
|||||||
ImGui.PropertyTableStartNewRow();
|
ImGui.PropertyTableStartNewRow();
|
||||||
if (ImGui.CollapsingHeader("Textures", .DefaultOpen | .AllowOverlap | .Framed | .SpanFullWidth | .SpanAllColumns))
|
if (ImGui.CollapsingHeader("Textures", .DefaultOpen | .AllowOverlap | .Framed | .SpanFullWidth | .SpanAllColumns))
|
||||||
{
|
{
|
||||||
|
String prettyVariableName = scope .();
|
||||||
for (var (textureName, texture) in ref material.Textures)
|
for (var (textureName, texture) in ref material.Textures)
|
||||||
{
|
{
|
||||||
ImGui.PushID(textureName);
|
ImGui.PushID(textureName);
|
||||||
@@ -116,7 +169,17 @@ class MaterialEditor
|
|||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
ImGui.PropertyTableName(textureName);
|
// TODO: Preview Name for textures
|
||||||
|
StringView displayName = "";//texture.PreviewName;
|
||||||
|
|
||||||
|
if (displayName.IsEmpty)
|
||||||
|
{
|
||||||
|
ToPrettyName(textureName, prettyVariableName);
|
||||||
|
displayName = prettyVariableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ImGui.PropertyTableName(displayName);
|
||||||
|
|
||||||
if (ComponentEditWindow.ShowAssetDropTarget<Texture>(ref texture.TextureHandle))
|
if (ComponentEditWindow.ShowAssetDropTarget<Texture>(ref texture.TextureHandle))
|
||||||
{
|
{
|
||||||
@@ -128,6 +191,8 @@ class MaterialEditor
|
|||||||
ImGui.PopID();
|
ImGui.PopID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return isDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool DrawLockButton(bool isLocked)
|
private static bool DrawLockButton(bool isLocked)
|
||||||
@@ -166,4 +231,70 @@ class MaterialEditor
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a variable name to a pretty name as good as reasonably possible.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uglyName">The name of a variable to prettify.</param>
|
||||||
|
/// <returns>The pretty string.</returns>
|
||||||
|
public static void ToPrettyName(StringView uglyName, String outPrettyName)
|
||||||
|
{
|
||||||
|
outPrettyName.PrepareBuffer(uglyName.Length);
|
||||||
|
outPrettyName.Clear();
|
||||||
|
|
||||||
|
bool wasUpper = false;
|
||||||
|
bool inWord = false;
|
||||||
|
bool inNumber = false;
|
||||||
|
|
||||||
|
for (char8 c in uglyName)
|
||||||
|
{
|
||||||
|
if (c.IsLetter)
|
||||||
|
{
|
||||||
|
if (inNumber)
|
||||||
|
{
|
||||||
|
outPrettyName.Append(' ');
|
||||||
|
inNumber = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool newWord = !inWord;
|
||||||
|
|
||||||
|
if (c.IsUpper && !wasUpper)
|
||||||
|
{
|
||||||
|
newWord = true;
|
||||||
|
wasUpper = true;
|
||||||
|
|
||||||
|
if (inWord)
|
||||||
|
{
|
||||||
|
outPrettyName.Append(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c.IsLower)
|
||||||
|
{
|
||||||
|
wasUpper = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
outPrettyName.Append(newWord ? c.ToUpper : c.ToLower);
|
||||||
|
|
||||||
|
inWord = true;
|
||||||
|
}
|
||||||
|
else if (c.IsDigit)
|
||||||
|
{
|
||||||
|
if (inWord)
|
||||||
|
{
|
||||||
|
outPrettyName.Append(' ');
|
||||||
|
inWord = false;
|
||||||
|
inNumber = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
outPrettyName.Append(c);
|
||||||
|
}
|
||||||
|
else if (inWord || inNumber)
|
||||||
|
{
|
||||||
|
outPrettyName.Append(' ');
|
||||||
|
inWord = false;
|
||||||
|
inNumber = false;
|
||||||
|
wasUpper = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -23,8 +23,8 @@ class ShaderExporter : IAssetExporter
|
|||||||
|
|
||||||
File Format:
|
File Format:
|
||||||
Vertex Shader Blob Length (uint64 / 8 bytes) (0 if null)
|
Vertex Shader Blob Length (uint64 / 8 bytes) (0 if null)
|
||||||
Vertex Shader Data...
|
|
||||||
Pixel Shader Blob Length (uint64 / 8 bytes) (0 if null)
|
Pixel Shader Blob Length (uint64 / 8 bytes) (0 if null)
|
||||||
|
Vertex Shader Data...
|
||||||
Pixel Shader Data...
|
Pixel Shader Data...
|
||||||
Texture Count (uint16)
|
Texture Count (uint16)
|
||||||
Textures
|
Textures
|
||||||
@@ -57,6 +57,11 @@ class ShaderExporter : IAssetExporter
|
|||||||
ArraySize (uint64)
|
ArraySize (uint64)
|
||||||
Name Length (uint16)
|
Name Length (uint16)
|
||||||
Name Data...
|
Name Data...
|
||||||
|
Preview Name Length (uint16)
|
||||||
|
Preview Name Data...
|
||||||
|
Type Editor Name Length (uint16)
|
||||||
|
Type Editor Name Data...
|
||||||
|
# TODO: Min and Max
|
||||||
}
|
}
|
||||||
RawData...
|
RawData...
|
||||||
}
|
}
|
||||||
@@ -92,11 +97,7 @@ class ShaderExporter : IAssetExporter
|
|||||||
Try!(stream.Write((uint8)textureEntry.TextureDimension));
|
Try!(stream.Write((uint8)textureEntry.TextureDimension));
|
||||||
Try!(stream.Write((int32)textureEntry.VertexShaderBindPoint));
|
Try!(stream.Write((int32)textureEntry.VertexShaderBindPoint));
|
||||||
Try!(stream.Write((int32)textureEntry.PixelShaderBindPoint));
|
Try!(stream.Write((int32)textureEntry.PixelShaderBindPoint));
|
||||||
|
WriteSizedString<uint16>(stream, textureName);
|
||||||
Log.EngineLogger.Assert(textureName.Length < int16.MaxValue);
|
|
||||||
|
|
||||||
Try!(stream.Write((int16)textureName.Length));
|
|
||||||
Try!(stream.Write(textureName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok;
|
return .Ok;
|
||||||
@@ -117,18 +118,9 @@ class ShaderExporter : IAssetExporter
|
|||||||
Try!(stream.Write((int32)bufferEntry.VertexShaderBindPoint));
|
Try!(stream.Write((int32)bufferEntry.VertexShaderBindPoint));
|
||||||
Try!(stream.Write((int32)bufferEntry.PixelShaderBindPoint));
|
Try!(stream.Write((int32)bufferEntry.PixelShaderBindPoint));
|
||||||
|
|
||||||
Log.EngineLogger.Assert(bufferName.Length < int16.MaxValue);
|
WriteSizedString<uint16>(stream, bufferName);
|
||||||
|
|
||||||
Try!(stream.Write((uint16)bufferName.Length));
|
WriteSizedString<uint16>(stream, bufferEntry.ConstantBuffer.EngineBufferName);
|
||||||
Try!(stream.Write(bufferName));
|
|
||||||
|
|
||||||
int engineBufferNameLength = bufferEntry.ConstantBuffer.EngineBufferName.Length;
|
|
||||||
Log.EngineLogger.Assert(engineBufferNameLength < int16.MaxValue);
|
|
||||||
|
|
||||||
Try!(stream.Write((uint16)engineBufferNameLength));
|
|
||||||
|
|
||||||
if (engineBufferNameLength > 0)
|
|
||||||
Try!(stream.Write(bufferEntry.ConstantBuffer.EngineBufferName));
|
|
||||||
|
|
||||||
Log.EngineLogger.Assert(buffer.Variables.Count < int16.MaxValue);
|
Log.EngineLogger.Assert(buffer.Variables.Count < int16.MaxValue);
|
||||||
|
|
||||||
@@ -148,10 +140,9 @@ class ShaderExporter : IAssetExporter
|
|||||||
Try!(stream.Write((uint8)variable.Columns));
|
Try!(stream.Write((uint8)variable.Columns));
|
||||||
Try!(stream.Write((uint64)variable.ArraySize));
|
Try!(stream.Write((uint64)variable.ArraySize));
|
||||||
|
|
||||||
Log.EngineLogger.Assert(variableName.Length < int16.MaxValue);
|
WriteSizedString<uint16>(stream, variableName);
|
||||||
|
WriteSizedString<uint16>(stream, variable.PreviewName);
|
||||||
Try!(stream.Write((uint16)variableName.Length));
|
WriteSizedString<uint16>(stream, variable.EditorType);
|
||||||
Try!(stream.Write(variableName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Try!(stream.Write(Span<uint8>(buffer.RawData, 0, buffer.Size)));
|
Try!(stream.Write(Span<uint8>(buffer.RawData, 0, buffer.Size)));
|
||||||
@@ -159,4 +150,20 @@ class ShaderExporter : IAssetExporter
|
|||||||
|
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Result<void> WriteSizedString<Tint>(Stream stream, StringView string)
|
||||||
|
where Tint : IInteger
|
||||||
|
where int : operator explicit Tint
|
||||||
|
where Tint : operator explicit int
|
||||||
|
where Tint : struct
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Assert(string.Length < (int)typeof(Tint).MaxValue);
|
||||||
|
|
||||||
|
Try!(stream.Write((Tint)string.Length));
|
||||||
|
|
||||||
|
if (string.Length > 0)
|
||||||
|
Try!(stream.WriteStrUnsized(string));
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace GlitchyEditor.Assets.Importers;
|
|||||||
abstract class Config
|
abstract class Config
|
||||||
{
|
{
|
||||||
[BonIgnore]
|
[BonIgnore]
|
||||||
protected bool _changed = true;
|
protected bool _changed = false;
|
||||||
|
|
||||||
public bool Changed => _changed;
|
public bool Changed => _changed;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,331 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using GlitchyEngine;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
|
||||||
|
namespace GlitchyEditor.Assets.Processors;
|
||||||
|
|
||||||
|
static class ShaderCodePreprocessor
|
||||||
|
{
|
||||||
|
public static Result<void> ProcessFileContent(String fileContent, String outVsName, String outPsName,
|
||||||
|
Dictionary<StringView, ShaderVariable> outVarDescs,
|
||||||
|
List<String> outBufferNames, Dictionary<StringView, StringView> outEngineBuffers)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
Dictionary<StringView, StringView> arguments = scope .();
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if ((int Start, int End) value = GetNextPreprocessor(fileContent, index, let name, arguments..Clear()))
|
||||||
|
{
|
||||||
|
index = value.End;
|
||||||
|
|
||||||
|
switch(name)
|
||||||
|
{
|
||||||
|
case "Effect":
|
||||||
|
for (let (argName, argValue) in arguments)
|
||||||
|
{
|
||||||
|
switch(argName)
|
||||||
|
{
|
||||||
|
case "VS", "VertexShader":
|
||||||
|
outVsName.Append(argValue);
|
||||||
|
case "PS", "PixelShader":
|
||||||
|
outPsName.Append(argValue);
|
||||||
|
default:
|
||||||
|
Log.EngineLogger.Error($"Unknown parameter name \"{name}\".");
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "EditorVariable":
|
||||||
|
Try!(ProcessEditorVariables(arguments, outVarDescs));
|
||||||
|
case "EngineBuffer":
|
||||||
|
Try!(ProcessEngineBuffer(arguments, outBufferNames, outEngineBuffers));
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommentLine(fileContent, value.Start);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CommentLine(StringView code, int commentPosition)
|
||||||
|
{
|
||||||
|
code[commentPosition] = '/';
|
||||||
|
code[commentPosition + 1] = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Result<(int Start, int End)> GetNextPreprocessor(StringView code, int startindex, out StringView name, Dictionary<StringView, StringView> arguments)
|
||||||
|
{
|
||||||
|
var startindex;
|
||||||
|
|
||||||
|
name = .();
|
||||||
|
|
||||||
|
int startOfLine = -1;
|
||||||
|
int startOfPragma = -1;
|
||||||
|
int endOfLine = startindex;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
repeat
|
||||||
|
{
|
||||||
|
startindex = endOfLine;
|
||||||
|
|
||||||
|
startOfPragma = code.IndexOf("#pragma", startindex);
|
||||||
|
|
||||||
|
if (startOfPragma == -1)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
endOfLine = code.IndexOf('\n', startOfPragma);
|
||||||
|
|
||||||
|
startOfLine = code[...startOfPragma].LastIndexOf('\n');
|
||||||
|
|
||||||
|
// If the line is commented out, look for the next
|
||||||
|
} while (startOfLine != -1 && code[startOfLine...startOfPragma].Contains("//"));
|
||||||
|
|
||||||
|
StringView line = (endOfLine != -1) ? code.Substring(startOfPragma, endOfLine - startOfPragma) : code.Substring(startOfPragma);
|
||||||
|
|
||||||
|
// cut off the #pragma
|
||||||
|
line = line.Substring(7);
|
||||||
|
|
||||||
|
int lBracketIndex = line.IndexOf('[');
|
||||||
|
|
||||||
|
if (lBracketIndex == -1)
|
||||||
|
{
|
||||||
|
name = line..Trim();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = line.Substring(0, lBracketIndex);
|
||||||
|
name.Trim();
|
||||||
|
|
||||||
|
int rBracketIndex = line.IndexOf(']');
|
||||||
|
|
||||||
|
if (rBracketIndex == -1)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error($"Pragma is missing closing Bracket (\"{line}\")");
|
||||||
|
rBracketIndex = line.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringView argumentText = line.Substring(lBracketIndex + 1, rBracketIndex - lBracketIndex - 1);
|
||||||
|
|
||||||
|
for (StringView argument in argumentText.Split(';'))
|
||||||
|
{
|
||||||
|
int equalsIndex = argument.IndexOf('=');
|
||||||
|
|
||||||
|
StringView argumentName = .();
|
||||||
|
StringView argumentValue = .();
|
||||||
|
|
||||||
|
if (equalsIndex == -1)
|
||||||
|
{
|
||||||
|
argumentName = argument;
|
||||||
|
argumentName.Trim();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
argumentName = argument.Substring(0, equalsIndex);
|
||||||
|
argumentName.Trim();
|
||||||
|
|
||||||
|
argumentValue = argument.Substring(equalsIndex + 1);
|
||||||
|
argumentValue.Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.ContainsKey(argumentName))
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error($"Arguments \"{argumentName}\" already exists.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments.Add(argumentName, argumentValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Ok((startOfPragma, endOfLine));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Result<void> ProcessEngineBuffer(Dictionary<StringView, StringView> arguments,
|
||||||
|
List<String> outBufferNames, Dictionary<StringView, StringView> outEngineBuffers)
|
||||||
|
{
|
||||||
|
String nameInEngine = null;
|
||||||
|
String nameInShader = null;
|
||||||
|
|
||||||
|
defer
|
||||||
|
{
|
||||||
|
if (@return case .Err)
|
||||||
|
{
|
||||||
|
delete nameInEngine;
|
||||||
|
delete nameInShader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var (argName, argValue) in arguments)
|
||||||
|
{
|
||||||
|
if (argValue.StartsWith('"') && argValue.EndsWith('"'))
|
||||||
|
{
|
||||||
|
argValue = argValue[1...^2];
|
||||||
|
}
|
||||||
|
switch (argName)
|
||||||
|
{
|
||||||
|
case "Name":
|
||||||
|
nameInShader = new String(argValue);
|
||||||
|
case "Binding":
|
||||||
|
nameInEngine = new String(argValue);
|
||||||
|
default:
|
||||||
|
Log.EngineLogger.Error($"Unknown parameter for EngineBuffer: \"{argName}\".");
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String.IsNullOrWhiteSpace(nameInEngine) || String.IsNullOrWhiteSpace(nameInShader))
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error($"Name and Binding need to be defined.");
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
outBufferNames.Add(nameInShader);
|
||||||
|
outBufferNames.Add(nameInEngine);
|
||||||
|
outEngineBuffers.Add(nameInShader, nameInEngine);
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Result<void> ProcessEditorVariables(Dictionary<StringView, StringView> arguments, Dictionary<StringView, ShaderVariable> outVarDescs)
|
||||||
|
{
|
||||||
|
ShaderVariable variable = new .();
|
||||||
|
|
||||||
|
defer
|
||||||
|
{
|
||||||
|
if (@return case .Err)
|
||||||
|
delete variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var (name, value) in arguments)
|
||||||
|
{
|
||||||
|
if (value.StartsWith('"') && value.EndsWith('"'))
|
||||||
|
{
|
||||||
|
value = value[1...^2];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(name)
|
||||||
|
{
|
||||||
|
case "Name":
|
||||||
|
variable.Name = value;
|
||||||
|
case "Preview":
|
||||||
|
variable.PreviewName = value;
|
||||||
|
case "Type":
|
||||||
|
variable.EditorType = value;
|
||||||
|
case "Min":
|
||||||
|
variable.MinValue = Try!(ParseVariableValue(value));
|
||||||
|
case "Max":
|
||||||
|
variable.MaxValue = Try!(ParseVariableValue(value));
|
||||||
|
default:
|
||||||
|
Variant paramValue = Variant.Create(new String(value), true);
|
||||||
|
variable.AddParameter(name, paramValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (variable.Name.IsWhiteSpace)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("Failed to process shader: Missing argument \"Name\" int variable description.");
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
outVarDescs.Add(variable.Name, variable);
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Result<Variant> ParseVariableValue(StringView valueString)
|
||||||
|
{
|
||||||
|
// TODO: Simply always use double?
|
||||||
|
|
||||||
|
if (valueString[0].IsDigit || valueString[0] == '-')
|
||||||
|
{
|
||||||
|
var valueString;
|
||||||
|
|
||||||
|
if (valueString.EndsWith('f'))
|
||||||
|
valueString.Length--;
|
||||||
|
|
||||||
|
float value = Try!(float.Parse(valueString));
|
||||||
|
|
||||||
|
return Variant.Create(value);
|
||||||
|
}
|
||||||
|
else if (valueString.StartsWith("float"))
|
||||||
|
{
|
||||||
|
int index = 5;
|
||||||
|
|
||||||
|
int numComponents = valueString[index++] - '0';
|
||||||
|
|
||||||
|
while (valueString[index] != '(')
|
||||||
|
{
|
||||||
|
if (!valueString[index].IsWhiteSpace)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("Failed to process shader: Expected '('.");
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numComponents < 2 || numComponents > 4)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error($"Failed to process shader: Unsupported component count {numComponents}. Value must be between 2 and 4.");
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] floats = scope float[numComponents];
|
||||||
|
|
||||||
|
for (int i < numComponents)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char8 c = valueString[++index];
|
||||||
|
|
||||||
|
if (c.IsDigit || c == '.' || c == '-')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int start = index;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char8 c = valueString[++index];
|
||||||
|
|
||||||
|
if (!c.IsDigit && c != '.')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int end = index;
|
||||||
|
|
||||||
|
StringView numberView = .(valueString, start, end - start);
|
||||||
|
|
||||||
|
var result = float.Parse(numberView);
|
||||||
|
|
||||||
|
if (result case .Ok(let value))
|
||||||
|
{
|
||||||
|
floats[i] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numComponents == 2)
|
||||||
|
return Variant.Create(*(float2*)floats.Ptr);
|
||||||
|
else if (numComponents == 3)
|
||||||
|
return Variant.Create(*(float3*)floats.Ptr);
|
||||||
|
else
|
||||||
|
return Variant.Create(*(float4*)floats.Ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error($"Failed to process shader: Unsupported variable value: \"{valueString}\".");
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -109,6 +109,8 @@ class ReflectedTexture
|
|||||||
class ReflectedConstantBufferVariable
|
class ReflectedConstantBufferVariable
|
||||||
{
|
{
|
||||||
private String _name ~ delete _;
|
private String _name ~ delete _;
|
||||||
|
private String _previewName ~ delete _;
|
||||||
|
private String _editorType ~ delete _;
|
||||||
|
|
||||||
public StringView Name
|
public StringView Name
|
||||||
{
|
{
|
||||||
@@ -116,6 +118,18 @@ class ReflectedConstantBufferVariable
|
|||||||
set => String.NewOrSet!(_name, value);
|
set => String.NewOrSet!(_name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StringView PreviewName
|
||||||
|
{
|
||||||
|
get => _previewName;
|
||||||
|
set => String.NewOrSet!(_previewName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView EditorType
|
||||||
|
{
|
||||||
|
get => _editorType;
|
||||||
|
set => String.NewOrSet!(_editorType, value);
|
||||||
|
}
|
||||||
|
|
||||||
public int Offset;
|
public int Offset;
|
||||||
public int SizeInBytes;
|
public int SizeInBytes;
|
||||||
public bool IsUsed;
|
public bool IsUsed;
|
||||||
@@ -125,6 +139,9 @@ class ReflectedConstantBufferVariable
|
|||||||
public int Columns;
|
public int Columns;
|
||||||
|
|
||||||
public int ArraySize;
|
public int ArraySize;
|
||||||
|
|
||||||
|
public Variant MinValue;
|
||||||
|
public Variant MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Dx11
|
// TODO: Dx11
|
||||||
@@ -146,16 +163,29 @@ class ShaderCompiler
|
|||||||
|
|
||||||
CompiledShader shader = new CompiledShader();
|
CompiledShader shader = new CompiledShader();
|
||||||
|
|
||||||
Try!(PlatformCompileShaderFromSource(code, assetIdentifier, entryPoint, compileTarget, defines, shader));
|
ShaderCompilationContext context = scope .();
|
||||||
|
|
||||||
Try!(PlatformReflectShader(shader));
|
Try!(PlatformCompileShaderFromSource(code, assetIdentifier, entryPoint, compileTarget, defines, shader, context));
|
||||||
|
|
||||||
|
Try!(PlatformReflectShader(shader, context));
|
||||||
|
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static extern Result<void> PlatformCompileShaderFromSource(StringView code, AssetIdentifier fileName, StringView entryPoint, StringView compileTarget, Span<ShaderDefineValue> defines, CompiledShader outShader);
|
protected static extern Result<void> PlatformCompileShaderFromSource(StringView code, AssetIdentifier fileName, StringView entryPoint, StringView compileTarget, Span<ShaderDefineValue> defines, CompiledShader outShader, ShaderCompilationContext context);
|
||||||
|
|
||||||
protected static extern Result<void> PlatformReflectShader(CompiledShader shader);
|
protected static extern Result<void> PlatformReflectShader(CompiledShader shader, ShaderCompilationContext context);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShaderCompilationContext
|
||||||
|
{
|
||||||
|
public append String VsName = String();
|
||||||
|
public append String PsName = String();
|
||||||
|
|
||||||
|
public append Dictionary<StringView, ShaderVariable> Variables = .() ~ ClearDictionaryAndDeleteValues!(_);
|
||||||
|
public append List<String> BufferNames = .() ~ ClearAndDeleteItems!(_);
|
||||||
|
// Name in Shader -> Name in Engine
|
||||||
|
public append Dictionary<StringView, StringView> EngineBuffers = .();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Dx11
|
// TODO: Dx11
|
||||||
@@ -169,7 +199,7 @@ extension ShaderCompiler
|
|||||||
.OptimizationLevel3;
|
.OptimizationLevel3;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected static override Result<void> PlatformCompileShaderFromSource(StringView code, AssetIdentifier fileName, StringView entryPoint, StringView compileTarget, Span<ShaderDefineValue> defines, CompiledShader outShader)
|
protected static override Result<void> PlatformCompileShaderFromSource(StringView code, AssetIdentifier fileName, StringView entryPoint, StringView compileTarget, Span<ShaderDefineValue> defines, CompiledShader outShader, ShaderCompilationContext context)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
@@ -192,7 +222,11 @@ extension ShaderCompiler
|
|||||||
|
|
||||||
Path.GetDirectoryPath(fileName, directory);
|
Path.GetDirectoryPath(fileName, directory);
|
||||||
|
|
||||||
using (let includer = Includer(directory))
|
String shaderCode = new:ScopedAlloc! String(code);
|
||||||
|
|
||||||
|
Try!(ShaderCodePreprocessor.ProcessFileContent(shaderCode, context.VsName, context.PsName, context.Variables, context.BufferNames, context.EngineBuffers));
|
||||||
|
|
||||||
|
using (let includer = PreprocessingIncluder(directory, context))
|
||||||
{
|
{
|
||||||
var result = D3DCompiler.D3DCompile(code.Ptr, (.)code.Length, fileName.FullIdentifier.ToScopeCStr!(), nativeMacros, &includer, entryPoint.ToScopeCStr!(),
|
var result = D3DCompiler.D3DCompile(code.Ptr, (.)code.Length, fileName.FullIdentifier.ToScopeCStr!(), nativeMacros, &includer, entryPoint.ToScopeCStr!(),
|
||||||
compileTarget.ToScopeCStr!(), DefaultCompileFlags /* Pass down compile flags? */, .None, &outShader._shaderBlob, &errorBlob);
|
compileTarget.ToScopeCStr!(), DefaultCompileFlags /* Pass down compile flags? */, .None, &outShader._shaderBlob, &errorBlob);
|
||||||
@@ -210,7 +244,7 @@ extension ShaderCompiler
|
|||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override static Result<void> PlatformReflectShader(CompiledShader shader)
|
protected override static Result<void> PlatformReflectShader(CompiledShader shader, ShaderCompilationContext context)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
@@ -253,7 +287,7 @@ extension ShaderCompiler
|
|||||||
// ConstantBuffer
|
// ConstantBuffer
|
||||||
if(bufferDesc.Type == .D3D11_CT_CBUFFER)
|
if(bufferDesc.Type == .D3D11_CT_CBUFFER)
|
||||||
{
|
{
|
||||||
ReflectedConstantBuffer cbuffer = Try!(ReflectConstantBuffer(bindDesc, bufferReflection));
|
ReflectedConstantBuffer cbuffer = Try!(ReflectConstantBuffer(bindDesc, bufferReflection, context));
|
||||||
shader.AddConstantBuffer(cbuffer);
|
shader.AddConstantBuffer(cbuffer);
|
||||||
}
|
}
|
||||||
case .Texture:
|
case .Texture:
|
||||||
@@ -290,7 +324,7 @@ extension ShaderCompiler
|
|||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Result<ReflectedConstantBuffer> ReflectConstantBuffer(ShaderInputBindDescription bindDesc, ID3D11ShaderReflectionConstantBuffer* bufferReflection)
|
private static Result<ReflectedConstantBuffer> ReflectConstantBuffer(ShaderInputBindDescription bindDesc, ID3D11ShaderReflectionConstantBuffer* bufferReflection, ShaderCompilationContext context)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
@@ -310,17 +344,22 @@ extension ShaderCompiler
|
|||||||
{
|
{
|
||||||
ID3D11ShaderReflectionVariable* variableReflection = bufferReflection.GetVariableByIndex(v);
|
ID3D11ShaderReflectionVariable* variableReflection = bufferReflection.GetVariableByIndex(v);
|
||||||
|
|
||||||
if (ReflectConstantBufferVariable(buffer, variableReflection) case .Err)
|
if (ReflectConstantBufferVariable(buffer, variableReflection, context) case .Err)
|
||||||
{
|
{
|
||||||
delete buffer;
|
delete buffer;
|
||||||
return .Err;
|
return .Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context.EngineBuffers.TryGetValue(buffer.Name, let engineBufferName))
|
||||||
|
{
|
||||||
|
buffer.EngineBufferName = engineBufferName;
|
||||||
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Result<void> ReflectConstantBufferVariable(ReflectedConstantBuffer buffer, ID3D11ShaderReflectionVariable* variableReflection)
|
private static Result<void> ReflectConstantBufferVariable(ReflectedConstantBuffer buffer, ID3D11ShaderReflectionVariable* variableReflection, ShaderCompilationContext context)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
@@ -375,13 +414,23 @@ extension ShaderCompiler
|
|||||||
Internal.MemCpy(&buffer.RawData[variable.Offset], variableDescription.DefaultValue, variable.SizeInBytes);
|
Internal.MemCpy(&buffer.RawData[variable.Offset], variableDescription.DefaultValue, variable.SizeInBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context.Variables.TryGetValue(variable.Name, let variableAnnotation))
|
||||||
|
{
|
||||||
|
variable.PreviewName = variableAnnotation.PreviewName;
|
||||||
|
variable.EditorType = variableAnnotation.EditorType;
|
||||||
|
|
||||||
|
// TODO: We need to somehow validate against our variable type
|
||||||
|
variable.MinValue = variableAnnotation.MinValue;
|
||||||
|
variable.MaxValue = variableAnnotation.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
buffer.AddVariable(variable);
|
buffer.AddVariable(variable);
|
||||||
|
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Includer : ID3DInclude, IDisposable
|
struct PreprocessingIncluder : ID3DInclude, IDisposable
|
||||||
{
|
{
|
||||||
private VTable _vTable;
|
private VTable _vTable;
|
||||||
|
|
||||||
@@ -389,7 +438,9 @@ struct Includer : ID3DInclude, IDisposable
|
|||||||
|
|
||||||
private String _parentFileDirectory;
|
private String _parentFileDirectory;
|
||||||
|
|
||||||
public this(String parentFileDirectory)
|
private ShaderCompilationContext _context;
|
||||||
|
|
||||||
|
public this(String parentFileDirectory, ShaderCompilationContext context)
|
||||||
{
|
{
|
||||||
_parentFileDirectory = parentFileDirectory;
|
_parentFileDirectory = parentFileDirectory;
|
||||||
_loadedFiles = new Dictionary<StringView, (String FileName, String FileContent)>();
|
_loadedFiles = new Dictionary<StringView, (String FileName, String FileContent)>();
|
||||||
@@ -398,6 +449,8 @@ struct Includer : ID3DInclude, IDisposable
|
|||||||
_vTable.Close = => Close;
|
_vTable.Close = => Close;
|
||||||
|
|
||||||
_vt = &_vTable;
|
_vt = &_vTable;
|
||||||
|
|
||||||
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -413,7 +466,7 @@ struct Includer : ID3DInclude, IDisposable
|
|||||||
|
|
||||||
public static HResult Open(ID3DInclude* self, IncludeType includeType, char8* fileNamePtr, void* parentData, void** data, uint32* bytes)
|
public static HResult Open(ID3DInclude* self, IncludeType includeType, char8* fileNamePtr, void* parentData, void** data, uint32* bytes)
|
||||||
{
|
{
|
||||||
Includer* includer = (.)self;
|
PreprocessingIncluder* includer = (.)self;
|
||||||
|
|
||||||
StringView fileName = StringView(fileNamePtr);
|
StringView fileName = StringView(fileNamePtr);
|
||||||
|
|
||||||
@@ -453,6 +506,7 @@ struct Includer : ID3DInclude, IDisposable
|
|||||||
|
|
||||||
if (fileStream == null)
|
if (fileStream == null)
|
||||||
{
|
{
|
||||||
|
return .E_FILENOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
String fileContent = new String();
|
String fileContent = new String();
|
||||||
@@ -469,6 +523,13 @@ struct Includer : ID3DInclude, IDisposable
|
|||||||
|
|
||||||
delete fileStream;
|
delete fileStream;
|
||||||
|
|
||||||
|
String trashbin = scope String();
|
||||||
|
|
||||||
|
if (ShaderCodePreprocessor.ProcessFileContent(fileContent, trashbin, trashbin, includer._context.Variables, includer._context.BufferNames, includer._context.EngineBuffers) case .Err)
|
||||||
|
{
|
||||||
|
return .E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
*data = (void*)fileContent.Ptr;
|
*data = (void*)fileContent.Ptr;
|
||||||
*bytes = (uint32)fileContent.Length;
|
*bytes = (uint32)fileContent.Length;
|
||||||
|
|
||||||
@@ -477,7 +538,7 @@ struct Includer : ID3DInclude, IDisposable
|
|||||||
|
|
||||||
public static HResult Close(ID3DInclude* self, void** data)
|
public static HResult Close(ID3DInclude* self, void** data)
|
||||||
{
|
{
|
||||||
Includer* includer = (.)self;
|
PreprocessingIncluder* includer = (.)self;
|
||||||
|
|
||||||
for (var v in includer._loadedFiles)
|
for (var v in includer._loadedFiles)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ class ProcessedShader : ProcessedResource
|
|||||||
class ShaderVariable
|
class ShaderVariable
|
||||||
{
|
{
|
||||||
private String _name ~ delete _;
|
private String _name ~ delete _;
|
||||||
|
private String _previewName ~ delete _;
|
||||||
|
private String _editorType ~ delete _;
|
||||||
|
|
||||||
private Dictionary<String, Variant> _parameters = new .() ~ {
|
private Dictionary<String, Variant> _parameters = new .() ~ {
|
||||||
for (var (entryKey, entry) in _)
|
for (var (entryKey, entry) in _)
|
||||||
@@ -85,6 +87,21 @@ class ShaderVariable
|
|||||||
set => String.NewOrSet!(_name, value);
|
set => String.NewOrSet!(_name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StringView PreviewName
|
||||||
|
{
|
||||||
|
get => _previewName;
|
||||||
|
set => String.NewOrSet!(_previewName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView EditorType
|
||||||
|
{
|
||||||
|
get => _editorType;
|
||||||
|
set => String.NewOrSet!(_editorType, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Variant MinValue ~ _.Dispose();
|
||||||
|
public Variant MaxValue ~ _.Dispose();
|
||||||
|
|
||||||
public Dictionary<String, Variant> Parameters => _parameters;
|
public Dictionary<String, Variant> Parameters => _parameters;
|
||||||
|
|
||||||
public void AddParameter(StringView name, Variant value)
|
public void AddParameter(StringView name, Variant value)
|
||||||
@@ -134,10 +151,12 @@ class ShaderProcessor : IAssetProcessor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String code = new String(importedShader.HlslCode);
|
String tmpCode = new String(importedShader.HlslCode);
|
||||||
defer { delete code; }
|
|
||||||
|
|
||||||
Try!(ProcessFileContent(code, vsName, psName, variables, bufferNames, engineBuffers));
|
// TODO: This is terrible. Currently we process too often... (here + each shader stage)
|
||||||
|
Try!(ShaderCodePreprocessor.ProcessFileContent(tmpCode , vsName, psName, variables, bufferNames, engineBuffers));
|
||||||
|
|
||||||
|
delete tmpCode;
|
||||||
|
|
||||||
if (String.IsNullOrWhiteSpace(vsName) && String.IsNullOrWhiteSpace(psName))
|
if (String.IsNullOrWhiteSpace(vsName) && String.IsNullOrWhiteSpace(psName))
|
||||||
{
|
{
|
||||||
@@ -147,28 +166,24 @@ class ShaderProcessor : IAssetProcessor
|
|||||||
|
|
||||||
processedShader = new ProcessedShader(new AssetIdentifier(importedShader.AssetIdentifier), config.AssetHandle);
|
processedShader = new ProcessedShader(new AssetIdentifier(importedShader.AssetIdentifier), config.AssetHandle);
|
||||||
|
|
||||||
Try!(CompileAndReflect(vsName, psName, importedShader, code, processedShader));
|
Try!(CompileAndReflect(vsName, psName, importedShader, importedShader.HlslCode, processedShader));
|
||||||
|
|
||||||
Try!(MergeResources(processedShader, variables, engineBuffers));
|
Try!(MergeResources(processedShader));
|
||||||
|
|
||||||
outProcessedResources.Add(processedShader);
|
outProcessedResources.Add(processedShader);
|
||||||
|
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Result<void> MergeResources(ProcessedShader processedShader,
|
private static Result<void> MergeResources(ProcessedShader processedShader)
|
||||||
Dictionary<StringView, ShaderVariable> variables,
|
|
||||||
Dictionary<StringView, StringView> engineBuffers)
|
|
||||||
{
|
{
|
||||||
Try!(MergeConstantBuffers(processedShader, variables, engineBuffers));
|
Try!(MergeConstantBuffers(processedShader));
|
||||||
Try!(MergeTextures(processedShader));
|
Try!(MergeTextures(processedShader));
|
||||||
|
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Result<void> MergeConstantBuffers(ProcessedShader processedShader,
|
private static Result<void> MergeConstantBuffers(ProcessedShader processedShader)
|
||||||
Dictionary<StringView, ShaderVariable> variables,
|
|
||||||
Dictionary<StringView, StringView> engineBuffers)
|
|
||||||
{
|
{
|
||||||
HashSet<StringView> bufferNames = scope .();
|
HashSet<StringView> bufferNames = scope .();
|
||||||
|
|
||||||
@@ -211,11 +226,6 @@ class ShaderProcessor : IAssetProcessor
|
|||||||
Log.EngineLogger.Assert(constantBufferEntry.ConstantBuffer != null);
|
Log.EngineLogger.Assert(constantBufferEntry.ConstantBuffer != null);
|
||||||
Log.EngineLogger.Assert(constantBufferEntry.VertexShaderBindPoint > -1 || constantBufferEntry.PixelShaderBindPoint > -1);
|
Log.EngineLogger.Assert(constantBufferEntry.VertexShaderBindPoint > -1 || constantBufferEntry.PixelShaderBindPoint > -1);
|
||||||
|
|
||||||
if (engineBuffers.TryGetValue(constantBufferEntry.ConstantBuffer.Name, let engineBufferName))
|
|
||||||
{
|
|
||||||
constantBufferEntry.ConstantBuffer.EngineBufferName = engineBufferName;
|
|
||||||
}
|
|
||||||
|
|
||||||
processedShader.AddConstantBuffer(constantBufferEntry);
|
processedShader.AddConstantBuffer(constantBufferEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,304 +293,4 @@ class ShaderProcessor : IAssetProcessor
|
|||||||
|
|
||||||
return ShaderCompiler.CompileAndReflectShader(code, importedShader.AssetIdentifier, vsName, "ps_5_0", .());
|
return ShaderCompiler.CompileAndReflectShader(code, importedShader.AssetIdentifier, vsName, "ps_5_0", .());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Result<void> ProcessFileContent(String fileContent, String outVsName, String outPsName,
|
|
||||||
Dictionary<StringView, ShaderVariable> outVarDescs,
|
|
||||||
List<String> outBufferNames, Dictionary<StringView, StringView> outEngineBuffers)
|
|
||||||
{
|
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
|
||||||
|
|
||||||
Dictionary<StringView, StringView> arguments = scope .();
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if ((int Start, int End) value = GetNextPreprocessor(fileContent, index, let name, arguments..Clear()))
|
|
||||||
{
|
|
||||||
index = value.End;
|
|
||||||
|
|
||||||
switch(name)
|
|
||||||
{
|
|
||||||
case "Effect":
|
|
||||||
for (let (argName, argValue) in arguments)
|
|
||||||
{
|
|
||||||
switch(argName)
|
|
||||||
{
|
|
||||||
case "VS", "VertexShader":
|
|
||||||
outVsName.Append(argValue);
|
|
||||||
case "PS", "PixelShader":
|
|
||||||
outPsName.Append(argValue);
|
|
||||||
default:
|
|
||||||
Log.EngineLogger.Error($"Unknown parameter name \"{name}\".");
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "EditorVariable":
|
|
||||||
Try!(ProcessEditorVariables(arguments, outVarDescs));
|
|
||||||
case "EngineBuffer":
|
|
||||||
Try!(ProcessEngineBuffer(arguments, outBufferNames, outEngineBuffers));
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommentLine(fileContent, value.Start);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return .Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CommentLine(StringView code, int commentPosition)
|
|
||||||
{
|
|
||||||
code[commentPosition] = '/';
|
|
||||||
code[commentPosition + 1] = '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Result<(int Start, int End)> GetNextPreprocessor(StringView code, int startindex, out StringView name, Dictionary<StringView, StringView> arguments)
|
|
||||||
{
|
|
||||||
name = .();
|
|
||||||
|
|
||||||
int startOfLine;
|
|
||||||
int endOfLine;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
startOfLine = code.IndexOf("#pragma", startindex);
|
|
||||||
|
|
||||||
if (startOfLine == -1)
|
|
||||||
return .Err;
|
|
||||||
|
|
||||||
endOfLine = code.IndexOf('\n', startOfLine);
|
|
||||||
|
|
||||||
StringView line = (endOfLine != -1) ? code.Substring(startOfLine, endOfLine - startOfLine) : code.Substring(startOfLine);
|
|
||||||
|
|
||||||
// cut off the #pragma
|
|
||||||
line = line.Substring(7);
|
|
||||||
|
|
||||||
int lBracketIndex = line.IndexOf('[');
|
|
||||||
|
|
||||||
if (lBracketIndex == -1)
|
|
||||||
{
|
|
||||||
name = line..Trim();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
name = line.Substring(0, lBracketIndex);
|
|
||||||
name.Trim();
|
|
||||||
|
|
||||||
int rBracketIndex = line.IndexOf(']');
|
|
||||||
|
|
||||||
if (rBracketIndex == -1)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"Pragma is missing closing Bracket (\"{line}\")");
|
|
||||||
rBracketIndex = line.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringView argumentText = line.Substring(lBracketIndex + 1, rBracketIndex - lBracketIndex - 1);
|
|
||||||
|
|
||||||
for (StringView argument in argumentText.Split(';'))
|
|
||||||
{
|
|
||||||
int equalsIndex = argument.IndexOf('=');
|
|
||||||
|
|
||||||
StringView argumentName = .();
|
|
||||||
StringView argumentValue = .();
|
|
||||||
|
|
||||||
if (equalsIndex == -1)
|
|
||||||
{
|
|
||||||
argumentName = argument;
|
|
||||||
argumentName.Trim();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
argumentName = argument.Substring(0, equalsIndex);
|
|
||||||
argumentName.Trim();
|
|
||||||
|
|
||||||
argumentValue = argument.Substring(equalsIndex + 1);
|
|
||||||
argumentValue.Trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arguments.ContainsKey(argumentName))
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"Arguments \"{argumentName}\" already exists.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
arguments.Add(argumentName, argumentValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return .Ok((startOfLine, endOfLine));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Result<void> ProcessEngineBuffer(Dictionary<StringView, StringView> arguments,
|
|
||||||
List<String> outBufferNames, Dictionary<StringView, StringView> outEngineBuffers)
|
|
||||||
{
|
|
||||||
String nameInEngine = null;
|
|
||||||
String nameInShader = null;
|
|
||||||
|
|
||||||
for (var (argName, argValue) in arguments)
|
|
||||||
{
|
|
||||||
if (argValue.StartsWith('"') && argValue.EndsWith('"'))
|
|
||||||
{
|
|
||||||
argValue = argValue[1...^2];
|
|
||||||
}
|
|
||||||
switch (argName)
|
|
||||||
{
|
|
||||||
case "Name":
|
|
||||||
nameInShader = new String(argValue);
|
|
||||||
case "Binding":
|
|
||||||
nameInEngine = new String(argValue);
|
|
||||||
default:
|
|
||||||
Log.EngineLogger.Error($"Unknown parameter for EngineBuffer: \"{argName}\".");
|
|
||||||
delete nameInEngine;
|
|
||||||
delete nameInShader;
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (String.IsNullOrWhiteSpace(nameInEngine) || String.IsNullOrWhiteSpace(nameInShader))
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"Name and Binding need to be defined.");
|
|
||||||
delete nameInEngine;
|
|
||||||
delete nameInShader;
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
|
|
||||||
outBufferNames.Add(nameInShader);
|
|
||||||
outBufferNames.Add(nameInEngine);
|
|
||||||
outEngineBuffers.Add(nameInShader, nameInEngine);
|
|
||||||
|
|
||||||
return .Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Result<void> ProcessEditorVariables(Dictionary<StringView, StringView> arguments, Dictionary<StringView, ShaderVariable> outVarDescs)
|
|
||||||
{
|
|
||||||
ShaderVariable variable = new .();
|
|
||||||
|
|
||||||
for (var (name, value) in arguments)
|
|
||||||
{
|
|
||||||
if (value.StartsWith('"') && value.EndsWith('"'))
|
|
||||||
{
|
|
||||||
value = value[1...^2];
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(name)
|
|
||||||
{
|
|
||||||
case "Name":
|
|
||||||
variable.Name = value;
|
|
||||||
case "Min", "Max":
|
|
||||||
if (Variant paramValue = ParseVariableValue(value))
|
|
||||||
variable.AddParameter(name, paramValue);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete variable;
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
Variant paramValue = Variant.Create(new String(value), true);
|
|
||||||
variable.AddParameter(name, paramValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (variable.Name.IsWhiteSpace)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error("Failed to process shader: Missing argument \"Name\" int variable description.");
|
|
||||||
|
|
||||||
delete variable;
|
|
||||||
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
|
|
||||||
outVarDescs.Add(variable.Name, variable);
|
|
||||||
|
|
||||||
return .Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Result<Variant> ParseVariableValue(StringView valueString)
|
|
||||||
{
|
|
||||||
if (valueString[0].IsDigit || valueString[0] == '-')
|
|
||||||
{
|
|
||||||
var valueString;
|
|
||||||
|
|
||||||
if (valueString.EndsWith('f'))
|
|
||||||
valueString.Length--;
|
|
||||||
|
|
||||||
float value = Try!(float.Parse(valueString));
|
|
||||||
|
|
||||||
return Variant.Create(value);
|
|
||||||
}
|
|
||||||
else if (valueString.StartsWith("float"))
|
|
||||||
{
|
|
||||||
int index = 5;
|
|
||||||
|
|
||||||
int numComponents = valueString[index++] - '0';
|
|
||||||
|
|
||||||
while (valueString[index] != '(')
|
|
||||||
{
|
|
||||||
if (!valueString[index].IsWhiteSpace)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error("Failed to process shader: Expected '('.");
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numComponents < 2 || numComponents > 4)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"Failed to process shader: Unsupported component count {numComponents}. Value must be between 2 and 4.");
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
|
|
||||||
float[] floats = scope float[numComponents];
|
|
||||||
|
|
||||||
for (int i < numComponents)
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
char8 c = valueString[++index];
|
|
||||||
|
|
||||||
if (c.IsDigit || c == '.' || c == '-')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int start = index;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
char8 c = valueString[++index];
|
|
||||||
|
|
||||||
if (!c.IsDigit && c != '.')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int end = index;
|
|
||||||
|
|
||||||
StringView numberView = .(valueString, start, end - start);
|
|
||||||
|
|
||||||
var result = float.Parse(numberView);
|
|
||||||
|
|
||||||
if (result case .Ok(let value))
|
|
||||||
{
|
|
||||||
floats[i] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numComponents == 2)
|
|
||||||
return Variant.Create(*(float2*)floats.Ptr);
|
|
||||||
else if (numComponents == 3)
|
|
||||||
return Variant.Create(*(float3*)floats.Ptr);
|
|
||||||
else
|
|
||||||
return Variant.Create(*(float4*)floats.Ptr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"Failed to process shader: Unsupported variable value: \"{valueString}\".");
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,15 +172,13 @@ class InspectorWindow : EditorWindow
|
|||||||
(assetFile.AssetConfig?.ProcessorConfig?.Changed == true) ||
|
(assetFile.AssetConfig?.ProcessorConfig?.Changed == true) ||
|
||||||
(assetFile.AssetConfig?.ExporterConfig?.Changed == true);
|
(assetFile.AssetConfig?.ExporterConfig?.Changed == true);
|
||||||
|
|
||||||
if (!hasChanges)
|
ImGui.BeginDisabled(!hasChanges);
|
||||||
ImGui.BeginDisabled();
|
|
||||||
|
|
||||||
if (ImGui.Button("Apply"))
|
if (ImGui.Button("Apply"))
|
||||||
{
|
{
|
||||||
assetFile.SaveAssetConfigIfChanged();
|
assetFile.SaveAssetConfigIfChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasChanges)
|
|
||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,22 @@ class ShaderLoader : IProcessedAssetLoader
|
|||||||
return effect;
|
return effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static mixin ReadScopedSizedString<Tint>(Stream stream)
|
||||||
|
where Tint : IInteger
|
||||||
|
where int : operator explicit Tint
|
||||||
|
where Tint : operator explicit int
|
||||||
|
where Tint : struct
|
||||||
|
{
|
||||||
|
int bufferNameLength = (int)Try!(stream.Read<Tint>());
|
||||||
|
|
||||||
|
String string = scope:mixin String(bufferNameLength);
|
||||||
|
|
||||||
|
if (bufferNameLength > 0)
|
||||||
|
stream.ReadStrSized32(bufferNameLength, string);
|
||||||
|
|
||||||
|
string
|
||||||
|
}
|
||||||
|
|
||||||
private static Result<void> LoadBuffer(Stream stream, Effect effect)
|
private static Result<void> LoadBuffer(Stream stream, Effect effect)
|
||||||
{
|
{
|
||||||
int64 bufferSize = Try!(stream.Read<int64>());
|
int64 bufferSize = Try!(stream.Read<int64>());
|
||||||
@@ -93,24 +109,10 @@ class ShaderLoader : IProcessedAssetLoader
|
|||||||
int32 vertexShaderBindPoint = Try!(stream.Read<int32>());
|
int32 vertexShaderBindPoint = Try!(stream.Read<int32>());
|
||||||
int32 pixelShaderBindPoint = Try!(stream.Read<int32>());
|
int32 pixelShaderBindPoint = Try!(stream.Read<int32>());
|
||||||
|
|
||||||
int16 bufferNameLength = Try!(stream.Read<int16>());
|
String bufferName = ReadScopedSizedString!<uint16>(stream);
|
||||||
String bufferName = scope String(bufferNameLength);
|
String engineBufferName = ReadScopedSizedString!<uint16>(stream);
|
||||||
stream.ReadStrSized32(bufferNameLength, bufferName);
|
|
||||||
|
|
||||||
int16 engineBufferNameLength = Try!(stream.Read<int16>());
|
using (ConstantBuffer buffer = new ConstantBuffer(bufferName, bufferSize, engineBufferName))
|
||||||
String engineBufferName = null;
|
|
||||||
|
|
||||||
if (engineBufferNameLength > 0)
|
|
||||||
{
|
|
||||||
scope String(engineBufferNameLength);
|
|
||||||
stream.ReadStrSized32(engineBufferNameLength, engineBufferName);
|
|
||||||
|
|
||||||
// TODO: Engine buffers currently do nothing. The bind points for each engine buffer are hardcoded.
|
|
||||||
// It only marks the buffer as engine buffer, preventing the variables from becomming accessible.
|
|
||||||
//effect.[Friend]_engineBuffers.Add()
|
|
||||||
}
|
|
||||||
|
|
||||||
using (ConstantBuffer buffer = new ConstantBuffer(bufferName, bufferSize))
|
|
||||||
{
|
{
|
||||||
uint16 variableCount = Try!(stream.Read<uint16>());
|
uint16 variableCount = Try!(stream.Read<uint16>());
|
||||||
|
|
||||||
@@ -124,26 +126,25 @@ class ShaderLoader : IProcessedAssetLoader
|
|||||||
uint8 columns = Try!(stream.Read<uint8>());
|
uint8 columns = Try!(stream.Read<uint8>());
|
||||||
uint64 arraySize = Try!(stream.Read<uint64>());
|
uint64 arraySize = Try!(stream.Read<uint64>());
|
||||||
|
|
||||||
int16 variableNameLength = Try!(stream.Read<int16>());
|
String variableName = ReadScopedSizedString!<uint16>(stream);
|
||||||
String variableName = scope String(variableNameLength);
|
String previewName = ReadScopedSizedString!<uint16>(stream);
|
||||||
stream.ReadStrSized32(variableNameLength, variableName);
|
String editorTypeName = ReadScopedSizedString!<uint16>(stream);
|
||||||
|
|
||||||
if (engineBufferName == null)
|
buffer.AddVariable(variableName, previewName, editorTypeName, variableOffset, sizeInBytes, isUsed, type, rows, columns, arraySize);
|
||||||
buffer.AddVariable(variableName, variableOffset, sizeInBytes, isUsed, type, rows, columns, arraySize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Try!(stream.TryRead(buffer.RawData));
|
Try!(stream.TryRead(buffer.RawData));
|
||||||
Try!(buffer.Apply());
|
Try!(buffer.Apply());
|
||||||
|
|
||||||
if (vertexShaderBindPoint != -1)
|
if (vertexShaderBindPoint != -1)
|
||||||
effect.VertexShader.Buffers.Add(vertexShaderBindPoint, buffer.Name, buffer);
|
effect.VertexShader.Buffers.Add(vertexShaderBindPoint, buffer.Name, engineBufferName, buffer);
|
||||||
|
|
||||||
if (pixelShaderBindPoint != -1)
|
if (pixelShaderBindPoint != -1)
|
||||||
effect.PixelShader.Buffers.Add(pixelShaderBindPoint, buffer.Name, buffer);
|
effect.PixelShader.Buffers.Add(pixelShaderBindPoint, buffer.Name, engineBufferName, buffer);
|
||||||
|
|
||||||
// TODO: Allow binding buffers to different indices? Does this theoretically work with textures?
|
// TODO: Allow binding buffers to different indices? Does this theoretically work with textures?
|
||||||
let tempBindPoint = (vertexShaderBindPoint != -1) ? vertexShaderBindPoint : pixelShaderBindPoint;
|
let tempBindPoint = (vertexShaderBindPoint != -1) ? vertexShaderBindPoint : pixelShaderBindPoint;
|
||||||
effect.Buffers.Add(tempBindPoint, buffer.Name, buffer);
|
effect.Buffers.Add(tempBindPoint, buffer.Name, engineBufferName, buffer);
|
||||||
|
|
||||||
for (var variable in buffer.Variables)
|
for (var variable in buffer.Variables)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,15 +4,16 @@ using GlitchyEngine.Core;
|
|||||||
|
|
||||||
namespace GlitchyEngine.Renderer
|
namespace GlitchyEngine.Renderer
|
||||||
{
|
{
|
||||||
public class BufferCollection : RefCounter, IEnumerable<(String Name, Buffer Buffer)>
|
public class BufferCollection : RefCounter, IEnumerable<(String Name, String EngineBufferName, Buffer Buffer)>
|
||||||
{
|
{
|
||||||
public static extern int MaxBufferSlotCount { get; }
|
public static extern int MaxBufferSlotCount { get; }
|
||||||
|
|
||||||
public typealias BufferEntry = (String Name, Buffer Buffer);
|
public typealias BufferEntry = (String Name, String EngineBufferName, Buffer Buffer);
|
||||||
|
|
||||||
BufferEntry[] _buffers ~ DeleteBufferEntries!(_);
|
BufferEntry[] _buffers ~ DeleteBufferEntries!(_);
|
||||||
|
|
||||||
Dictionary<StringView, BufferEntry*> _strToBuf ~ delete _;
|
Dictionary<StringView, BufferEntry*> _strToBuf ~ delete _;
|
||||||
|
Dictionary<StringView, BufferEntry*> _engineBuffers ~ delete _;
|
||||||
|
|
||||||
[AllowAppend]
|
[AllowAppend]
|
||||||
public this()
|
public this()
|
||||||
@@ -22,9 +23,11 @@ namespace GlitchyEngine.Renderer
|
|||||||
// Todo: append allocate as soon as it's fixed
|
// Todo: append allocate as soon as it's fixed
|
||||||
let buffers = new BufferEntry[MaxBufferSlotCount];
|
let buffers = new BufferEntry[MaxBufferSlotCount];
|
||||||
let strToBuf = new Dictionary<StringView, BufferEntry*>();
|
let strToBuf = new Dictionary<StringView, BufferEntry*>();
|
||||||
|
let engineBuffers = new Dictionary<StringView, BufferEntry*>();
|
||||||
|
|
||||||
_buffers = buffers;
|
_buffers = buffers;
|
||||||
_strToBuf = strToBuf;
|
_strToBuf = strToBuf;
|
||||||
|
_engineBuffers = engineBuffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
@@ -40,6 +43,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
for(let entry in entries)
|
for(let entry in entries)
|
||||||
{
|
{
|
||||||
delete entry.Name;
|
delete entry.Name;
|
||||||
|
delete entry.EngineBufferName;
|
||||||
entry.Buffer?.ReleaseRef();
|
entry.Buffer?.ReleaseRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,13 +124,21 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(int slot, StringView name, Buffer buffer)
|
public void Add(int slot, StringView name, StringView engineBufferName, Buffer buffer)
|
||||||
{
|
{
|
||||||
ref BufferEntry bufferEntry = ref _buffers[slot];
|
ref BufferEntry bufferEntry = ref _buffers[slot];
|
||||||
|
|
||||||
SetReference!(bufferEntry.Buffer, buffer);
|
SetReference!(bufferEntry.Buffer, buffer);
|
||||||
String.NewOrSet!(bufferEntry.Name, name);
|
String.NewOrSet!(bufferEntry.Name, name);
|
||||||
|
|
||||||
|
if (engineBufferName.IsEmpty)
|
||||||
|
DeleteAndNullify!(bufferEntry.EngineBufferName);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String.NewOrSet!(bufferEntry.EngineBufferName, engineBufferName);
|
||||||
|
_engineBuffers.Add(bufferEntry.EngineBufferName, &bufferEntry);
|
||||||
|
}
|
||||||
|
|
||||||
_strToBuf.Add(bufferEntry.Name, &bufferEntry);
|
_strToBuf.Add(bufferEntry.Name, &bufferEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ namespace GlitchyEngine.Renderer
|
|||||||
private ConstantBuffer _constantBuffer;
|
private ConstantBuffer _constantBuffer;
|
||||||
|
|
||||||
private String _name ~ delete _;
|
private String _name ~ delete _;
|
||||||
|
protected String _previewName ~ delete _;
|
||||||
|
protected String _editorTypeName ~ delete _;
|
||||||
|
|
||||||
private ShaderVariableType _elementType;
|
private ShaderVariableType _elementType;
|
||||||
|
|
||||||
@@ -41,6 +43,8 @@ namespace GlitchyEngine.Renderer
|
|||||||
public ShaderVariableType ElementType => _elementType;
|
public ShaderVariableType ElementType => _elementType;
|
||||||
|
|
||||||
public String Name => _name;
|
public String Name => _name;
|
||||||
|
public StringView PreviewName => _previewName;
|
||||||
|
public StringView EditorTypeName => _editorTypeName;
|
||||||
|
|
||||||
public bool IsUsed => _flags.HasFlag(.Used);
|
public bool IsUsed => _flags.HasFlag(.Used);
|
||||||
|
|
||||||
@@ -70,9 +74,11 @@ namespace GlitchyEngine.Renderer
|
|||||||
[Inline]
|
[Inline]
|
||||||
internal uint8* firstByte => _constantBuffer.rawData.CArray() + _offset;
|
internal uint8* firstByte => _constantBuffer.rawData.CArray() + _offset;
|
||||||
|
|
||||||
public this(StringView name, ConstantBuffer constantBuffer, ShaderVariableType type, uint32 columns, uint32 rows, uint32 offset, uint32 sizeInBytes, uint32 arrayElements, bool isUsed)
|
public this(StringView name, ConstantBuffer constantBuffer, ShaderVariableType type, uint32 columns, uint32 rows, uint32 offset, uint32 sizeInBytes, uint32 arrayElements, bool isUsed, StringView previewName, StringView editorTypeName)
|
||||||
{
|
{
|
||||||
_name = new String(name);
|
_name = new String(name);
|
||||||
|
_previewName = new String(previewName);
|
||||||
|
_editorTypeName = new String(editorTypeName);
|
||||||
_constantBuffer = constantBuffer; // Only hold a weak reference. This variable has to die with the buffer
|
_constantBuffer = constantBuffer; // Only hold a weak reference. This variable has to die with the buffer
|
||||||
_elementType = type;
|
_elementType = type;
|
||||||
_columns = columns;
|
_columns = columns;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
public class ConstantBuffer : Buffer
|
public class ConstantBuffer : Buffer
|
||||||
{
|
{
|
||||||
protected String _name ~ delete _;
|
protected String _name ~ delete _;
|
||||||
|
protected String _engineBufferName ~ delete _;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The buffer that contains the buffer data on the CPU.
|
* The buffer that contains the buffer data on the CPU.
|
||||||
@@ -23,6 +24,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
/// Gets the name of the constant buffer.
|
/// Gets the name of the constant buffer.
|
||||||
public StringView Name => _name;
|
public StringView Name => _name;
|
||||||
|
public StringView EngineBufferName => _engineBufferName;
|
||||||
|
|
||||||
public BufferVariableCollection Variables => _variables;
|
public BufferVariableCollection Variables => _variables;
|
||||||
|
|
||||||
@@ -31,9 +33,15 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
protected this() {}
|
protected this() {}
|
||||||
|
|
||||||
public this(StringView name, int64 size)
|
public this(StringView name, int64 size, StringView engineBufferName = "")
|
||||||
{
|
{
|
||||||
_name = new String(name);
|
_name = new String(name);
|
||||||
|
|
||||||
|
if (!engineBufferName.IsEmpty)
|
||||||
|
{
|
||||||
|
_engineBufferName = new String(engineBufferName);
|
||||||
|
}
|
||||||
|
|
||||||
rawData = new uint8[size];
|
rawData = new uint8[size];
|
||||||
ConstructBuffer();
|
ConstructBuffer();
|
||||||
}
|
}
|
||||||
@@ -43,9 +51,9 @@ namespace GlitchyEngine.Renderer
|
|||||||
_variables.Add(ownVariable);
|
_variables.Add(ownVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddVariable(StringView name, uint64 offset, uint64 sizeInBytes, bool isUsed, ShaderVariableType type, uint8 rows, uint8 columns, uint64 arraySize)
|
public void AddVariable(StringView name, StringView previewName, StringView editorTypeName, uint64 offset, uint64 sizeInBytes, bool isUsed, ShaderVariableType type, uint8 rows, uint8 columns, uint64 arraySize)
|
||||||
{
|
{
|
||||||
_variables.Add(new BufferVariable(name, this, type, columns, rows, (uint32)offset, (uint32)sizeInBytes, (uint32)arraySize, isUsed));
|
_variables.Add(new BufferVariable(name, this, type, columns, rows, (uint32)offset, (uint32)sizeInBytes, (uint32)arraySize, isUsed, previewName, editorTypeName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ public class Material : Asset
|
|||||||
|
|
||||||
BufferCollection parentBuffers = _parent?._bufferCollection ?? _effect.Buffers;
|
BufferCollection parentBuffers = _parent?._bufferCollection ?? _effect.Buffers;
|
||||||
|
|
||||||
for (let (bufferName, buffer) in parentBuffers)
|
for (let (bufferName, engineBufferName, buffer) in parentBuffers)
|
||||||
{
|
{
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
continue;
|
continue;
|
||||||
@@ -104,7 +104,7 @@ public class Material : Asset
|
|||||||
{
|
{
|
||||||
using (OverridingConstantBuffer childConstBuffer = new OverridingConstantBuffer(parentConstBuffer))
|
using (OverridingConstantBuffer childConstBuffer = new OverridingConstantBuffer(parentConstBuffer))
|
||||||
{
|
{
|
||||||
_bufferCollection.Add(@bufferName.Index, childConstBuffer.Name, childConstBuffer);
|
_bufferCollection.Add(@bufferName.Index, childConstBuffer.Name, engineBufferName, childConstBuffer);
|
||||||
InitVariables(childConstBuffer);
|
InitVariables(childConstBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,7 @@ public class Material : Asset
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
for (let (bufferName, buffer) in _bufferCollection)
|
for (let (bufferName, engineBufferName, buffer) in _bufferCollection)
|
||||||
{
|
{
|
||||||
if (let cbuffer = buffer as ConstantBuffer)
|
if (let cbuffer = buffer as ConstantBuffer)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class OverridingConstantBuffer : ConstantBuffer
|
|||||||
|
|
||||||
public ConstantBuffer Parent => _parent;
|
public ConstantBuffer Parent => _parent;
|
||||||
|
|
||||||
public this(ConstantBuffer parent) : base(parent.Name, parent.RawData.Length)
|
public this(ConstantBuffer parent) : base(parent.Name, parent.RawData.Length, parent.EngineBufferName)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.AssertDebug(parent != null);
|
Log.EngineLogger.AssertDebug(parent != null);
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
@@ -25,7 +25,7 @@ class OverridingConstantBuffer : ConstantBuffer
|
|||||||
for (BufferVariable parentVariable in _parent.Variables)
|
for (BufferVariable parentVariable in _parent.Variables)
|
||||||
{
|
{
|
||||||
BufferVariable newVariable = new BufferVariable(parentVariable.Name, this, parentVariable.ElementType, parentVariable.Columns,
|
BufferVariable newVariable = new BufferVariable(parentVariable.Name, this, parentVariable.ElementType, parentVariable.Columns,
|
||||||
parentVariable.Rows, parentVariable.Offset, parentVariable._sizeInBytes, parentVariable.ArrayElements, parentVariable.IsUsed);
|
parentVariable.Rows, parentVariable.Offset, parentVariable._sizeInBytes, parentVariable.ArrayElements, parentVariable.IsUsed, parentVariable.PreviewName, parentVariable.EditorTypeName);
|
||||||
|
|
||||||
if (parentVariable.Flags.HasFlag(.Locked))
|
if (parentVariable.Flags.HasFlag(.Locked))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user