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]
Name = "GlitchyEngine"
ProcessorMacros = ["GE_ERROR_SHADER_MATRIX_MISMATCH", "GE_ERROR_SHADER_VAR_TYPE_MISMATCH"]
[Configs.Debug.Win32]
PreprocessorMacros = ["DEBUG", "GE_WINDOWS"]
-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();
+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, 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;
+286 -246
View File
@@ -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<ColorRGBA> _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!<VertexShader>(Application.Get().Window.Context, "content\\basicShader.hlsl", "VS");
_effect.VertexShader = _vertexShader;
_pixelShader = Shader.FromFile!<PixelShader>(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<ColorRGBA>(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<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();
}
}
}
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<ColorRGBA> _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!<VertexShader>(Application.Get().Window.Context, "content\\basicShader.hlsl", "VS");
_effect.VertexShader = vs;
vs.ReleaseRef();
let ps = Shader.FromFile!<PixelShader>(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<ColorRGBA>(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<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();
}
}
}