First working effects with new pipeline

This commit is contained in:
Simon Lübeß
2024-08-22 00:34:20 +02:00
parent 7b7a3dc645
commit 66e62f42ec
20 changed files with 652 additions and 43 deletions
@@ -0,0 +1,162 @@
using GlitchyEngine;
using GlitchyEditor.Assets.Importers;
using GlitchyEditor.Assets.Processors;
using GlitchyEngine.Content;
using System;
using System.IO;
namespace GlitchyEditor.Assets.Exporters;
class ShaderExporter : IAssetExporter
{
public static AssetType ExportedAssetType => .Shader;
public AssetExporterConfig CreateDefaultConfig() => new AssetExporterConfig();
public Result<void> Export(Stream stream, ProcessedResource processedResource, AssetConfig config)
{
Log.EngineLogger.AssertDebug(processedResource is ProcessedShader);
ProcessedShader shader = (.)processedResource;
/*
File Format:
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 Data...
Texture Count (uint16)
Textures
{
Texture Dimension (1 byte)
Vertex Shader Bind Point (int32, 4 bytes)
Pixel Shader Bind Point (int32, 4 bytes)
Texture Name Length (16 bytes)
Texture Name Data...
}
Buffer Count (uint16)
Buffers
{
Buffer Size (int64)
Vertex Shader Bind Point (int32, 4 bytes)
Pixel Shader Bind Point (int32, 4 bytes)
Buffer Name Length (16 bytes)
Buffer Name Data...
Engine Buffer Name Length (16 bytes)
Engine Buffer Name Data...
Variable Count (uint16)
Variables
{
Offset (uint64)
Size In Bytes (uint64)
IsUsed (bool, 1 byte)
ShaderVariableType (1 Byte)
Rows (uint8)
Columns (uint8)
ArraySize (uint64)
Name Length (16 bytes)
Name Data...
}
RawData...
}
*/
Span<uint8> vsData = shader.VertexShader?.Blob ?? Span<uint8>();
Span<uint8> psData = shader.PixelShader?.Blob ?? Span<uint8>();
Try!(stream.Write((uint64)vsData.Length));
Try!(stream.Write((uint64)psData.Length));
if (vsData.Ptr != null)
Try!(stream.Write(vsData));
if (psData.Ptr != null)
Try!(stream.Write(psData));
Try!(WriteTextures(stream, shader));
Try!(WriteConstantBuffers(stream, shader));
return .Ok;
}
private Result<void> WriteTextures(Stream stream, ProcessedShader shader)
{
Log.EngineLogger.Assert(shader.Textures.Count < int16.MaxValue);
Try!(stream.Write((uint16)shader.Textures.Count));
for (let (textureName, textureEntry) in shader.Textures)
{
Try!(stream.Write((uint8)textureEntry.TextureDimension));
Try!(stream.Write((int32)textureEntry.VertexShaderBindPoint));
Try!(stream.Write((int32)textureEntry.PixelShaderBindPoint));
Log.EngineLogger.Assert(textureName.Length < int16.MaxValue);
Try!(stream.Write((int16)textureName.Length));
Try!(stream.Write(textureName));
}
return .Ok;
}
private Result<void> WriteConstantBuffers(Stream stream, ProcessedShader shader)
{
Log.EngineLogger.Assert(shader.ConstantBuffers.Count < int16.MaxValue);
Try!(stream.Write((uint16)shader.ConstantBuffers.Count));
for (let (bufferName, bufferEntry) in shader.ConstantBuffers)
{
ReflectedConstantBuffer buffer = bufferEntry.ConstantBuffer;
Try!(stream.Write((uint64)buffer.Size));
Try!(stream.Write((int32)bufferEntry.VertexShaderBindPoint));
Try!(stream.Write((int32)bufferEntry.PixelShaderBindPoint));
Log.EngineLogger.Assert(bufferName.Length < int16.MaxValue);
Try!(stream.Write((uint16)bufferName.Length));
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);
Try!(stream.Write((uint16)buffer.Variables.Count));
for (let (variableName, variable) in buffer.Variables)
{
Try!(stream.Write((uint64)variable.Offset));
Try!(stream.Write((uint64)variable.SizeInBytes));
Try!(stream.Write((uint8)(variable.IsUsed ? 1 : 0)));
Try!(stream.Write((uint8)(variable.ElementType)));
Log.EngineLogger.Assert(variable.Rows < int8.MaxValue);
Log.EngineLogger.Assert(variable.Columns < int8.MaxValue);
Try!(stream.Write((uint8)variable.Rows));
Try!(stream.Write((uint8)variable.Columns));
Try!(stream.Write((uint64)variable.ArraySize));
Log.EngineLogger.Assert(variableName.Length < int16.MaxValue);
Try!(stream.Write((uint16)variableName.Length));
Try!(stream.Write(variableName));
}
Try!(stream.Write(Span<uint8>(buffer.RawData, 0, buffer.Size)));
}
return .Ok;
}
}
@@ -26,7 +26,7 @@ class TextureExporter : IAssetExporter
/*
File Format:
TextureType (1 byte)
Texture Dimension (1 byte)
Pixel Format (4 bytes)
Width of larges mip-slice (4 bytes)
Height of larges mip-slice (4 bytes)
@@ -35,6 +35,11 @@ class CompiledShader
private Dictionary<StringView, ReflectedConstantBuffer> _buffers = new .() ~ DeleteDictionaryAndValues!(_);
private Dictionary<StringView, ReflectedTexture> _textures = new .() ~ DeleteDictionaryAndValues!(_);
public Dictionary<StringView, ReflectedConstantBuffer> ConstantBuffers => _buffers;
public Dictionary<StringView, ReflectedTexture> Textures => _textures;
public extern Span<uint8> Blob {get;}
public void AddConstantBuffer(ReflectedConstantBuffer buffer)
{
_buffers.Add(buffer.Name, buffer);
@@ -49,17 +54,28 @@ class CompiledShader
class ReflectedConstantBuffer
{
private String _name ~ delete _;
private String _engineBufferName ~ delete _;
public int Size;
public int BindPoint;
public StringView Name
{
get => _name;
set => String.NewOrSet!(_name, value);
}
public StringView EngineBufferName
{
get => _engineBufferName;
set => String.NewOrSet!(_engineBufferName, value);
}
private Dictionary<StringView, ReflectedConstantBufferVariable> _variables = new .() ~ DeleteDictionaryAndValues!(_);
public Dictionary<StringView, ReflectedConstantBufferVariable> Variables => _variables;
public void AddVariable(ReflectedConstantBufferVariable vaiable)
{
_variables.Add(vaiable.Name, vaiable);
@@ -115,6 +131,8 @@ class ReflectedConstantBufferVariable
extension CompiledShader
{
internal ID3DBlob* _shaderBlob;
public override Span<uint8> Blob => Span<uint8>((uint8*)_shaderBlob.GetBufferPointer(), (int)_shaderBlob.GetBufferSize());
}
class ShaderCompiler
@@ -226,6 +244,7 @@ extension ShaderCompiler
switch(bindDesc.Type)
{
case .ConstantBuffer:
//var bufferReflection = reflection.GetConstantBufferByName(bindDesc.Name);
var bufferReflection = reflection.GetConstantBufferByName(bindDesc.Name);
bufferReflection.GetDescription(let bufferDesc);
@@ -233,7 +252,7 @@ extension ShaderCompiler
// ConstantBuffer
if(bufferDesc.Type == .D3D11_CT_CBUFFER)
{
ReflectedConstantBuffer cbuffer = Try!(ReflectConstantBuffer(bufferReflection));
ReflectedConstantBuffer cbuffer = Try!(ReflectConstantBuffer(bindDesc, bufferReflection));
shader.AddConstantBuffer(cbuffer);
}
case .Texture:
@@ -261,8 +280,7 @@ extension ShaderCompiler
shader.AddTexture(new ReflectedTexture(StringView(bindDesc.Name), bindDesc.BindPoint, textureDimension));
case .Sampler:
// TODO: do we have to do something for samplers?
// i.e. can we get default values?
// There is nothing to do for samplers
default:
Log.EngineLogger.Warning($"Unhandled shader resource type: \"{bindDesc.Type}\"");
}
@@ -271,7 +289,7 @@ extension ShaderCompiler
return .Ok;
}
private static Result<ReflectedConstantBuffer> ReflectConstantBuffer(ID3D11ShaderReflectionConstantBuffer* bufferReflection)
private static Result<ReflectedConstantBuffer> ReflectConstantBuffer(ShaderInputBindDescription bindDesc, ID3D11ShaderReflectionConstantBuffer* bufferReflection)
{
Debug.Profiler.ProfileResourceFunction!();
@@ -284,6 +302,7 @@ extension ShaderCompiler
buffer.Name = StringView(bufferDescription.Name);
buffer.Size = bufferDescription.Size;
buffer.BindPoint = bindDesc.BindPoint;
buffer.RawData = new uint8[buffer.Size];
for(uint32 v = 0; v < bufferDescription.Variables; v++)
@@ -10,15 +10,60 @@ namespace GlitchyEditor.Assets.Processors;
class ProcessedShader : ProcessedResource
{
public struct TextureEntry
{
public StringView Name;
public TextureDimension TextureDimension;
public int32 VertexShaderBindPoint;
public int32 PixelShaderBindPoint;
public static readonly TextureEntry Default = .() {
Name = null,
TextureDimension = .Unknown,
VertexShaderBindPoint = -1,
PixelShaderBindPoint = -1
};
}
public struct ConstantBufferEntry
{
public ReflectedConstantBuffer ConstantBuffer;
public int32 VertexShaderBindPoint;
public int32 PixelShaderBindPoint;
public static readonly Self Default = .() {
ConstantBuffer = null,
VertexShaderBindPoint = -1,
PixelShaderBindPoint = -1,
};
}
public override AssetType AssetType => .Shader;
public CompiledShader VertexShader ~ delete _;
public CompiledShader PixelShader ~ delete _;
Dictionary<StringView, ConstantBufferEntry> _constantBuffers = new .() ~ delete _; // Only delete container, Buffers come from shaders
Dictionary<StringView, TextureEntry> _textures = new .() ~ delete _;
public Dictionary<StringView, ConstantBufferEntry> ConstantBuffers => _constantBuffers;
public Dictionary<StringView, TextureEntry> Textures => _textures;
public this(AssetIdentifier ownAssetIdentifier, AssetHandle assetHandle) : base(ownAssetIdentifier, assetHandle)
{
}
public void AddConstantBuffer(ConstantBufferEntry buffer)
{
_constantBuffers.Add(buffer.ConstantBuffer.Name, buffer);
}
public void AddTextureEntry(TextureEntry textureEntry)
{
_textures.Add(textureEntry.Name, textureEntry);
}
}
class ShaderVariable
@@ -72,23 +117,20 @@ class ShaderProcessor : IAssetProcessor
String psName = scope String();
Dictionary<StringView, ShaderVariable> variables = scope .();
Dictionary<String, String> engineBuffers = scope .();
List<String> bufferNames = scope .();
// Name in Shader -> Name in Engine
Dictionary<StringView, StringView> engineBuffers = scope .();
defer
{
ClearDictionaryAndDeleteValues!(variables);
for (let (key, value) in engineBuffers)
{
delete key;
delete value;
}
ClearAndDeleteItems!(bufferNames);
}
String code = new String(importedShader.HlslCode);
defer { delete code; }
Try!(ProcessFileContent(code, vsName, psName, variables, engineBuffers));
Try!(ProcessFileContent(code, vsName, psName, variables, bufferNames, engineBuffers));
if (String.IsNullOrWhiteSpace(vsName) && String.IsNullOrWhiteSpace(psName))
{
@@ -100,16 +142,108 @@ class ShaderProcessor : IAssetProcessor
Try!(CompileAndReflect(vsName, psName, importedShader, code, processedShader));
Try!(MergeResources(processedShader));
Try!(MergeResources(processedShader, variables, engineBuffers));
outProcessedResources.Add(processedShader);
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!(MergeTextures(processedShader));
return .Ok;
}
private static Result<void> MergeConstantBuffers(ProcessedShader processedShader,
Dictionary<StringView, ShaderVariable> variables,
Dictionary<StringView, StringView> engineBuffers)
{
HashSet<StringView> bufferNames = scope .();
void AddBufferNames(CompiledShader shader)
{
for (StringView name in shader.ConstantBuffers.Keys)
{
bufferNames.Add(name);
}
}
AddBufferNames(processedShader.VertexShader);
AddBufferNames(processedShader.PixelShader);
for (StringView bufferName in bufferNames)
{
Result<ReflectedConstantBuffer> vsBufferResult = processedShader.VertexShader.ConstantBuffers.GetValue(bufferName);
Result<ReflectedConstantBuffer> psBufferResult = processedShader.PixelShader.ConstantBuffers.GetValue(bufferName);
ProcessedShader.ConstantBufferEntry constantBufferEntry = .Default;
if (vsBufferResult case .Ok(let vsBuffer) && psBufferResult case .Ok(let psBuffer))
{
// Choose larger buffer
constantBufferEntry.ConstantBuffer = (vsBuffer.Size >= psBuffer.Size) ? vsBuffer : psBuffer;
constantBufferEntry.VertexShaderBindPoint = (.)vsBuffer.BindPoint;
constantBufferEntry.PixelShaderBindPoint = (.)psBuffer.BindPoint;
}
else if (vsBufferResult case .Ok(let vsBuffer))
{
constantBufferEntry.ConstantBuffer = vsBuffer;
constantBufferEntry.VertexShaderBindPoint = (.)vsBuffer.BindPoint;
}
else if (psBufferResult case .Ok(let psBuffer))
{
constantBufferEntry.ConstantBuffer = psBuffer;
constantBufferEntry.PixelShaderBindPoint = (.)psBuffer.BindPoint;
}
Log.EngineLogger.Assert(constantBufferEntry.ConstantBuffer != null);
Log.EngineLogger.Assert(constantBufferEntry.VertexShaderBindPoint > -1 || constantBufferEntry.PixelShaderBindPoint > -1);
if (engineBuffers.TryGetValue(constantBufferEntry.ConstantBuffer.Name, let engineBufferName))
{
constantBufferEntry.ConstantBuffer.EngineBufferName = engineBufferName;
}
processedShader.AddConstantBuffer(constantBufferEntry);
}
return .Ok;
}
static ref ProcessedShader.TextureEntry AddOrGetTextureEntry(ProcessedShader processedShader, ReflectedTexture reflectedTexture)
{
if (!processedShader.Textures.ContainsKey(reflectedTexture.Name))
{
ProcessedShader.TextureEntry textureEntry = .Default;
textureEntry.Name = reflectedTexture.Name;
textureEntry.TextureDimension = reflectedTexture.TextureDimension;
processedShader.Textures.Add(textureEntry.Name, textureEntry);
}
ref ProcessedShader.TextureEntry entry = ref processedShader.Textures[reflectedTexture.Name];
return ref entry;
}
private static Result<void> MergeTextures(ProcessedShader processedShader)
{
for (let (textureName, reflectedTexture) in processedShader.VertexShader.Textures)
{
ref ProcessedShader.TextureEntry textureEntry = ref AddOrGetTextureEntry(processedShader, reflectedTexture);
textureEntry.VertexShaderBindPoint = (int32)reflectedTexture.BindPoint;
}
for (let (textureName, reflectedTexture) in processedShader.PixelShader.Textures)
{
ref ProcessedShader.TextureEntry textureEntry = ref AddOrGetTextureEntry(processedShader, reflectedTexture);
textureEntry.PixelShaderBindPoint = (int32)reflectedTexture.BindPoint;
}
return .Ok;
}
@@ -143,7 +277,9 @@ class ShaderProcessor : IAssetProcessor
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, Dictionary<String, String> outEngineBuffers)
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!();
@@ -176,7 +312,7 @@ class ShaderProcessor : IAssetProcessor
case "EditorVariable":
Try!(ProcessEditorVariables(arguments, outVarDescs));
case "EngineBuffer":
Try!(ProcessEngineBuffer(arguments, outEngineBuffers));
Try!(ProcessEngineBuffer(arguments, outBufferNames, outEngineBuffers));
default:
continue;
}
@@ -273,7 +409,8 @@ class ShaderProcessor : IAssetProcessor
return .Ok((startOfLine, endOfLine));
}
private static Result<void> ProcessEngineBuffer(Dictionary<StringView, StringView> arguments, Dictionary<String, String> outEngineBuffers)
private static Result<void> ProcessEngineBuffer(Dictionary<StringView, StringView> arguments,
List<String> outBufferNames, Dictionary<StringView, StringView> outEngineBuffers)
{
String nameInEngine = null;
String nameInShader = null;
@@ -306,7 +443,9 @@ class ShaderProcessor : IAssetProcessor
return .Err;
}
outEngineBuffers.Add(nameInEngine, nameInShader);
outBufferNames.Add(nameInShader);
outBufferNames.Add(nameInEngine);
outEngineBuffers.Add(nameInShader, nameInEngine);
return .Ok;
}
+1 -1
View File
@@ -45,7 +45,7 @@ namespace GlitchyEditor
_contentManager.RegisterAssetImporter<ShaderImporter>();
_contentManager.RegisterAssetProcessor<ShaderProcessor>();
//_contentManager.RegisterAssetExporter<ShaderEx>();
_contentManager.RegisterAssetExporter<ShaderExporter>();
_contentManager.SetGlobalAssetCacheDirectory(".cache");
_contentManager.SetResourcesDirectory("Resources");
@@ -11,6 +11,7 @@ using System.Linq;
using System.Threading.Tasks;
using GlitchyEditor.Assets.Importers;
using GlitchyEngine.Core;
using GlitchyEngine.Content.Loaders;
using internal GlitchyEngine.Content.Asset;
@@ -944,6 +945,7 @@ class EditorContentManager : IContentManager
// TODO: obviously use a map or something...
TextureLoader textureLoader = new .() ~ delete _;
SpriteLoader spriteLoader = new .() ~ delete _;
ShaderLoader shaderLoader = new .() ~ delete _;
private IProcessedAssetLoader GetLoader(AssetType assetType)
{
@@ -953,6 +955,8 @@ class EditorContentManager : IContentManager
return textureLoader;
case .Sprite:
return spriteLoader;
case .Shader:
return shaderLoader;
default:
return null;
}