forked from Misaki/GhostEngine
Refactor shader pipeline and improve modularity
- Added `generatedCodePath` to `FullPassDescriptor` for better shader code organization. - Removed redundant `IID_PPV_ARGS` method and unused `Misaki.HighPerformance.Unsafe` reference. - Refactored `Material` and `MaterialAccessor` to use `CBuffer` and updated buffer size handling. - Renamed command buffer variables in `RenderingContext` for consistency. - Updated `D3D12PipelineLibrary` to cache compiled shader results and added `ShaderPassKey`. - Refactored `D3D12GraphicsEngine` to integrate `_copyCommandBuffer` lifecycle. - Enhanced `D3D12ResourceAllocator` with shader pass creation using constant buffer info. - Simplified `D3D12ShaderCompiler` with `GENERATED_CODE_PATH` support and improved reflection handling. - Introduced `CBufferPropertyInfo` and `CBufferInfo` structs for better encapsulation. - Updated HLSL shaders to use `g_PerMaterialData` and dynamic includes. - Improved error handling in `SDLCompiler` with try-catch blocks and better messages. - Refactored `test.gshader` to use dynamically generated includes. - Fixed typos, improved code readability, and removed unused code.
This commit is contained in:
@@ -63,17 +63,17 @@ public struct Material : IResourceReleasable, IHandleType
|
||||
for (var i = 0; i < shader.PassCount; i++)
|
||||
{
|
||||
var pass = database.GetShaderPass(shader.GetPassKey(i));
|
||||
var cbufferInfo = pass.PassPropertyInfo;
|
||||
var cbufferInfo = pass.CBuffer;
|
||||
|
||||
var desc = new BufferDesc
|
||||
{
|
||||
Size = cbufferInfo.Size,
|
||||
Size = cbufferInfo.SizeInBytes,
|
||||
Usage = BufferUsage.Constant,
|
||||
MemoryType = ResourceMemoryType.Default,
|
||||
};
|
||||
|
||||
var buffer = allocator.CreateBuffer(ref desc);
|
||||
_materialPropertiesCache[i] = new CBufferCache(buffer, cbufferInfo.Size);
|
||||
_materialPropertiesCache[i] = new CBufferCache(buffer, cbufferInfo.SizeInBytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ public ref struct MaterialAccessor
|
||||
}
|
||||
|
||||
ref var cache = ref _materialData.GetPassCache(index);
|
||||
Unsafe.WriteUnaligned(ref cache.CpuData[propertyInfo.ByteOffset], value);
|
||||
Unsafe.WriteUnaligned(ref cache.CpuData[propertyInfo.StartOffset], value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@ namespace Ghost.Graphics.Core;
|
||||
public unsafe readonly ref struct RenderingContext
|
||||
{
|
||||
private readonly IGraphicsEngine _engine;
|
||||
private readonly ICommandBuffer _directCmb;
|
||||
private readonly ICommandBuffer _copyCmb;
|
||||
private readonly ICommandBuffer _computeCmb;
|
||||
private readonly ICommandBuffer _directCmd;
|
||||
private readonly ICommandBuffer _copyCmd;
|
||||
private readonly ICommandBuffer _computeCmd;
|
||||
|
||||
public ICommandBuffer DirectCommandBuffer => _directCmb;
|
||||
public ICommandBuffer CopyCommandBuffer => _copyCmb;
|
||||
public ICommandBuffer ComputeCommandBuffer => _computeCmb;
|
||||
public ICommandBuffer DirectCommandBuffer => _directCmd;
|
||||
public ICommandBuffer CopyCommandBuffer => _copyCmd;
|
||||
public ICommandBuffer ComputeCommandBuffer => _computeCmd;
|
||||
|
||||
public IResourceAllocator ResourceAllocator => _engine.ResourceAllocator;
|
||||
public IResourceDatabase ResourceDatabase => _engine.ResourceDatabase;
|
||||
@@ -29,9 +29,9 @@ public unsafe readonly ref struct RenderingContext
|
||||
ICommandBuffer computeCmd)
|
||||
{
|
||||
_engine = engine;
|
||||
_directCmb = directCmd;
|
||||
_copyCmb = copyCmd;
|
||||
_computeCmb = computeCmd;
|
||||
_directCmd = directCmd;
|
||||
_copyCmd = copyCmd;
|
||||
_computeCmd = computeCmd;
|
||||
}
|
||||
|
||||
public ICommandBuffer CrearteCommandBuffer(CommandBufferType type)
|
||||
@@ -88,29 +88,25 @@ public unsafe readonly ref struct RenderingContext
|
||||
|
||||
if (needVertexTransition)
|
||||
{
|
||||
_copyCmb.ResourceBarrier(meshData.vertexBuffer.AsResource(), vertexState, ResourceState.CopyDest);
|
||||
ResourceDatabase.SetResourceState(meshData.vertexBuffer.AsResource(), ResourceState.CopyDest);
|
||||
_directCmd.ResourceBarrier(meshData.vertexBuffer.AsResource(), vertexState, ResourceState.CopyDest);
|
||||
}
|
||||
|
||||
if (needIndexTransition)
|
||||
{
|
||||
_copyCmb.ResourceBarrier(meshData.indexBuffer.AsResource(), indexState, ResourceState.CopyDest);
|
||||
ResourceDatabase.SetResourceState(meshData.indexBuffer.AsResource(), ResourceState.CopyDest);
|
||||
_directCmd.ResourceBarrier(meshData.indexBuffer.AsResource(), indexState, ResourceState.CopyDest);
|
||||
}
|
||||
|
||||
_copyCmb.UploadBuffer<Vertex>(meshData.vertexBuffer, meshData.vertices.AsSpan());
|
||||
_copyCmb.UploadBuffer<uint>(meshData.indexBuffer, meshData.indices.AsSpan());
|
||||
_directCmd.UploadBuffer(meshData.vertexBuffer, meshData.vertices.AsSpan());
|
||||
_directCmd.UploadBuffer(meshData.indexBuffer, meshData.indices.AsSpan());
|
||||
|
||||
if (needVertexTransition)
|
||||
{
|
||||
_copyCmb.ResourceBarrier(meshData.vertexBuffer.AsResource(), ResourceState.CopyDest, vertexState);
|
||||
ResourceDatabase.SetResourceState(meshData.vertexBuffer.AsResource(), vertexState);
|
||||
_directCmd.ResourceBarrier(meshData.vertexBuffer.AsResource(), ResourceState.CopyDest, vertexState);
|
||||
}
|
||||
|
||||
if (needIndexTransition)
|
||||
{
|
||||
ResourceDatabase.SetResourceState(meshData.indexBuffer.AsResource(), indexState);
|
||||
_copyCmb.ResourceBarrier(meshData.indexBuffer.AsResource(), ResourceState.CopyDest, indexState);
|
||||
_directCmd.ResourceBarrier(meshData.indexBuffer.AsResource(), ResourceState.CopyDest, indexState);
|
||||
}
|
||||
|
||||
if (markMeshStatic)
|
||||
@@ -141,20 +137,18 @@ public unsafe readonly ref struct RenderingContext
|
||||
|
||||
if (needTransition)
|
||||
{
|
||||
_copyCmb.ResourceBarrier(texture.AsResource(), sateBefore, ResourceState.CopyDest);
|
||||
ResourceDatabase.SetResourceState(texture.AsResource(), ResourceState.CopyDest);
|
||||
_directCmd.ResourceBarrier(texture.AsResource(), sateBefore, ResourceState.CopyDest);
|
||||
}
|
||||
|
||||
_copyCmb.UploadTexture(texture, subresourceData);
|
||||
_directCmd.UploadTexture(texture, subresourceData);
|
||||
|
||||
if (needTransition)
|
||||
{
|
||||
_copyCmb.ResourceBarrier(texture.AsResource(), ResourceState.CopyDest, sateBefore);
|
||||
ResourceDatabase.SetResourceState(texture.AsResource(), sateBefore);
|
||||
_directCmd.ResourceBarrier(texture.AsResource(), ResourceState.CopyDest, sateBefore);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Ideally we should queue the draw call to our rendering system, and render it in the full rendering pipeline.
|
||||
// TODO: Ideally we should queue the draw call to our rendering system, and render it in a full rendering pipeline.
|
||||
// This is just a place holder for now for testing purpose.
|
||||
public void DispatchMesh(Handle<Mesh> mesh, Handle<Material> material, string passName, uint numThreadsX)
|
||||
{
|
||||
@@ -172,20 +166,20 @@ public unsafe readonly ref struct RenderingContext
|
||||
|
||||
hash.rtvFormats[0] = TextureFormat.B8G8R8A8_UNorm;
|
||||
var pipelineKey = hash.GetKey();
|
||||
_directCmb.SetPipelineState(pipelineKey);
|
||||
_directCmd.SetPipelineState(pipelineKey);
|
||||
|
||||
// NOTE: We use fixed root signature layout for bindless rendering.
|
||||
ref var cache = ref materialRef.GetPassCache(passIndex);
|
||||
_directCmb.SetConstantBufferView(RootSignatureLayout.PER_MATERIAL_BUFFER_SLOT, cache.GpuResource);
|
||||
_directCmd.SetConstantBufferView(RootSignatureLayout.PER_MATERIAL_BUFFER_SLOT, cache.GpuResource);
|
||||
|
||||
// NOTE: Since we are using true bindless resources, we only need to set the descriptor heaps, not individual tables.
|
||||
// TODO: Matbe handle the transitional bindless model?
|
||||
// TODO: Maybe handle the traditional bindless model?
|
||||
#if false
|
||||
var samplerGpuHandle = _descriptorAllocator.GetSamplerHeap()->GetGPUDescriptorHandleForHeapStart();
|
||||
_commandList.Get()->SetGraphicsRootDescriptorTable(rootParamIndex, samplerGpuHandle);
|
||||
#endif
|
||||
|
||||
var threadGroupCountX = ((uint)meshRef.indices.Count + numThreadsX - 1) / numThreadsX;
|
||||
_directCmb.DispatchMesh(threadGroupCountX, 1, 1);
|
||||
_directCmd.DispatchMesh(threadGroupCountX, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,66 +7,23 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ghost.Graphics.Core;
|
||||
|
||||
public readonly struct TextureInfo
|
||||
{
|
||||
public uint RegisterSlot
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
|
||||
public uint RootParameterIndex
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct PropertyInfo
|
||||
{
|
||||
public uint CBufferIndex
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
|
||||
public uint ByteOffset
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
|
||||
public uint Size
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct CBufferInfo
|
||||
{
|
||||
public uint Size
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
|
||||
public uint RegisterSlot
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe class ShaderPass : IResourceReleasable
|
||||
public class ShaderPass : IResourceReleasable
|
||||
{
|
||||
private CBufferInfo _cbufferInfo;
|
||||
// NOTE: This is for per pass cbuffer only. Global, per view, and per mesh cbuffers are fixed.
|
||||
private readonly Dictionary<string, int> _propertyLookup;
|
||||
private readonly UnsafeList<PropertyInfo> _properties;
|
||||
|
||||
internal CBufferInfo PassPropertyInfo
|
||||
{
|
||||
get;
|
||||
}
|
||||
public CBufferInfo CBuffer => _cbufferInfo;
|
||||
|
||||
public ShaderPass(CBufferInfo info, UnsafeList<PropertyInfo> properties, Dictionary<string, int> propertyNameToIdMap)
|
||||
public ShaderPass(CBufferInfo info)
|
||||
{
|
||||
PassPropertyInfo = info;
|
||||
_properties = properties;
|
||||
_propertyLookup = propertyNameToIdMap;
|
||||
_cbufferInfo = info;
|
||||
|
||||
_propertyLookup = new Dictionary<string, int>(info.Properties.Count);
|
||||
for (var i = 0; i < info.Properties.Count; i++)
|
||||
{
|
||||
_propertyLookup[info.Properties[i].Name] = i;
|
||||
}
|
||||
}
|
||||
|
||||
public int GetPropertyId(string propertyName)
|
||||
@@ -74,19 +31,18 @@ public unsafe class ShaderPass : IResourceReleasable
|
||||
return _propertyLookup.TryGetValue(propertyName, out var id) ? id : -1;
|
||||
}
|
||||
|
||||
public PropertyInfo GetPropertyInfo(int id)
|
||||
public CBufferPropertyInfo GetPropertyInfo(int id)
|
||||
{
|
||||
return _properties[id];
|
||||
return _cbufferInfo.Properties[id];
|
||||
}
|
||||
|
||||
public PropertyInfo GetPropertyInfo(string propertyName)
|
||||
public CBufferPropertyInfo GetPropertyInfo(string propertyName)
|
||||
{
|
||||
return _properties[GetPropertyId(propertyName)];
|
||||
return _cbufferInfo.Properties[GetPropertyId(propertyName)];
|
||||
}
|
||||
|
||||
void IResourceReleasable.ReleaseResource(IResourceDatabase database)
|
||||
{
|
||||
_properties.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user