Skip to content

Commit

Permalink
Reworked SimplePipeline, Working on PrimitiveBatch.
Browse files Browse the repository at this point in the history
  • Loading branch information
MrScautHD committed Sep 8, 2024
1 parent a4ce7d0 commit 5f645ba
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 78 deletions.
92 changes: 22 additions & 70 deletions src/Bliss/CSharp/Graphics/Pipelines/SimplePipeline.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Bliss.CSharp.Effects;
using Bliss.CSharp.Graphics.Pipelines.Buffers;
using Bliss.CSharp.Graphics.Pipelines.Textures;
using Veldrid;
Expand All @@ -11,37 +10,11 @@ public class SimplePipeline : Disposable {
/// Represents the graphics device used by the pipeline for creating and managing graphics resources.
/// </summary>
public GraphicsDevice GraphicsDevice { get; private set; }

/// <summary>
/// Represents the shader effect used by the pipeline.
/// </summary>
public Effect Effect { get; private set; }

/// <summary>
/// Defines the output configuration for the rendering pipeline, including target formats for color and depth-stencil buffers.
/// </summary>
public OutputDescription Output { get; private set; }

/// <summary>
/// Defines the state associated with blend operations, such as how pixel colors from a source and destination should be combined.
/// </summary>
public BlendStateDescription BlendState { get; private set; }

/// <summary>
/// Specifies the face culling mode for the graphics pipeline, determining which faces of polygons are culled during rendering.
/// </summary>
public FaceCullMode CullMode { get; private set; }

/// <summary>
/// Represents an array of buffers used in the graphics pipeline.
/// Each buffer is utilized for storing and managing data required for rendering operations.
/// </summary>
public ISimpleBuffer[] Buffers { get; private set; }


/// <summary>
/// Represents an array of texture layouts used in the pipeline.
/// Contains the configuration details for setting up a graphics pipeline, including states and resource layouts.
/// </summary>
public SimpleTextureLayout[] TextureLayouts { get; private set; }
public SimplePipelineDescription PipelineDescription;

/// <summary>
/// Represents the array of resource layouts used by the pipeline to manage buffer and texture resources.
Expand All @@ -52,59 +25,38 @@ public class SimplePipeline : Disposable {
/// Represents the graphics pipeline used to render graphics objects.
/// </summary>
public Pipeline Pipeline { get; private set; }

/// <summary>
/// Initializes a new instance of the <see cref="SimplePipeline"/> class with the specified graphics device, effect, output description, blend state, cull mode, buffers, and texture layouts.
/// Initializes a new instance of the <see cref="SimplePipeline"/> class using the provided graphics device and pipeline description.
/// </summary>
/// <param name="graphicsDevice">The graphics device to create the pipeline.</param>
/// <param name="effect">The effect containing the shaders and vertex layout.</param>
/// <param name="output">The output description specifying the render targets and depth buffer.</param>
/// <param name="blendState">The blend state description used for blending operations.</param>
/// <param name="cullMode">The face cull mode determining which faces of the primitives are culled.</param>
/// <param name="buffers">The array of buffers used for resource layouts in the pipeline.</param>
/// <param name="textureLayouts">The array of texture layouts used for resource layouts in the pipeline.</param>
public SimplePipeline(GraphicsDevice graphicsDevice, Effect effect, OutputDescription output, BlendStateDescription blendState, FaceCullMode cullMode, ISimpleBuffer[] buffers, SimpleTextureLayout[] textureLayouts) {
/// <param name="graphicsDevice">The graphics device that will be used to create the pipeline.</param>
/// <param name="pipelineDescription">The description of the pipeline, containing configurations like blend state, shader set, and resource layouts.</param>
public SimplePipeline(GraphicsDevice graphicsDevice, SimplePipelineDescription pipelineDescription) {
this.GraphicsDevice = graphicsDevice;
this.Effect = effect;
this.Output = output;
this.BlendState = blendState;
this.CullMode = cullMode;
this.Buffers = buffers;
this.TextureLayouts = textureLayouts;
this.ResourceLayouts = new ResourceLayout[buffers.Length + textureLayouts.Length];
this.PipelineDescription = pipelineDescription;
this.ResourceLayouts = new ResourceLayout[this.PipelineDescription.Buffers.Length + this.PipelineDescription.TextureLayouts.Length];

int layoutIndex = 0;
foreach (ISimpleBuffer buffer in buffers) {

foreach (ISimpleBuffer buffer in this.PipelineDescription.Buffers) {
this.ResourceLayouts[layoutIndex] = buffer.ResourceLayout;
layoutIndex += 1;
}

foreach (SimpleTextureLayout textureLayout in textureLayouts) {
foreach (SimpleTextureLayout textureLayout in this.PipelineDescription.TextureLayouts) {
this.ResourceLayouts[layoutIndex] = textureLayout.Layout;
layoutIndex += 1;
}

this.Pipeline = this.GraphicsDevice.ResourceFactory.CreateGraphicsPipeline(new GraphicsPipelineDescription() {
BlendState = this.BlendState,
DepthStencilState = new DepthStencilStateDescription(true, true, ComparisonKind.LessEqual),
RasterizerState = new RasterizerStateDescription() {
DepthClipEnabled = true,
CullMode = this.CullMode,
ScissorTestEnabled = true
},
PrimitiveTopology = PrimitiveTopology.TriangleList,
ResourceLayouts = this.ResourceLayouts,
ShaderSet = new ShaderSetDescription() {
VertexLayouts = [
this.Effect.VertexLayout
],
Shaders = [
this.Effect.Shader.Item1,
this.Effect.Shader.Item2
]
},
Outputs = this.Output
BlendState = pipelineDescription.BlendState,
DepthStencilState = pipelineDescription.DepthStencilState,
RasterizerState = pipelineDescription.RasterizerState,
PrimitiveTopology = pipelineDescription.PrimitiveTopology,
ResourceLayouts = this.ResourceLayouts,
ShaderSet = pipelineDescription.ShaderSet,
Outputs = pipelineDescription.Outputs,
ResourceBindingModel = pipelineDescription.ResourceBindingModel
});
}

Expand All @@ -114,7 +66,7 @@ public SimplePipeline(GraphicsDevice graphicsDevice, Effect effect, OutputDescri
/// <param name="name">The name of the buffer to retrieve.</param>
/// <returns>The buffer with the specified name, or null if no such buffer exists.</returns>
public ISimpleBuffer? GetBuffer(string name) {
return this.Buffers.FirstOrDefault(buffer => buffer.Name == name);
return this.PipelineDescription.Buffers.FirstOrDefault(buffer => buffer.Name == name);
}

protected override void Dispose(bool disposing) {
Expand Down
76 changes: 76 additions & 0 deletions src/Bliss/CSharp/Graphics/Pipelines/SimplePipelineDescription.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using Bliss.CSharp.Graphics.Pipelines.Buffers;
using Bliss.CSharp.Graphics.Pipelines.Textures;
using Veldrid;

namespace Bliss.CSharp.Graphics.Pipelines;

public struct SimplePipelineDescription {

/// <summary>
/// Defines the blend state configuration, controlling how colors are blended in the pipeline.
/// </summary>
public BlendStateDescription BlendState;

/// <summary>
/// Defines the depth and stencil state configuration, controlling depth testing and stencil operations in the pipeline.
/// </summary>
public DepthStencilStateDescription DepthStencilState;

/// <summary>
/// Defines the rasterizer state configuration, which determines how primitives are rasterized (e.g., culling mode, fill mode).
/// </summary>
public RasterizerStateDescription RasterizerState;

/// <summary>
/// Specifies the primitive topology, which defines how the input vertices are interpreted (e.g., triangles, lines).
/// </summary>
public PrimitiveTopology PrimitiveTopology;

/// <summary>
/// An array of buffers that are bound to the pipeline, containing vertex data and possibly other information.
/// </summary>
public ISimpleBuffer[] Buffers;

/// <summary>
/// An array of texture layouts, describing how textures are arranged and accessed in the pipeline.
/// </summary>
public SimpleTextureLayout[] TextureLayouts;

/// <summary>
/// Describes the shader set, including the vertex and fragment shaders used by the pipeline.
/// </summary>
public ShaderSetDescription ShaderSet;

/// <summary>
/// Defines the output configuration, specifying render targets and the depth-stencil buffer for the pipeline.
/// </summary>
public OutputDescription Outputs;

/// <summary>
/// An optional resource binding model that maps resources such as textures and buffers to the pipeline.
/// </summary>
public ResourceBindingModel? ResourceBindingModel;

/// <summary>
/// Initializes a new instance of the <see cref="SimplePipelineDescription"/> struct with the provided pipeline configuration details.
/// </summary>
/// <param name="blendState">The blend state configuration of the pipeline.</param>
/// <param name="depthStencilState">The depth and stencil state configuration of the pipeline.</param>
/// <param name="rasterizerState">The rasterizer state configuration of the pipeline.</param>
/// <param name="primitiveTopology">The primitive topology that defines how vertex data is interpreted.</param>
/// <param name="buffers">An array of buffers to be used by the pipeline.</param>
/// <param name="textureLayouts">An array of texture layouts to be used in the pipeline.</param>
/// <param name="shaderSet">The shader set description that defines the vertex and fragment shaders.</param>
/// <param name="outputs">The output configuration of the pipeline, specifying the render targets and depth-stencil buffer.</param>
public SimplePipelineDescription(BlendStateDescription blendState, DepthStencilStateDescription depthStencilState, RasterizerStateDescription rasterizerState, PrimitiveTopology primitiveTopology, ISimpleBuffer[] buffers, SimpleTextureLayout[] textureLayouts, ShaderSetDescription shaderSet, OutputDescription outputs) {
this.BlendState = blendState;
this.DepthStencilState = depthStencilState;
this.RasterizerState = rasterizerState;
this.PrimitiveTopology = primitiveTopology;
this.Buffers = buffers;
this.TextureLayouts = textureLayouts;
this.ShaderSet = shaderSet;
this.Outputs = outputs;
this.ResourceBindingModel = null;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
using System.Numerics;
using System.Runtime.InteropServices;
using Bliss.CSharp.Effects;
using Bliss.CSharp.Geometry;
using Bliss.CSharp.Graphics.Pipelines;
using Bliss.CSharp.Graphics.Pipelines.Buffers;
using Bliss.CSharp.Windowing;
using Veldrid;

namespace Bliss.CSharp.Graphics.Rendering.Batches.Primitives;

Expand All @@ -23,21 +30,94 @@ public class PrimitiveBatch : Disposable {
2, 1, 0,
2, 3, 1
};

public GraphicsDevice GraphicsDevice { get; private set; }
public Window Window { get; private set; }
public uint Capacity { get; private set; }
public int DrawCallCount { get; private set; }

private SimpleBuffer<Matrix4x4> _projViewBuffer;

private Effect _effect;
private SimplePipeline _pipelineTriangleList;
private SimplePipeline _pipelineTriangleStrip;
private SimplePipeline _pipelineLineLoop;

private bool _begun;

private CommandList _currentCommandList;

public PrimitiveBatch() {
private SimplePipeline _currentPipeline;

public PrimitiveBatch(GraphicsDevice graphicsDevice, Window window, uint capacity = 15360) {
this.GraphicsDevice = graphicsDevice;
this.Window = window;
this.Capacity = capacity;

// Create effects.
this._effect = new Effect(graphicsDevice.ResourceFactory, Vertex2D.VertexLayout, "content/shaders/primitive.vert", "content/shaders/primitive.frag");

// Create pipelines.
SimplePipelineDescription pipelineDescription = new SimplePipelineDescription() {
BlendState = BlendState.AlphaBlend.Description,
DepthStencilState = new DepthStencilStateDescription(true, true, ComparisonKind.LessEqual),
RasterizerState = new RasterizerStateDescription() {
DepthClipEnabled = true,
CullMode = FaceCullMode.None
},
ShaderSet = new ShaderSetDescription() {
VertexLayouts = [
Vertex2D.VertexLayout
],
Shaders = [
this._effect.Shader.Item1,
this._effect.Shader.Item2
]
},
Outputs = graphicsDevice.SwapchainFramebuffer.OutputDescription
};

pipelineDescription.PrimitiveTopology = PrimitiveTopology.TriangleList;
this._pipelineTriangleList = new SimplePipeline(graphicsDevice, pipelineDescription);

pipelineDescription.PrimitiveTopology = PrimitiveTopology.TriangleStrip;
this._pipelineTriangleStrip = new SimplePipeline(graphicsDevice, pipelineDescription);

pipelineDescription.PrimitiveTopology = PrimitiveTopology.LineStrip;
this._pipelineLineLoop = new SimplePipeline(graphicsDevice, pipelineDescription);

// Create projection view buffer.
this._projViewBuffer = new SimpleBuffer<Matrix4x4>(graphicsDevice, "ProjectionViewBuffer", (uint) Marshal.SizeOf<Matrix4x4>(), SimpleBufferType.Uniform, ShaderStages.Vertex);
}

public void Begin() {
public void Begin(CommandList commandList, Matrix4x4? view = null, Matrix4x4? projection = null) {
if (this._begun) {
throw new Exception("The PrimitiveBatch has already begun!");
}

this._begun = true;
this._currentCommandList = commandList;

Matrix4x4 finalView = view ?? Matrix4x4.Identity;
Matrix4x4 finalProj = projection ?? Matrix4x4.CreateOrthographicOffCenter(0.0F, this.Window.Width, this.Window.Height, 0.0F, 0.0F, 1.0F);

this._projViewBuffer.SetValue(0, finalView * finalProj, true);
this.DrawCallCount = 0;
}

public void End() {

if (!this._begun) {
throw new Exception("The PrimitiveBatch has not begun yet!");
}

this._begun = false;
this.Flush();
}

private void Flush() {



this.DrawCallCount++;
}

protected override void Dispose(bool disposing) {
Expand Down
33 changes: 29 additions & 4 deletions src/Bliss/CSharp/Graphics/Rendering/Batches/Sprites/SpriteBatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public class SpriteBatch : Disposable {
/// <summary>
/// Specifies the maximum number of sprites that the SpriteBatch can process in a single draw call.
/// </summary>
public uint Capacity { get; }
public uint Capacity { get; private set; }

/// <summary>
/// Gets the number of draw calls made during the current batch rendering session.
Expand Down Expand Up @@ -200,10 +200,10 @@ public SpriteBatch(GraphicsDevice graphicsDevice, Window window, uint capacity =
graphicsDevice.UpdateBuffer(this._indexBuffer, 0, this._indices);

// Create texture layout.
this._textureLayout = new SimpleTextureLayout(this.GraphicsDevice, "fTexture");
this._textureLayout = new SimpleTextureLayout(graphicsDevice, "fTexture");

// Create projection view buffer.
this._projViewBuffer = new SimpleBuffer<Matrix4x4>(this.GraphicsDevice, "ProjectionViewBuffer", (uint) Marshal.SizeOf<Matrix4x4>(), SimpleBufferType.Uniform, ShaderStages.Vertex);
this._projViewBuffer = new SimpleBuffer<Matrix4x4>(graphicsDevice, "ProjectionViewBuffer", (uint) Marshal.SizeOf<Matrix4x4>(), SimpleBufferType.Uniform, ShaderStages.Vertex);
}

/// <summary>
Expand Down Expand Up @@ -460,7 +460,32 @@ public void Flush() {
/// <returns>A SimplePipeline object configured with the provided effect and blend state.</returns>
private SimplePipeline GetOrCreatePipeline(Effect effect, BlendState blendState) {
if (!this._cachedPipelines.TryGetValue((effect, blendState), out SimplePipeline? pipeline)) {
SimplePipeline newPipeline = new SimplePipeline(this.GraphicsDevice, effect, this.GraphicsDevice.SwapchainFramebuffer.OutputDescription, blendState.Description, FaceCullMode.None, [ this._projViewBuffer ], [ this._textureLayout ]);
SimplePipeline newPipeline = new SimplePipeline(this.GraphicsDevice, new SimplePipelineDescription() {
BlendState = blendState.Description,
DepthStencilState = new DepthStencilStateDescription(true, true, ComparisonKind.LessEqual),
RasterizerState = new RasterizerStateDescription() {
DepthClipEnabled = true,
CullMode = FaceCullMode.None,
ScissorTestEnabled = true
},
PrimitiveTopology = PrimitiveTopology.TriangleList,
Buffers = [
this._projViewBuffer
],
TextureLayouts = [
this._textureLayout
],
ShaderSet = new ShaderSetDescription() {
VertexLayouts = [
effect.VertexLayout
],
Shaders = [
effect.Shader.Item1,
effect.Shader.Item2
]
},
Outputs = this.GraphicsDevice.SwapchainFramebuffer.OutputDescription
});

this._cachedPipelines.Add((effect, blendState), newPipeline);
return newPipeline;
Expand Down
9 changes: 9 additions & 0 deletions src/Bliss/content/shaders/primitive.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#version 450

layout (location = 1) in vec4 fColor;

layout (location = 0) out vec4 fFragColor;

void main() {
fFragColor = fColor;
}
Loading

0 comments on commit 5f645ba

Please sign in to comment.