Added RefCounting, added ConstantBuffers

This commit is contained in:
Simon Lübeß
2021-02-06 19:37:07 +01:00
parent a2e4b5563e
commit 9ea56d6786
17 changed files with 759 additions and 293 deletions
@@ -0,0 +1,212 @@
using DirectX.D3D11Shader;
using System;
using System.Collections;
using GlitchyEngine.Math;
using internal GlitchyEngine.Renderer;
namespace GlitchyEngine.Renderer
{
public class ConstantBuffer : Buffer
{
protected String _name ~ delete _;
/**
* The buffer that contains the buffer data on the CPU.
*/
protected internal uint8[] rawData ~ delete _;
protected List<BufferVariable> _variables = new .() ~ DeleteContainerAndItems!(_);
protected Dictionary<String, BufferVariable> _nameToVariable = new .() ~ delete _;
/// Gets the name of the constant buffer.
public String Name => _name;
protected this(GraphicsContext context) : base(context) {}
public BufferVariable this[String name] => _nameToVariable[name];
protected internal void AddVariable(BufferVariable ownVariable)
{
_variables.Add(ownVariable);
_nameToVariable.Add(ownVariable.Name, ownVariable);
}
/**
* Construct the buffer description.
*/
protected void ConstructBuffer()
{
_description.Size = (.)rawData.Count;
_description.BindFlags = .Constant;
_description.CPUAccess = .Write;
_description.Usage = .Dynamic;
_description.MiscFlags = .None;
}
/**
* Uploads the date to the GPU.
*/
public void Update()
{
PlatformSetData(rawData.CArray(), (uint32)rawData.Count, 0, .WriteDiscard);
}
}
public enum ShaderVariableType
{
Float,
// todo
}
public class BufferVariable
{
private ConstantBuffer _constantBuffer ~ _constantBuffer?.ReleaseRef();
private String _name ~ delete _;
private ShaderVariableType _type;
private uint32 _columns;
private uint32 _rows;
private uint32 _offset;
private uint32 _sizeInBytes;
private bool _isUsed;
public ConstantBuffer ConstantBuffer => _constantBuffer;
public ShaderVariableType Type => _type;
public String Name => _name;
/**
* Gets a pointer to the start of the variable in the constant buffers backing data.
*/
[Inline]
internal uint8* firstByte => _constantBuffer.rawData.CArray() + _offset;
public this(ConstantBuffer constantBuffer, ShaderVariableType type, uint32 columns, uint32 rows, uint32 offset, uint32 sizeInBytes, bool isUsed)
{
_constantBuffer = constantBuffer..AddRef();
_type = type;
_columns = columns;
_rows = rows;
_offset = offset;
_sizeInBytes = sizeInBytes;
_isUsed = isUsed;
}
public void EnsureTypeMatch(int rows, int cols, ShaderVariableType type)
{
#if GE_ERROR_SHADER_MATRIX_MISMATCH
Log.EngineLogger.Assert(rows == _rows || cols == _columns, scope $"The matrix-dimensions do not match: Expected {_rows} rows and {_rows} columns but Received {rows} rows and {cols} columns instead. Variable: \"{_name}\" of buffer: \"{_constantBuffer.Name}\"");
#elif GE_WARN_SHADER_MATRIX_MISMATCH
if (rows != _rows || cols != _columns)
Log.EngineLogger.Warning($"The matrix-dimensions do not match: Expected {_rows} rows and {_rows} columns but Received {rows} rows and {cols} columns instead. Variable: \"{_name}\" of buffer: \"{_constantBuffer.Name}\"");
#endif
#if GE_ERROR_SHADER_VAR_TYPE_MISMATCH
Log.EngineLogger.Assert(type == _type, scope $"The types do not match: Expected \"{_type}\" but Received \"{type}\" instead. Variable: \"{_name}\" of buffer: \"{_constantBuffer.Name}\"");
#elif GE_WARN_SHADER_VAR_TYPE_MISMATCH
if (type != _type)
Log.EngineLogger.Warning($"The types do not match: Expected \"{_type}\" but Received \"{type}\" instead. Variable: \"{_name}\" of buffer: \"{_constantBuffer.Name}\"");
#endif
}
public void SetData(float value)
{
EnsureTypeMatch(1, 1, .Float);
*(float*)firstByte = value;
}
public void SetData(Vector2 value)
{
EnsureTypeMatch(1, 2, .Float);
*(Vector2*)firstByte = value;
}
public void SetData(Vector3 value)
{
EnsureTypeMatch(1, 3, .Float);
*(Vector3*)firstByte = value;
}
public void SetData(Vector4 value)
{
EnsureTypeMatch(1, 4, .Float);
*(Vector4*)firstByte = value;
}
public void SetData(Matrix4x3 value)
{
// I think this is right
EnsureTypeMatch(4, 3, .Float);
*(Matrix4x3*)firstByte = value;
}
public void SetData(Matrix3x3 value)
{
EnsureTypeMatch(3, 3, .Float);
*(Matrix4x3*)firstByte = Matrix4x3(value);
// Todo: maybe manual copy
}
public void SetData(Matrix value)
{
EnsureTypeMatch(4, 4, .Float);
*(Matrix*)firstByte = value;
}
public void SetData(ColorRGB value)
{
EnsureTypeMatch(1, 3, .Float);
*(ColorRGB*)firstByte = value;
}
public void SetData(ColorRGBA value)
{
EnsureTypeMatch(1, 4, .Float);
*(ColorRGBA*)firstByte = value;
}
public void SetData(Color value)
{
EnsureTypeMatch(1, 4, .Float);
*(ColorRGBA*)firstByte = (ColorRGBA)value;
}
// Todo: add all the other SetData-Methods
/**
* Sets the raw data of the variable.
* @param rawData The pointer to the raw data. If rawData is null the raw data will be set to zero.
*/
internal void SetRawData(void* rawData)
{
#if DEBUG && !GE_IGNORE_UNUSED_VARIABLE
if(!_isUsed)
{
Log.EngineLogger.Warning($"Setting data for unused Variable \"{_name}\" of constant buffer \"{_constantBuffer.Name}\".");
}
#endif
if(rawData != null)
Internal.MemCpy(firstByte, rawData, _sizeInBytes);
else
Internal.MemSet(firstByte, 0, _sizeInBytes);
}
}
}