From 9ea56d6786eec79e54b06c4f8b85aab30acbc3a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Sat, 6 Feb 2021 18:26:14 +0100 Subject: [PATCH] Added RefCounting, added ConstantBuffers --- Defines.txt | 11 + GlitchyEngine/BeefProj.toml | 1 + GlitchyEngine/src/Application.bf | 2 - .../DX11/Renderer/Dx11ConstantBuffer.bf | 77 +++ .../src/Platform/DX11/Renderer/Dx11Effect.bf | 25 + .../Platform/DX11/Renderer/Dx11PixelShader.bf | 8 +- .../src/Platform/DX11/Renderer/Dx11Shader.bf | 21 +- .../DX11/Renderer/Dx11VertexShader.bf | 2 - GlitchyEngine/src/Renderer/Buffer.bf | 2 +- .../src/Renderer/BufferCollection.bf | 44 +- GlitchyEngine/src/Renderer/ConstantBuffer.bf | 212 +++++++ GlitchyEngine/src/Renderer/Effect.bf | 33 +- GlitchyEngine/src/Renderer/Material.bf | 29 + GlitchyEngine/src/Renderer/Renderer.bf | 24 +- GlitchyEngine/src/Renderer/Shader.bf | 12 +- Sandbox/content/basicShader.hlsl | 17 +- Sandbox/src/SandboxApp.bf | 532 ++++++++++-------- 17 files changed, 759 insertions(+), 293 deletions(-) create mode 100644 Defines.txt create mode 100644 GlitchyEngine/src/Platform/DX11/Renderer/Dx11ConstantBuffer.bf create mode 100644 GlitchyEngine/src/Platform/DX11/Renderer/Dx11Effect.bf create mode 100644 GlitchyEngine/src/Renderer/ConstantBuffer.bf create mode 100644 GlitchyEngine/src/Renderer/Material.bf diff --git a/Defines.txt b/Defines.txt new file mode 100644 index 0000000..fa6b099 --- /dev/null +++ b/Defines.txt @@ -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. \ No newline at end of file diff --git a/GlitchyEngine/BeefProj.toml b/GlitchyEngine/BeefProj.toml index 66d5f93..70ac447 100644 --- a/GlitchyEngine/BeefProj.toml +++ b/GlitchyEngine/BeefProj.toml @@ -3,6 +3,7 @@ Dependencies = {GlitchLog = "*", corlib = "*", DirectX = "*", ImGui = "*", ImGui [Project] Name = "GlitchyEngine" +ProcessorMacros = ["GE_ERROR_SHADER_MATRIX_MISMATCH", "GE_ERROR_SHADER_VAR_TYPE_MISMATCH"] [Configs.Debug.Win32] PreprocessorMacros = ["DEBUG", "GE_WINDOWS"] diff --git a/GlitchyEngine/src/Application.bf b/GlitchyEngine/src/Application.bf index 3f60aa6..d44dd8f 100644 --- a/GlitchyEngine/src/Application.bf +++ b/GlitchyEngine/src/Application.bf @@ -1,8 +1,6 @@ using System; using GlitchyEngine.Events; using GlitchyEngine.ImGui; -using GlitchyEngine.Math; -using System.Diagnostics; using GlitchyEngine.Renderer; namespace GlitchyEngine diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11ConstantBuffer.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11ConstantBuffer.bf new file mode 100644 index 0000000..7622cf7 --- /dev/null +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11ConstantBuffer.bf @@ -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); + } + } + } +} diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11Effect.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11Effect.bf new file mode 100644 index 0000000..c90fd2b --- /dev/null +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11Effect.bf @@ -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() + { + + } + } +} diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11PixelShader.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11PixelShader.bf index ad66f7b..096b4cf 100644 --- a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11PixelShader.bf +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11PixelShader.bf @@ -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); } } } diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11Shader.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11Shader.bf index e947095..066c689 100644 --- a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11Shader.bf +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11Shader.bf @@ -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(rawData, bufferDesc.Size)); } + */ } reflection.Release(); } diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11VertexShader.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11VertexShader.bf index 611f622..0e2fc9d 100644 --- a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11VertexShader.bf +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11VertexShader.bf @@ -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); diff --git a/GlitchyEngine/src/Renderer/Buffer.bf b/GlitchyEngine/src/Renderer/Buffer.bf index 532a1de..a9da7f9 100644 --- a/GlitchyEngine/src/Renderer/Buffer.bf +++ b/GlitchyEngine/src/Renderer/Buffer.bf @@ -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; diff --git a/GlitchyEngine/src/Renderer/BufferCollection.bf b/GlitchyEngine/src/Renderer/BufferCollection.bf index 394cd61..ef97959 100644 --- a/GlitchyEngine/src/Renderer/BufferCollection.bf +++ b/GlitchyEngine/src/Renderer/BufferCollection.bf @@ -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 _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); diff --git a/GlitchyEngine/src/Renderer/ConstantBuffer.bf b/GlitchyEngine/src/Renderer/ConstantBuffer.bf new file mode 100644 index 0000000..7f79c0b --- /dev/null +++ b/GlitchyEngine/src/Renderer/ConstantBuffer.bf @@ -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 _variables = new .() ~ DeleteContainerAndItems!(_); + protected Dictionary _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); + } + } + +} diff --git a/GlitchyEngine/src/Renderer/Effect.bf b/GlitchyEngine/src/Renderer/Effect.bf index 4ee4e67..b2c2219 100644 --- a/GlitchyEngine/src/Renderer/Effect.bf +++ b/GlitchyEngine/src/Renderer/Effect.bf @@ -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); } } diff --git a/GlitchyEngine/src/Renderer/Material.bf b/GlitchyEngine/src/Renderer/Material.bf new file mode 100644 index 0000000..2f26d8b --- /dev/null +++ b/GlitchyEngine/src/Renderer/Material.bf @@ -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 + } +} diff --git a/GlitchyEngine/src/Renderer/Renderer.bf b/GlitchyEngine/src/Renderer/Renderer.bf index 9f049b4..c2fc90d 100644 --- a/GlitchyEngine/src/Renderer/Renderer.bf +++ b/GlitchyEngine/src/Renderer/Renderer.bf @@ -9,15 +9,25 @@ namespace GlitchyEngine.Renderer public Matrix ViewProjection; } + struct ObjectConstants + { + public Matrix Transform; + } + static GraphicsContext _context; - static Buffer _sceneConstants ~ delete _; + static Buffer _sceneConstants ~ _?.ReleaseRef(); + + static Buffer _objectConstants ~ _?.ReleaseRef(); public static void Init(GraphicsContext context) { _context = context; _sceneConstants = new Buffer(_context, .(0, .Constant, .Dynamic, .Write)); _sceneConstants.Update(); + + _objectConstants = new Buffer(_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); } diff --git a/GlitchyEngine/src/Renderer/Shader.bf b/GlitchyEngine/src/Renderer/Shader.bf index ec74f36..1950165 100644 --- a/GlitchyEngine/src/Renderer/Shader.bf +++ b/GlitchyEngine/src/Renderer/Shader.bf @@ -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(GraphicsContext context, String fileName, String entryPoint, ShaderDefine[] macros = null) where T : Shader { String fileContent = new String(); diff --git a/Sandbox/content/basicShader.hlsl b/Sandbox/content/basicShader.hlsl index 2a41105..9ab791a 100644 --- a/Sandbox/content/basicShader.hlsl +++ b/Sandbox/content/basicShader.hlsl @@ -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, 0, 1, 0, 0, 0, 0, 1); } -cbuffer Constants : register(b1) +cbuffer ObjectConstants +{ + float4x4 Transform; +} + + +cbuffer Constants { float4 BaseColor; } @@ -26,7 +32,10 @@ struct PS_IN PS_IN VS(VS_IN input) { 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; return output; diff --git a/Sandbox/src/SandboxApp.bf b/Sandbox/src/SandboxApp.bf index 0022f79..d07a9f2 100644 --- a/Sandbox/src/SandboxApp.bf +++ b/Sandbox/src/SandboxApp.bf @@ -1,246 +1,286 @@ -using System; -using GlitchyEngine; -using GlitchyEngine.Events; -using System.Diagnostics; -using GlitchLog; -using GlitchyEngine.ImGui; -using ImGui; -using GlitchyEngine.Renderer; -using GlitchyEngine.Math; - -namespace Sandbox -{ - class ExampleLayer : Layer - { - private OrthographicCamera _camera ~ delete _; - - struct VertexColor : IVertexData - { - public Vector3 Position; - public Color Color; - - public this() => this = default; - - public this(Vector3 pos, Color color) - { - Position = pos; - Color = color; - } - - //public static readonly InputElementDescription[] InputLayout ~ delete _; - - public static readonly VertexLayout VertexLayout ~ delete _; - - public static VertexLayout IVertexData.VertexLayout => VertexLayout; - - static this() - { - //VertexLayout = new VertexLayout(); - } - } - - VertexLayout _vertexLayout ~ delete _; - - GeometryBinding _geometryBinding ~ delete _; - VertexBuffer _vertexBuffer ~ delete _; - IndexBuffer _indexBuffer ~ delete _; - - GeometryBinding _quadGeometryBinding ~ delete _; - VertexBuffer _quadVertexBuffer ~ delete _; - IndexBuffer _quadIndexBuffer ~ delete _; - - RasterizerState _rasterizerState ~ delete _; - - Effect _effect ~ delete _; - VertexShader _vertexShader ~ delete _; - PixelShader _pixelShader ~ delete _; - - Buffer _cBuffer ~ delete _; - - private Vector3 CircleCoord(float angle) - { - return .(Math.Cos(angle), Math.Sin(angle), 0); - } - - [AllowAppend] - public this() : base("Example") - { - { - _effect = new Effect(); - - _vertexShader = Shader.FromFile!(Application.Get().Window.Context, "content\\basicShader.hlsl", "VS"); - _effect.VertexShader = _vertexShader; - - _pixelShader = Shader.FromFile!(Application.Get().Window.Context, "content\\basicShader.hlsl", "PS"); - _effect.PixelShader = _pixelShader; - } - - // Create Input Layout - - _vertexLayout = new VertexLayout(Application.Get().Window.Context, new .( - VertexElement(.R32G32B32_Float, "POSITION"), - VertexElement(.R8G8B8A8_UNorm, "COLOR"), - ), _vertexShader); - - _cBuffer = new Buffer(Application.Get().Window.Context, .(0, .Constant, .Immutable)); - _cBuffer.Data = .White; - _cBuffer.Update(); - - _pixelShader.Buffers.ReplaceBuffer("Constants", _cBuffer); - - // Create hexagon - { - _geometryBinding = new GeometryBinding(Application.Get().Window.Context); - _geometryBinding.SetPrimitiveTopology(.TriangleList); - _geometryBinding.SetVertexLayout(_vertexLayout); - - float pO3 = Math.PI_f / 3.0f; - VertexColor[?] vertices = .( - VertexColor(.Zero, Color(255,255,255)), - VertexColor(CircleCoord(0), Color(255, 0, 0)), - VertexColor(CircleCoord(pO3), Color(255,255, 0)), - VertexColor(CircleCoord(pO3*2), Color( 0,255, 0)), - VertexColor(CircleCoord(Math.PI_f), Color( 0,255,255)), - VertexColor(CircleCoord(-pO3*2), Color( 0, 0,255)), - VertexColor(CircleCoord(-pO3), Color(255, 0,255)), - ); - - _vertexBuffer = new VertexBuffer(Application.Get().Window.Context, typeof(VertexColor), (.)vertices.Count, .Immutable); - _vertexBuffer.SetData(vertices); - _geometryBinding.SetVertexBufferSlot(_vertexBuffer, 0); - - uint16[?] indices = .( - 0, 1, 2, - 0, 2, 3, - 0, 3, 4, - 0, 4, 5, - 0, 5, 6, - 0, 6, 1); - - _indexBuffer = new IndexBuffer(Application.Get().Window.Context, (.)indices.Count, .Immutable); - _indexBuffer.SetData(indices); - _geometryBinding.SetIndexBuffer(_indexBuffer); - } - - // Create Quad - { - _quadGeometryBinding = new GeometryBinding(Application.Get().Window.Context); - _quadGeometryBinding.SetPrimitiveTopology(.TriangleList); - _quadGeometryBinding.SetVertexLayout(_vertexLayout); - - VertexColor[?] vertices = .( - VertexColor(Vector3(-0.75f, 0.75f, 0), Color.Blue), - VertexColor(Vector3(-0.75f, -0.75f, 0), Color.Blue), - VertexColor(Vector3(0.75f, -0.75f, 0), Color.Blue), - VertexColor(Vector3(0.75f, 0.75f, 0), Color.Blue), - ); - - _quadVertexBuffer = new VertexBuffer(Application.Get().Window.Context, typeof(VertexColor), (.)vertices.Count, .Immutable); - _quadVertexBuffer.SetData(vertices); - _quadGeometryBinding.SetVertexBufferSlot(_quadVertexBuffer, 0); - - uint16[?] indices = .( - 0, 1, 2, - 2, 3, 0); - - _quadIndexBuffer = new IndexBuffer(Application.Get().Window.Context, (.)indices.Count, .Immutable); - _quadIndexBuffer.SetData(indices); - _quadGeometryBinding.SetIndexBuffer(_quadIndexBuffer); - } - - // Create rasterizer state - GlitchyEngine.Renderer.RasterizerStateDescription rsDesc = .(.Solid, .Back, true); - _rasterizerState = new RasterizerState(Application.Get().Window.Context, rsDesc); - - // Camera - _camera = new OrthographicCamera(); - _camera.NearPlane = -1; - _camera.FarPlane = 1; - } - - public override void Update(GameTime gameTime) - { - Vector2 movement = .(); - - if(Input.IsKeyPressed(Key.W)) - { - movement.Y += 1; - } - else if(Input.IsKeyPressed(Key.S)) - { - movement.Y -= 1; - } - - if(Input.IsKeyPressed(Key.A)) - { - movement.X -= 1; - } - else if(Input.IsKeyPressed(Key.D)) - { - movement.X += 1; - } - - if(movement != .Zero) - movement.Normalize(); - - movement *= (float)(gameTime.FrameTime.TotalSeconds); - - _camera.Position += .(movement, 0); - - _camera.Width = Application.Get().Window.Context.SwapChain.BackbufferViewport.Width / 256; - _camera.Height = Application.Get().Window.Context.SwapChain.BackbufferViewport.Height / 256; - - _camera.Update(); - - RenderCommand.Clear(null, .(0.2f, 0.2f, 0.2f)); - - // Draw test geometry - Application.Get().Window.Context.SetRenderTarget(null); - Application.Get().Window.Context.BindRenderTargets(); - - Application.Get().Window.Context.SetRasterizerState(_rasterizerState); - - Application.Get().Window.Context.SetViewport(Application.Get().Window.Context.SwapChain.BackbufferViewport); - - Renderer.BeginScene(_camera); - - Renderer.Submit(_geometryBinding, _effect); - Renderer.Submit(_quadGeometryBinding, _effect); - - Renderer.EndScene(); - - } - - public override void OnEvent(Event event) - { - Log.ClientLogger.Trace($"{event}"); - - EventDispatcher dispatcher = scope EventDispatcher(event); - - dispatcher.Dispatch(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(); - } - } -} +using System; +using GlitchyEngine; +using GlitchyEngine.Events; +using System.Diagnostics; +using GlitchLog; +using GlitchyEngine.ImGui; +using ImGui; +using GlitchyEngine.Renderer; +using GlitchyEngine.Math; + +namespace Sandbox +{ + class ExampleLayer : Layer + { + private OrthographicCamera _camera ~ delete _; // PerspectiveCamera + + struct VertexColor : IVertexData + { + public Vector3 Position; + public Color Color; + + public this() => this = default; + + public this(Vector3 pos, Color color) + { + Position = pos; + Color = color; + } + + //public static readonly InputElementDescription[] InputLayout ~ delete _; + + public static readonly VertexLayout VertexLayout ~ delete _; + + public static VertexLayout IVertexData.VertexLayout => VertexLayout; + + static this() + { + //VertexLayout = new VertexLayout(); + } + } + + VertexLayout _vertexLayout ~ delete _; + + GeometryBinding _geometryBinding ~ delete _; + VertexBuffer _vertexBuffer ~ _?.ReleaseRef(); + IndexBuffer _indexBuffer ~ _?.ReleaseRef(); + + GeometryBinding _quadGeometryBinding ~ delete _; + VertexBuffer _quadVertexBuffer ~ _?.ReleaseRef(); + IndexBuffer _quadIndexBuffer ~ _?.ReleaseRef(); + + RasterizerState _rasterizerState ~ delete _; + + Effect _effect ~ _?.ReleaseRef(); + + //Buffer _cBuffer ~ _?.ReleaseRef(); + ConstantBuffer _cBuffer ~ _?.ReleaseRef(); + + private Vector3 CircleCoord(float angle) + { + return .(Math.Cos(angle), Math.Sin(angle), 0); + } + + [AllowAppend] + public this() : base("Example") + { + { + _effect = new Effect(); + + let vs = Shader.FromFile!(Application.Get().Window.Context, "content\\basicShader.hlsl", "VS"); + _effect.VertexShader = vs; + vs.ReleaseRef(); + + let ps = Shader.FromFile!(Application.Get().Window.Context, "content\\basicShader.hlsl", "PS"); + _effect.PixelShader = ps; + ps.ReleaseRef(); + } + + // Create Input Layout + + _vertexLayout = new VertexLayout(Application.Get().Window.Context, new .( + VertexElement(.R32G32B32_Float, "POSITION"), + VertexElement(.R8G8B8A8_UNorm, "COLOR"), + ), _effect.VertexShader); + /* + _cBuffer = new Buffer(Application.Get().Window.Context, .(0, .Constant, .Dynamic, .Write)); + _cBuffer.Data = .White; + _cBuffer.Update(); + */ + + //_effect.PixelShader.Buffers.ReplaceBuffer("Constants", _cBuffer); + + Buffer buffer = _effect.PixelShader.Buffers["Constants"]; + _cBuffer = buffer as ConstantBuffer; + _cBuffer.AddRef(); + + if(_cBuffer != null) + { + _cBuffer["BaseColor"].SetData(ColorRGBA.Red); + _cBuffer.Update(); + } + + // Create hexagon + { + _geometryBinding = new GeometryBinding(Application.Get().Window.Context); + _geometryBinding.SetPrimitiveTopology(.TriangleList); + _geometryBinding.SetVertexLayout(_vertexLayout); + + float pO3 = Math.PI_f / 3.0f; + VertexColor[?] vertices = .( + VertexColor(.Zero, Color(255,255,255)), + VertexColor(CircleCoord(0), Color(255, 0, 0)), + VertexColor(CircleCoord(pO3), Color(255,255, 0)), + VertexColor(CircleCoord(pO3*2), Color( 0,255, 0)), + VertexColor(CircleCoord(Math.PI_f), Color( 0,255,255)), + VertexColor(CircleCoord(-pO3*2), Color( 0, 0,255)), + VertexColor(CircleCoord(-pO3), Color(255, 0,255)), + ); + + _vertexBuffer = new VertexBuffer(Application.Get().Window.Context, typeof(VertexColor), (.)vertices.Count, .Immutable); + _vertexBuffer.SetData(vertices); + _geometryBinding.SetVertexBufferSlot(_vertexBuffer, 0); + + uint16[?] indices = .( + 0, 1, 2, + 0, 2, 3, + 0, 3, 4, + 0, 4, 5, + 0, 5, 6, + 0, 6, 1); + + _indexBuffer = new IndexBuffer(Application.Get().Window.Context, (.)indices.Count, .Immutable); + _indexBuffer.SetData(indices); + _geometryBinding.SetIndexBuffer(_indexBuffer); + } + + // Create Quad + { + _quadGeometryBinding = new GeometryBinding(Application.Get().Window.Context); + _quadGeometryBinding.SetPrimitiveTopology(.TriangleList); + _quadGeometryBinding.SetVertexLayout(_vertexLayout); + + VertexColor[?] vertices = .( + VertexColor(Vector3(-0.75f, 0.75f, 0), Color.White), + VertexColor(Vector3(-0.75f, -0.75f, 0), Color.White), + VertexColor(Vector3(0.75f, -0.75f, 0), Color.White), + VertexColor(Vector3(0.75f, 0.75f, 0), Color.White), + ); + + _quadVertexBuffer = new VertexBuffer(Application.Get().Window.Context, typeof(VertexColor), (.)vertices.Count, .Immutable); + _quadVertexBuffer.SetData(vertices); + _quadGeometryBinding.SetVertexBufferSlot(_quadVertexBuffer, 0); + + uint16[?] indices = .( + 0, 1, 2, + 2, 3, 0); + + _quadIndexBuffer = new IndexBuffer(Application.Get().Window.Context, (.)indices.Count, .Immutable); + _quadIndexBuffer.SetData(indices); + _quadGeometryBinding.SetIndexBuffer(_quadIndexBuffer); + } + + // Create rasterizer state + GlitchyEngine.Renderer.RasterizerStateDescription rsDesc = .(.Solid, .Back, true); + _rasterizerState = new RasterizerState(Application.Get().Window.Context, rsDesc); + + // Camera + _camera = new OrthographicCamera(); + _camera.NearPlane = -1; + _camera.FarPlane = 1; + /* + _camera = new PerspectiveCamera(); + _camera.NearPlane = 0.1f; + _camera.FarPlane = 10.0f; + _camera.FovY = Math.PI_f / 4; + _camera.Position = .(0, -1, -5); + */ + } + + public override void Update(GameTime gameTime) + { + Vector2 movement = .(); + + if(Input.IsKeyPressed(Key.W)) + { + movement.Y += 1; + } + if(Input.IsKeyPressed(Key.S)) + { + movement.Y -= 1; + } + + if(Input.IsKeyPressed(Key.A)) + { + movement.X -= 1; + } + if(Input.IsKeyPressed(Key.D)) + { + movement.X += 1; + } + + if(movement != .Zero) + movement.Normalize(); + + movement *= (float)(gameTime.FrameTime.TotalSeconds); + + _camera.Position += .(movement, 0); + + _camera.Width = Application.Get().Window.Context.SwapChain.BackbufferViewport.Width / 256; + _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; + + _camera.Update(); + + RenderCommand.Clear(null, .(0.2f, 0.2f, 0.2f)); + + // Draw test geometry + Application.Get().Window.Context.SetRenderTarget(null); + Application.Get().Window.Context.BindRenderTargets(); + + Application.Get().Window.Context.SetRasterizerState(_rasterizerState); + + Application.Get().Window.Context.SetViewport(Application.Get().Window.Context.SwapChain.BackbufferViewport); + + Renderer.BeginScene(_camera); + + //_cBuffer.Data = .White; + _cBuffer["BaseColor"].SetData(ColorRGBA.White); + _cBuffer.Update(); + + Renderer.Submit(_geometryBinding, _effect); + Renderer.Submit(_quadGeometryBinding, _effect, .Translation(2, 0, 0)); + + for(int x < 20) + for(int y < 20) + { + if((x + y) % 2 == 0) + //_cBuffer.Data = .Red; + _cBuffer["BaseColor"].SetData(ColorRGBA.Red); + else + _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(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(); + } + } +}