using System; using GlitchyEngine.Math; using DirectX.D3D11Shader; using internal GlitchyEngine.Renderer; namespace GlitchyEngine.Renderer { public class ConstantBuffer : Buffer { protected String _name ~ delete _; protected String _engineBufferName ~ delete _; /** * The buffer that contains the buffer data on the CPU. */ protected internal uint8[] rawData ~ delete _; protected BufferVariableCollection _variables = new BufferVariableCollection() ~ delete _; protected bool _isDirty = true; protected internal int _generation = 0; /// Gets the name of the constant buffer. public StringView Name => _name; public StringView EngineBufferName => _engineBufferName; public BufferVariableCollection Variables => _variables; /// Gets a span to the rawData held on the CPU. public Span RawData => rawData; protected this() {} public this(StringView name, int64 size, StringView engineBufferName = "") { _name = new String(name); if (!engineBufferName.IsEmpty) { _engineBufferName = new String(engineBufferName); } rawData = new uint8[size]; ConstructBuffer(); } protected internal void AddVariable(BufferVariable ownVariable) { _variables.Add(ownVariable); } public void AddVariable(StringView name, StringView previewName, StringView editorTypeName, uint64 offset, uint64 sizeInBytes, bool isUsed, ShaderVariableType type, uint8 rows, uint8 columns, uint64 arraySize) { _variables.Add(new BufferVariable(name, this, type, columns, rows, (uint32)offset, (uint32)sizeInBytes, (uint32)arraySize, isUsed, previewName, editorTypeName)); } /** * 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. * @returns true if the GPU buffer was updated, false otherwise (i.e. it wasn't dirty). */ public virtual Result Apply() { bool isDirty = false; for (BufferVariable variable in _variables) { if (variable.IsDirty) { isDirty = true; Enum.ClearFlag(ref variable.[Friend]_flags, .Dirty); } } if (isDirty) { Result setDataResult = PlatformSetData(rawData.CArray(), (uint32)rawData.Count, 0, .WriteDiscard); if (setDataResult case .Err) return .Err; _generation++; } return .Ok; } } public enum ShaderVariableType { case Bool; case Float; case Int; case UInt; // todo public int ElementSizeInBytes() { switch (this) { case .Bool: // TODO: I'm pretty sure this is wrong and should be 4 as well! return 1; case .Float: return 4; case .Int: return 4; case .UInt: return 4; default: return 0; } } } }