forked from Misaki/GhostEngine
Update RenderingContext and D3D12Renderer to use new API.
This commit is contained in:
@@ -13,8 +13,8 @@ public enum ShaderPropertyType
|
||||
Int, Int2, Int3, Int4,
|
||||
UInt, UInt2, UInt3, UInt4,
|
||||
Bool, Bool2, Bool3, Bool4,
|
||||
Texture2D, Texture3D, TextureCube,
|
||||
Texture2DArray, TextureCubeArray,
|
||||
Texture2DBindless, Texture3DBindless, TextureCubeBindless,
|
||||
Texture2DArrayBindless, TextureCubeArrayBindless,
|
||||
}
|
||||
|
||||
public struct ShaderEntryPoint
|
||||
@@ -101,4 +101,4 @@ public class ShaderDescriptor
|
||||
public string name = string.Empty;
|
||||
public List<PropertyDescriptor> globalProperties = new();
|
||||
public List<IPassDescriptor> passes = new();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using Ghost.Graphics.Core;
|
||||
using Ghost.Graphics.RHI;
|
||||
|
||||
namespace Ghost.Graphics.Contracts;
|
||||
|
||||
public interface IRenderPass
|
||||
{
|
||||
public void Initialize(ICommandBuffer cmd);
|
||||
public void Execute(ICommandBuffer cmd);
|
||||
public void Initialize(ref readonly RenderingContext ctx);
|
||||
public void Execute(ref readonly RenderingContext ctx);
|
||||
public void Cleanup(IResourceDatabase resourceDatabase);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ public ref struct MaterialAccessor
|
||||
for (var i = 0; i < _shader.PassCount; i++)
|
||||
{
|
||||
ref var cache = ref _materialData.GetPassCache(i);
|
||||
cmb.Upload(cache.GpuResource, cache.CpuData.AsSpan());
|
||||
cmb.UploadBuffer<byte>(cache.GpuResource, cache.CpuData.AsSpan());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,35 +9,54 @@ namespace Ghost.Graphics.Core;
|
||||
|
||||
public unsafe readonly ref struct RenderingContext
|
||||
{
|
||||
private readonly IRenderDevice _device;
|
||||
private readonly IGraphicsEngine _engine;
|
||||
private readonly ICommandBuffer _directCmb;
|
||||
private readonly ICommandBuffer _copyCmb;
|
||||
private readonly ICommandBuffer _computeCmb;
|
||||
private readonly IResourceAllocator _resourceAllocator;
|
||||
private readonly IResourceDatabase _resourceDatabase;
|
||||
private readonly IPipelineLibrary _stateController;
|
||||
|
||||
public ICommandBuffer DirectCommandBuffer => _directCmb;
|
||||
public ICommandBuffer CopyCommandBuffer => _copyCmb;
|
||||
public ICommandBuffer ComputeCommandBuffer => _computeCmb;
|
||||
|
||||
public IResourceAllocator ResourceAllocator => _engine.ResourceAllocator;
|
||||
public IResourceDatabase ResourceDatabase => _engine.ResourceDatabase;
|
||||
public IPipelineLibrary PipelineLibrary => _engine.PipelineLibrary;
|
||||
|
||||
internal RenderingContext(
|
||||
IRenderDevice device,
|
||||
IGraphicsEngine engine,
|
||||
ICommandBuffer directCmd,
|
||||
ICommandBuffer copyCmd,
|
||||
ICommandBuffer computeCmd,
|
||||
IResourceAllocator resourceAllocator,
|
||||
IResourceDatabase resourceDatabase,
|
||||
IPipelineLibrary stateController)
|
||||
ICommandBuffer computeCmd)
|
||||
{
|
||||
_device = device;
|
||||
_engine = engine;
|
||||
_directCmb = directCmd;
|
||||
_copyCmb = copyCmd;
|
||||
_computeCmb = computeCmd;
|
||||
_resourceAllocator = resourceAllocator;
|
||||
_resourceDatabase = resourceDatabase;
|
||||
_stateController = stateController;
|
||||
}
|
||||
|
||||
public ICommandBuffer CrearteCommandBuffer(CommandBufferType type)
|
||||
{
|
||||
return _engine.CreateCommandBuffer(type);
|
||||
}
|
||||
|
||||
// TODO: ExecuteCommandBufferAsync with fencene.Device.GraphicsQueue.Submit(commandBuffer);
|
||||
public void ExecuteCommandBuffer(ICommandBuffer commandBuffer)
|
||||
{
|
||||
var queue = commandBuffer.Type switch
|
||||
{
|
||||
CommandBufferType.Graphics => _engine.Device.GraphicsQueue,
|
||||
CommandBufferType.Compute => _engine.Device.ComputeQueue,
|
||||
CommandBufferType.Copy => _engine.Device.CopyQueue,
|
||||
_ => throw new ArgumentOutOfRangeException(),
|
||||
};
|
||||
|
||||
queue.Submit(commandBuffer);
|
||||
queue.WaitIdle();
|
||||
}
|
||||
|
||||
public Handle<Mesh> CreateMesh(UnsafeList<Vertex> vertices, UnsafeList<uint> indices)
|
||||
{
|
||||
var mesh = _resourceAllocator.CreateMesh(vertices, indices);
|
||||
var mesh = ResourceAllocator.CreateMesh(vertices, indices);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
@@ -61,36 +80,36 @@ public unsafe readonly ref struct RenderingContext
|
||||
/// <param name="markMeshStatic">Whether to mark the mesh as static. If it's true, the cpu buffer of the mesh will not be avaliable any more</param>
|
||||
public void UploadMesh(Handle<Mesh> mesh, bool markMeshStatic)
|
||||
{
|
||||
ref var meshData = ref _resourceDatabase.GetMeshReference(mesh);
|
||||
var vertexState = _resourceDatabase.GetResourceState(meshData.vertexBuffer.AsResource());
|
||||
var indexState = _resourceDatabase.GetResourceState(meshData.indexBuffer.AsResource());
|
||||
ref var meshData = ref ResourceDatabase.GetMeshReference(mesh);
|
||||
var vertexState = ResourceDatabase.GetResourceState(meshData.vertexBuffer.AsResource());
|
||||
var indexState = ResourceDatabase.GetResourceState(meshData.indexBuffer.AsResource());
|
||||
var needVertexTransition = vertexState != ResourceState.CopyDest;
|
||||
var needIndexTransition = indexState != ResourceState.CopyDest;
|
||||
|
||||
if (needVertexTransition)
|
||||
{
|
||||
_copyCmb.ResourceBarrier(meshData.vertexBuffer.AsResource(), vertexState, ResourceState.CopyDest);
|
||||
_resourceDatabase.SetResourceState(meshData.vertexBuffer.AsResource(), ResourceState.CopyDest);
|
||||
ResourceDatabase.SetResourceState(meshData.vertexBuffer.AsResource(), ResourceState.CopyDest);
|
||||
}
|
||||
|
||||
if (needIndexTransition)
|
||||
{
|
||||
_copyCmb.ResourceBarrier(meshData.indexBuffer.AsResource(), indexState, ResourceState.CopyDest);
|
||||
_resourceDatabase.SetResourceState(meshData.indexBuffer.AsResource(), ResourceState.CopyDest);
|
||||
ResourceDatabase.SetResourceState(meshData.indexBuffer.AsResource(), ResourceState.CopyDest);
|
||||
}
|
||||
|
||||
_copyCmb.Upload(meshData.vertexBuffer, meshData.vertices.AsSpan());
|
||||
_copyCmb.Upload(meshData.indexBuffer, meshData.indices.AsSpan());
|
||||
_copyCmb.UploadBuffer<Vertex>(meshData.vertexBuffer, meshData.vertices.AsSpan());
|
||||
_copyCmb.UploadBuffer<uint>(meshData.indexBuffer, meshData.indices.AsSpan());
|
||||
|
||||
if (needVertexTransition)
|
||||
{
|
||||
_copyCmb.ResourceBarrier(meshData.vertexBuffer.AsResource(), ResourceState.CopyDest, vertexState);
|
||||
_resourceDatabase.SetResourceState(meshData.vertexBuffer.AsResource(), vertexState);
|
||||
ResourceDatabase.SetResourceState(meshData.vertexBuffer.AsResource(), vertexState);
|
||||
}
|
||||
|
||||
if (needIndexTransition)
|
||||
{
|
||||
_resourceDatabase.SetResourceState(meshData.indexBuffer.AsResource(), indexState);
|
||||
ResourceDatabase.SetResourceState(meshData.indexBuffer.AsResource(), indexState);
|
||||
_copyCmb.ResourceBarrier(meshData.indexBuffer.AsResource(), ResourceState.CopyDest, indexState);
|
||||
}
|
||||
|
||||
@@ -102,12 +121,12 @@ public unsafe readonly ref struct RenderingContext
|
||||
|
||||
public Handle<Texture> CreateTexture(ref readonly TextureDesc desc, bool tempResource = false)
|
||||
{
|
||||
return _resourceAllocator.CreateTexture(in desc, tempResource);
|
||||
return ResourceAllocator.CreateTexture(in desc, tempResource);
|
||||
}
|
||||
|
||||
public void UploadTexture(Handle<Texture> texture, ReadOnlySpan<byte> data)
|
||||
{
|
||||
var desc = _resourceDatabase.GetResourceDescription(texture.AsResource());
|
||||
var desc = ResourceDatabase.GetResourceDescription(texture.AsResource());
|
||||
desc.textureDescription.Format.GetSurfaceInfo((int)desc.textureDescription.Width, (int)desc.textureDescription.Height, out var rowPitch, out var slicePitch, out _);
|
||||
|
||||
var subresourceData = new SubResourceData
|
||||
@@ -117,78 +136,31 @@ public unsafe readonly ref struct RenderingContext
|
||||
slicePitch = slicePitch
|
||||
};
|
||||
|
||||
var sateBefore = _resourceDatabase.GetResourceState(texture.AsResource());
|
||||
var sateBefore = ResourceDatabase.GetResourceState(texture.AsResource());
|
||||
var needTransition = sateBefore != ResourceState.CopyDest;
|
||||
|
||||
if (needTransition)
|
||||
{
|
||||
_copyCmb.ResourceBarrier(texture.AsResource(), sateBefore, ResourceState.CopyDest);
|
||||
_resourceDatabase.SetResourceState(texture.AsResource(), ResourceState.CopyDest);
|
||||
ResourceDatabase.SetResourceState(texture.AsResource(), ResourceState.CopyDest);
|
||||
}
|
||||
|
||||
_copyCmb.Upload(texture, subresourceData);
|
||||
_copyCmb.UploadTexture(texture, subresourceData);
|
||||
|
||||
if (needTransition)
|
||||
{
|
||||
_copyCmb.ResourceBarrier(texture.AsResource(), ResourceState.CopyDest, sateBefore);
|
||||
_resourceDatabase.SetResourceState(texture.AsResource(), sateBefore);
|
||||
ResourceDatabase.SetResourceState(texture.AsResource(), sateBefore);
|
||||
}
|
||||
}
|
||||
#if false
|
||||
// TODO: Ideally we should queue the draw call to our rendering system, and render it in the full rendering pipeline.
|
||||
// This is just a place holder for now for testing purpose.
|
||||
// TODO: Since we are using mesh shader, we should use dispatch mesh instead of draw calls.
|
||||
public void RenderMesh(Handle<Mesh> mesh, Handle<Material> material, string passName)
|
||||
{
|
||||
ref var meshRef = ref _resourceDatabase.GetMeshReference(mesh);
|
||||
ref var materialRef = ref _resourceDatabase.GetMaterialReference(material);
|
||||
var shader = _resourceDatabase.GetShaderReference(materialRef.Shader);
|
||||
|
||||
shader.TryGetPassKey(passName, out var passIndex, out var passKey);
|
||||
var hash = new GraphicsPipelineHash
|
||||
{
|
||||
id = passKey,
|
||||
rtvCount = 1,
|
||||
dsvFormat = TextureFormat.Unknown,
|
||||
};
|
||||
|
||||
hash.rtvFormats[0] = TextureFormat.B8G8R8A8_UNorm;
|
||||
var pipelineKey = hash.GetKey();
|
||||
_directCmb.SetPipelineState(pipelineKey);
|
||||
|
||||
// FIX: Get valid root signature. In D3D12, we use fixed root signature layout for bindless rendering.
|
||||
// However, our code should not assume that blindly. Each pipeline should have contained root signature info even if there are fixed.
|
||||
// This ensures that future changes to root signature layout can be accommodated.
|
||||
|
||||
// for (int i = 0; i < 4; i++)
|
||||
{
|
||||
ref var cache = ref materialRef.GetPassCache(passIndex);
|
||||
_directCmb.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?
|
||||
#if false
|
||||
var samplerGpuHandle = _descriptorAllocator.GetSamplerHeap()->GetGPUDescriptorHandleForHeapStart();
|
||||
_commandList.Get()->SetGraphicsRootDescriptorTable(rootParamIndex, samplerGpuHandle);
|
||||
#endif
|
||||
_directCmb.SetPrimitiveTopology(PrimitiveTopology.Triangle);
|
||||
|
||||
// Draw without vertex/index buffers - use instanced drawing
|
||||
// Each instance represents a triangle (3 vertices)
|
||||
var triangleCount = (uint)meshRef.indices.Count / 3;
|
||||
_directCmb.Draw(3, triangleCount, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: Ideally we should queue the draw call to our rendering system, and render it in the full rendering pipeline.
|
||||
// This is just a place holder for now for testing purpose.
|
||||
// TODO: Since we are using mesh shader, we should use dispatch mesh instead of draw calls.
|
||||
public void DispatchMesh(Handle<Mesh> mesh, Handle<Material> material, string passName, uint numThreadsX)
|
||||
{
|
||||
ref var meshRef = ref _resourceDatabase.GetMeshReference(mesh);
|
||||
ref var materialRef = ref _resourceDatabase.GetMaterialReference(material);
|
||||
var shader = _resourceDatabase.GetShaderReference(materialRef.Shader);
|
||||
ref var meshRef = ref ResourceDatabase.GetMeshReference(mesh);
|
||||
ref var materialRef = ref ResourceDatabase.GetMaterialReference(material);
|
||||
var shader = ResourceDatabase.GetShaderReference(materialRef.Shader);
|
||||
|
||||
shader.TryGetPassKey(passName, out var passIndex, out var passKey);
|
||||
var hash = new GraphicsPipelineHash
|
||||
@@ -202,15 +174,9 @@ public unsafe readonly ref struct RenderingContext
|
||||
var pipelineKey = hash.GetKey();
|
||||
_directCmb.SetPipelineState(pipelineKey);
|
||||
|
||||
// FIX: Get valid root signature. In D3D12, we use fixed root signature layout for bindless rendering.
|
||||
// However, our code should not assume that blindly. Each pipeline should have contained root signature info even if there are fixed.
|
||||
// This ensures that future changes to root signature layout can be accommodated.
|
||||
|
||||
// for (int i = 0; i < 4; i++)
|
||||
{
|
||||
ref var cache = ref materialRef.GetPassCache(passIndex);
|
||||
_directCmb.SetConstantBufferView(RootSignatureLayout.PER_MATERIAL_BUFFER_SLOT, cache.GpuResource);
|
||||
}
|
||||
// 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);
|
||||
|
||||
// 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?
|
||||
@@ -222,10 +188,4 @@ public unsafe readonly ref struct RenderingContext
|
||||
var threadGroupCountX = ((uint)meshRef.indices.Count + numThreadsX - 1) / numThreadsX;
|
||||
_directCmb.DispatchMesh(threadGroupCountX, 1, 1);
|
||||
}
|
||||
|
||||
public void ExecuteCopyCommands()
|
||||
{
|
||||
_device.CopyQueue.Submit(_copyCmb);
|
||||
_device.CopyQueue.WaitIdle();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
// _commandList.Get()->DispatchRays();
|
||||
}
|
||||
|
||||
public void Upload<T>(Handle<GraphicsBuffer> buffer, ReadOnlySpan<T> data)
|
||||
public void UploadBuffer<T>(Handle<GraphicsBuffer> buffer, ReadOnlySpan<T> data)
|
||||
where T : unmanaged
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -422,7 +422,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
_commandList.Get()->CopyBufferRegion(pResource, 0, pUploadResource, 0, sizeInBytes);
|
||||
}
|
||||
|
||||
public void Upload(Handle<Texture> texture, params ReadOnlySpan<SubResourceData> subresources)
|
||||
public void UploadTexture(Handle<Texture> texture, params ReadOnlySpan<SubResourceData> subresources)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
ThrowIfNotRecording();
|
||||
|
||||
@@ -9,7 +9,7 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
|
||||
#endif
|
||||
|
||||
private readonly D3D12RenderDevice _device;
|
||||
private readonly D3D12PipelineLibrary _stateController;
|
||||
private readonly D3D12PipelineLibrary _pipelineLibrary;
|
||||
private readonly D3D12DescriptorAllocator _descriptorAllocator;
|
||||
|
||||
private readonly D3D12ResourceDatabase _resourceDatabase;
|
||||
@@ -17,13 +17,11 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
|
||||
|
||||
private readonly D3D12CommandBuffer _copyCommandBuffer;
|
||||
|
||||
|
||||
public IRenderDevice Device => _device;
|
||||
public IPipelineLibrary PipelineLibrary => _pipelineLibrary;
|
||||
public IResourceDatabase ResourceDatabase => _resourceDatabase;
|
||||
public IResourceAllocator ResourceAllocator => _resourceAllocator;
|
||||
|
||||
public IPipelineLibrary PipelineStateController => _stateController;
|
||||
|
||||
public D3D12GraphicsEngine(RenderSystem renderSystem)
|
||||
{
|
||||
#if DEBUG
|
||||
@@ -35,10 +33,10 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
|
||||
_resourceDatabase = new(_descriptorAllocator);
|
||||
_resourceAllocator = new(renderSystem, _device, _descriptorAllocator, _resourceDatabase);
|
||||
|
||||
_stateController = new(_device, _resourceDatabase, null);
|
||||
_pipelineLibrary = new(_device, _resourceDatabase);
|
||||
_copyCommandBuffer = new(
|
||||
_device,
|
||||
_stateController,
|
||||
_pipelineLibrary,
|
||||
_resourceDatabase,
|
||||
_resourceAllocator,
|
||||
_descriptorAllocator,
|
||||
@@ -59,7 +57,7 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
|
||||
{
|
||||
return new D3D12CommandBuffer(
|
||||
_device,
|
||||
_stateController,
|
||||
_pipelineLibrary,
|
||||
_resourceDatabase,
|
||||
_resourceAllocator,
|
||||
_descriptorAllocator,
|
||||
@@ -84,7 +82,7 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
|
||||
public void Dispose()
|
||||
{
|
||||
_copyCommandBuffer.Dispose();
|
||||
_stateController.Dispose();
|
||||
_pipelineLibrary.Dispose();
|
||||
|
||||
_resourceAllocator.Dispose();
|
||||
_resourceDatabase.Dispose();
|
||||
@@ -97,4 +95,4 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +184,21 @@ internal unsafe class D3D12Renderer : IRenderer
|
||||
{
|
||||
var clearColor = new Color128 { r = 1.0f, g = 0.0f, b = 1.0f, a = 1.0f };
|
||||
|
||||
cmd.BeginRenderPass(target, Handle<Texture>.Invalid, clearColor);
|
||||
Span<PassRenderTargetDesc> rtDesc = stackalloc PassRenderTargetDesc[1];
|
||||
rtDesc[0] = new PassRenderTargetDesc
|
||||
{
|
||||
texture = target,
|
||||
clearColor = clearColor,
|
||||
};
|
||||
|
||||
var depthDesc = new PassDepthStencilDesc
|
||||
{
|
||||
texture = Handle<Texture>.Invalid,
|
||||
clearDepth = 1.0f,
|
||||
clearStencil = 0,
|
||||
};
|
||||
|
||||
cmd.BeginRenderPass(rtDesc, depthDesc, false);
|
||||
|
||||
var viewport = new ViewportDesc { width = _currentSize.x, height = _currentSize.y, minDepth = 0, maxDepth = 1 };
|
||||
var scissor = new RectDesc { right = _currentSize.x, bottom = _currentSize.y };
|
||||
@@ -213,17 +227,12 @@ internal unsafe class D3D12Renderer : IRenderer
|
||||
// For now, we'll do a simple copy operation
|
||||
// In a real implementation, you would use a blit shader for post-processing
|
||||
|
||||
// TODO: Implement proper blit operation with shader
|
||||
// FIX: Implement proper blit operation with shader
|
||||
// This is a placeholder - in D3D12, you would typically:
|
||||
// 1. Set render target to the destination
|
||||
// 2. Use a full-screen quad/triangle with a shader that samples from the source
|
||||
// 3. Apply post-processing effects (tone mapping, gamma correction, etc.)
|
||||
|
||||
// For now, just clear the destination (this should be replaced with actual blit)
|
||||
var clearColor = new Color128 { r = 0.0f, g = 0.0f, b = 0.0f, a = 1.0f };
|
||||
cmd.BeginRenderPass(destination, Handle<Texture>.Invalid, clearColor);
|
||||
cmd.EndRenderPass();
|
||||
|
||||
// Handle swap chain back buffer transitions if needed
|
||||
if (_swapChain != null)
|
||||
{
|
||||
|
||||
@@ -90,12 +90,6 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
private struct Slot<T>
|
||||
{
|
||||
public T value;
|
||||
public bool occupied;
|
||||
}
|
||||
|
||||
private readonly D3D12DescriptorAllocator _descriptorAllocator;
|
||||
|
||||
private UnsafeSlotMap<ResourceRecord> _resources;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Core.Utilities;
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
@@ -204,11 +202,11 @@ internal static unsafe class D3D12ShaderCompiler
|
||||
using ComPtr<IDxcIncludeHandler> includeHandler = default;
|
||||
|
||||
// Create DXC compiler and utils
|
||||
var pDxcCompiler = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcCompiler);
|
||||
var pDxcUtils = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcUtils);
|
||||
var dxccID = CLSID.CLSID_DxcCompiler;
|
||||
var dxcuID = CLSID.CLSID_DxcUtils;
|
||||
|
||||
ThrowIfFailed(DxcCreateInstance(pDxcCompiler, compiler.IID(), compiler.PPV()));
|
||||
ThrowIfFailed(DxcCreateInstance(pDxcUtils, utils.IID(), utils.PPV()));
|
||||
ThrowIfFailed(DxcCreateInstance(&dxccID, compiler.IID(), compiler.PPV()));
|
||||
ThrowIfFailed(DxcCreateInstance(&dxcuID, utils.IID(), utils.PPV()));
|
||||
|
||||
//includeHandler.Get()->LoadSource();
|
||||
utils.Get()->CreateDefaultIncludeHandler(includeHandler.GetAddressOf());
|
||||
@@ -299,9 +297,9 @@ internal static unsafe class D3D12ShaderCompiler
|
||||
}
|
||||
|
||||
// Create DXC utils to parse reflection data
|
||||
var pDxcUtils = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcUtils);
|
||||
var dxcuID = CLSID.CLSID_DxcUtils;
|
||||
using ComPtr<IDxcUtils> utils = default;
|
||||
ThrowIfFailed(DxcCreateInstance(pDxcUtils, utils.IID(), utils.PPV()));
|
||||
ThrowIfFailed(DxcCreateInstance(&dxcuID, utils.IID(), utils.PPV()));
|
||||
|
||||
// Create reflection interface from blob
|
||||
var reflectionBuffer = new DxcBuffer
|
||||
|
||||
@@ -171,7 +171,7 @@ public interface ICommandBuffer : IDisposable
|
||||
/// <param name="buffer">A handle to the buffer that will receive the uploaded data.</param>
|
||||
/// <param name="data">A read-only span containing the data to upload to the buffer. The span must contain elements of type
|
||||
/// <typeparamref name="T"/>.</param>
|
||||
void Upload<T>(Handle<GraphicsBuffer> buffer, ReadOnlySpan<T> data)
|
||||
void UploadBuffer<T>(Handle<GraphicsBuffer> buffer, ReadOnlySpan<T> data)
|
||||
where T : unmanaged;
|
||||
|
||||
/// <summary>
|
||||
@@ -182,7 +182,7 @@ public interface ICommandBuffer : IDisposable
|
||||
/// <param name="subresources">A reference to the structure containing the subresource data to upload. The data must match the format and layout expected by the texture.</param>
|
||||
/// <param name="numSubresources">The number of subresources to upload, starting from <paramref name="firstSubresource"/>.
|
||||
/// Must be greater than zero and not exceed the remaining subresources in the texture.</param>
|
||||
void Upload(Handle<Texture> texture, params ReadOnlySpan<SubResourceData> subresources);
|
||||
void UploadTexture(Handle<Texture> texture, params ReadOnlySpan<SubResourceData> subresources);
|
||||
|
||||
/// <summary>
|
||||
/// Copies a specified number of bytes from the source graphics buffer to the destination graphics buffer.
|
||||
|
||||
@@ -2,44 +2,49 @@ namespace Ghost.Graphics.RHI;
|
||||
|
||||
public interface IGraphicsEngine : IDisposable
|
||||
{
|
||||
public IRenderDevice Device
|
||||
IRenderDevice Device
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public IResourceDatabase ResourceDatabase
|
||||
IPipelineLibrary PipelineLibrary
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public IResourceAllocator ResourceAllocator
|
||||
IResourceDatabase ResourceDatabase
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public IRenderer CreateRenderer();
|
||||
IResourceAllocator ResourceAllocator
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
IRenderer CreateRenderer();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a command buffer for recording rendering commands
|
||||
/// </summary>
|
||||
/// <param name="type">Type of command buffer to create</param>
|
||||
/// <returns>A new command buffer instance</returns>
|
||||
public ICommandBuffer CreateCommandBuffer(CommandBufferType type = CommandBufferType.Graphics);
|
||||
ICommandBuffer CreateCommandBuffer(CommandBufferType type = CommandBufferType.Graphics);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a swap chain for presentation
|
||||
/// </summary>
|
||||
/// <param name="desc">Swap chain description</param>
|
||||
/// <returns>A new swap chain instance</returns>
|
||||
public ISwapChain CreateSwapChain(SwapChainDesc desc);
|
||||
ISwapChain CreateSwapChain(SwapChainDesc desc);
|
||||
|
||||
/// <summary>
|
||||
/// Begins a new rendering frame, preparing the graphics context for drawing operations.
|
||||
/// </summary>
|
||||
public void BeginFrame();
|
||||
void BeginFrame();
|
||||
|
||||
/// <summary>
|
||||
/// Completes the current rendering frame and performs any necessary finalization steps.
|
||||
/// </summary>
|
||||
public void EndFrame();
|
||||
}
|
||||
void EndFrame();
|
||||
}
|
||||
|
||||
@@ -26,19 +26,19 @@ internal unsafe class MeshRenderPass : IRenderPass
|
||||
"C:/Users/Misaki/Downloads/Im/yande.re 1134666 blue_archive nakamasa_ichika sugarhigh.jpg"
|
||||
];
|
||||
|
||||
public void Initialize(ref readonly RenderingContext ctx, IResourceAllocator resourceAllocator, IPipelineLibrary pipelineLibrary)
|
||||
public void Initialize(ref readonly RenderingContext ctx)
|
||||
{
|
||||
var shaderDescriptor = SDLCompiler.CompileShader("F:\\csharp\\GhostEngine\\Ghost.Graphics\\RenderPasses\\ShaderCode.hlsl").GetValueOrThrow();
|
||||
|
||||
var key = pipelineLibrary.CompilePassPSO(shaderDescriptor.passes[0], [TextureFormat.B8G8R8A8_UNorm], TextureFormat.Unknown);
|
||||
var key = ctx.PipelineLibrary.CompilePassPSO(shaderDescriptor.passes[0], [TextureFormat.B8G8R8A8_UNorm], TextureFormat.Unknown);
|
||||
|
||||
MeshBuilder.CreateCube(0.75f, default, out var vertices, out var indices);
|
||||
|
||||
_mesh = ctx.CreateMesh(vertices, indices);
|
||||
ctx.UploadMesh(_mesh, true);
|
||||
|
||||
_shader = resourceAllocator.CreateShader(shaderDescriptor);
|
||||
_material = resourceAllocator.CreateMaterial(_shader);
|
||||
_shader = ctx.ResourceAllocator.CreateShader(shaderDescriptor);
|
||||
_material = ctx.ResourceAllocator.CreateMaterial(_shader);
|
||||
|
||||
var imageResults = new ImageResult[_textureFiles.Length];
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ shader "MyShader/Standard"
|
||||
properties
|
||||
{
|
||||
float4 color = float4(1, 1, 1, 1);
|
||||
texture2d texture1 = texture2d(black);
|
||||
texture2d texture2 = texture2d(white);
|
||||
texture2d texture3 = texture2d(grey);
|
||||
texture2d texture4 = texture2d(normal);
|
||||
tex2d_b texture1 = tex2d_b(black);
|
||||
tex2d_b texture2 = tex2d_b(white);
|
||||
tex2d_b texture3 = tex2d_b(grey);
|
||||
tex2d_b texture4 = tex2d_b(normal);
|
||||
}
|
||||
|
||||
pipeline
|
||||
@@ -28,4 +28,4 @@ shader "MyShader/Standard"
|
||||
"F:/csharp/GhostEngine/Ghost.Shader/BuiltIn/Common.hlsl";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
#undef USE_TRADITIONAL_BINDLESS // Just for testing, this should be handled by engine feature level.
|
||||
|
||||
|
||||
// Resource descriptor heap definitions
|
||||
|
||||
#if defined(USE_TRADITIONAL_BINDLESS)
|
||||
#define GLOBAL_TEXTURE2D_HEAP_SIZE 32768
|
||||
#define GLOBAL_TEXTURE3D_HEAP_SIZE 32
|
||||
@@ -27,6 +30,8 @@
|
||||
#endif
|
||||
|
||||
|
||||
// Bindless resource type definitions
|
||||
|
||||
#define TEXTURE2D_BINDLESS uint
|
||||
#define TEXTURE3D_BINDLESS uint
|
||||
#define TEXTURECUBE_BINDLESS uint
|
||||
@@ -38,6 +43,19 @@
|
||||
#define STRUCT_BUFFER_BINDLESS uint
|
||||
#define BYTE_ADDRESS_BUFFER_BINDLESS uint
|
||||
|
||||
#define TEXTURE2D Texture2D<float4>
|
||||
#define TEXTURE3D Texture3D<float4>
|
||||
#define TEXTURECUBE TextureCube<float4>
|
||||
#define TEXTURE2D_ARRAY Texture2DArray<float4>
|
||||
#define TEXTURECUBE_ARRAY TextureCubeArray<float4>
|
||||
|
||||
#define SAMPLER SamplerState
|
||||
|
||||
#define STRUCT_BUFFER(type) StructuredBuffer<type>
|
||||
#define BYTE_ADDRESS_BUFFER ByteAddressBuffer
|
||||
|
||||
|
||||
// Texture and sampler access macros
|
||||
|
||||
#define GET_TEXTURE2D_BINDLESS(id) GLOBAL_TEXTURE2D_HEAP[id]
|
||||
#define GET_TEXTURE2D_ARRAY_BINDLESS(id) GLOBAL_TEXTURE2D_ARRAY_HEAP[id]
|
||||
@@ -47,6 +65,8 @@
|
||||
#define GET_SAMPLER_BINDLESS(id) GLOBAL_SAMPLER_HEAP[id]
|
||||
|
||||
|
||||
// Texture sampling macros
|
||||
|
||||
#define SAMPLE_TEXTURE2D(tex, samp, uv) tex.Sample(samp, uv)
|
||||
#define SAMPLE_TEXTURE2D_LEVEL(tex, samp, uv, level) tex.SampleLevel(samp, uv, level)
|
||||
#define SAMPLE_TEXTURE2D_BINDLESS(texId, sampId, uv) GET_TEXTURE2D_BINDLESS(texId).Sample(GET_BINDLESS_SAMPLER(sampId), uv)
|
||||
@@ -55,4 +75,8 @@
|
||||
#define SAMPLE_TEXTURE2D_ARRAY(tex, samp, uv, index) tex.Sample(samp, uv, index)
|
||||
#define SAMPLE_TEXTURE2D_ARRAY_BINDLESS(texId, sampId, uv, index) GET_TEXTURE2D_ARRAY_BINDLESS(texId).Sample(GET_BINDLESS_SAMPLER(sampId), uv, index)
|
||||
|
||||
#endif // COMMON_HLSL
|
||||
|
||||
|
||||
#define MESH_SHADER_THREADS(x) [NumThreads(x, 1, 1)]
|
||||
|
||||
#endif // COMMON_HLSL
|
||||
|
||||
@@ -73,9 +73,9 @@ internal class PropertiesBlock : IBlockParser<PropertiesSyntax, List<PropertySem
|
||||
ParseBoolValue(syntax[3], errors))),
|
||||
|
||||
// Textures (single identifier argument)
|
||||
[ShaderPropertyType.Texture2D] = new(1, TokenType.Identifier, (syntax, errors) => ParseTextureDefault(syntax[0], errors)),
|
||||
[ShaderPropertyType.Texture3D] = new(1, TokenType.Identifier, (syntax, errors) => ParseTextureDefault(syntax[0], errors)),
|
||||
[ShaderPropertyType.TextureCube] = new(1, TokenType.Identifier, (syntax, errors) => ParseTextureDefault(syntax[0], errors)),
|
||||
[ShaderPropertyType.Texture2DBindless] = new(1, TokenType.Identifier, (syntax, errors) => ParseTextureDefault(syntax[0], errors)),
|
||||
[ShaderPropertyType.Texture3DBindless] = new(1, TokenType.Identifier, (syntax, errors) => ParseTextureDefault(syntax[0], errors)),
|
||||
[ShaderPropertyType.TextureCubeBindless] = new(1, TokenType.Identifier, (syntax, errors) => ParseTextureDefault(syntax[0], errors)),
|
||||
};
|
||||
|
||||
private static float ParseFloatValue(Token token, List<SDLError> errors)
|
||||
@@ -162,25 +162,25 @@ internal class PropertiesBlock : IBlockParser<PropertiesSyntax, List<PropertySem
|
||||
{
|
||||
return type.ToLower() switch
|
||||
{
|
||||
"float" => ShaderPropertyType.Float,
|
||||
"float2" => ShaderPropertyType.Float2,
|
||||
"float3" => ShaderPropertyType.Float3,
|
||||
"float4" => ShaderPropertyType.Float4,
|
||||
"int" => ShaderPropertyType.Int,
|
||||
"int2" => ShaderPropertyType.Int2,
|
||||
"int3" => ShaderPropertyType.Int3,
|
||||
"int4" => ShaderPropertyType.Int4,
|
||||
"uint" => ShaderPropertyType.UInt,
|
||||
"uint2" => ShaderPropertyType.UInt2,
|
||||
"uint3" => ShaderPropertyType.UInt3,
|
||||
"uint4" => ShaderPropertyType.UInt4,
|
||||
"bool" => ShaderPropertyType.Bool,
|
||||
"bool2" => ShaderPropertyType.Bool2,
|
||||
"bool3" => ShaderPropertyType.Bool3,
|
||||
"bool4" => ShaderPropertyType.Bool4,
|
||||
"texture2d" => ShaderPropertyType.Texture2D,
|
||||
"texture3d" => ShaderPropertyType.Texture3D,
|
||||
"texturecube" => ShaderPropertyType.TextureCube,
|
||||
TokenLexicon.KnownTypes.FLOAT => ShaderPropertyType.Float,
|
||||
TokenLexicon.KnownTypes.FLOAT2 => ShaderPropertyType.Float2,
|
||||
TokenLexicon.KnownTypes.FLOAT3 => ShaderPropertyType.Float3,
|
||||
TokenLexicon.KnownTypes.FLOAT4 => ShaderPropertyType.Float4,
|
||||
TokenLexicon.KnownTypes.INT => ShaderPropertyType.Int,
|
||||
TokenLexicon.KnownTypes.INT2 => ShaderPropertyType.Int2,
|
||||
TokenLexicon.KnownTypes.INT3 => ShaderPropertyType.Int3,
|
||||
TokenLexicon.KnownTypes.INT4 => ShaderPropertyType.Int4,
|
||||
TokenLexicon.KnownTypes.UINT => ShaderPropertyType.UInt,
|
||||
TokenLexicon.KnownTypes.UINT2 => ShaderPropertyType.UInt2,
|
||||
TokenLexicon.KnownTypes.UINT3 => ShaderPropertyType.UInt3,
|
||||
TokenLexicon.KnownTypes.UINT4 => ShaderPropertyType.UInt4,
|
||||
TokenLexicon.KnownTypes.BOOL => ShaderPropertyType.Bool,
|
||||
TokenLexicon.KnownTypes.BOOL2 => ShaderPropertyType.Bool2,
|
||||
TokenLexicon.KnownTypes.BOOL3 => ShaderPropertyType.Bool3,
|
||||
TokenLexicon.KnownTypes.BOOL4 => ShaderPropertyType.Bool4,
|
||||
TokenLexicon.KnownTypes.TEXTURE2D_BINDLESS => ShaderPropertyType.Texture2DBindless,
|
||||
TokenLexicon.KnownTypes.TEXTURE3D_BINDLESS => ShaderPropertyType.Texture3DBindless,
|
||||
TokenLexicon.KnownTypes.TEXTURECUBE_BINDLESS => ShaderPropertyType.TextureCubeBindless,
|
||||
_ => ShaderPropertyType.None,
|
||||
};
|
||||
}
|
||||
@@ -464,4 +464,4 @@ internal class PropertiesBlock : IBlockParser<PropertiesSyntax, List<PropertySem
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,11 +22,11 @@ internal static class SDLCompiler
|
||||
private const string _GLOBAL_PROPERTY_FILE_NAME = "GlobalData.g.hlsl";
|
||||
private const string _GENERATED_FILE_HEADER = "// Auto-generated shader file. Please do not edit this file directly.";
|
||||
|
||||
private struct ShaderInheritance
|
||||
{
|
||||
public SDLSemantics? parent;
|
||||
public List<ShaderInheritance>? children;
|
||||
}
|
||||
// private struct ShaderInheritance
|
||||
// {
|
||||
// public SDLSemantics? parent;
|
||||
// public List<ShaderInheritance>? children;
|
||||
// }
|
||||
|
||||
public static List<SDLSyntax> ParseShaders(TokenStream stream)
|
||||
{
|
||||
@@ -289,11 +289,11 @@ internal static class SDLCompiler
|
||||
ShaderPropertyType.Bool3 => "bool3",
|
||||
ShaderPropertyType.Bool4 => "bool4",
|
||||
// NOTE: Textures here are bindless, represented as uint (descriptor index).
|
||||
ShaderPropertyType.Texture2D => "TEXTURE2D_BINDLESS",
|
||||
ShaderPropertyType.Texture3D => "TEXTURE3D_BINDLESS",
|
||||
ShaderPropertyType.TextureCube => "TEXTURECUBE_BINDLESS",
|
||||
ShaderPropertyType.Texture2DArray => "TEXTURE2D_ARRAY_BINDLESS",
|
||||
ShaderPropertyType.TextureCubeArray => "TEXTURECUBE_ARRAY_BINDLESS",
|
||||
ShaderPropertyType.Texture2DBindless => "TEXTURE2D_BINDLESS",
|
||||
ShaderPropertyType.Texture3DBindless => "TEXTURE3D_BINDLESS",
|
||||
ShaderPropertyType.TextureCubeBindless => "TEXTURECUBE_BINDLESS",
|
||||
ShaderPropertyType.Texture2DArrayBindless => "TEXTURE2D_ARRAY_BINDLESS",
|
||||
ShaderPropertyType.TextureCubeArrayBindless => "TEXTURECUBE_ARRAY_BINDLESS",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), $"Unsupported shader property type: {type}")
|
||||
};
|
||||
}
|
||||
@@ -396,4 +396,4 @@ struct GlobalData
|
||||
GeneratePass(pass, targetDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,11 +170,11 @@ internal static class TokenLexicon
|
||||
public const string BOOL4 = "bool4";
|
||||
|
||||
// Texture types
|
||||
public const string TEXTURE2D = "texture2d";
|
||||
public const string TEXTURE2D_ARRAY = "texture2d_array";
|
||||
public const string TEXTURE3D = "texture3d";
|
||||
public const string TEXTURECUBE = "texturecube";
|
||||
public const string TEXTURECUBE_ARRAY = "texturecube_array";
|
||||
public const string TEXTURE2D_BINDLESS = "tex2d_b";
|
||||
public const string TEXTURE2D_ARRAY_BINDLESS = "tex2d_arr_b";
|
||||
public const string TEXTURE3D_BINDLESS = "tex3d_b";
|
||||
public const string TEXTURECUBE_BINDLESS = "texcube_b";
|
||||
public const string TEXTURECUBE_ARRAY_BINDLESS = "texcube_arr_b";
|
||||
}
|
||||
|
||||
public static class KnownTextureValue
|
||||
@@ -215,8 +215,8 @@ internal static class TokenLexicon
|
||||
KnownTypes.INT, KnownTypes.INT2, KnownTypes.INT3, KnownTypes.INT4,
|
||||
KnownTypes.UINT, KnownTypes.UINT2, KnownTypes.UINT3, KnownTypes.UINT4,
|
||||
KnownTypes.BOOL, KnownTypes.BOOL2, KnownTypes.BOOL3, KnownTypes.BOOL4,
|
||||
KnownTypes.TEXTURE2D, KnownTypes.TEXTURE2D_ARRAY, KnownTypes.TEXTURE3D,
|
||||
KnownTypes.TEXTURECUBE, KnownTypes.TEXTURECUBE_ARRAY,
|
||||
KnownTypes.TEXTURE2D_BINDLESS, KnownTypes.TEXTURE2D_ARRAY_BINDLESS, KnownTypes.TEXTURE3D_BINDLESS,
|
||||
KnownTypes.TEXTURECUBE_BINDLESS, KnownTypes.TEXTURECUBE_ARRAY_BINDLESS,
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> s_textureDefaultValues = new()
|
||||
|
||||
Reference in New Issue
Block a user