Files
GhostEngine/Ghost.Graphics/Core/Shader.cs
Misaki bd97d233cb Refactor and optimize rendering pipeline
- Added `<IsTrimmable>` property in project files for trimming.
- Replaced bindless texture types with non-bindless equivalents.
- Refactored `ShaderDescriptor` and `ShaderPass` for better modularity.
- Introduced `ShaderDescriptorExtensions` for property size calculations.
- Simplified constant buffer handling in `Material.cs`.
- Improved resource management in `D3D12` components.
- Added support for static meshes and optimized resource barriers.
- Refactored shader code generation and property merging in `SDLCompiler`.
- Removed unused or redundant code (e.g., `IncludesBlock` parser).
- Updated comments, documentation, and error handling for clarity.
2025-11-28 18:58:50 +09:00

122 lines
3.0 KiB
C#

using Ghost.Core;
using Ghost.Core.Graphics;
using Ghost.Graphics.RHI;
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
using System.Runtime.CompilerServices;
namespace Ghost.Graphics.Core;
public struct ShaderPass : IResourceReleasable
{
public ShaderPassKey Identifier
{
get; init;
}
public ZTestOptions ZTest
{
get; set;
}
public ZWriteOptions ZWrite
{
get; set;
}
public CullOptions Cull
{
get; set;
}
public BlendOptions Blend
{
get; set;
}
public uint ColorMask
{
get; set;
}
// TODO: Shader variant.
void IResourceReleasable.ReleaseResource(IResourceDatabase database)
{
}
}
/// <summary>
/// A representation of a GPU shader, including all the passes it contains.
/// </summary>
public class Shader : IResourceReleasable, IIdentifierType
{
private readonly uint _cbufferSize;
private UnsafeArray<ShaderPass> _passes;
// TODO: Optmize lookups with a better data structure if needed
private readonly Dictionary<string, int> _passLookup; // pass name to index
public int PassCount => _passes.Count;
public uint CBufferSize => _cbufferSize;
internal Shader(ShaderDescriptor descriptor)
{
_cbufferSize = descriptor.cbufferSize;
_passes = new UnsafeArray<ShaderPass>(descriptor.passes.Count, Allocator.Persistent);
_passLookup = new Dictionary<string, int>(descriptor.passes.Count);
for (var i = 0; i < descriptor.passes.Count; i++)
{
var pass = descriptor.passes[i];
// TODO: Handle inherited passes
if (pass is not FullPassDescriptor fullPass)
{
continue;
}
var passKey = new ShaderPassKey(pass.Identifier);
_passes[i] = new ShaderPass
{
Identifier = passKey,
ZTest = fullPass.localPipeline.zTest,
ZWrite = fullPass.localPipeline.zWrite,
Cull = fullPass.localPipeline.cull,
Blend = fullPass.localPipeline.blend,
ColorMask = fullPass.localPipeline.colorMask
};
_passLookup[pass.Name] = i;
}
}
public int GetPassIndex(string passName)
{
return _passLookup.GetValueOrDefault(passName, -1);
}
public ref ShaderPass GetPassReference(int index)
{
return ref _passes[index];
}
public RefResult<ShaderPass, ResultStatus> TryGetPassKey(string passName, out int passIndex)
{
var index = _passLookup.GetValueOrDefault(passName, -1);
if (index == -1)
{
passIndex = -1;
return Result.CreateRef(ref Unsafe.NullRef<ShaderPass>(), ResultStatus.NotFound);
}
passIndex = index;
return Result.CreateRef(ref _passes[index], ResultStatus.Success);
}
void IResourceReleasable.ReleaseResource(IResourceDatabase database)
{
_passes.Dispose();
}
}