mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Removed old shader loading stuff
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
using Bon;
|
||||
using GlitchyEngine.Content;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using GlitchyEngine;
|
||||
using GlitchyEngine.Renderer;
|
||||
|
||||
namespace GlitchyEditor.Assets;
|
||||
|
||||
class EffectAssetPropertiesEditor : AssetPropertiesEditor
|
||||
{
|
||||
public this(AssetFile asset) : base(asset)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void ShowEditor()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static AssetPropertiesEditor Factory(AssetFile assetFile)
|
||||
{
|
||||
return new Self(assetFile);
|
||||
}
|
||||
}
|
||||
|
||||
[BonTarget, BonPolyRegister]
|
||||
class EffectAssetLoaderConfig : AssetLoaderConfig
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class EffectAssetLoader : IAssetLoader //, IReloadingAssetLoader
|
||||
{
|
||||
private static readonly List<StringView> _fileExtensions = new .(){".hlsl"} ~ delete _;
|
||||
|
||||
public static List<StringView> FileExtensions => _fileExtensions;
|
||||
|
||||
public AssetLoaderConfig GetDefaultConfig()
|
||||
{
|
||||
return new EffectAssetLoaderConfig();
|
||||
}
|
||||
|
||||
public Asset LoadAsset(Stream file, AssetLoaderConfig config, StringView assetIdentifier, StringView? subAsset, IContentManager contentManager)
|
||||
{
|
||||
Effect effect = new Effect(file, assetIdentifier, contentManager);
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
public Asset GetPlaceholderAsset(Type assetType)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
public Asset GetErrorAsset(Type assetType)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
@@ -33,10 +33,6 @@ namespace GlitchyEditor
|
||||
_contentManager.SetAsDefaultAssetLoader<MaterialAssetLoader>(".mat");
|
||||
_contentManager.SetAssetPropertiesEditor<MaterialAssetLoader>(=> MaterialAssetPropertiesEditor.Factory);
|
||||
|
||||
_contentManager.RegisterAssetLoader<EffectAssetLoader>();
|
||||
_contentManager.SetAsDefaultAssetLoader<EffectAssetLoader>(".hlsl");
|
||||
_contentManager.SetAssetPropertiesEditor<EffectAssetLoader>(=> EffectAssetPropertiesEditor.Factory);
|
||||
|
||||
_contentManager.RegisterAssetImporter<TextureImporter>();
|
||||
_contentManager.RegisterAssetProcessor<TextureProcessor>();
|
||||
_contentManager.RegisterAssetExporter<TextureExporter>();
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
#if GE_GRAPHICS_DX11
|
||||
|
||||
using DirectX.Common;
|
||||
using DirectX.D3D11Shader;
|
||||
using System;
|
||||
|
||||
using internal GlitchyEngine.Renderer;
|
||||
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
extension BufferVariable
|
||||
{
|
||||
internal this(ConstantBuffer constantBuffer, ID3D11ShaderReflectionVariable* variableReflection)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
_constantBuffer = constantBuffer;
|
||||
|
||||
HResult result = variableReflection.GetDescription(let variableDescription);
|
||||
Log.EngineLogger.Assert(result.Succeeded, scope $"Failed to get variable description. Error({(int)result}): {result}");
|
||||
|
||||
_name = new String(variableDescription.Name);
|
||||
|
||||
_offset = variableDescription.StartOffset;
|
||||
_sizeInBytes = variableDescription.Size;
|
||||
_isUsed = variableDescription.uFlags.HasFlag(.Used);
|
||||
|
||||
let variableType = variableReflection.GetVariableType();
|
||||
result = variableType.GetDescription(let shaderTypeDescription);
|
||||
Log.EngineLogger.Assert(result.Succeeded, scope $"Failed to get variable type description. Error({(int)result}): {result}");
|
||||
|
||||
switch(shaderTypeDescription.Type)
|
||||
{
|
||||
case .Bool:
|
||||
_type = .Bool;
|
||||
case .Float:
|
||||
_type = .Float;
|
||||
case .Int:
|
||||
_type = .Int;
|
||||
case .UInt:
|
||||
_type = .UInt;
|
||||
default:
|
||||
Log.EngineLogger.Assert(false, scope $"Unhandled shader variable type: {shaderTypeDescription.Type}");
|
||||
}
|
||||
|
||||
_columns = shaderTypeDescription.Columns;
|
||||
_rows = shaderTypeDescription.Rows;
|
||||
_elements = shaderTypeDescription.Elements;
|
||||
|
||||
SetRawData(variableDescription.DefaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
extension ConstantBuffer
|
||||
{
|
||||
internal this(ID3D11ShaderReflectionConstantBuffer* bufferReflection)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
Reflect(bufferReflection);
|
||||
|
||||
ConstructBuffer();
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
private void Reflect(ID3D11ShaderReflectionConstantBuffer* bufferReflection)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
HResult result = bufferReflection.GetDescription(let bufferDescription);
|
||||
Log.EngineLogger.Assert(result.Succeeded, scope $"Failed to get buffer description. Error({(int)result}): {result}");
|
||||
|
||||
Log.EngineLogger.AssertDebug(bufferDescription.Type == .D3D_CT_CBUFFER, "The buffer is not of type \"D3D_CT_CBUFFER\"");
|
||||
|
||||
_name = new String(bufferDescription.Name);
|
||||
|
||||
rawData = new uint8[bufferDescription.Size];
|
||||
|
||||
// Flags seem to be irrelevant for us here
|
||||
|
||||
for(uint32 v = 0; v < bufferDescription.Variables; v++)
|
||||
{
|
||||
ID3D11ShaderReflectionVariable* variableReflection = bufferReflection.GetVariableByIndex(v);
|
||||
|
||||
BufferVariable variable = new BufferVariable(this, variableReflection);
|
||||
|
||||
AddVariable(variable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,37 +0,0 @@
|
||||
#if GE_GRAPHICS_DX11
|
||||
|
||||
using System;
|
||||
using DirectX.D3D11;
|
||||
using DirectX.D3DCompiler;
|
||||
using GlitchyEngine.Platform.DX11;
|
||||
using GlitchyEngine.Content;
|
||||
|
||||
using internal GlitchyEngine.Renderer;
|
||||
using internal GlitchyEngine.Platform.DX11;
|
||||
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
extension PixelShader
|
||||
{
|
||||
public override void CompileFromSource(StringView code, StringView? fileName, String entryPoint, IContentManager contentManager, ShaderDefine[] macros = null)
|
||||
{
|
||||
Debug.Profiler.ProfileRendererFunction!();
|
||||
|
||||
Shader.PlattformCompileShaderFromSource(code, fileName, macros, entryPoint, "ps_5_0", DefaultCompileFlags, contentManager, out nativeCode);
|
||||
|
||||
{
|
||||
Debug.Profiler.ProfileResourceScope!("CreateNativePixelShader");
|
||||
|
||||
var result = NativeDevice.CreatePixelShader(nativeCode.GetBufferPointer(), nativeCode.GetBufferSize(), null, (ID3D11PixelShader**)&nativeShader);
|
||||
if(result.Failed)
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to create pixel shader: Message ({(int)result}): {result}");
|
||||
}
|
||||
}
|
||||
|
||||
Reflect(nativeCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -26,98 +26,6 @@ using internal GlitchyEngine.Platform.DX11;
|
||||
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
struct ContentManagerInclude : ID3DInclude, IDisposable
|
||||
{
|
||||
private VTable _vTable;
|
||||
|
||||
private IContentManager _contentManager;
|
||||
|
||||
private Dictionary<char8*, (String FileContent, void* Data, uint32 Length)> _loadedFiles;
|
||||
|
||||
private String _parentFileDirectory;
|
||||
|
||||
public this(IContentManager contentManager, String parentFileDirectory)
|
||||
{
|
||||
_contentManager = contentManager;
|
||||
_parentFileDirectory = parentFileDirectory;
|
||||
_loadedFiles = new Dictionary<char8*, (String FileContent, void* Data, uint32 Length)>();
|
||||
|
||||
_vTable.Open = => Open;
|
||||
_vTable.Close = => Close;
|
||||
|
||||
_vt = &_vTable;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
delete _loadedFiles;
|
||||
}
|
||||
|
||||
public static HResult Open(ID3DInclude* self, IncludeType includeType, char8* fileName, void* parentData, void** data, uint32* bytes)
|
||||
{
|
||||
ContentManagerInclude* includer = (.)self;
|
||||
|
||||
if (includer._loadedFiles.TryGetValue(fileName, let value))
|
||||
{
|
||||
*data = value.Data;
|
||||
*bytes = value.Length;
|
||||
|
||||
return .S_OK;
|
||||
}
|
||||
|
||||
String pathNextToParent = scope .();
|
||||
|
||||
Path.Combine(pathNextToParent, includer._parentFileDirectory, StringView(fileName));
|
||||
|
||||
Stream fileStream = Application.Instance.ContentManager.GetStream(pathNextToParent);
|
||||
|
||||
if (fileStream == null)
|
||||
{
|
||||
fileStream = Application.Instance.ContentManager.GetStream(StringView(fileName));
|
||||
}
|
||||
|
||||
if (fileStream == null)
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to include file \"{fileName}\"");
|
||||
return .E_FILENOTFOUND;
|
||||
}
|
||||
|
||||
String fileContent = new String();
|
||||
|
||||
{
|
||||
StreamReader reader = scope .(fileStream);
|
||||
|
||||
reader.ReadToEnd(fileContent);
|
||||
|
||||
includer._loadedFiles.Add(fileName, (fileContent, fileContent.Ptr, (uint32)fileContent.Length));
|
||||
}
|
||||
|
||||
delete fileStream;
|
||||
|
||||
*data = (void*)fileContent.Ptr;
|
||||
*bytes = (uint32)fileContent.Length;
|
||||
|
||||
return .S_OK;
|
||||
}
|
||||
|
||||
public static HResult Close(ID3DInclude* self, void** data)
|
||||
{
|
||||
ContentManagerInclude* includer = (.)self;
|
||||
|
||||
for (var v in includer._loadedFiles)
|
||||
{
|
||||
if (v.value.Data == data)
|
||||
{
|
||||
delete v.value.FileContent;
|
||||
|
||||
includer._loadedFiles.Remove(v.key);
|
||||
}
|
||||
}
|
||||
|
||||
return .S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
extension Shader
|
||||
{
|
||||
internal ID3D11DeviceChild* nativeShader ~ _?.Release();
|
||||
@@ -160,130 +68,6 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
protected const ShaderCompileFlags DefaultCompileFlags = .EnableStrictness |
|
||||
#if DEBUG
|
||||
.Debug;
|
||||
#else
|
||||
.OptimizationLevel3;
|
||||
#endif
|
||||
|
||||
internal static void PlattformCompileShaderFromSource(StringView code, StringView? fileName, ShaderDefine[] macros, String entryPoint, String target, ShaderCompileFlags compileFlags, IContentManager contentManager, out ID3DBlob* shaderBlob)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
ShaderMacro* nativeMacros = macros == null ? null : new:ScopedAlloc! ShaderMacro[macros.Count]*;
|
||||
|
||||
for(int i < macros?.Count ?? 0)
|
||||
{
|
||||
nativeMacros[i].Name = macros[i].Name.ToScopedNativeWChar!();
|
||||
nativeMacros[i].Definition = macros[i].Definition.ToScopedNativeWChar!();
|
||||
}
|
||||
|
||||
// Todo: sourceName, includes,
|
||||
// Todo: variable shader target?
|
||||
|
||||
ID3DBlob* errorBlob = null;
|
||||
|
||||
String directory = scope .();
|
||||
|
||||
Path.GetDirectoryPath(fileName.Value, directory);
|
||||
|
||||
using (ContentManagerInclude includer = .(contentManager, directory))
|
||||
{
|
||||
//ID3DInclude.StandardInclude
|
||||
|
||||
shaderBlob = null;
|
||||
var result = D3DCompiler.D3DCompile(code.Ptr, (.)code.Length, fileName?.ToScopeCStr!(), nativeMacros, &includer, entryPoint, target, compileFlags, .None, &shaderBlob, &errorBlob);
|
||||
|
||||
if(result.Failed)
|
||||
{
|
||||
StringView str = StringView((char8*)errorBlob.GetBufferPointer(), (int)errorBlob.GetBufferSize());
|
||||
Log.EngineLogger.Error($"Failed to compile Shader: Error Code({(int)result}): {result} | Error Message: {str}");
|
||||
}
|
||||
}
|
||||
|
||||
Log.EngineLogger.Assert(shaderBlob != null, "Shader compilation failed.");
|
||||
}
|
||||
|
||||
protected internal void Reflect(ID3DBlob* shaderCode)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
ID3D11ShaderReflection* reflection = null;
|
||||
{
|
||||
Debug.Profiler.ProfileResourceScope!("D3DReflect");
|
||||
|
||||
var result = D3DCompiler.D3DReflect(shaderCode.GetBufferPointer(), shaderCode.GetBufferSize(), &reflection);
|
||||
if(result.Failed)
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to reflect shader: Message ({(int)result}): {result}");
|
||||
}
|
||||
}
|
||||
|
||||
reflection.GetDescription(let desc);
|
||||
|
||||
uint32 resourceCount = desc.BoundResources;
|
||||
for (uint32 i < resourceCount)
|
||||
{
|
||||
var res = reflection.GetResourceBindingDescription(i, let bindDesc);
|
||||
|
||||
if (res.Failed)
|
||||
{
|
||||
Log.EngineLogger.Error($"Error({(int)res}) {res}: Failed to get resource binding desc for resource {i}");
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(bindDesc.Type)
|
||||
{
|
||||
case .ConstantBuffer:
|
||||
var bufferReflection = reflection.GetConstantBufferByName(bindDesc.Name);
|
||||
|
||||
bufferReflection.GetDescription(let bufferDesc);
|
||||
|
||||
// ConstantBuffer
|
||||
if(bufferDesc.Type == .D3D11_CT_CBUFFER)
|
||||
{
|
||||
let buffer = new ConstantBuffer(bufferReflection);
|
||||
|
||||
_buffers.Add(bindDesc.BindPoint, buffer.Name, buffer);
|
||||
|
||||
buffer.ReleaseRef();
|
||||
}
|
||||
case .Texture:
|
||||
|
||||
TextureDimension texDim;
|
||||
|
||||
switch (bindDesc.Dimension)
|
||||
{
|
||||
case .Texture1D:
|
||||
texDim = .Texture1D;
|
||||
case .Texture1DArray:
|
||||
texDim = .Texture1DArray;
|
||||
case .Texture2D:
|
||||
texDim = .Texture2D;
|
||||
case .Texture2DArray:
|
||||
texDim = .Texture2DArray;
|
||||
case .Texture3D:
|
||||
texDim = .Texture3D;
|
||||
case .TextureCube:
|
||||
texDim = .TextureCube;
|
||||
case .TextureCubeArray:
|
||||
texDim = .TextureCubeArray;
|
||||
default:
|
||||
texDim = .Unknown;
|
||||
}
|
||||
|
||||
_textures.Add(scope String(bindDesc.Name), bindDesc.BindPoint, TextureViewBinding(null, null), texDim);
|
||||
case .Sampler:
|
||||
// TODO: do we have to do something for samplers?
|
||||
default:
|
||||
Log.EngineLogger.Warning($"Unhandled shader resource type: \"{bindDesc.Type}\"");
|
||||
}
|
||||
}
|
||||
|
||||
reflection.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#if GE_GRAPHICS_DX11
|
||||
|
||||
using System;
|
||||
using GlitchyEngine.Renderer;
|
||||
using DirectX.D3D11;
|
||||
using DirectX.D3DCompiler;
|
||||
using GlitchyEngine.Platform.DX11;
|
||||
using GlitchyEngine.Content;
|
||||
|
||||
using internal GlitchyEngine.Renderer;
|
||||
using internal GlitchyEngine.Platform.DX11;
|
||||
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
extension VertexShader
|
||||
{
|
||||
public override void CompileFromSource(StringView code, StringView? fileName, String entryPoint, IContentManager contentManager = null, ShaderDefine[] macros = null)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
Shader.PlattformCompileShaderFromSource(code, fileName, macros, entryPoint, "vs_5_0", DefaultCompileFlags, contentManager, out nativeCode);
|
||||
|
||||
{
|
||||
Debug.Profiler.ProfileResourceScope!("CreateNativeVertexShader");
|
||||
|
||||
var result = NativeDevice.CreateVertexShader(nativeCode.GetBufferPointer(), nativeCode.GetBufferSize(), null, (ID3D11VertexShader**)&nativeShader);
|
||||
if(result.Failed)
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to create vertex shader: Message ({(int)result}): {result}");
|
||||
}
|
||||
}
|
||||
|
||||
Reflect(nativeCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -84,38 +84,6 @@ public class Effect : Asset
|
||||
public BufferCollection Buffers => _bufferCollection;
|
||||
public BufferVariableCollection Variables => _variables;
|
||||
|
||||
[Obsolete("", false)]
|
||||
public this(String filename)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
String fileContent = scope String();
|
||||
String vsName = scope String();
|
||||
String psName = scope String();
|
||||
|
||||
ProcessFile(filename, fileContent, vsName, psName, _variableDescriptions, _engineBuffers);
|
||||
|
||||
Compile(fileContent, filename, vsName, psName);
|
||||
|
||||
MergeResources();
|
||||
}
|
||||
|
||||
[Obsolete("", false)]
|
||||
public this(Stream data, StringView assetIdentifier, IContentManager contentManager)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
String fileContent = scope String();
|
||||
String vsName = scope String();
|
||||
String psName = scope String();
|
||||
|
||||
ProcessStream(data, fileContent, vsName, psName, _variableDescriptions, _engineBuffers);
|
||||
|
||||
Compile(fileContent, assetIdentifier, vsName, psName, contentManager);
|
||||
|
||||
MergeResources();
|
||||
}
|
||||
|
||||
public this()
|
||||
{
|
||||
_bufferCollection = new BufferCollection();
|
||||
@@ -203,480 +171,4 @@ public class Effect : Asset
|
||||
RenderCommand.BindVertexShader(_vs);
|
||||
RenderCommand.BindPixelShader(_ps);
|
||||
}
|
||||
|
||||
/*private void CompileFromFile(String filename, String vsEntry, String psEntry)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
let vs = Shader.FromFile!<VertexShader>(filename, vsEntry);
|
||||
VertexShader = vs;
|
||||
vs.ReleaseRef();
|
||||
let ps = Shader.FromFile!<PixelShader>(filename, psEntry);
|
||||
PixelShader = ps;
|
||||
ps.ReleaseRef();
|
||||
}*/
|
||||
|
||||
private void Compile(String fileContent, StringView fileName, String vsEntry, String psEntry, IContentManager contentManager = null)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
// TODO: vsEntry and psEntry could be empty (which is a valid case.)
|
||||
let vs = new VertexShader(fileContent, fileName, vsEntry, contentManager);
|
||||
VertexShader = vs;
|
||||
vs.ReleaseRef();
|
||||
let ps = new PixelShader(fileContent, fileName, psEntry, contentManager);
|
||||
PixelShader = ps;
|
||||
ps.ReleaseRef();
|
||||
}
|
||||
|
||||
const String effectKeyword = "#effect";
|
||||
|
||||
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 void ProcessStream(Stream rawData, String fileContent, String outVsName, String outPsName, VariableDesc outVarDescs, Dictionary<String, String> outEngineBuffers)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
StreamReader streamReader = scope .(rawData);
|
||||
streamReader.ReadToEnd(fileContent);
|
||||
// append line ending just in case the file doesn't end with one.
|
||||
fileContent.Append('\n');
|
||||
|
||||
ProcessFileContent(fileContent, outVsName, outPsName, outVarDescs, outEngineBuffers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the effect file and extracts the names of the vertex- and pixel-shader.
|
||||
* @param filename The path of the effect file.
|
||||
* @param fileContent The preprocessed effect file.
|
||||
* @param outVsName The string that will receive the vertex shader entry point.
|
||||
* @param outPsName The string that will receive the pixel shader entry point.
|
||||
* @param outVarDescs The dictionary that will contain the Variable descriptions.
|
||||
*/
|
||||
private static void ProcessFile(String filename, String fileContent, String outVsName, String outPsName, VariableDesc outVarDescs, Dictionary<String, String> outEngineBuffers)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
File.ReadAllText(filename, fileContent, true);
|
||||
// append line ending just in case the file doesn't end with one.
|
||||
fileContent.Append('\n');
|
||||
|
||||
ProcessFileContent(fileContent, outVsName, outPsName, outVarDescs, outEngineBuffers);
|
||||
}
|
||||
|
||||
private static void ProcessFileContent(String fileContent, String outVsName, String outPsName, VariableDesc outVarDescs, Dictionary<String, String> outEngineBuffers)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
Dictionary<StringView, StringView> arguments = scope .();
|
||||
|
||||
int index = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
Result<(int Start, int End)> result = GetNextPreprocessor(fileContent, index, let name, arguments..Clear());
|
||||
|
||||
if (result case .Err)
|
||||
break;
|
||||
else if (result case .Ok(let value))
|
||||
{
|
||||
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.Assert(false, scope $"Unknown parameter name \"{name}\".");
|
||||
}
|
||||
}
|
||||
case "EditorVariable":
|
||||
ProcessEditorVariables(arguments, outVarDescs);
|
||||
case "EngineBuffer":
|
||||
ProcessEngineBuffer(arguments, outEngineBuffers);
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
CommentLine(fileContent, value.Start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessEngineBuffer(Dictionary<StringView, StringView> arguments, Dictionary<String, String> 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.Assert(false, scope $"Unknown parameter for EngineBuffer: \"{argName}\".");
|
||||
}
|
||||
}
|
||||
|
||||
Log.EngineLogger.AssertDebug(nameInEngine != null);
|
||||
Log.EngineLogger.AssertDebug(nameInShader != null);
|
||||
|
||||
outEngineBuffers.Add(nameInEngine, nameInShader);
|
||||
}
|
||||
|
||||
private static void ProcessEditorVariables(Dictionary<StringView, StringView> arguments, VariableDesc outVarDescs)
|
||||
{
|
||||
String variableName = null;
|
||||
|
||||
Dictionary<String, Variant> parameters = new .();
|
||||
|
||||
for (var (name, value) in arguments)
|
||||
{
|
||||
if (value.StartsWith('"') && value.EndsWith('"'))
|
||||
{
|
||||
value = value[1...^2];
|
||||
}
|
||||
|
||||
switch(name)
|
||||
{
|
||||
case "Name":
|
||||
variableName = new String(value);
|
||||
case "Min", "Max":
|
||||
Variant paramValue = ParseVariableValue(value);
|
||||
parameters.Add(new String(name), paramValue);
|
||||
default:
|
||||
Variant paramValue = Variant.Create(new String(value), true);
|
||||
parameters.Add(new String(name), paramValue);
|
||||
}
|
||||
}
|
||||
|
||||
Log.EngineLogger.AssertDebug(variableName != null, "Missing argument \"Name\" int variable description.");
|
||||
|
||||
outVarDescs.Add(variableName, parameters);
|
||||
|
||||
}
|
||||
|
||||
private static Variant ParseVariableValue(StringView valueString)
|
||||
{
|
||||
if (valueString[0].IsDigit || valueString[0] == '-')
|
||||
{
|
||||
var valueString;
|
||||
|
||||
if (valueString.EndsWith('f'))
|
||||
valueString.Length--;
|
||||
|
||||
var result = float.Parse(valueString);
|
||||
|
||||
Log.EngineLogger.AssertDebug(result case .Ok);
|
||||
|
||||
if (result case .Ok(let value))
|
||||
return Variant.Create(value);
|
||||
}
|
||||
else if (valueString.StartsWith("float"))
|
||||
{
|
||||
int index = 5;
|
||||
|
||||
int numComponents = valueString[index++] - '0';
|
||||
|
||||
while (valueString[index] != '(')
|
||||
{
|
||||
Log.EngineLogger.AssertDebug(valueString[index].IsWhiteSpace, "Expected '('.");
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
Log.EngineLogger.AssertDebug(numComponents >= 2 && numComponents <= 4, scope $"Unsupported component count {numComponents}. Value must be between 2 and 4");
|
||||
|
||||
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 if (numComponents == 4)
|
||||
return Variant.Create(*(float4*)floats.Ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.EngineLogger.Error($"Unsupported variable value: \"{valueString}\"");
|
||||
}
|
||||
|
||||
return Variant.Create(0.0f);
|
||||
}
|
||||
|
||||
//protected extern void Compile(String code, String fileName, String vsEntry, String psEntry);
|
||||
|
||||
private void MergeResources()
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
MergeConstantBuffers();
|
||||
MergeBufferVariables();
|
||||
MergeTextures();
|
||||
}
|
||||
|
||||
private void MergeConstantBuffers()
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
_bufferCollection = new BufferCollection();
|
||||
|
||||
HashSet<String> bufferNames = scope HashSet<String>();
|
||||
|
||||
AddShaderBuffers(_vs, bufferNames);
|
||||
AddShaderBuffers(_ps, bufferNames);
|
||||
|
||||
int internalIndex = 0;
|
||||
|
||||
for(String bufferName in bufferNames)
|
||||
{
|
||||
let vsBuffer = _vs.Buffers.TryGetBufferEntry(bufferName);
|
||||
let psBuffer = _ps.Buffers.TryGetBufferEntry(bufferName);
|
||||
|
||||
if(vsBuffer != null && psBuffer != null)
|
||||
{
|
||||
BufferCollection.BufferEntry* fxBuffer = null;
|
||||
// choose the larger of the two
|
||||
if(psBuffer.Buffer.Description.Size > vsBuffer.Buffer.Description.Size)
|
||||
fxBuffer = psBuffer;
|
||||
else
|
||||
fxBuffer = vsBuffer;
|
||||
|
||||
_bufferCollection.Add(internalIndex, bufferName, fxBuffer.Buffer);
|
||||
|
||||
_vs.Buffers.TryReplaceBuffer(vsBuffer.Index, fxBuffer.Buffer);
|
||||
_ps.Buffers.TryReplaceBuffer(psBuffer.Index, fxBuffer.Buffer);
|
||||
}
|
||||
else if(vsBuffer != null)
|
||||
{
|
||||
_bufferCollection.Add(internalIndex, bufferName, vsBuffer.Buffer);
|
||||
}
|
||||
else if(psBuffer != null)
|
||||
{
|
||||
_bufferCollection.Add(internalIndex, bufferName, psBuffer.Buffer);
|
||||
}
|
||||
|
||||
internalIndex++;
|
||||
}
|
||||
|
||||
SetReference!(_vs.[Friend]_buffers, _bufferCollection);
|
||||
SetReference!(_ps.[Friend]_buffers, _bufferCollection);
|
||||
}
|
||||
|
||||
private void MergeBufferVariables()
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
_variables = new BufferVariableCollection(false);
|
||||
|
||||
outer: for(let buffer in _bufferCollection)
|
||||
{
|
||||
for (let eb in _engineBuffers)
|
||||
{
|
||||
if (eb.value == buffer.Name)
|
||||
{
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
|
||||
if(let cbuffer = buffer.Buffer as ConstantBuffer)
|
||||
{
|
||||
for(let variable in cbuffer.Variables)
|
||||
{
|
||||
_variables.TryAdd(variable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddShaderBuffers(Shader shader, HashSet<String> bufferNames)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
if(shader != null)
|
||||
{
|
||||
for(let buffer in shader.Buffers)
|
||||
{
|
||||
bufferNames.Add(buffer.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Merges the texture slots of all shaders into one dictionary.
|
||||
private void MergeTextures()
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
delete _textures;
|
||||
_textures = new .();
|
||||
|
||||
EnumerateShaderTextures(_vs);
|
||||
EnumerateShaderTextures(_ps);
|
||||
}
|
||||
|
||||
/** @brief Merges all textures of the given shader into the _textures dictionary.
|
||||
* @param shader The shader whose textures will be merged into the dictionary.
|
||||
*/
|
||||
private void EnumerateShaderTextures<T>(T shader) where T : Shader
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
//for(var (name, index, texture) in shader.Resources)
|
||||
for(var shaderEntry in ref shader.Textures)
|
||||
{
|
||||
TextureEntry entry;
|
||||
|
||||
// Get existing entry or create new
|
||||
if(!_textures.TryGetValue(shaderEntry.Name, out entry))
|
||||
{
|
||||
entry = .(shaderEntry.BoundTexture, shaderEntry.Dimension, null, null);
|
||||
entry.BoundTexture.AddRef();
|
||||
}
|
||||
|
||||
// Set the corresponding shader resource slot
|
||||
if(typeof(T) == typeof(VertexShader))
|
||||
{
|
||||
entry.VsSlot = &shaderEntry;
|
||||
}
|
||||
else if(typeof(T) == typeof(PixelShader))
|
||||
{
|
||||
entry.PsSlot = &shaderEntry;
|
||||
}
|
||||
|
||||
// If the entry has no texture but the shader has one -> set texture
|
||||
if(entry.BoundTexture.IsEmpty && !shaderEntry.BoundTexture.IsEmpty)
|
||||
{
|
||||
entry.BoundTexture = shaderEntry.BoundTexture;
|
||||
entry.BoundTexture.AddRef();
|
||||
}
|
||||
|
||||
// save entry
|
||||
_textures[new String(shaderEntry.Name)] = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,6 @@ namespace GlitchyEngine.Renderer
|
||||
{
|
||||
public class PixelShader : Shader
|
||||
{
|
||||
[AllowAppend]
|
||||
public this(StringView code, StringView? fileName, String entryPoint, IContentManager contentManager, ShaderDefine[] macros = null)
|
||||
: base(code, fileName, entryPoint, contentManager, macros) { }
|
||||
|
||||
public this() : base() { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,19 +43,6 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
public ShaderType ShaderType => _shaderType;
|
||||
|
||||
[AllowAppend]
|
||||
public this(StringView code, StringView? fileName, String entryPoint, IContentManager contentManager, ShaderDefine[] macros = null)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
// Todo: append as soon as it's fixed.
|
||||
//let buffers = new BufferCollection();
|
||||
_buffers = new BufferCollection();
|
||||
_textures = new ShaderTextureCollection();
|
||||
|
||||
CompileFromSource(code, fileName, entryPoint, contentManager);
|
||||
}
|
||||
|
||||
public this()
|
||||
{
|
||||
_buffers = new BufferCollection();
|
||||
@@ -64,6 +51,8 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
public static Result<Shader> CreateFromBlob(Span<uint8> shaderBlob, ShaderType shaderType)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
Shader shader = null;
|
||||
|
||||
defer
|
||||
@@ -97,8 +86,6 @@ namespace GlitchyEngine.Renderer
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
}
|
||||
|
||||
public abstract void CompileFromSource(StringView code, StringView? fileName, String entryPoint, IContentManager contentManager, ShaderDefine[] macros = null);
|
||||
|
||||
protected abstract Result<void> InternalCreateFromBlob(Span<uint8> blob);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,6 @@ namespace GlitchyEngine.Renderer
|
||||
{
|
||||
public class VertexShader : Shader
|
||||
{
|
||||
[AllowAppend]
|
||||
public this(StringView code, StringView? fileName, String entryPoint, IContentManager contentManager = null, ShaderDefine[] macros = null)
|
||||
: base(code, fileName, entryPoint, contentManager, macros) { }
|
||||
|
||||
public this() : base() { }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user