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
+11
View File
@@ -0,0 +1,11 @@
GE_ERROR_SHADER_MATRIX_MISMATCH:
If this macro is set, the engine checks at runtime whether or not the dimensions of the given value match the dimensions of the shader variable. (Applies to: BufferVariable.SetData)
GE_WARN_SHADER_MATRIX_MISMATCH:
Same as GE_ERROR_SHADER_MATRIX_MISMATCH but instead of crashing a warning will written to the console.
GE_ERROR_SHADER_VAR_TYPE_MISMATCH:
If this macro is set, upon calling BufferVariable.SetData the type of the provided value will be checked against the actual value type. If they do not match, the application will crash.
GE_WARN_SHADER_VAR_TYPE_MISMATCH:
Same as GE_ERROR_SHADER_VAR_TYPE_MISMATCH but instead of crashing a warning will be written to the console.
+1
View File
@@ -3,6 +3,7 @@ Dependencies = {GlitchLog = "*", corlib = "*", DirectX = "*", ImGui = "*", ImGui
[Project] [Project]
Name = "GlitchyEngine" Name = "GlitchyEngine"
ProcessorMacros = ["GE_ERROR_SHADER_MATRIX_MISMATCH", "GE_ERROR_SHADER_VAR_TYPE_MISMATCH"]
[Configs.Debug.Win32] [Configs.Debug.Win32]
PreprocessorMacros = ["DEBUG", "GE_WINDOWS"] PreprocessorMacros = ["DEBUG", "GE_WINDOWS"]
-2
View File
@@ -1,8 +1,6 @@
using System; using System;
using GlitchyEngine.Events; using GlitchyEngine.Events;
using GlitchyEngine.ImGui; using GlitchyEngine.ImGui;
using GlitchyEngine.Math;
using System.Diagnostics;
using GlitchyEngine.Renderer; using GlitchyEngine.Renderer;
namespace GlitchyEngine 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) 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) if(result.Failed)
{ {
Log.EngineLogger.Error($"Failed to create pixel shader: Message ({(int)result}): {result}"); Log.EngineLogger.Error($"Failed to create pixel shader: Message ({(int)result}): {result}");
} }
Reflect(shaderBlob); Reflect(nativeCode);
shaderBlob?.Release();
} }
} }
} }
@@ -11,6 +11,11 @@ namespace GlitchyEngine.Renderer
{ {
extension Shader extension Shader
{ {
/**
* Internal compiled code of the shader.
*/
internal ID3DBlob* nativeCode ~ _?.Release();
protected const ShaderCompileFlags DefaultCompileFlags = protected const ShaderCompileFlags DefaultCompileFlags =
#if DEBUG #if DEBUG
.Debug; .Debug;
@@ -62,6 +67,18 @@ namespace GlitchyEngine.Renderer
bufferReflection.GetDescription(let bufferDesc); 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 // ConstantBuffer
if(bufferDesc.Type == .D3D11_CT_CBUFFER) if(bufferDesc.Type == .D3D11_CT_CBUFFER)
{ {
@@ -69,7 +86,8 @@ namespace GlitchyEngine.Renderer
let buffer = new Buffer(_context, cBufferDesc); 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 // Buffer for default values
uint8* rawData = new:ScopedAlloc! uint8[bufferDesc.Size]*; uint8* rawData = new:ScopedAlloc! uint8[bufferDesc.Size]*;
@@ -87,6 +105,7 @@ namespace GlitchyEngine.Renderer
buffer.SetData(Span<uint8>(rawData, bufferDesc.Size)); buffer.SetData(Span<uint8>(rawData, bufferDesc.Size));
} }
*/
} }
reflection.Release(); reflection.Release();
} }
@@ -12,8 +12,6 @@ namespace GlitchyEngine.Renderer
{ {
internal ID3D11VertexShader* nativeShader ~ _?.Release(); internal ID3D11VertexShader* nativeShader ~ _?.Release();
internal ID3DBlob* nativeCode ~ _?.Release();
public override void CompileFromSource(String code, String entryPoint, ShaderDefine[] macros = null) public override void CompileFromSource(String code, String entryPoint, ShaderDefine[] macros = null)
{ {
Shader.PlattformCompileShaderFromSource(code, macros, entryPoint, "vs_5_0", DefaultCompileFlags, out nativeCode); 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. /// Represents a buffer containing binary data on the GPU.
public class Buffer public class Buffer : RefCounted
{ {
internal GraphicsContext _context; internal GraphicsContext _context;
+25 -19
View File
@@ -5,7 +5,7 @@ namespace GlitchyEngine.Renderer
{ {
public class BufferCollection 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!(_); List<BufferEntry> _buffers ~ DeleteBufferEntries!(_);
@@ -33,8 +33,7 @@ namespace GlitchyEngine.Renderer
for(let entry in entries) for(let entry in entries)
{ {
delete entry.Name; delete entry.Name;
if(entry.OwnsBuffer) entry.Buffer.ReleaseRef();
delete entry.Buffer;
} }
delete entries; delete entries;
@@ -49,7 +48,7 @@ namespace GlitchyEngine.Renderer
* @param buffer The new buffer. * @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. * @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)) if(_idxToBuf.TryGetValue(idx, let oldBuffer))
{ {
@@ -59,11 +58,13 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.Assert(idx == bufferDesc.Index); Log.EngineLogger.Assert(idx == bufferDesc.Index);
if(bufferDesc.OwnsBuffer) oldBuffer.ReleaseRef();
delete bufferDesc.Buffer; //if(bufferDesc.OwnsBuffer)
// delete bufferDesc.Buffer;
buffer.AddRef();
bufferDesc.Buffer = buffer; bufferDesc.Buffer = buffer;
bufferDesc.OwnsBuffer = passOwnership; //bufferDesc.OwnsBuffer = passOwnership;
_strToBuf[bufferDesc.Name] = buffer; _strToBuf[bufferDesc.Name] = buffer;
_idxToBuf[bufferDesc.Index] = buffer; _idxToBuf[bufferDesc.Index] = buffer;
@@ -80,7 +81,7 @@ namespace GlitchyEngine.Renderer
* @param buffer The new buffer. * @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. * @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)) if(_strToBuf.TryGetValue(name, let oldBuffer))
{ {
@@ -90,11 +91,13 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.Assert(name == bufferDesc.Name); Log.EngineLogger.Assert(name == bufferDesc.Name);
if(bufferDesc.OwnsBuffer) oldBuffer.ReleaseRef();
delete bufferDesc.Buffer; //if(bufferDesc.OwnsBuffer)
// delete bufferDesc.Buffer;
buffer.AddRef();
bufferDesc.Buffer = buffer; bufferDesc.Buffer = buffer;
bufferDesc.OwnsBuffer = passOwnership; //bufferDesc.OwnsBuffer = passOwnership;
_strToBuf[bufferDesc.Name] = buffer; _strToBuf[bufferDesc.Name] = buffer;
_idxToBuf[bufferDesc.Index] = buffer; _idxToBuf[bufferDesc.Index] = buffer;
@@ -111,7 +114,7 @@ namespace GlitchyEngine.Renderer
* @param buffer The new buffer. * @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. * @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)) if(_strToBuf.TryGetValue(name, let oldBuffer))
{ {
@@ -121,11 +124,13 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.Assert(name == bufferDesc.Name); Log.EngineLogger.Assert(name == bufferDesc.Name);
if(bufferDesc.OwnsBuffer) //if(bufferDesc.OwnsBuffer)
delete bufferDesc.Buffer; // delete bufferDesc.Buffer;
oldBuffer.ReleaseRef();
buffer.AddRef();
bufferDesc.Buffer = buffer; bufferDesc.Buffer = buffer;
bufferDesc.OwnsBuffer = passOwnership; //bufferDesc.OwnsBuffer = passOwnership;
_strToBuf[bufferDesc.Name] = buffer; _strToBuf[bufferDesc.Name] = buffer;
_idxToBuf[bufferDesc.Index] = 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); String nameStr = new String(name);
BufferEntry entry = (nameStr, index, buffer, passOwnership); BufferEntry entry = (nameStr, index, buffer); //, passOwnership
buffer.AddRef();
_buffers.Add(entry); _buffers.Add(entry);
_strToBuf.Add(entry.Name, entry.Buffer); _strToBuf.Add(entry.Name, entry.Buffer);
_idxToBuf.Add(entry.Index, 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 namespace GlitchyEngine.Renderer
{ {
public class Effect public class Effect : RefCounted
{ {
protected GraphicsContext _context; protected GraphicsContext _context;
internal VertexShader _vs; internal VertexShader _vs ~ _?.ReleaseRef();
internal PixelShader _ps; internal PixelShader _ps ~ _?.ReleaseRef();
public GraphicsContext Context => _context; public GraphicsContext Context => _context;
public VertexShader VertexShader public VertexShader VertexShader
{ {
get => _vs; get => _vs;
set => _vs = value; set
{
_vs?.ReleaseRef();
_vs = value;
_vs?.AddRef();
}
} }
public PixelShader PixelShader public PixelShader PixelShader
{ {
get => _ps; get => _ps;
set => _ps = value; set
{
_ps?.ReleaseRef();
_ps = value;
_ps?.AddRef();
}
} }
public void Bind(GraphicsContext context) public void Bind(GraphicsContext context)
@@ -27,5 +37,18 @@ namespace GlitchyEngine.Renderer
context.SetVertexShader(_vs); context.SetVertexShader(_vs);
context.SetPixelShader(_ps); 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; public Matrix ViewProjection;
} }
struct ObjectConstants
{
public Matrix Transform;
}
static GraphicsContext _context; static GraphicsContext _context;
static Buffer<SceneConstants> _sceneConstants ~ delete _; static Buffer<SceneConstants> _sceneConstants ~ _?.ReleaseRef();
static Buffer<ObjectConstants> _objectConstants ~ _?.ReleaseRef();
public static void Init(GraphicsContext context) public static void Init(GraphicsContext context)
{ {
_context = context; _context = context;
_sceneConstants = new Buffer<SceneConstants>(_context, .(0, .Constant, .Dynamic, .Write)); _sceneConstants = new Buffer<SceneConstants>(_context, .(0, .Constant, .Dynamic, .Write));
_sceneConstants.Update(); _sceneConstants.Update();
_objectConstants = new Buffer<ObjectConstants>(_context, .(0, .Constant, .Dynamic, .Write));
_objectConstants.Update();
} }
public static void BeginScene(Camera camera) public static void BeginScene(Camera camera)
@@ -28,13 +38,19 @@ namespace GlitchyEngine.Renderer
public static void EndScene(){} 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.PixelShader?.Buffers.TryReplaceBuffer("SceneConstants", _sceneConstants);
effect.VertexShader?.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(); geometry.Bind();
RenderCommand.DrawIndexed(geometry); RenderCommand.DrawIndexed(geometry);
} }
+8 -4
View File
@@ -1,7 +1,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Collections; using System.Collections;
using System.Diagnostics;
namespace GlitchyEngine.Renderer namespace GlitchyEngine.Renderer
{ {
@@ -19,7 +18,7 @@ namespace GlitchyEngine.Renderer
} }
} }
public abstract class Shader public abstract class Shader : RefCounted
{ {
protected GraphicsContext _context; protected GraphicsContext _context;
@@ -33,13 +32,18 @@ namespace GlitchyEngine.Renderer
public this(GraphicsContext context, String source, String entryPoint, ShaderDefine[] macros = null) public this(GraphicsContext context, String source, String entryPoint, ShaderDefine[] macros = null)
{ {
// Todo: append as soon as it's fixed. // Todo: append as soon as it's fixed.
let buffers = new BufferCollection(); //let buffers = new BufferCollection();
_buffers = buffers; _buffers = new BufferCollection();
_context = context; _context = context;
CompileFromSource(source, entryPoint); CompileFromSource(source, entryPoint);
} }
public ~this()
{
}
public static mixin FromFile<T>(GraphicsContext context, String fileName, String entryPoint, ShaderDefine[] macros = null) where T : Shader public static mixin FromFile<T>(GraphicsContext context, String fileName, String entryPoint, ShaderDefine[] macros = null) where T : Shader
{ {
String fileContent = new String(); String fileContent = new String();
+13 -4
View File
@@ -1,12 +1,18 @@
cbuffer SceneConstants : register(b0) cbuffer SceneConstants
{ {
float4x4 Transform = float4x4(1, 0, 0, 0, float4x4 ViewProjection = float4x4(1, 0, 0, 0,
0, 1, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1); 0, 0, 0, 1);
} }
cbuffer Constants : register(b1) cbuffer ObjectConstants
{
float4x4 Transform;
}
cbuffer Constants
{ {
float4 BaseColor; float4 BaseColor;
} }
@@ -26,7 +32,10 @@ struct PS_IN
PS_IN VS(VS_IN input) PS_IN VS(VS_IN input)
{ {
PS_IN output; PS_IN output;
output.Position = mul(Transform, float4(input.Position, 1));
float4 worldPosition = mul(Transform, float4(input.Position, 1));
output.Position = mul(ViewProjection, worldPosition);
output.Color = input.Color; output.Color = input.Color;
return output; return output;
+286 -246
View File
@@ -1,246 +1,286 @@
using System; using System;
using GlitchyEngine; using GlitchyEngine;
using GlitchyEngine.Events; using GlitchyEngine.Events;
using System.Diagnostics; using System.Diagnostics;
using GlitchLog; using GlitchLog;
using GlitchyEngine.ImGui; using GlitchyEngine.ImGui;
using ImGui; using ImGui;
using GlitchyEngine.Renderer; using GlitchyEngine.Renderer;
using GlitchyEngine.Math; using GlitchyEngine.Math;
namespace Sandbox namespace Sandbox
{ {
class ExampleLayer : Layer class ExampleLayer : Layer
{ {
private OrthographicCamera _camera ~ delete _; private OrthographicCamera _camera ~ delete _; // PerspectiveCamera
struct VertexColor : IVertexData struct VertexColor : IVertexData
{ {
public Vector3 Position; public Vector3 Position;
public Color Color; public Color Color;
public this() => this = default; public this() => this = default;
public this(Vector3 pos, Color color) public this(Vector3 pos, Color color)
{ {
Position = pos; Position = pos;
Color = color; Color = color;
} }
//public static readonly InputElementDescription[] InputLayout ~ delete _; //public static readonly InputElementDescription[] InputLayout ~ delete _;
public static readonly VertexLayout VertexLayout ~ delete _; public static readonly VertexLayout VertexLayout ~ delete _;
public static VertexLayout IVertexData.VertexLayout => VertexLayout; public static VertexLayout IVertexData.VertexLayout => VertexLayout;
static this() static this()
{ {
//VertexLayout = new VertexLayout(); //VertexLayout = new VertexLayout();
} }
} }
VertexLayout _vertexLayout ~ delete _; VertexLayout _vertexLayout ~ delete _;
GeometryBinding _geometryBinding ~ delete _; GeometryBinding _geometryBinding ~ delete _;
VertexBuffer _vertexBuffer ~ delete _; VertexBuffer _vertexBuffer ~ _?.ReleaseRef();
IndexBuffer _indexBuffer ~ delete _; IndexBuffer _indexBuffer ~ _?.ReleaseRef();
GeometryBinding _quadGeometryBinding ~ delete _; GeometryBinding _quadGeometryBinding ~ delete _;
VertexBuffer _quadVertexBuffer ~ delete _; VertexBuffer _quadVertexBuffer ~ _?.ReleaseRef();
IndexBuffer _quadIndexBuffer ~ delete _; IndexBuffer _quadIndexBuffer ~ _?.ReleaseRef();
RasterizerState _rasterizerState ~ delete _; RasterizerState _rasterizerState ~ delete _;
Effect _effect ~ delete _; Effect _effect ~ _?.ReleaseRef();
VertexShader _vertexShader ~ delete _;
PixelShader _pixelShader ~ delete _; //Buffer<ColorRGBA> _cBuffer ~ _?.ReleaseRef();
ConstantBuffer _cBuffer ~ _?.ReleaseRef();
Buffer<ColorRGBA> _cBuffer ~ delete _;
private Vector3 CircleCoord(float angle)
private Vector3 CircleCoord(float angle) {
{ return .(Math.Cos(angle), Math.Sin(angle), 0);
return .(Math.Cos(angle), Math.Sin(angle), 0); }
}
[AllowAppend]
[AllowAppend] public this() : base("Example")
public this() : base("Example") {
{ {
{ _effect = new Effect();
_effect = new Effect();
let vs = Shader.FromFile!<VertexShader>(Application.Get().Window.Context, "content\\basicShader.hlsl", "VS");
_vertexShader = Shader.FromFile!<VertexShader>(Application.Get().Window.Context, "content\\basicShader.hlsl", "VS"); _effect.VertexShader = vs;
_effect.VertexShader = _vertexShader; vs.ReleaseRef();
_pixelShader = Shader.FromFile!<PixelShader>(Application.Get().Window.Context, "content\\basicShader.hlsl", "PS"); let ps = Shader.FromFile!<PixelShader>(Application.Get().Window.Context, "content\\basicShader.hlsl", "PS");
_effect.PixelShader = _pixelShader; _effect.PixelShader = ps;
} ps.ReleaseRef();
}
// Create Input Layout
// Create Input Layout
_vertexLayout = new VertexLayout(Application.Get().Window.Context, new .(
VertexElement(.R32G32B32_Float, "POSITION"), _vertexLayout = new VertexLayout(Application.Get().Window.Context, new .(
VertexElement(.R8G8B8A8_UNorm, "COLOR"), VertexElement(.R32G32B32_Float, "POSITION"),
), _vertexShader); VertexElement(.R8G8B8A8_UNorm, "COLOR"),
), _effect.VertexShader);
_cBuffer = new Buffer<ColorRGBA>(Application.Get().Window.Context, .(0, .Constant, .Immutable)); /*
_cBuffer.Data = .White; _cBuffer = new Buffer<ColorRGBA>(Application.Get().Window.Context, .(0, .Constant, .Dynamic, .Write));
_cBuffer.Update(); _cBuffer.Data = .White;
_cBuffer.Update();
_pixelShader.Buffers.ReplaceBuffer("Constants", _cBuffer); */
// Create hexagon //_effect.PixelShader.Buffers.ReplaceBuffer("Constants", _cBuffer);
{
_geometryBinding = new GeometryBinding(Application.Get().Window.Context); Buffer buffer = _effect.PixelShader.Buffers["Constants"];
_geometryBinding.SetPrimitiveTopology(.TriangleList); _cBuffer = buffer as ConstantBuffer;
_geometryBinding.SetVertexLayout(_vertexLayout); _cBuffer.AddRef();
float pO3 = Math.PI_f / 3.0f; if(_cBuffer != null)
VertexColor[?] vertices = .( {
VertexColor(.Zero, Color(255,255,255)), _cBuffer["BaseColor"].SetData(ColorRGBA.Red);
VertexColor(CircleCoord(0), Color(255, 0, 0)), _cBuffer.Update();
VertexColor(CircleCoord(pO3), Color(255,255, 0)), }
VertexColor(CircleCoord(pO3*2), Color( 0,255, 0)),
VertexColor(CircleCoord(Math.PI_f), Color( 0,255,255)), // Create hexagon
VertexColor(CircleCoord(-pO3*2), Color( 0, 0,255)), {
VertexColor(CircleCoord(-pO3), Color(255, 0,255)), _geometryBinding = new GeometryBinding(Application.Get().Window.Context);
); _geometryBinding.SetPrimitiveTopology(.TriangleList);
_geometryBinding.SetVertexLayout(_vertexLayout);
_vertexBuffer = new VertexBuffer(Application.Get().Window.Context, typeof(VertexColor), (.)vertices.Count, .Immutable);
_vertexBuffer.SetData(vertices); float pO3 = Math.PI_f / 3.0f;
_geometryBinding.SetVertexBufferSlot(_vertexBuffer, 0); VertexColor[?] vertices = .(
VertexColor(.Zero, Color(255,255,255)),
uint16[?] indices = .( VertexColor(CircleCoord(0), Color(255, 0, 0)),
0, 1, 2, VertexColor(CircleCoord(pO3), Color(255,255, 0)),
0, 2, 3, VertexColor(CircleCoord(pO3*2), Color( 0,255, 0)),
0, 3, 4, VertexColor(CircleCoord(Math.PI_f), Color( 0,255,255)),
0, 4, 5, VertexColor(CircleCoord(-pO3*2), Color( 0, 0,255)),
0, 5, 6, VertexColor(CircleCoord(-pO3), Color(255, 0,255)),
0, 6, 1); );
_indexBuffer = new IndexBuffer(Application.Get().Window.Context, (.)indices.Count, .Immutable); _vertexBuffer = new VertexBuffer(Application.Get().Window.Context, typeof(VertexColor), (.)vertices.Count, .Immutable);
_indexBuffer.SetData(indices); _vertexBuffer.SetData(vertices);
_geometryBinding.SetIndexBuffer(_indexBuffer); _geometryBinding.SetVertexBufferSlot(_vertexBuffer, 0);
}
uint16[?] indices = .(
// Create Quad 0, 1, 2,
{ 0, 2, 3,
_quadGeometryBinding = new GeometryBinding(Application.Get().Window.Context); 0, 3, 4,
_quadGeometryBinding.SetPrimitiveTopology(.TriangleList); 0, 4, 5,
_quadGeometryBinding.SetVertexLayout(_vertexLayout); 0, 5, 6,
0, 6, 1);
VertexColor[?] vertices = .(
VertexColor(Vector3(-0.75f, 0.75f, 0), Color.Blue), _indexBuffer = new IndexBuffer(Application.Get().Window.Context, (.)indices.Count, .Immutable);
VertexColor(Vector3(-0.75f, -0.75f, 0), Color.Blue), _indexBuffer.SetData(indices);
VertexColor(Vector3(0.75f, -0.75f, 0), Color.Blue), _geometryBinding.SetIndexBuffer(_indexBuffer);
VertexColor(Vector3(0.75f, 0.75f, 0), Color.Blue), }
);
// Create Quad
_quadVertexBuffer = new VertexBuffer(Application.Get().Window.Context, typeof(VertexColor), (.)vertices.Count, .Immutable); {
_quadVertexBuffer.SetData(vertices); _quadGeometryBinding = new GeometryBinding(Application.Get().Window.Context);
_quadGeometryBinding.SetVertexBufferSlot(_quadVertexBuffer, 0); _quadGeometryBinding.SetPrimitiveTopology(.TriangleList);
_quadGeometryBinding.SetVertexLayout(_vertexLayout);
uint16[?] indices = .(
0, 1, 2, VertexColor[?] vertices = .(
2, 3, 0); VertexColor(Vector3(-0.75f, 0.75f, 0), Color.White),
VertexColor(Vector3(-0.75f, -0.75f, 0), Color.White),
_quadIndexBuffer = new IndexBuffer(Application.Get().Window.Context, (.)indices.Count, .Immutable); VertexColor(Vector3(0.75f, -0.75f, 0), Color.White),
_quadIndexBuffer.SetData(indices); VertexColor(Vector3(0.75f, 0.75f, 0), Color.White),
_quadGeometryBinding.SetIndexBuffer(_quadIndexBuffer); );
}
_quadVertexBuffer = new VertexBuffer(Application.Get().Window.Context, typeof(VertexColor), (.)vertices.Count, .Immutable);
// Create rasterizer state _quadVertexBuffer.SetData(vertices);
GlitchyEngine.Renderer.RasterizerStateDescription rsDesc = .(.Solid, .Back, true); _quadGeometryBinding.SetVertexBufferSlot(_quadVertexBuffer, 0);
_rasterizerState = new RasterizerState(Application.Get().Window.Context, rsDesc);
uint16[?] indices = .(
// Camera 0, 1, 2,
_camera = new OrthographicCamera(); 2, 3, 0);
_camera.NearPlane = -1;
_camera.FarPlane = 1; _quadIndexBuffer = new IndexBuffer(Application.Get().Window.Context, (.)indices.Count, .Immutable);
} _quadIndexBuffer.SetData(indices);
_quadGeometryBinding.SetIndexBuffer(_quadIndexBuffer);
public override void Update(GameTime gameTime) }
{
Vector2 movement = .(); // Create rasterizer state
GlitchyEngine.Renderer.RasterizerStateDescription rsDesc = .(.Solid, .Back, true);
if(Input.IsKeyPressed(Key.W)) _rasterizerState = new RasterizerState(Application.Get().Window.Context, rsDesc);
{
movement.Y += 1; // Camera
} _camera = new OrthographicCamera();
else if(Input.IsKeyPressed(Key.S)) _camera.NearPlane = -1;
{ _camera.FarPlane = 1;
movement.Y -= 1; /*
} _camera = new PerspectiveCamera();
_camera.NearPlane = 0.1f;
if(Input.IsKeyPressed(Key.A)) _camera.FarPlane = 10.0f;
{ _camera.FovY = Math.PI_f / 4;
movement.X -= 1; _camera.Position = .(0, -1, -5);
} */
else if(Input.IsKeyPressed(Key.D)) }
{
movement.X += 1; public override void Update(GameTime gameTime)
} {
Vector2 movement = .();
if(movement != .Zero)
movement.Normalize(); if(Input.IsKeyPressed(Key.W))
{
movement *= (float)(gameTime.FrameTime.TotalSeconds); movement.Y += 1;
}
_camera.Position += .(movement, 0); if(Input.IsKeyPressed(Key.S))
{
_camera.Width = Application.Get().Window.Context.SwapChain.BackbufferViewport.Width / 256; movement.Y -= 1;
_camera.Height = Application.Get().Window.Context.SwapChain.BackbufferViewport.Height / 256; }
_camera.Update(); if(Input.IsKeyPressed(Key.A))
{
RenderCommand.Clear(null, .(0.2f, 0.2f, 0.2f)); movement.X -= 1;
}
// Draw test geometry if(Input.IsKeyPressed(Key.D))
Application.Get().Window.Context.SetRenderTarget(null); {
Application.Get().Window.Context.BindRenderTargets(); movement.X += 1;
}
Application.Get().Window.Context.SetRasterizerState(_rasterizerState);
if(movement != .Zero)
Application.Get().Window.Context.SetViewport(Application.Get().Window.Context.SwapChain.BackbufferViewport); movement.Normalize();
Renderer.BeginScene(_camera); movement *= (float)(gameTime.FrameTime.TotalSeconds);
Renderer.Submit(_geometryBinding, _effect); _camera.Position += .(movement, 0);
Renderer.Submit(_quadGeometryBinding, _effect);
_camera.Width = Application.Get().Window.Context.SwapChain.BackbufferViewport.Width / 256;
Renderer.EndScene(); _camera.Height = Application.Get().Window.Context.SwapChain.BackbufferViewport.Height / 256;
} //_camera.AspectRatio = Application.Get().Window.Context.SwapChain.BackbufferViewport.Width /
// Application.Get().Window.Context.SwapChain.BackbufferViewport.Height;
public override void OnEvent(Event event)
{ _camera.Update();
Log.ClientLogger.Trace($"{event}");
RenderCommand.Clear(null, .(0.2f, 0.2f, 0.2f));
EventDispatcher dispatcher = scope EventDispatcher(event);
// Draw test geometry
dispatcher.Dispatch<ImGuiRenderEvent>(scope (e) => OnImGuiRender(e)); Application.Get().Window.Context.SetRenderTarget(null);
} Application.Get().Window.Context.BindRenderTargets();
private bool OnImGuiRender(ImGuiRenderEvent e) Application.Get().Window.Context.SetRasterizerState(_rasterizerState);
{
ImGui.Begin("Test"); Application.Get().Window.Context.SetViewport(Application.Get().Window.Context.SwapChain.BackbufferViewport);
ImGui.End(); Renderer.BeginScene(_camera);
return false; //_cBuffer.Data = .White;
} _cBuffer["BaseColor"].SetData(ColorRGBA.White);
} _cBuffer.Update();
class SandboxApp : Application Renderer.Submit(_geometryBinding, _effect);
{ Renderer.Submit(_quadGeometryBinding, _effect, .Translation(2, 0, 0));
public this()
{ for(int x < 20)
PushLayer(new ExampleLayer()); for(int y < 20)
} {
if((x + y) % 2 == 0)
[Export, LinkName("CreateApplication")] //_cBuffer.Data = .Red;
public static Application CreateApplication() _cBuffer["BaseColor"].SetData(ColorRGBA.Red);
{ else
return new SandboxApp(); _cBuffer["BaseColor"].SetData(ColorRGBA.Blue);
} //_cBuffer.Data = .Blue;
}
} _cBuffer.Update();
Matrix transform = Matrix.Translation(x * 0.2f, y * 0.2f, 0) * Matrix.Scaling(0.1f);
Renderer.Submit(_quadGeometryBinding, _effect, transform);
}
Renderer.EndScene();
}
public override void OnEvent(Event event)
{
EventDispatcher dispatcher = scope EventDispatcher(event);
dispatcher.Dispatch<ImGuiRenderEvent>(scope (e) => OnImGuiRender(e));
}
private bool OnImGuiRender(ImGuiRenderEvent e)
{
ImGui.Begin("Test");
ImGui.End();
return false;
}
}
class SandboxApp : Application
{
public this()
{
PushLayer(new ExampleLayer());
}
[Export, LinkName("CreateApplication")]
public static Application CreateApplication()
{
return new SandboxApp();
}
}
}