mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-06 05:01:53 +00:00
Render basic geometry
Added GraphicsContext, SwapChain, Buffer, VertexBuffer, IndexBuffer and a basic DX11 implementation.
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
using System;
|
||||
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
/**
|
||||
* Identifies expected resource use during rendering.
|
||||
* The usage directly reflects whether a resource is accessible by the CPU and/or the graphics processing unit (GPU).
|
||||
*/
|
||||
public enum Usage
|
||||
{
|
||||
/**
|
||||
* A resource that requires read and write access by the GPU.
|
||||
* This is likely to be the most common usage choice.
|
||||
*/
|
||||
Default = 0,
|
||||
/**
|
||||
* A resource that can only be read by the GPU. It cannot be written by the GPU, and cannot be accessed at all by the CPU.
|
||||
*/
|
||||
Immutable = 1,
|
||||
/**
|
||||
* A resource that is accessible by both the GPU (read only) and the CPU (write only).
|
||||
* A dynamic resource is a good choice for a resource that will be updated by the CPU at least once per frame.
|
||||
* To update a dynamic resource, use a Map method.
|
||||
*/
|
||||
Dynamic = 2,
|
||||
/**
|
||||
* A resource that supports data transfer (copy) from the GPU to the CPU.
|
||||
*/
|
||||
Staging = 3
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines how the CPU can access a resource.
|
||||
*/
|
||||
public enum CPUAccessFlags
|
||||
{
|
||||
/// The CPU has no access to the resource.
|
||||
None = 0,
|
||||
/// The CPU has read access to the resource.
|
||||
Read = 1,
|
||||
/// The CPU has write access to the resource.
|
||||
Write = 2
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines how to bind a buffer to the pipeline.
|
||||
*/
|
||||
public enum BufferBindFlags
|
||||
{
|
||||
/// No binding flags specified
|
||||
None = 0,
|
||||
/// The Buffer contains vertex data
|
||||
Vertex = 1,
|
||||
/// The Buffer contains index data
|
||||
Index = 2,
|
||||
// The Buffer contains constant data
|
||||
Constant = 4,
|
||||
// ShaderResource?
|
||||
// UnorderedAccess?
|
||||
}
|
||||
|
||||
public enum BufferMiscFlags
|
||||
{
|
||||
None = 0,
|
||||
//AllowRawView = 1,
|
||||
//Structured = 2,
|
||||
}
|
||||
|
||||
typealias Format = DirectX.DXGI.Format;
|
||||
|
||||
public struct BufferDescription
|
||||
{
|
||||
/**
|
||||
* The size of the buffer in bytes.
|
||||
*/
|
||||
public uint32 Size;
|
||||
|
||||
/**
|
||||
* Identify how the buffer is expected to be read from and written to. Frequency of update is a key factor.
|
||||
* The most common value is typically Default.
|
||||
*/
|
||||
public Usage Usage;
|
||||
|
||||
public CPUAccessFlags CPUAccess;
|
||||
|
||||
public BufferBindFlags BindFlags;
|
||||
|
||||
public BufferMiscFlags MiscFlags;
|
||||
|
||||
// Strucutred Byte stride.
|
||||
|
||||
public this() => this = default;
|
||||
|
||||
public this(uint32 size, BufferBindFlags bindFlags, Usage usage = .Default, CPUAccessFlags cpuAccess = .None, BufferMiscFlags miscFlags = .None)
|
||||
{
|
||||
Size = size;
|
||||
BindFlags = bindFlags;
|
||||
Usage = usage;
|
||||
CPUAccess = cpuAccess;
|
||||
MiscFlags = miscFlags;
|
||||
}
|
||||
}
|
||||
|
||||
public enum MapType
|
||||
{
|
||||
case None;
|
||||
case Read;
|
||||
case Write;
|
||||
case ReadWrite;
|
||||
case WriteDiscard;
|
||||
case WriteNoOverwrite;
|
||||
|
||||
public bool CanWrite => this == Write ||
|
||||
this == ReadWrite ||
|
||||
this == WriteDiscard ||
|
||||
this == WriteNoOverwrite;
|
||||
|
||||
public bool CanRead => this == Read ||
|
||||
this == ReadWrite;
|
||||
}
|
||||
|
||||
/// Represents a buffer containing binary data on the GPU.
|
||||
public class Buffer
|
||||
{
|
||||
internal GraphicsContext _context;
|
||||
|
||||
protected BufferDescription _description;
|
||||
|
||||
public GraphicsContext Context => _context;
|
||||
|
||||
public BufferDescription Description => _description;
|
||||
|
||||
protected this(GraphicsContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a Buffer.
|
||||
* @param description The buffer description.
|
||||
*/
|
||||
public this(GraphicsContext context, BufferDescription description) : this(context)
|
||||
{
|
||||
_description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data The span containing the data that will be copied into the buffer.
|
||||
* @param destinationByteOffset The offset in bytes form the start of the destination buffer.
|
||||
* @param mapType Only relevant for dynamic buffers...
|
||||
*/
|
||||
public Result<void> SetData<T>(Span<T> data, uint32 destinationByteOffset = 0, MapType mapType = .Write) where T : struct
|
||||
{
|
||||
return PlatformSetData(data.Ptr, (uint32)(data.Length * sizeof(T)), destinationByteOffset, mapType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data The span containing the data that will be copied into the buffer.
|
||||
* @param destinationByteOffset The offset in bytes form the start of the destination buffer.
|
||||
* @param mapType Only relevant for dynamic buffers...
|
||||
*/
|
||||
public Result<void> SetData<T>(T* data, uint32 elementCount, uint32 destinationByteOffset = 0, MapType mapType = .Write) where T : struct
|
||||
{
|
||||
return PlatformSetData(data, elementCount * (uint32)sizeof(T), destinationByteOffset, mapType);
|
||||
}
|
||||
|
||||
public Result<void> SetData<T, CLength>(T[CLength] data, uint32 destinationByteOffset = 0, MapType mapType = .Write) where T : struct where CLength : const int
|
||||
{
|
||||
var data;
|
||||
return PlatformSetData(&data, (uint32)sizeof(T[CLength]), destinationByteOffset, mapType);
|
||||
}
|
||||
|
||||
/**
|
||||
* // Todo: as soon as Beef supports generic method override, change to generic?
|
||||
* Platform specific implementation of SetData.
|
||||
* @param data The pointer to the source data that will be copied to the buffer.
|
||||
* @param data The number of bytes that will be copied.
|
||||
* @param dstByteOffset The offset from the start of the target buffer.
|
||||
*/
|
||||
protected extern Result<void> PlatformSetData(void* data, uint32 byteLength, uint32 dstByteOffset, MapType mapType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of data contained in an input slot.
|
||||
*/
|
||||
public enum InputClassification
|
||||
{
|
||||
/**
|
||||
* Input data is per-vertex data.
|
||||
*/
|
||||
PerVertexData = 0,
|
||||
/**
|
||||
* Input data is per-instance data.
|
||||
*/
|
||||
PerInstanceData = 1
|
||||
}
|
||||
|
||||
public struct VertexElement
|
||||
{
|
||||
/**
|
||||
* The semantic associated with this element in a shader input-signature.
|
||||
*/
|
||||
public String SemanticName;
|
||||
/**
|
||||
* The semantic index for the element.
|
||||
* A semantic index modifies a semantic, with an integer index number.
|
||||
* A semantic index is only needed in a case where there is more than one element with the same semantic.
|
||||
* For example, a 4x4 matrix would have four components each with the semantic name "matrix",
|
||||
* however each of the four component would have different semantic indices (0, 1, 2, and 3).
|
||||
*/
|
||||
public uint32 SemanticIndex;
|
||||
/**
|
||||
* The data type of the element data.
|
||||
*/
|
||||
public Format Format;
|
||||
/**
|
||||
* An integer value that identifies the input-assembler (see input slot). Valid values are between 0 and 15.
|
||||
*/
|
||||
public uint32 InputSlot;
|
||||
/**
|
||||
* Optional. Offset (in bytes) from the start of the vertex. Use AppendAligned for convenience to define the current element directly after the previous one, including any packing if necessary.
|
||||
*/
|
||||
public uint32 AlignedByteOffset;
|
||||
/**
|
||||
* Identifies the input data class for a single input slot.
|
||||
*/
|
||||
public InputClassification InputSlotClass;
|
||||
/**
|
||||
* The number of instances to draw using the same per-instance data before advancing in the buffer by one element.
|
||||
* This value must be 0 for an element that contains per-vertex data (the slot class is set to PerVertexData).
|
||||
*/
|
||||
public uint32 InstanceDataStepRate;
|
||||
|
||||
public this() => this = default;
|
||||
|
||||
public this(String semanticName, uint32 semanticIndex, Format format, uint32 inputSlot, uint32 offset = (.)-1, InputClassification slotClass = .PerVertexData, uint32 instanceStepRate = 0)
|
||||
{
|
||||
SemanticName = semanticName;
|
||||
SemanticIndex = semanticIndex;
|
||||
Format = format;
|
||||
InputSlot = inputSlot;
|
||||
AlignedByteOffset = offset;
|
||||
InputSlotClass = slotClass;
|
||||
InstanceDataStepRate = instanceStepRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use AppendAligned for convenience to define the current element directly after the previous one, including any packing if necessary.
|
||||
*/
|
||||
public static readonly uint32 AppendAligned = 0xffffffff;
|
||||
}
|
||||
|
||||
public abstract class VertexLayout
|
||||
{
|
||||
private GraphicsContext _context;
|
||||
|
||||
private VertexElement[] _elements ~ delete _;
|
||||
|
||||
public GraphicsContext Context => _context;
|
||||
|
||||
public VertexElement[] Elements => _elements;
|
||||
|
||||
/// Takes ownership of ownElements!
|
||||
public this(GraphicsContext context, VertexElement[] ownElements)
|
||||
{
|
||||
_context = context;
|
||||
_elements = ownElements;
|
||||
|
||||
//CreateNativeLayout();
|
||||
}
|
||||
|
||||
private extern void CreateNativeLayout();
|
||||
}
|
||||
|
||||
public interface IVertexData
|
||||
{
|
||||
static VertexLayout VertexLayout {get;}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using GlitchyEngine.Math;
|
||||
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
public class RenderTarget;
|
||||
|
||||
//public abstract class GraphicsContext
|
||||
public class GraphicsContext
|
||||
{
|
||||
//public abstract SwapChain SwapChain {get;}
|
||||
public extern SwapChain SwapChain {get;}
|
||||
|
||||
/**
|
||||
* The maximum number of simultaneous rendertargets supported.
|
||||
*/
|
||||
//public static extern uint32 MaxRenderTargetCount();
|
||||
|
||||
//public abstract void Init();
|
||||
public extern void Init();
|
||||
|
||||
/**
|
||||
* Sets a rendertarget.
|
||||
* @param renderTarget The render target.
|
||||
* @param slot The slot to which the rendertarget will be bound.
|
||||
* @remarks When @RenderTarget is null the backbuffer will be bound.
|
||||
* @BindRenderTargets has to be called in order to bind the rendertargets.
|
||||
*/
|
||||
//public abstract void SetRenderTarget(RenderTarget renderTarget, int slot = 0);
|
||||
public extern void SetRenderTarget(RenderTarget renderTarget, int slot = 0);
|
||||
|
||||
/**
|
||||
* Binds all.
|
||||
* @param renderTarget The render target.
|
||||
* @param slot The slot to which the rendertarget will be bound.
|
||||
* @remarks When @RenderTarget is null the backbuffer will be bound.
|
||||
*/
|
||||
//public abstract void BindRenderTargets(); // Todo: maybe do this automatically when a drawcall is issued
|
||||
public extern void BindRenderTargets(); // Todo: maybe do this automatically when a drawcall is issued
|
||||
|
||||
/**
|
||||
* Sets all elements in the given render target to one value.
|
||||
* @param renderTarget The render target.
|
||||
* @param color The color to clear the render target with.
|
||||
* @remarks When @renderTarget is null the backbuffer will be cleared.
|
||||
*/
|
||||
//public abstract void ClearRenderTarget(RenderTarget renderTarget, ColorRGBA color);
|
||||
public extern void ClearRenderTarget(RenderTarget renderTarget, ColorRGBA color);
|
||||
|
||||
//public abstract void SetViewport(Viewport viewport);
|
||||
|
||||
/**
|
||||
* Binds a VertexBuffer to the pipeline.
|
||||
* @param buffer The vertex buffer to bind.
|
||||
* Note: the buffer has to have BindFlags.Vertex!
|
||||
* @param slot The slot the vertex buffer will be bound to.
|
||||
* @param offset The offset in bytes from the start of the buffer.
|
||||
* @param stride The stride of the
|
||||
*/
|
||||
public extern void SetVertexBuffer(uint32 slot, Buffer buffer, uint32 stride, uint32 offset = 0);
|
||||
|
||||
/**
|
||||
* Binds a VertexBuffer to the pipeline.
|
||||
*/
|
||||
public void SetVertexBuffer(uint32 slot, VertexBufferBinding binding)
|
||||
{
|
||||
SetVertexBuffer(slot, binding.Buffer, binding.Stride, binding.Offset);
|
||||
}
|
||||
|
||||
public extern void Draw(uint32 vertexCount, uint32 startVertexIndex = 0);
|
||||
|
||||
public extern void DrawIndexed(uint32 indexCount, uint32 startIndexLocation = 0, int32 vertexOffset = 0);
|
||||
|
||||
public void SetIndexBuffer(IndexBuffer indexBuffer, uint32 byteOffset = 0)
|
||||
{
|
||||
SetIndexBuffer(indexBuffer, indexBuffer.Format, byteOffset);
|
||||
}
|
||||
|
||||
public extern void SetIndexBuffer(Buffer buffer, IndexFormat indexFormat = .Index16Bit, uint32 byteOffset = 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
public enum IndexFormat
|
||||
{
|
||||
Index16Bit,
|
||||
Index32Bit,
|
||||
}
|
||||
|
||||
public class IndexBuffer : Buffer
|
||||
{
|
||||
private uint32 _indexCount;
|
||||
private IndexFormat _format;
|
||||
|
||||
public uint32 IndexCount => _indexCount;
|
||||
public IndexFormat Format => _format;
|
||||
|
||||
public this(GraphicsContext context, uint32 indexCount, Usage usage = .Default, CPUAccessFlags cpuAccess = .None, IndexFormat indexFormat = .Index16Bit) : base(context)
|
||||
{
|
||||
_indexCount = indexCount;
|
||||
_format = indexFormat;
|
||||
|
||||
_description = .()
|
||||
{
|
||||
Size = (_format == .Index32Bit ? 4 : 2) * _indexCount,
|
||||
Usage = usage,
|
||||
CPUAccess = cpuAccess,
|
||||
BindFlags = .Index,
|
||||
MiscFlags = .None
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
public class SwapChain
|
||||
{
|
||||
public extern GraphicsContext Context {get;}
|
||||
|
||||
/**
|
||||
* Gets or Sets the backbuffers width.
|
||||
* @remarks @ApplyChanges() needs to be called in order to apply the ganges.
|
||||
*/
|
||||
public extern uint32 Width {get; set;}
|
||||
/**
|
||||
* Gets or Sets the backbuffers height.
|
||||
* @remarks @ApplyChanges() needs to be called in order to apply the ganges.
|
||||
*/
|
||||
public extern uint32 Height {get; set;}
|
||||
|
||||
public extern void Init();
|
||||
|
||||
/**
|
||||
* Applies all changes to the swapchain.
|
||||
*/
|
||||
public extern void ApplyChanges();
|
||||
|
||||
/**
|
||||
* Swaps the front- and backbuffer.
|
||||
*/
|
||||
public extern void Present();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
public struct VertexBufferBinding
|
||||
{
|
||||
public Buffer Buffer;
|
||||
public uint32 Stride;
|
||||
public uint32 Offset;
|
||||
|
||||
public this(Buffer buffer, uint32 stride, uint32 offset = 0)
|
||||
{
|
||||
Buffer = buffer;
|
||||
Stride = stride;
|
||||
Offset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
public class VertexBuffer<T> : Buffer where T: struct, IVertexData
|
||||
{
|
||||
private VertexBufferBinding _defaultBinding;
|
||||
|
||||
public VertexBufferBinding Binding => _defaultBinding;
|
||||
|
||||
public this(GraphicsContext context, uint32 vertexCount, Usage usage = .Default, CPUAccessFlags cpuAccess = .None) : base(context)
|
||||
{
|
||||
_description = .(){
|
||||
Size = ((uint32)sizeof(T) * vertexCount),
|
||||
Usage = usage,
|
||||
CPUAccess = cpuAccess,
|
||||
BindFlags = .Vertex,
|
||||
MiscFlags = .None
|
||||
};
|
||||
|
||||
_defaultBinding = .(this, (.)sizeof(T), 0);
|
||||
}
|
||||
|
||||
public Result<void> SetData(Span<T> data, uint32 destinationVertexOffset = 0, MapType mapType = .Write)
|
||||
{
|
||||
return SetData<T>(data, destinationVertexOffset * (uint32)sizeof(T));
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public static implicit operator VertexBufferBinding(Self buffer) => buffer._defaultBinding;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
public struct Viewport
|
||||
{
|
||||
/// X position of the left hand side of the viewport.
|
||||
public float Left;
|
||||
/// Y position of the top of the viewport. Ranges between BoundsMin and BoundsMax.
|
||||
public float Top;
|
||||
/// Width of the viewport.
|
||||
public float Width;
|
||||
/// Height of the viewport.
|
||||
public float Height;
|
||||
/// Minimum depth of the viewport. Ranges between 0 and 1.
|
||||
public float MinDepth;
|
||||
/// Maximum depth of the viewport. Ranges between 0 and 1.
|
||||
public float MaxDepth;
|
||||
|
||||
public this() => this = default;
|
||||
|
||||
public this(float left, float top, float width, float height, float minDepth = 0.0f, float maxDepth = 1.0f)
|
||||
{
|
||||
Left = left;
|
||||
Top = top;
|
||||
Width = width;
|
||||
Height = height;
|
||||
MinDepth = minDepth;
|
||||
MaxDepth = maxDepth;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user