New material loading pipeline almost working

This commit is contained in:
Simon Lübeß
2025-01-31 13:18:49 +01:00
parent 2f0505241f
commit acfb052137
11 changed files with 419 additions and 81 deletions
@@ -0,0 +1,96 @@
using System;
using System.IO;
using GlitchyEngine.Renderer;
using GlitchyEditor.Assets.Processors;
using GlitchyEngine;
using GlitchyEditor.Assets.Importers;
using GlitchyEngine.Content;
using System.Diagnostics;
namespace GlitchyEditor.Assets.Exporters;
class MaterialExporter : IAssetExporter
{
public static AssetType ExportedAssetType => .Material;
public AssetExporterConfig CreateDefaultConfig()
{
return new AssetExporterConfig();
}
public Result<void> Export(Stream stream, ProcessedResource processedResource, AssetConfig config)
{
Log.EngineLogger.AssertDebug(processedResource is ProcessedMaterial);
ProcessedMaterial processedMaterial = (.)processedResource;
Compiler.Assert(sizeof(AssetHandle) == 8);
/*
File Format:
Effect Asset Handle (8 byte)
Texture Count (uint16)
Textures
{
Texture Handle (8 byte)
Texture Name Length (int16)
Texture Name Data...
}
Buffer Count (uint16)
Buffers
{
Buffer Size (int64)
Buffer Name Length (int16)
Buffer Name Data...
Raw Buffer Data...
}
*/
Try!(stream.Write((AssetHandle)processedMaterial.EffectHandle));
Try!(WriteTextures(stream, processedMaterial));
Try!(WriteBuffers(stream, processedMaterial));
return .Ok;
}
private Result<void> WriteTextures(Stream stream, ProcessedMaterial processedMaterial)
{
Log.EngineLogger.Assert(processedMaterial.Textures.Count < int16.MaxValue);
Try!(stream.Write((uint16)processedMaterial.Textures.Count));
for (let (textureName, textureHandle) in processedMaterial.Textures)
{
Try!(stream.Write((AssetHandle)textureHandle));
Log.EngineLogger.Assert(textureName.Length < int16.MaxValue);
Try!(stream.Write((int16)textureName.Length));
Try!(stream.Write(textureName));
}
return .Ok;
}
private Result<void> WriteBuffers(Stream stream, ProcessedMaterial processedMaterial)
{
Log.EngineLogger.Assert(processedMaterial.Buffers.Count < int16.MaxValue);
Try!(stream.Write((uint16)processedMaterial.Buffers.Count));
for (let (bufferName, bufferData) in processedMaterial.Buffers)
{
Try!(stream.Write((int64)bufferData.Count));
Log.EngineLogger.Assert(bufferName.Length < int16.MaxValue);
Try!(stream.Write((int16)bufferName.Length));
Try!(stream.Write(bufferName));
Try!(stream.Write(Span<uint8>(bufferData)));
}
return .Ok;
}
}
@@ -30,20 +30,20 @@ class ShaderExporter : IAssetExporter
Textures Textures
{ {
Texture Dimension (1 byte) Texture Dimension (1 byte)
Vertex Shader Bind Point (int32, 4 bytes) Vertex Shader Bind Point (int32, 4 bytes) # TODO: ASSUME same bind point for all shader stages?
Pixel Shader Bind Point (int32, 4 bytes) Pixel Shader Bind Point (int32, 4 bytes) # TODO: ASSUME same bind point for all shader stages?
Texture Name Length (16 bytes) Texture Name Length (uint16)
Texture Name Data... Texture Name Data...
} }
Buffer Count (uint16) Buffer Count (uint16)
Buffers Buffers
{ {
Buffer Size (int64) Buffer Size (int64)
Vertex Shader Bind Point (int32, 4 bytes) Vertex Shader Bind Point (int32, 4 bytes) # TODO: ASSUME same bind point for all shader stages?
Pixel Shader Bind Point (int32, 4 bytes) Pixel Shader Bind Point (int32, 4 bytes) # TODO: ASSUME same bind point for all shader stages?
Buffer Name Length (16 bytes) Buffer Name Length (uint16)
Buffer Name Data... Buffer Name Data...
Engine Buffer Name Length (16 bytes) Engine Buffer Name Length (uint16)
Engine Buffer Name Data... Engine Buffer Name Data...
Variable Count (uint16) Variable Count (uint16)
Variables Variables
@@ -55,7 +55,7 @@ class ShaderExporter : IAssetExporter
Rows (uint8) Rows (uint8)
Columns (uint8) Columns (uint8)
ArraySize (uint64) ArraySize (uint64)
Name Length (16 bytes) Name Length (uint16)
Name Data... Name Data...
} }
RawData... RawData...
@@ -5,60 +5,44 @@ using GlitchyEngine.Renderer;
using Bon; using Bon;
using GlitchyEngine.Math; using GlitchyEngine.Math;
using System.IO; using System.IO;
using Bon.Integrated;
using GlitchyEngine;
namespace GlitchyEditor.Assets.Importers; namespace GlitchyEditor.Assets.Importers;
[BonTarget] [BonTarget]
class NewMaterialFile : ImportedResource class MaterialVariable
{ {
public AssetHandle<Effect> Effect; public ShaderVariableType ElementType;
public int MatrixColumns;
public int MatrixRows;
public int ArrayElements;
public Dictionary<String, AssetHandle<Texture>> Textures = new .() ~ DeleteDictionaryAndKeys!(_); public uint8[] RawData ~ delete _;
public Dictionary<String, MaterialVariableValue> Constants = new .() ~ DeleteDictionaryAndKeys!(_);
public this(AssetIdentifier ownAssetIdentifier) : base(ownAssetIdentifier) public this()
{ {
} }
}
public this(ShaderVariableType elementType, int matrixColumns, int matrixRows, int arrayElements)
{
ElementType = elementType;
MatrixColumns = matrixColumns;
MatrixRows = matrixRows;
ArrayElements = arrayElements;
[BonTarget] RawData = new uint8[elementType.ElementSizeInBytes() * matrixColumns * matrixRows * arrayElements];
public enum MaterialVariableValue }
{
case bool(bool Value);
case bool2(bool2 Value);
case bool3(bool3 Value);
case bool4(bool4 Value);
case int(int Value);
case int2(int2 Value);
case int3(int3 Value);
case int4(int4 Value);
case uint(uint Value);
case uint2(uint2 Value);
case uint3(uint3 Value);
case uint4(uint4 Value);
case Float(float Value);
case Float2(float2 Value);
case Float3(float3 Value);
case Float4(float4 Value);
case Half(half Value);
case Half2(half2 Value);
case Half3(half3 Value);
case Half4(half4 Value);
case ColorRGB(ColorRGB Value);
case ColorRGBA(ColorRGBA Value);
case None;
/*static this() static this()
{ {
gBonEnv.typeHandlers.Add(typeof(Self), gBonEnv.typeHandlers.Add(typeof(Self),
((.)new => VariableValueSerialize, (.)new => VariableValueDeserialize)); ((.)new => VariableValueSerialize, (.)new => VariableValueDeserialize));
} }
static void VariableValueSerialize(BonWriter writer, ValueView value, BonEnvironment env, SerializeValueState state)
static void VariableValueSerialize(BonWriter writer, ValueView value, BonEnvironment env)
{ {
Log.EngineLogger.Assert(value.type == typeof(Self)); /*Log.EngineLogger.Assert(value.type == typeof(Self));
let variableValue = value.Get<Self>(); let variableValue = value.Get<Self>();
@@ -69,15 +53,152 @@ public enum MaterialVariableValue
Serialize.Value(writer, nameof(MaterialFile.Textures), materialFile.Textures, env); Serialize.Value(writer, nameof(MaterialFile.Textures), materialFile.Textures, env);
} }*/
} }
static Result<void> VariableValueDeserialize(BonReader reader, ValueView val, BonEnvironment env) static Result<void> VariableValueDeserialize(BonReader reader, ValueView val, BonEnvironment env, DeserializeValueState state)
{ {
MaterialVariable output = val.Get<MaterialVariable>();
StringView typeName = Try!(reader.EnumName());
// If we don't find a digit, we assume entire type name is element type and rows string ends up being an empty string.
int firstDigitIndex = typeName.Length;
for (char8 c in typeName)
{
if (c.IsDigit)
{
firstDigitIndex = @c.Index;
}
}
Result<ShaderVariableType> elementTypeResult = Enum.Parse<ShaderVariableType>(typeName.Substring(0, firstDigitIndex), true);
if (elementTypeResult case .Err)
{
Deserialize.Error!("Unknown element type.", reader);
}
int xIndex = typeName.LastIndexOf('x');
StringView rowsString = null;
StringView columnsString = null;
if (xIndex != -1)
{
rowsString = typeName.Substring(firstDigitIndex ..< xIndex);
columnsString = typeName.Substring(xIndex + 1);
}
else
{
rowsString = typeName.Substring(firstDigitIndex);
}
Result<int, Int.ParseError> rowsResult = int.Parse(rowsString);
if (rowsResult case .Err(let error))
{
switch (error)
{
case .NoValue:
rowsResult = 1;
case .Overflow:
Deserialize.Error!("Integer overflow in row count.", reader);
case .InvalidChar:
Deserialize.Error!("Invalid character in row count.", reader);
default:
return .Err;
}
}
Result<int, Int.ParseError> columnsResult = int.Parse(columnsString);
if (columnsResult case .Err(let error))
{
switch (error)
{
case .NoValue:
columnsResult = 1;
case .Overflow:
Deserialize.Error!("Integer overflow in column count.", reader);
case .InvalidChar:
Deserialize.Error!("Invalid character in column count.", reader);
default:
return .Err;
}
}
// TODO: Array
/*if (reader.[Friend]Check('['))
{
}*/
output.ElementType = elementTypeResult.Get();
output.MatrixRows = rowsResult.Get();
output.MatrixColumns = columnsResult.Get();
output.ArrayElements = 1;
int elementSize = output.ElementType.ElementSizeInBytes();
int elementCount = output.MatrixColumns * output.MatrixRows;
output.RawData = new uint8[elementSize * elementCount * output.ArrayElements];
Try!(reader.ObjectBlock());
for (int currentElementIndex < elementCount)
{
switch (output.ElementType)
{
case .Float:
StringView valueString = Try!(reader.Floating());
float* rawFloats = (float*)output.RawData.Ptr;
rawFloats[currentElementIndex] = Try!(float.Parse(valueString));
case .Bool:
// TODO: I'm pretty sure this is wrong, bools in c buffers are usually 32 bit
bool value = Try!(reader.Bool());
((bool*)&output.RawData)[currentElementIndex] = value;
case .Int:
StringView valueString = Try!(reader.Integer());
((int32*)&output.RawData)[currentElementIndex] = Try!(int32.Parse(valueString));
case .UInt:
StringView valueString = Try!(reader.Integer());
((uint32*)&output.RawData)[currentElementIndex] = Try!(uint32.Parse(valueString));
}
if (reader.ObjectHasMore())
{
Try!(reader.EntryEnd());
}
else
{
Log.EngineLogger.Warning("Vector/Matrix doesn't contain enough elements.");
break;
}
}
Try!(reader.ObjectBlockEnd());
return .Ok; return .Ok;
}*/ }
} }
[BonTarget]
class NewMaterialFile : ImportedResource
{
public AssetHandle<Effect> Effect;
public Dictionary<String, AssetHandle<Texture>> Textures = new .() ~ DeleteDictionaryAndKeys!(_);
public Dictionary<String, MaterialVariable> Constants = new .() ~ DeleteDictionaryAndKeysAndValues!(_);
public this(AssetIdentifier ownAssetIdentifier) : base(ownAssetIdentifier)
{
}
}
class MaterialImporter: IAssetImporter class MaterialImporter: IAssetImporter
{ {
@@ -106,7 +227,7 @@ class MaterialImporter: IAssetImporter
String fullText = scope .(); String fullText = scope .();
Try!(File.ReadAllText(fullFileName, fullText, true)); Try!(File.ReadAllText(fullFileName, fullText, true));
Try!(Bon.Deserialize<NewMaterialFile>(ref material, fullText)); Try!(Bon.Deserialize<NewMaterialFile>(ref material, fullText));
return material; return material;
@@ -144,7 +144,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
{ {
if (previewType.Get<String>().Equals("Color", .InvariantCultureIgnoreCase)) if (previewType.Get<String>().Equals("Color", .InvariantCultureIgnoreCase))
{ {
Log.EngineLogger.AssertDebug(variable.Type == .Float && variable.Rows == 1); Log.EngineLogger.AssertDebug(variable.ElementType == .Float && variable.Rows == 1);
if (variable.Columns == 3) if (variable.Columns == 3)
{ {
@@ -173,7 +173,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
} }
else if (previewType.Get<String>().Equals("ColorHDR", .InvariantCultureIgnoreCase)) else if (previewType.Get<String>().Equals("ColorHDR", .InvariantCultureIgnoreCase))
{ {
Log.EngineLogger.AssertDebug(variable.Type == .Float && variable.Rows == 1); Log.EngineLogger.AssertDebug(variable.ElementType == .Float && variable.Rows == 1);
if (variable.Columns == 3) if (variable.Columns == 3)
{ {
@@ -203,7 +203,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
} }
//ImGui.ColorEdit3("", null, .HDR | .Float) //ImGui.ColorEdit3("", null, .HDR | .Float)
else if (variable.Type == .Float && variable.Rows == 1) else if (variable.ElementType == .Float && variable.Rows == 1)
{ {
bool hasMin = TryGetValue(arguments, "Min", var min); bool hasMin = TryGetValue(arguments, "Min", var min);
bool hasMax = TryGetValue(arguments, "Max", var max); bool hasMax = TryGetValue(arguments, "Max", var max);
@@ -495,7 +495,7 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
if (hasPreviewType && previewType.Get<String>() == "Color") if (hasPreviewType && previewType.Get<String>() == "Color")
{ {
Log.EngineLogger.AssertDebug(variable.Type == .Float && variable.Rows == 1); Log.EngineLogger.AssertDebug(variable.ElementType == .Float && variable.Rows == 1);
if (variable.Columns == 3) if (variable.Columns == 3)
{ {
@@ -515,7 +515,7 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
variableValue = .ColorRGBA(value); variableValue = .ColorRGBA(value);
} }
} }
else if (variable.Type == .Float && variable.Rows == 1) else if (variable.ElementType == .Float && variable.Rows == 1)
{ {
switch (variable.Columns) switch (variable.Columns)
{ {
@@ -4,26 +4,42 @@ using GlitchyEditor.Assets.Importers;
using GlitchyEngine.Renderer; using GlitchyEngine.Renderer;
using GlitchyEngine; using GlitchyEngine;
using GlitchyEngine.Content; using GlitchyEngine.Content;
using System.Diagnostics;
namespace GlitchyEditor.Assets.Processors; namespace GlitchyEditor.Assets.Processors;
class ProcessedMaterial : ProcessedResource class ProcessedMaterial : ProcessedResource
{ {
public AssetHandle EffectHandle;
private Dictionary<String, uint8[]> _bufferData = new .() ~ DeleteDictionaryAndKeysAndValues!(_); private Dictionary<String, uint8[]> _bufferData = new .() ~ DeleteDictionaryAndKeysAndValues!(_);
private Dictionary<String, AssetHandle> _textures = new .() ~ DeleteDictionaryAndKeys!(_);
public override AssetType AssetType => .Material; public override AssetType AssetType => .Material;
public Dictionary<String, uint8[]> Buffers => _bufferData;
public Dictionary<String, AssetHandle> Textures => _textures;
public this(AssetIdentifier ownAssetIdentifier, AssetHandle assetHandle) : base(ownAssetIdentifier, assetHandle) public this(AssetIdentifier ownAssetIdentifier, AssetHandle assetHandle) : base(ownAssetIdentifier, assetHandle)
{ {
} }
public uint8[] CloneBuffer(ConstantBuffer cBuffer) public Span<uint8> CloneBuffer(String name, ConstantBuffer cBuffer)
{ {
String name = new String(cBuffer.Name); String copyName = new String(name);
//uint8[] data = cBuffer. uint8[] data = new uint8[cBuffer.RawData.Length];
cBuffer.RawData.CopyTo(data);
return null; _bufferData.Add(copyName, data);
return data;
}
public void AddTexture(StringView name, AssetHandle textureHandle)
{
String copyName = new String(name);
_textures.Add(copyName, textureHandle);
} }
} }
@@ -47,22 +63,67 @@ class MaterialProcessor : IAssetProcessor
Effect effect = Content.GetAsset<Effect>(importedMaterial.Effect, blocking: true); Effect effect = Content.GetAsset<Effect>(importedMaterial.Effect, blocking: true);
if (effect == null)
// TODO: Don't error out, use the error-effect
return .Err;
ProcessedMaterial processedMaterial = new .(new AssetIdentifier(importedMaterial.AssetIdentifier), config.AssetHandle); ProcessedMaterial processedMaterial = new .(new AssetIdentifier(importedMaterial.AssetIdentifier), config.AssetHandle);
processedMaterial.EffectHandle = importedMaterial.Effect;
for (let buffer in effect.Buffers) for (let buffer in effect.Buffers)
{ {
// TODO: Skip engine buffers
if (buffer.Buffer == null)
continue;
ConstantBuffer cBuffer = buffer.Buffer as ConstantBuffer; ConstantBuffer cBuffer = buffer.Buffer as ConstantBuffer;
if (cBuffer == null) if (cBuffer == null)
{ {
Log.EngineLogger.Error("The buffers of a material must be ConstantBuffers.");
continue;
// TODO: Why even allow any kind of Buffer for Materials? Will this make sense later if we can create and bind Buffers from C#?
} }
processedMaterial.CloneBuffer(cBuffer); Span<uint8> data = processedMaterial.CloneBuffer(buffer.Name, cBuffer);
for (BufferVariable effectVariable in cBuffer.Variables)
{
if (importedMaterial.Constants.TryGetValue(effectVariable.Name, let materialValue))
{
if (effectVariable.ElementType != materialValue.ElementType)
{
Log.EngineLogger.Error("Element type doesn't match between material and effect.");
continue;
}
int effectVariableSize = effectVariable.Rows * effectVariable.Columns * Math.Max(1, effectVariable.ArrayElements) * effectVariable.ElementType.ElementSizeInBytes();
if (effectVariableSize != materialValue.RawData.Count)
{
Log.EngineLogger.Warning("Warning, matrix size in matrix and effect doesn't match. Truncating value.");
}
int bytesToCopy = Math.Min(effectVariableSize, materialValue.RawData.Count);
Debug.Assert(effectVariable.Offset + bytesToCopy <= data.Length, "Material value goes out of bounds ");
Internal.MemCpy(data.Ptr + effectVariable.Offset, materialValue.RawData.Ptr, bytesToCopy);
}
}
} }
// Create buffers for (let (textureName, textureBinding) in effect.Textures)
{
if (importedMaterial.Textures.TryGetValue(textureName, let textureHandle))
{
processedMaterial.AddTexture(textureName, textureHandle);
}
}
return default; outProcessedResources.Add(processedMaterial);
return .Ok;
} }
} }
+4 -4
View File
@@ -29,10 +29,6 @@ namespace GlitchyEditor
_contentManager.SetAsDefaultAssetLoader<ModelAssetLoader>(".glb", ".gltf"); _contentManager.SetAsDefaultAssetLoader<ModelAssetLoader>(".glb", ".gltf");
_contentManager.SetAssetPropertiesEditor<ModelAssetLoader>(=> ModelAssetPropertiesEditor.Factory); _contentManager.SetAssetPropertiesEditor<ModelAssetLoader>(=> ModelAssetPropertiesEditor.Factory);
_contentManager.RegisterAssetLoader<MaterialAssetLoader>();
_contentManager.SetAsDefaultAssetLoader<MaterialAssetLoader>(".mat");
_contentManager.SetAssetPropertiesEditor<MaterialAssetLoader>(=> MaterialAssetPropertiesEditor.Factory);
_contentManager.RegisterAssetImporter<TextureImporter>(); _contentManager.RegisterAssetImporter<TextureImporter>();
_contentManager.RegisterAssetProcessor<TextureProcessor>(); _contentManager.RegisterAssetProcessor<TextureProcessor>();
_contentManager.RegisterAssetExporter<TextureExporter>(); _contentManager.RegisterAssetExporter<TextureExporter>();
@@ -43,6 +39,10 @@ namespace GlitchyEditor
_contentManager.RegisterAssetProcessor<ShaderProcessor>(); _contentManager.RegisterAssetProcessor<ShaderProcessor>();
_contentManager.RegisterAssetExporter<ShaderExporter>(); _contentManager.RegisterAssetExporter<ShaderExporter>();
_contentManager.RegisterAssetImporter<MaterialImporter>();
_contentManager.RegisterAssetProcessor<MaterialProcessor>();
_contentManager.RegisterAssetExporter<MaterialExporter>();
_contentManager.SetGlobalAssetCacheDirectory(".cache"); _contentManager.SetGlobalAssetCacheDirectory(".cache");
_contentManager.SetResourcesDirectory("Resources"); _contentManager.SetResourcesDirectory("Resources");
@@ -946,6 +946,7 @@ class EditorContentManager : IContentManager
TextureLoader textureLoader = new .() ~ delete _; TextureLoader textureLoader = new .() ~ delete _;
SpriteLoader spriteLoader = new .() ~ delete _; SpriteLoader spriteLoader = new .() ~ delete _;
ShaderLoader shaderLoader = new .() ~ delete _; ShaderLoader shaderLoader = new .() ~ delete _;
MaterialLoader materialLoader = new .() ~ delete _;
private IProcessedAssetLoader GetLoader(AssetType assetType) private IProcessedAssetLoader GetLoader(AssetType assetType)
{ {
@@ -957,6 +958,8 @@ class EditorContentManager : IContentManager
return spriteLoader; return spriteLoader;
case .Shader: case .Shader:
return shaderLoader; return shaderLoader;
case .Material:
return materialLoader;
default: default:
return null; return null;
} }
@@ -0,0 +1,53 @@
using System;
using System.Collections;
using System.IO;
using GlitchyEngine.Renderer;
namespace GlitchyEngine.Content.Loaders;
class MaterialLoader : IProcessedAssetLoader
{
public Result<Asset> Load(Stream stream)
{
Compiler.Assert(sizeof(AssetHandle) == 8);
AssetHandle<Effect> effectHandle = Try!(stream.Read<AssetHandle>());
Effect effect = Content.GetAsset<Effect>(effectHandle, blocking: true);
Material material = new Material(effect);
uint16 textureCount = Try!(stream.Read<uint16>());
for (int i < textureCount)
{
AssetHandle<Texture> textureHandle = Try!(stream.Read<AssetHandle>());
int16 textureNameLength = Try!(stream.Read<int16>());
String textureName = scope String(textureNameLength);
stream.ReadStrSized32(textureNameLength, textureName);
material.SetTexture(textureName, textureHandle);
}
uint16 bufferCount = Try!(stream.Read<uint16>());
for (int i < bufferCount)
{
int64 bufferDataSize = Try!(stream.Read<int64>());
int16 textureNameLength = Try!(stream.Read<int16>());
String textureName = scope String(textureNameLength);
stream.ReadStrSized32(textureNameLength, textureName);
uint8[] data = new:ScopedAlloc! uint8[bufferDataSize];
Try!(stream.TryRead(data));
// TODO: Somehow get buffer data into material
}
material.SetVariable("AlbedoColor", GlitchyEngine.Math.float4(1.0f, 0, 0, 1.0f));
return material;
}
}
+14 -11
View File
@@ -10,20 +10,20 @@ namespace GlitchyEngine.Renderer
private String _name ~ delete _; private String _name ~ delete _;
private ShaderVariableType _type; private ShaderVariableType _elementType;
internal uint32 _columns; internal uint32 _columns;
internal uint32 _rows; internal uint32 _rows;
private uint32 _offset; private uint32 _offset;
internal uint32 _sizeInBytes; internal uint32 _sizeInBytes;
// Number of elements in the array // Number of elements in the array
internal uint32 _elements; internal uint32 _arrayElements;
private bool _isUsed; private bool _isUsed;
public ConstantBuffer ConstantBuffer => _constantBuffer; public ConstantBuffer ConstantBuffer => _constantBuffer;
public ShaderVariableType Type => _type; public ShaderVariableType ElementType => _elementType;
public String Name => _name; public String Name => _name;
@@ -31,6 +31,9 @@ namespace GlitchyEngine.Renderer
public uint32 Columns => _columns; public uint32 Columns => _columns;
public uint32 Rows => _rows; public uint32 Rows => _rows;
public uint32 ArrayElements => _arrayElements;
public uint32 Offset => _offset;
/** /**
* Gets a pointer to the start of the variable in the constant buffers backing data. * Gets a pointer to the start of the variable in the constant buffers backing data.
@@ -38,16 +41,16 @@ 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 elements, bool isUsed) public this(StringView name, ConstantBuffer constantBuffer, ShaderVariableType type, uint32 columns, uint32 rows, uint32 offset, uint32 sizeInBytes, uint32 arrayElements, bool isUsed)
{ {
_name = new String(name); _name = new String(name);
_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
_type = type; _elementType = type;
_columns = columns; _columns = columns;
_rows = rows; _rows = rows;
_offset = offset; _offset = offset;
_sizeInBytes = sizeInBytes; _sizeInBytes = sizeInBytes;
_elements = elements; _arrayElements = arrayElements;
_isUsed = isUsed; _isUsed = isUsed;
} }
@@ -64,8 +67,8 @@ namespace GlitchyEngine.Renderer
#endif #endif
#if GE_SHADER_VAR_TYPE_MISMATCH_IS_ERROR #if GE_SHADER_VAR_TYPE_MISMATCH_IS_ERROR
if (type != _type) if (type != _elementType)
Log.EngineLogger.Assert(false, scope $"The types do not match: Expected \"{_type}\" but Received \"{type}\" instead. Variable: \"{_name}\" of buffer: \"{_constantBuffer.Name}\""); Log.EngineLogger.Assert(false, scope $"The types do not match: Expected \"{_elementType}\" but Received \"{type}\" instead. Variable: \"{_name}\" of buffer: \"{_constantBuffer.Name}\"");
#elif GE_SHADER_VAR_TYPE_MISMATCH_IS_WARNING #elif GE_SHADER_VAR_TYPE_MISMATCH_IS_WARNING
if (type != _type) if (type != _type)
Log.EngineLogger.Warning($"The types do not match: Expected \"{_type}\" but Received \"{type}\" instead. Variable: \"{_name}\" of buffer: \"{_constantBuffer.Name}\""); Log.EngineLogger.Warning($"The types do not match: Expected \"{_type}\" but Received \"{type}\" instead. Variable: \"{_name}\" of buffer: \"{_constantBuffer.Name}\"");
@@ -174,7 +177,7 @@ namespace GlitchyEngine.Renderer
// TODO: assert length // TODO: assert length
Internal.MemCpy(firstByte, value.Ptr, sizeof(Matrix4x3) * Math.Min(value.Count, _elements)); Internal.MemCpy(firstByte, value.Ptr, sizeof(Matrix4x3) * Math.Min(value.Count, _arrayElements));
} }
public void SetData(Matrix3x3 value) public void SetData(Matrix3x3 value)
@@ -192,7 +195,7 @@ namespace GlitchyEngine.Renderer
// TODO: assert length // TODO: assert length
for(int i < Math.Min(value.Count, _elements)) for(int i < Math.Min(value.Count, _arrayElements))
{ {
((Matrix4x3*)firstByte)[i] = Matrix4x3(value[i]); ((Matrix4x3*)firstByte)[i] = Matrix4x3(value[i]);
} }
@@ -206,7 +209,7 @@ namespace GlitchyEngine.Renderer
// TODO: assert length // TODO: assert length
Internal.MemCpy(firstByte, value.Ptr, sizeof(Matrix) * Math.Min(value.Count, _elements)); Internal.MemCpy(firstByte, value.Ptr, sizeof(Matrix) * Math.Min(value.Count, _arrayElements));
} }
// Todo: add all the other SetData-Methods // Todo: add all the other SetData-Methods
@@ -78,6 +78,7 @@ namespace GlitchyEngine.Renderer
switch (this) switch (this)
{ {
case .Bool: case .Bool:
// TODO: I'm pretty sure this is wrong and should be 4 as well!
return 1; return 1;
case .Float: case .Float:
return 4; return 4;
+4 -4
View File
@@ -93,9 +93,9 @@ public class Material : Asset
{ {
if (_variables.TryGetValue(newKey, let oldEntry)) if (_variables.TryGetValue(newKey, let oldEntry))
{ {
if (oldEntry.Variable.Type == newValue.Variable.Type) if (oldEntry.Variable.ElementType == newValue.Variable.ElementType)
{ {
int elementSize = newValue.Variable.Type.ElementSizeInBytes(); int elementSize = newValue.Variable.ElementType.ElementSizeInBytes();
for (int r = 0; r < Math.Min(oldEntry.Variable.Rows, newValue.Variable.Rows); r++) for (int r = 0; r < Math.Min(oldEntry.Variable.Rows, newValue.Variable.Rows); r++)
for (int c = 0; c < Math.Min(oldEntry.Variable.Columns, newValue.Variable.Columns); c++) for (int c = 0; c < Math.Min(oldEntry.Variable.Columns, newValue.Variable.Columns); c++)
@@ -259,7 +259,7 @@ public class Material : Asset
{ {
entry.Variable.EnsureTypeMatch<Matrix3x3>(); entry.Variable.EnsureTypeMatch<Matrix3x3>();
int count = Math.Min(values.Count, entry.Variable._elements); int count = Math.Min(values.Count, entry.Variable._arrayElements);
for(int i < count) for(int i < count)
{ {
@@ -281,7 +281,7 @@ public class Material : Asset
{ {
entry.Variable.EnsureTypeMatch<Matrix>(); entry.Variable.EnsureTypeMatch<Matrix>();
Internal.MemCpy(RawPointer!<Matrix>(entry.Offset), values.Ptr, sizeof(Matrix) * Math.Min(values.Count, entry.Variable._elements)); Internal.MemCpy(RawPointer!<Matrix>(entry.Offset), values.Ptr, sizeof(Matrix) * Math.Min(values.Count, entry.Variable._arrayElements));
} }
else else
{ {