Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Graphite.sln
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Graphite.Vulkan", "src\Grap
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Graphite.D3D11", "src\Graphite.D3D11\Graphite.D3D11.csproj", "{4DEE157C-DDCE-4133-A562-4C869765A07F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Graphite.OpenGL", "src\Graphite.OpenGL\Graphite.OpenGL.csproj", "{DAE5F38B-568D-45D9-AAEF-A71E49B564FD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -50,6 +52,10 @@ Global
{4DEE157C-DDCE-4133-A562-4C869765A07F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4DEE157C-DDCE-4133-A562-4C869765A07F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4DEE157C-DDCE-4133-A562-4C869765A07F}.Release|Any CPU.Build.0 = Release|Any CPU
{DAE5F38B-568D-45D9-AAEF-A71E49B564FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DAE5F38B-568D-45D9-AAEF-A71E49B564FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DAE5F38B-568D-45D9-AAEF-A71E49B564FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DAE5F38B-568D-45D9-AAEF-A71E49B564FD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{7E5E2B62-B479-4BD2-A8E9-3974FE6A3C76} = {0802471C-F455-4B4B-A50C-93EB36406339}
Expand Down
3 changes: 2 additions & 1 deletion src/Graphite.D3D11/D3D11Device.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ public override CommandList CreateCommandList()
return new D3D11CommandList(_device);
}

public override ShaderModule CreateShaderModule(byte[] code, string entryPoint, ShaderMappingInfo mapping = default)
public override ShaderModule CreateShaderModule(ShaderStage stage, byte[] code, string entryPoint,
ShaderMappingInfo mapping = default)
{
return new D3D11ShaderModule(code, in mapping);
}
Expand Down
24 changes: 24 additions & 0 deletions src/Graphite.OpenGL/GLBuffer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Silk.NET.OpenGL;

namespace Graphite.OpenGL;

internal sealed unsafe class GLBuffer : Buffer
{
private readonly GL _gl;

public readonly uint Buffer;

public GLBuffer(GL gl, ref readonly BufferInfo info, void* pData) : base(info)
{
_gl = gl;

Buffer = _gl.GenBuffer();
_gl.BindBuffer(BufferTargetARB.ArrayBuffer, Buffer);
_gl.BufferData(BufferTargetARB.ArrayBuffer, info.SizeInBytes, pData, BufferUsageARB.StaticDraw);
}

public override void Dispose()
{
_gl.DeleteBuffer(Buffer);
}
}
91 changes: 91 additions & 0 deletions src/Graphite.OpenGL/GLCommandList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using Graphite.Core;
using Graphite.OpenGL.Instructions;

namespace Graphite.OpenGL;

internal sealed class GLCommandList : CommandList
{
public readonly List<IInstruction> Instructions;

public GLCommandList()
{
Instructions = [];
}

public override void Begin()
{
Instructions.Clear();
}

public override void End() { }

public override void CopyBufferToBuffer(Buffer src, uint srcOffset, Buffer dest, uint destOffset, uint copySize = 0)
{
throw new NotImplementedException();
}

public override void CopyBufferToTexture(Buffer src, uint srcOffset, Texture dest, Region3D? region = null)
{
throw new NotImplementedException();
}

public override void GenerateMipmaps(Texture texture)
{
throw new NotImplementedException();
}

public override void BeginRenderPass(in ReadOnlySpan<ColorAttachmentInfo> colorAttachments)
{
Instructions.Add(new BeginRenderPassInstruction
{
ColorAttachments = Array.ConvertAll(colorAttachments.ToArray(), input => (GLTexture) input.Texture),
ClearColor = colorAttachments[0].ClearColor
});
}

public override void EndRenderPass() { }

public override void SetGraphicsPipeline(Pipeline pipeline)
{
Instructions.Add(new SetPipelineInstruction()
{
Pipeline = (GLPipeline) pipeline
});
}

public override void SetDescriptorSet(uint slot, Pipeline pipeline, DescriptorSet set)
{
throw new NotImplementedException();
}

public override void SetVertexBuffer(uint slot, Buffer buffer, uint stride, uint offset = 0)
{
Instructions.Add(new SetVertexBufferInstruction(slot, (GLBuffer) buffer, stride, offset));
}

public override void SetIndexBuffer(Buffer buffer, Format format, uint offset = 0)
{
Instructions.Add(new SetIndexBufferInstruction((GLBuffer) buffer, format, offset));
}

public override void PushDescriptors(uint slot, Pipeline pipeline, params ReadOnlySpan<Descriptor> descriptors)
{
throw new NotImplementedException();
}

public override void Draw(uint numVertices, uint firstVertex = 0)
{
Instructions.Add(new DrawInstruction()
{
NumVertices = numVertices,
FirstVertex = firstVertex
});
}

public override void DrawIndexed(uint numIndices, uint firstIndex = 0, int baseVertex = 0)
{
Instructions.Add(new DrawIndexedInstruction(numIndices, firstIndex, baseVertex));
}

public override void Dispose() { }
}
14 changes: 14 additions & 0 deletions src/Graphite.OpenGL/GLContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Graphite.OpenGL;

public class GLContext
{
public Func<string, nint> GetProcAddressFunc;

public Action<int> PresentFunc;

public GLContext(Func<string, IntPtr> getProcAddressFunc, Action<int> presentFunc)
{
GetProcAddressFunc = getProcAddressFunc;
PresentFunc = presentFunc;
}
}
196 changes: 196 additions & 0 deletions src/Graphite.OpenGL/GLDevice.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
using Graphite.Core;
using Graphite.OpenGL.Instructions;
using Silk.NET.OpenGL;

namespace Graphite.OpenGL;

internal sealed unsafe class GLDevice : Device
{
private readonly GL _gl;
private readonly GLContext _context;

private readonly Dictionary<int, uint> _framebufferCache;

public override Backend Backend => OpenGLBackend.Backend;

public GLDevice(GL gl, GLContext context)
{
_gl = gl;
_context = context;

_framebufferCache = [];
}

public override Swapchain CreateSwapchain(in SwapchainInfo info)
{
return new GLSwapchain(_gl, _context, in info);
}

public override CommandList CreateCommandList()
{
return new GLCommandList();
}

public override ShaderModule CreateShaderModule(ShaderStage stage, byte[] code, string entryPoint,
ShaderMappingInfo mapping = default)
{
return new GLShaderModule(_gl, stage, code);
}

public override Pipeline CreateGraphicsPipeline(in GraphicsPipelineInfo info)
{
return new GLPipeline(_gl, in info);
}

public override unsafe Buffer CreateBuffer(in BufferInfo info, void* data)
{
return new GLBuffer(_gl, in info, data);
}

public override unsafe Texture CreateTexture(in TextureInfo info, void* pData)
{
throw new NotImplementedException();
}

public override DescriptorLayout CreateDescriptorLayout(in DescriptorLayoutInfo info)
{
throw new NotImplementedException();
}

public override DescriptorSet CreateDescriptorSet(DescriptorLayout layout, params ReadOnlySpan<Descriptor> descriptors)
{
throw new NotImplementedException();
}

public override Sampler CreateSampler(in SamplerInfo info)
{
throw new NotImplementedException();
}

public override void ExecuteCommandList(CommandList cl)
{
GLCommandList glList = (GLCommandList) cl;

DrawElementsType elementsType = 0;

foreach (IInstruction instruction in glList.Instructions)
{
switch (instruction)
{
case BeginRenderPassInstruction renderPass:
{
uint framebuffer = GetFramebuffer(renderPass.ColorAttachments);
_gl.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer);

_gl.ClearColor(renderPass.ClearColor.R, renderPass.ClearColor.G, renderPass.ClearColor.B,
renderPass.ClearColor.A);
_gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

break;
}

case SetPipelineInstruction setPipeline:
{
GLPipeline pipeline = setPipeline.Pipeline;
_gl.BindVertexArray(pipeline.VertexArray);
_gl.UseProgram(pipeline.ShaderProgram);
break;
}

case SetVertexBufferInstruction setVertexBuffer:
{
_gl.BindVertexBuffer(setVertexBuffer.Slot, setVertexBuffer.Buffer.Buffer,
(nint) setVertexBuffer.Offset, setVertexBuffer.Stride);
break;
}

case SetIndexBufferInstruction setIndexBuffer:
{
_gl.BindBuffer(BufferTargetARB.ElementArrayBuffer, setIndexBuffer.Buffer.Buffer);
elementsType = setIndexBuffer.Format switch
{
Format.R8_UInt => DrawElementsType.UnsignedByte,
Format.R16_UInt => DrawElementsType.UnsignedShort,
Format.R32_UInt => DrawElementsType.UnsignedInt,
_ => throw new NotSupportedException()
};
break;
}

case DrawInstruction draw:
{
_gl.DrawArrays(PrimitiveType.Triangles, (int) draw.FirstVertex, draw.NumVertices);
break;
}

case DrawIndexedInstruction drawIndexed:
{
_gl.DrawElementsBaseVertex(PrimitiveType.Triangles, drawIndexed.NumIndices, elementsType,
(void*) drawIndexed.FirstIndex, drawIndexed.BaseVertex);
break;
}

default:
throw new ArgumentOutOfRangeException();
}
}
}

public override void UpdateBuffer(Buffer buffer, uint offset, uint size, void* pData)
{
throw new NotImplementedException();
}

public override void UpdateTexture(Texture texture, in Region3D region, void* pData)
{
throw new NotImplementedException();
}

public override IntPtr MapBuffer(Buffer buffer)
{
throw new NotImplementedException();
}

public override void UnmapBuffer(Buffer buffer)
{
throw new NotImplementedException();
}

public override void Dispose() { }

public uint GetFramebuffer(ReadOnlySpan<GLTexture> colorAttachments, GLTexture? depthAttachment = null)
{
HashCode code = new HashCode();

foreach (GLTexture texture in colorAttachments)
code.Add(texture);

if (depthAttachment != null)
code.Add(depthAttachment);

int hashCode = code.ToHashCode();

if (!_framebufferCache.TryGetValue(hashCode, out uint framebuffer))
{
GraphiteLog.Log($"Creating framebuffer {hashCode}.");
framebuffer = _gl.CreateFramebuffer();
_gl.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer);

foreach (GLTexture texture in colorAttachments)
{
_gl.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0,
TextureTarget.Texture2D, texture.Texture, 0);
}

if (depthAttachment != null)
throw new NotImplementedException();

if (_gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != GLEnum.FramebufferComplete)
throw new Exception("Framebuffer is not complete!");

_framebufferCache.Add(hashCode, framebuffer);
}

return framebuffer;
}
}
Loading