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
-2
View File
@@ -1,8 +1,6 @@
using System;
using GlitchyEngine.Events;
using GlitchyEngine.ImGui;
using GlitchyEngine.Math;
using System.Diagnostics;
using GlitchyEngine.Renderer;
namespace GlitchyEngine
@@ -0,0 +1,77 @@
using DirectX.Common;
using DirectX.D3D11Shader;
using System;
using internal GlitchyEngine.Renderer;
namespace GlitchyEngine.Renderer
{
extension BufferVariable
{
internal this(ConstantBuffer constantBuffer, ID3D11ShaderReflectionVariable* variableReflection)
{
_constantBuffer = constantBuffer..AddRef();
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 .Float:
_type = .Float;
default:
Log.EngineLogger.Assert(false, scope $"Unhandled shader variable type: {shaderTypeDescription.Type}");
}
_columns = shaderTypeDescription.Columns;
_rows = shaderTypeDescription.Rows;
SetRawData(variableDescription.DefaultValue);
}
}
extension ConstantBuffer
{
internal this(GraphicsContext context, ID3D11ShaderReflectionConstantBuffer* bufferReflection) : base(context)
{
Reflect(bufferReflection);
ConstructBuffer();
Update();
}
private void Reflect(ID3D11ShaderReflectionConstantBuffer* bufferReflection)
{
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);
}
}
}
}
@@ -0,0 +1,25 @@
using System;
using DirectX;
using DirectX.D3D11;
using internal GlitchyEngine.Renderer;
namespace GlitchyEngine.Renderer
{
extension Effect
{
protected override void Compile(String vsPath, String vsEntry, String psPath, String psEntry)
{
// Todo: macros
VertexShader = new VertexShader(_context, vsPath, vsEntry);
PixelShader = new PixelShader(_context, psPath, psEntry);
Reflect();
}
private void Reflect()
{
}
}
}
@@ -12,17 +12,15 @@ namespace GlitchyEngine.Renderer
public override void CompileFromSource(String code, String entryPoint, ShaderDefine[] macros = null)
{
Shader.PlattformCompileShaderFromSource(code, macros, entryPoint, "ps_5_0", DefaultCompileFlags, let shaderBlob);
Shader.PlattformCompileShaderFromSource(code, macros, entryPoint, "ps_5_0", DefaultCompileFlags, out nativeCode);
var result = _context.nativeDevice.CreatePixelShader(shaderBlob.GetBufferPointer(), shaderBlob.GetBufferSize(), null, &nativeShader);
var result = _context.nativeDevice.CreatePixelShader(nativeCode.GetBufferPointer(), nativeCode.GetBufferSize(), null, &nativeShader);
if(result.Failed)
{
Log.EngineLogger.Error($"Failed to create pixel shader: Message ({(int)result}): {result}");
}
Reflect(shaderBlob);
shaderBlob?.Release();
Reflect(nativeCode);
}
}
}
@@ -11,6 +11,11 @@ namespace GlitchyEngine.Renderer
{
extension Shader
{
/**
* Internal compiled code of the shader.
*/
internal ID3DBlob* nativeCode ~ _?.Release();
protected const ShaderCompileFlags DefaultCompileFlags =
#if DEBUG
.Debug;
@@ -62,6 +67,18 @@ namespace GlitchyEngine.Renderer
bufferReflection.GetDescription(let bufferDesc);
// ConstantBuffer
if(bufferDesc.Type == .D3D11_CT_CBUFFER)
{
let buffer = new ConstantBuffer(_context, bufferReflection);
_buffers.Add(bindDesc.BindPoint, buffer.Name, buffer);
buffer.ReleaseRef();
}
/*
bufferReflection.GetDescription(let bufferDesc);
// ConstantBuffer
if(bufferDesc.Type == .D3D11_CT_CBUFFER)
{
@@ -69,7 +86,8 @@ namespace GlitchyEngine.Renderer
let buffer = new Buffer(_context, cBufferDesc);
_buffers.Add(bindDesc.BindPoint, StringView(bufferDesc.Name), buffer, true);
_buffers.Add(bindDesc.BindPoint, StringView(bufferDesc.Name), buffer);//, true
buffer.ReleaseRef();
// Buffer for default values
uint8* rawData = new:ScopedAlloc! uint8[bufferDesc.Size]*;
@@ -87,6 +105,7 @@ namespace GlitchyEngine.Renderer
buffer.SetData(Span<uint8>(rawData, bufferDesc.Size));
}
*/
}
reflection.Release();
}
@@ -12,8 +12,6 @@ namespace GlitchyEngine.Renderer
{
internal ID3D11VertexShader* nativeShader ~ _?.Release();
internal ID3DBlob* nativeCode ~ _?.Release();
public override void CompileFromSource(String code, String entryPoint, ShaderDefine[] macros = null)
{
Shader.PlattformCompileShaderFromSource(code, macros, entryPoint, "vs_5_0", DefaultCompileFlags, out nativeCode);
+1 -1
View File
@@ -120,7 +120,7 @@ namespace GlitchyEngine.Renderer
}
/// Represents a buffer containing binary data on the GPU.
public class Buffer
public class Buffer : RefCounted
{
internal GraphicsContext _context;
+25 -19
View File
@@ -5,7 +5,7 @@ namespace GlitchyEngine.Renderer
{
public class BufferCollection
{
typealias BufferEntry = (String Name, int Index, Buffer Buffer, bool OwnsBuffer);
typealias BufferEntry = (String Name, int Index, Buffer Buffer);//, bool OwnsBuffer
List<BufferEntry> _buffers ~ DeleteBufferEntries!(_);
@@ -33,8 +33,7 @@ namespace GlitchyEngine.Renderer
for(let entry in entries)
{
delete entry.Name;
if(entry.OwnsBuffer)
delete entry.Buffer;
entry.Buffer.ReleaseRef();
}
delete entries;
@@ -49,7 +48,7 @@ namespace GlitchyEngine.Renderer
* @param buffer The new buffer.
* @param If set to true, the Collection will take ownership of the buffer; if false, the ownership will remain with the caller.
*/
public void ReplaceBuffer(int idx, Buffer buffer, bool passOwnership = false)
public void ReplaceBuffer(int idx, Buffer buffer)//, bool passOwnership = false
{
if(_idxToBuf.TryGetValue(idx, let oldBuffer))
{
@@ -59,11 +58,13 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.Assert(idx == bufferDesc.Index);
if(bufferDesc.OwnsBuffer)
delete bufferDesc.Buffer;
oldBuffer.ReleaseRef();
//if(bufferDesc.OwnsBuffer)
// delete bufferDesc.Buffer;
buffer.AddRef();
bufferDesc.Buffer = buffer;
bufferDesc.OwnsBuffer = passOwnership;
//bufferDesc.OwnsBuffer = passOwnership;
_strToBuf[bufferDesc.Name] = buffer;
_idxToBuf[bufferDesc.Index] = buffer;
@@ -80,7 +81,7 @@ namespace GlitchyEngine.Renderer
* @param buffer The new buffer.
* @param If set to true, the Collection will take ownership of the buffer; if false, the ownership will remain with the caller.
*/
public void ReplaceBuffer(StringView name, Buffer buffer, bool passOwnership = false)
public void ReplaceBuffer(StringView name, Buffer buffer) // , bool passOwnership = false
{
if(_strToBuf.TryGetValue(name, let oldBuffer))
{
@@ -90,11 +91,13 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.Assert(name == bufferDesc.Name);
if(bufferDesc.OwnsBuffer)
delete bufferDesc.Buffer;
oldBuffer.ReleaseRef();
//if(bufferDesc.OwnsBuffer)
// delete bufferDesc.Buffer;
buffer.AddRef();
bufferDesc.Buffer = buffer;
bufferDesc.OwnsBuffer = passOwnership;
//bufferDesc.OwnsBuffer = passOwnership;
_strToBuf[bufferDesc.Name] = buffer;
_idxToBuf[bufferDesc.Index] = buffer;
@@ -111,7 +114,7 @@ namespace GlitchyEngine.Renderer
* @param buffer The new buffer.
* @param If set to true, the Collection will take ownership of the buffer; if false, the ownership will remain with the caller.
*/
public bool TryReplaceBuffer(StringView name, Buffer buffer, bool passOwnership = false)
public bool TryReplaceBuffer(StringView name, Buffer buffer) // , bool passOwnership = false
{
if(_strToBuf.TryGetValue(name, let oldBuffer))
{
@@ -121,11 +124,13 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.Assert(name == bufferDesc.Name);
if(bufferDesc.OwnsBuffer)
delete bufferDesc.Buffer;
//if(bufferDesc.OwnsBuffer)
// delete bufferDesc.Buffer;
oldBuffer.ReleaseRef();
buffer.AddRef();
bufferDesc.Buffer = buffer;
bufferDesc.OwnsBuffer = passOwnership;
//bufferDesc.OwnsBuffer = passOwnership;
_strToBuf[bufferDesc.Name] = buffer;
_idxToBuf[bufferDesc.Index] = buffer;
@@ -138,11 +143,12 @@ namespace GlitchyEngine.Renderer
}
}
public void Add(int index, StringView name, Buffer buffer, bool passOwnership = false)
public void Add(int index, StringView name, Buffer buffer) //, bool passOwnership = false
{
String nameStr = new String(name);
BufferEntry entry = (nameStr, index, buffer, passOwnership);
BufferEntry entry = (nameStr, index, buffer); //, passOwnership
buffer.AddRef();
_buffers.Add(entry);
_strToBuf.Add(entry.Name, entry.Buffer);
_idxToBuf.Add(entry.Index, entry.Buffer);
@@ -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);
}
}
}
+28 -5
View File
@@ -2,24 +2,34 @@ using System;
namespace GlitchyEngine.Renderer
{
public class Effect
public class Effect : RefCounted
{
protected GraphicsContext _context;
internal VertexShader _vs;
internal PixelShader _ps;
internal VertexShader _vs ~ _?.ReleaseRef();
internal PixelShader _ps ~ _?.ReleaseRef();
public GraphicsContext Context => _context;
public VertexShader VertexShader
{
get => _vs;
set => _vs = value;
set
{
_vs?.ReleaseRef();
_vs = value;
_vs?.AddRef();
}
}
public PixelShader PixelShader
{
get => _ps;
set => _ps = value;
set
{
_ps?.ReleaseRef();
_ps = value;
_ps?.AddRef();
}
}
public void Bind(GraphicsContext context)
@@ -27,5 +37,18 @@ namespace GlitchyEngine.Renderer
context.SetVertexShader(_vs);
context.SetPixelShader(_ps);
}
[Obsolete("Will be removed in the future", false)]
public this()
{
}
public this(String vsPath, String vsEntry, String psPath, String psEntry)
{
Compile(vsPath, vsEntry, psPath, psEntry);
}
protected extern void Compile(String vsPath, String vsEntry, String psPath, String psEntry);
}
}
+29
View File
@@ -0,0 +1,29 @@
using System;
using GlitchyEngine.Math;
namespace GlitchyEngine.Renderer
{
public class Material : RefCounted
{
private Effect _effect ~ _?.ReleaseRef();
public this(Effect effect)
{
_effect = effect;
}
// public void Set(String name, VALUE)...
// Float, Float2, Float3, Float4
// Color, ColorRGB, ColorRGBA
// Matrix3x3, Matrix4x3, Matrix
// Int, Int2, Int3, Int4
// UInt, UInt2, UInt3, UInt4
// Bool, Bool2, Bool3, Bool4
// Half, Half2, Half3, Half4
// Byte, Byte2, Byte3, Byte4
// Texture
// Sampler
}
}
+20 -4
View File
@@ -9,15 +9,25 @@ namespace GlitchyEngine.Renderer
public Matrix ViewProjection;
}
struct ObjectConstants
{
public Matrix Transform;
}
static GraphicsContext _context;
static Buffer<SceneConstants> _sceneConstants ~ delete _;
static Buffer<SceneConstants> _sceneConstants ~ _?.ReleaseRef();
static Buffer<ObjectConstants> _objectConstants ~ _?.ReleaseRef();
public static void Init(GraphicsContext context)
{
_context = context;
_sceneConstants = new Buffer<SceneConstants>(_context, .(0, .Constant, .Dynamic, .Write));
_sceneConstants.Update();
_objectConstants = new Buffer<ObjectConstants>(_context, .(0, .Constant, .Dynamic, .Write));
_objectConstants.Update();
}
public static void BeginScene(Camera camera)
@@ -28,13 +38,19 @@ namespace GlitchyEngine.Renderer
public static void EndScene(){}
public static void Submit(GeometryBinding geometry, Effect effect)
public static void Submit(GeometryBinding geometry, Effect effect, Matrix transform = .Identity)
{
effect.Bind(_context);
effect.PixelShader?.Buffers.TryReplaceBuffer("SceneConstants", _sceneConstants);
effect.VertexShader?.Buffers.TryReplaceBuffer("SceneConstants", _sceneConstants);
_objectConstants.Data.Transform = transform;
_objectConstants.Update();
effect.PixelShader?.Buffers.TryReplaceBuffer("ObjectConstants", _objectConstants);
effect.VertexShader?.Buffers.TryReplaceBuffer("ObjectConstants", _objectConstants);
effect.Bind(_context);
geometry.Bind();
RenderCommand.DrawIndexed(geometry);
}
+8 -4
View File
@@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Collections;
using System.Diagnostics;
namespace GlitchyEngine.Renderer
{
@@ -19,7 +18,7 @@ namespace GlitchyEngine.Renderer
}
}
public abstract class Shader
public abstract class Shader : RefCounted
{
protected GraphicsContext _context;
@@ -33,13 +32,18 @@ namespace GlitchyEngine.Renderer
public this(GraphicsContext context, String source, String entryPoint, ShaderDefine[] macros = null)
{
// Todo: append as soon as it's fixed.
let buffers = new BufferCollection();
_buffers = buffers;
//let buffers = new BufferCollection();
_buffers = new BufferCollection();
_context = context;
CompileFromSource(source, entryPoint);
}
public ~this()
{
}
public static mixin FromFile<T>(GraphicsContext context, String fileName, String entryPoint, ShaderDefine[] macros = null) where T : Shader
{
String fileContent = new String();