forked from Misaki/GhostEngine
Add Ghost.Nvtt C# wrapper and integrate nvtt texture pipeline
- Introduce full managed C# wrapper for NVIDIA Texture Tools (nvtt) with safe handle classes, idiomatic APIs, and managed callback support. - Integrate Ghost.Nvtt into Ghost.Editor.Core and Ghost.MicroTest; update TextureAssetHandler to use the new nvtt wrapper for texture compression. - Add comprehensive end-to-end binding test (NvttBindingTest). - Refactor D3D12 resource management: add deferred/immediate release APIs, update allocator/database usage, and ensure proper resource cleanup. - Update project files for new native DLL layout and dependency versions. - Minor API cleanups: EditorApplication properties, D3D12 input layout, and removal of obsolete code. - Update shaders, tests, and documentation for new APIs and usage patterns.
This commit is contained in:
@@ -35,10 +35,9 @@ internal struct CBufferCache : IResourceReleasable
|
||||
}
|
||||
|
||||
_cpuData.Dispose();
|
||||
database.ScheduleReleaseResource(_gpuResource.AsResource());
|
||||
|
||||
database.ReleaseResource(GpuResource.AsResource());
|
||||
_gpuResource = Handle<GraphicsBuffer>.Invalid;
|
||||
|
||||
_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,9 +117,9 @@ public struct Mesh : IResourceReleasable
|
||||
{
|
||||
ReleaseCpuResources();
|
||||
|
||||
database.ReleaseResource(VertexBuffer.AsResource());
|
||||
database.ReleaseResource(IndexBuffer.AsResource());
|
||||
database.ReleaseResource(ObjectDataBuffer.AsResource());
|
||||
database.ScheduleReleaseResource(VertexBuffer.AsResource());
|
||||
database.ScheduleReleaseResource(IndexBuffer.AsResource());
|
||||
database.ScheduleReleaseResource(ObjectDataBuffer.AsResource());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,9 +47,9 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
_shaderCompiler = new DxcShaderCompiler();
|
||||
_descriptorAllocator = new D3D12DescriptorAllocator(_device);
|
||||
|
||||
_resourceDatabase = new D3D12ResourceDatabase(_descriptorAllocator);
|
||||
_resourceDatabase = new D3D12ResourceDatabase(renderSystem, _descriptorAllocator);
|
||||
_pipelineLibrary = new D3D12PipelineLibrary(_device, _resourceDatabase);
|
||||
_resourceAllocator = new D3D12ResourceAllocator(renderSystem, _device, _descriptorAllocator, _resourceDatabase, _pipelineLibrary);
|
||||
_resourceAllocator = new D3D12ResourceAllocator(_device, _descriptorAllocator, _resourceDatabase, _pipelineLibrary);
|
||||
|
||||
_renderers = ImmutableArray<IRenderer>.Empty;
|
||||
|
||||
@@ -127,7 +127,7 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
}
|
||||
}
|
||||
|
||||
_resourceAllocator.ReleaseTempResources();
|
||||
_resourceDatabase.EndFrame();
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -144,6 +144,8 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
renderer.Dispose();
|
||||
}
|
||||
|
||||
_resourceDatabase.ReleaseAllResourcesImmediately();
|
||||
|
||||
_resourceAllocator.Dispose();
|
||||
_pipelineLibrary.Dispose();
|
||||
_resourceDatabase.Dispose();
|
||||
|
||||
@@ -5,11 +5,8 @@ using Ghost.Graphics.Core;
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
@@ -454,21 +451,18 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
|
||||
private UniquePtr<D3D12MA_Allocator> _d3d12MA;
|
||||
|
||||
private readonly IFenceSynchronizer _fenceSynchronizer;
|
||||
private readonly D3D12RenderDevice _device;
|
||||
private readonly D3D12DescriptorAllocator _descriptorAllocator;
|
||||
private readonly D3D12ResourceDatabase _resourceDatabase;
|
||||
private readonly D3D12PipelineLibrary _pipelineLibrary;
|
||||
|
||||
private UnsafeQueue<Handle<GPUResource>> _tempResources;
|
||||
|
||||
// TODO: We should use ring buffer pool in d3d12ma for upload buffer.
|
||||
private readonly Handle<GraphicsBuffer> _uploadBatch;
|
||||
private ulong _uploadBatchOffset;
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public D3D12ResourceAllocator(
|
||||
IFenceSynchronizer fenceSynchronizer,
|
||||
D3D12RenderDevice device,
|
||||
D3D12DescriptorAllocator descriptorAllocator,
|
||||
D3D12ResourceDatabase resourceDatabase,
|
||||
@@ -485,14 +479,11 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
ThrowIfFailed(D3D12MA_CreateAllocator(&desc, &pAllocator));
|
||||
_d3d12MA.Attach(pAllocator);
|
||||
|
||||
_fenceSynchronizer = fenceSynchronizer;
|
||||
_device = device;
|
||||
_descriptorAllocator = descriptorAllocator;
|
||||
_resourceDatabase = resourceDatabase;
|
||||
_pipelineLibrary = pipelineLibrary;
|
||||
|
||||
_tempResources = new UnsafeQueue<Handle<GPUResource>>(64, Allocator.Persistent);
|
||||
|
||||
// Create an upload batch
|
||||
var uploadDesc = new BufferDesc
|
||||
{
|
||||
@@ -513,13 +504,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private Handle<GPUResource> TrackAllocation(D3D12MA_Allocation* allocation, ResourceBarrierData barrierData, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string name, bool isTemp)
|
||||
{
|
||||
var handle = _resourceDatabase.AddAllocation(allocation, _fenceSynchronizer.CPUFenceValue, barrierData, resourceDescriptor, desc, name);
|
||||
|
||||
if (isTemp)
|
||||
{
|
||||
_tempResources.Enqueue(handle);
|
||||
}
|
||||
|
||||
var handle = _resourceDatabase.AddAllocation(allocation, barrierData, resourceDescriptor, desc, name);
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -844,7 +829,10 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
};
|
||||
|
||||
offset = 0;
|
||||
return CreateBuffer(in bufferDesc, "TempUploadBuffer", options);
|
||||
var handle = CreateBuffer(in bufferDesc, "TempUploadBuffer", options);
|
||||
|
||||
_resourceDatabase.ScheduleReleaseResource(handle.AsResource());
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -943,35 +931,6 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
return _resourceDatabase.AddShader(shader);
|
||||
}
|
||||
|
||||
public void ReleaseTempResources()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
while (_tempResources.Count > 0)
|
||||
{
|
||||
var handle = _tempResources.Peek();
|
||||
var r = _resourceDatabase.GetResourceRecord(handle);
|
||||
if (r.IsFailure || !r.Value.Allocated)
|
||||
{
|
||||
// Resource already released or invalid, just dequeue
|
||||
_tempResources.Dequeue();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r.Value.cpuFenceValue > _fenceSynchronizer.GPUFenceValue)
|
||||
{
|
||||
// Resource still in use by GPU, stop processing.
|
||||
// Since resources are enqueued in order, we can break here.
|
||||
break;
|
||||
}
|
||||
|
||||
_resourceDatabase.ReleaseResource(handle);
|
||||
_tempResources.Dequeue();
|
||||
}
|
||||
|
||||
_uploadBatchOffset = 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
@@ -979,17 +938,8 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Assert(_tempResources.Count == 0, "Temporary resources should be released before disposing the allocator.");
|
||||
|
||||
foreach (var handle in _tempResources)
|
||||
{
|
||||
_resourceDatabase.ReleaseResource(handle);
|
||||
}
|
||||
|
||||
_resourceDatabase.ReleaseResource(_uploadBatch.AsResource());
|
||||
|
||||
_resourceDatabase.ReleaseResourceImmediately(_uploadBatch.AsResource());
|
||||
_d3d12MA.Dispose();
|
||||
_tempResources.Dispose();
|
||||
|
||||
_disposed = true;
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
@@ -6,8 +6,6 @@ using Misaki.HighPerformance.Collections;
|
||||
using Misaki.HighPerformance.LowLevel;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using TerraFX.Interop.DirectX;
|
||||
|
||||
@@ -43,19 +41,17 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
|
||||
public ResourceBarrierData barrierData;
|
||||
|
||||
public uint cpuFenceValue;
|
||||
public readonly bool isExternal;
|
||||
|
||||
public readonly bool Allocated => isExternal ? resource.resource.Get() != null : resource.allocation.Get() != null;
|
||||
public readonly SharedPtr<ID3D12Resource> ResourcePtr => isExternal ? resource.resource.Get() : resource.allocation.Get()->GetResource();
|
||||
|
||||
public ResourceRecord(D3D12MA_Allocation* allocation, uint cpuFenceValue, ResourceBarrierData barrierData, ResourceViewGroup resourceDescriptor, ResourceDesc desc)
|
||||
public ResourceRecord(D3D12MA_Allocation* allocation, ResourceBarrierData barrierData, ResourceViewGroup resourceDescriptor, ResourceDesc desc)
|
||||
{
|
||||
this.resource = new ResourceUnion(allocation);
|
||||
this.isExternal = false;
|
||||
|
||||
this.viewGroup = resourceDescriptor;
|
||||
this.cpuFenceValue = cpuFenceValue;
|
||||
this.barrierData = barrierData;
|
||||
this.desc = desc;
|
||||
}
|
||||
@@ -66,7 +62,6 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
this.isExternal = true;
|
||||
|
||||
this.viewGroup = viewGroup;
|
||||
this.cpuFenceValue = ~0u;
|
||||
this.barrierData = barrierData;
|
||||
this.desc = resource->GetDesc().ToResourceDesc();
|
||||
}
|
||||
@@ -91,6 +86,19 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
}
|
||||
}
|
||||
|
||||
private readonly struct ReleaseEntry
|
||||
{
|
||||
public readonly ResourceRecord record;
|
||||
public readonly uint fenceValue;
|
||||
|
||||
public ReleaseEntry(ResourceRecord record, uint fenceValue)
|
||||
{
|
||||
this.record = record;
|
||||
this.fenceValue = fenceValue;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly IFenceSynchronizer _fenceSynchronizer;
|
||||
private readonly D3D12DescriptorAllocator _descriptorAllocator;
|
||||
|
||||
private UnsafeSlotMap<ResourceRecord> _resources;
|
||||
@@ -103,10 +111,13 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
private UnsafeSlotMap<Material> _materials;
|
||||
private readonly DynamicArray<Shader> _shaders; // TODO: Use SlotMap?
|
||||
|
||||
private UnsafeQueue<ReleaseEntry> _releaseQueue;
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public D3D12ResourceDatabase(D3D12DescriptorAllocator descriptorAllocator)
|
||||
public D3D12ResourceDatabase(IFenceSynchronizer fenceSynchronizer, D3D12DescriptorAllocator descriptorAllocator)
|
||||
{
|
||||
_fenceSynchronizer = fenceSynchronizer;
|
||||
_descriptorAllocator = descriptorAllocator;
|
||||
|
||||
_resources = new UnsafeSlotMap<ResourceRecord>(64, Allocator.Persistent, AllocationOption.Clear);
|
||||
@@ -117,6 +128,8 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
_meshes = new UnsafeSlotMap<Mesh>(64, Allocator.Persistent, AllocationOption.Clear);
|
||||
_materials = new UnsafeSlotMap<Material>(16, Allocator.Persistent, AllocationOption.Clear);
|
||||
_shaders = new DynamicArray<Shader>(16);
|
||||
|
||||
_releaseQueue = new UnsafeQueue<ReleaseEntry>(32, Allocator.Persistent);
|
||||
}
|
||||
|
||||
~D3D12ResourceDatabase()
|
||||
@@ -124,14 +137,13 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private void ReleaseResource<T>(ref T resource)
|
||||
private void ReleaseResource<T>(T resource)
|
||||
where T : IResourceReleasable
|
||||
{
|
||||
resource.ReleaseResource(this);
|
||||
resource = default!;
|
||||
}
|
||||
|
||||
public unsafe Handle<GPUResource> ImportExternalResource(ID3D12Resource* pResource, ResourceBarrierData initialBarrierData, ResourceViewGroup viewGroup, string? name = null)
|
||||
internal unsafe Handle<GPUResource> ImportExternalResource(ID3D12Resource* pResource, ResourceBarrierData initialBarrierData, ResourceViewGroup viewGroup, string? name = null)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
@@ -157,7 +169,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
return handle;
|
||||
}
|
||||
|
||||
public unsafe Handle<GPUResource> AddAllocation(D3D12MA_Allocation* allocation, uint cpuFenceValue, ResourceBarrierData initialBarrierData, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string? name = null)
|
||||
public unsafe Handle<GPUResource> AddAllocation(D3D12MA_Allocation* allocation, ResourceBarrierData initialBarrierData, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string? name = null)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
if (allocation == null)
|
||||
@@ -168,7 +180,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
return Handle<GPUResource>.Invalid;
|
||||
}
|
||||
|
||||
var id = _resources.Add(new ResourceRecord(allocation, cpuFenceValue, initialBarrierData, resourceDescriptor, desc), out var generation);
|
||||
var id = _resources.Add(new ResourceRecord(allocation, initialBarrierData, resourceDescriptor, desc), out var generation);
|
||||
var handle = new Handle<GPUResource>(id, generation);
|
||||
|
||||
#if DEBUG || GHOST_EDITOR
|
||||
@@ -281,16 +293,29 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
return null;
|
||||
}
|
||||
|
||||
// FIX: This should be queued to be released after GPU is done with it.
|
||||
public void ReleaseResource(Handle<GPUResource> handle)
|
||||
public void ScheduleReleaseResource(Handle<GPUResource> handle)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
if (!handle.IsValid)
|
||||
if (_resources.TryGetElementAt(handle.ID, handle.Generation, out var record))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var entry = new ReleaseEntry(record, _fenceSynchronizer.CPUFenceValue);
|
||||
|
||||
_releaseQueue.Enqueue(entry);
|
||||
_resources.Remove(handle.ID, handle.Generation);
|
||||
|
||||
#if DEBUG || GHOST_EDITOR
|
||||
_resourceName.Remove(handle, out var name);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void ReleaseResourceImmediately(Handle<GPUResource> handle)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
ref var info = ref _resources.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
|
||||
if (!exist || !info.Allocated)
|
||||
{
|
||||
@@ -298,10 +323,6 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
}
|
||||
|
||||
info.Release(_descriptorAllocator);
|
||||
#if DEBUG || GHOST_EDITOR
|
||||
_resourceName.Remove(handle, out var name);
|
||||
#endif
|
||||
|
||||
_resources.Remove(handle.ID, handle.Generation);
|
||||
}
|
||||
|
||||
@@ -370,7 +391,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseResource(ref mesh);
|
||||
ReleaseResource(mesh);
|
||||
_meshes.Remove(handle.ID, handle.Generation);
|
||||
}
|
||||
|
||||
@@ -409,7 +430,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseResource(ref material);
|
||||
ReleaseResource(material);
|
||||
_materials.Remove(handle.ID, handle.Generation);
|
||||
}
|
||||
|
||||
@@ -448,49 +469,64 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
}
|
||||
|
||||
ref var shader = ref _shaders[id.Value]!;
|
||||
ReleaseResource(ref shader);
|
||||
ReleaseResource(shader);
|
||||
}
|
||||
|
||||
public void EndFrame()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
while (_releaseQueue.Count > 0)
|
||||
{
|
||||
var toRelease = _releaseQueue.Peek();
|
||||
if (toRelease.fenceValue > _fenceSynchronizer.GPUFenceValue)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_releaseQueue.Dequeue();
|
||||
|
||||
toRelease.record.Release(_descriptorAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ReleaseAllResourcesImmediately()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
foreach (var mesh in _meshes)
|
||||
{
|
||||
ReleaseResource(mesh);
|
||||
}
|
||||
|
||||
foreach (var material in _materials)
|
||||
{
|
||||
ReleaseResource(material);
|
||||
}
|
||||
|
||||
foreach (var shader in _shaders)
|
||||
{
|
||||
ReleaseResource(shader);
|
||||
}
|
||||
|
||||
foreach (ref var record in _resources)
|
||||
{
|
||||
record.Release(_descriptorAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
[DoesNotReturn]
|
||||
[Conditional("DEBUG")]
|
||||
static void ThrowMemoryLeakException(string resourceType, int count)
|
||||
{
|
||||
throw new MemoryLeakException($"ResourceAllocator is being disposed with {count} {resourceType} still registered. Ensure all resources are released before disposing.");
|
||||
}
|
||||
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_resources.Count > 0)
|
||||
{
|
||||
ThrowMemoryLeakException("GPU resources", _resources.Count);
|
||||
}
|
||||
|
||||
if (_meshes.Count > 0)
|
||||
{
|
||||
ThrowMemoryLeakException("meshes", _meshes.Count);
|
||||
}
|
||||
|
||||
if (_materials.Count > 0)
|
||||
{
|
||||
ThrowMemoryLeakException("materials", _materials.Count);
|
||||
}
|
||||
|
||||
// DSL are reference space, it will be managed by GC, so we don't throw exception here.
|
||||
for (var i = 0; i < _shaders.Count; i++)
|
||||
{
|
||||
ref var shader = ref _shaders[i];
|
||||
ReleaseResource(ref shader);
|
||||
}
|
||||
|
||||
_resources.Dispose();
|
||||
_samplers.Dispose();
|
||||
_meshes.Dispose();
|
||||
_materials.Dispose();
|
||||
_releaseQueue.Dispose();
|
||||
|
||||
_disposed = true;
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
// Release old back buffers and render targets
|
||||
for (var i = 0; i < _backBuffers.Count; i++)
|
||||
{
|
||||
_resourceDatabase.ReleaseResource(_backBuffers[i].AsResource());
|
||||
_resourceDatabase.ReleaseResourceImmediately(_backBuffers[i].AsResource());
|
||||
}
|
||||
|
||||
ThrowIfFailed(_swapChain.Get()->ResizeBuffers((uint)_backBuffers.Count, width, height, DXGI_FORMAT_B8G8R8A8_UNORM, (uint)DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING));
|
||||
@@ -252,7 +252,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
|
||||
for (var i = 0; i < _backBuffers.Count; i++)
|
||||
{
|
||||
_resourceDatabase.ReleaseResource(_backBuffers[i].AsResource());
|
||||
_resourceDatabase.ScheduleReleaseResource(_backBuffers[i].AsResource());
|
||||
}
|
||||
|
||||
_backBuffers.Dispose();
|
||||
|
||||
@@ -7,11 +7,11 @@ namespace Ghost.Graphics.D3D12.Utilities;
|
||||
internal unsafe static class D3D12PipelineResource
|
||||
{
|
||||
private readonly static D3D12_INPUT_ELEMENT_DESC[] s_inputElementDescs = [
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Position.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 0u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Normal.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 16u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Tangent.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 32u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Uv.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 48u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Color.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 64u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Position.GetUnsafePtr(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 0u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Normal.GetUnsafePtr(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 16u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Tangent.GetUnsafePtr(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 32u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Uv.GetUnsafePtr(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 48u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Color.GetUnsafePtr(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 64u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
];
|
||||
|
||||
public const DXGI_FORMAT SWAP_CHAIN_BACK_BUFFER_FORMAT = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
@@ -17,15 +17,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="runtime\win-x64\native\dxcompiler.dll" />
|
||||
<None Remove="runtime\win-x64\native\dxil.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="runtime\win-x64\native\dxcompiler.dll">
|
||||
<Content Include="runtimes\win-x64\native\dxcompiler.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="runtime\win-x64\native\dxil.dll">
|
||||
<Content Include="runtimes\win-x64\native\dxil.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram />
|
||||
@@ -96,10 +96,16 @@ public interface IResourceDatabase : IDisposable
|
||||
string? GetResourceName(Handle<GPUResource> handle);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a resource from the database using its handle.
|
||||
/// Releases the GPU resource associated with the specified handle, freeing any resources allocated to it.
|
||||
/// </summary>
|
||||
/// <param name="handle">The handle of the resource to be removed.</param>
|
||||
void ReleaseResource(Handle<GPUResource> handle);
|
||||
void ScheduleReleaseResource(Handle<GPUResource> handle);
|
||||
|
||||
/// <summary>
|
||||
/// Releases the GPU resource associated with the specified handle immediately, freeing any resources allocated to it.
|
||||
/// </summary>
|
||||
/// <param name="handle">The handle of the resource to be removed.</param>
|
||||
void ReleaseResourceImmediately(Handle<GPUResource> handle);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves an existing sampler identifier that matches the specified description, or creates a new one if none
|
||||
|
||||
@@ -212,10 +212,10 @@ internal sealed class RenderGraphCompiler
|
||||
continue;
|
||||
}
|
||||
|
||||
_graphicsEngine.ResourceDatabase.ReleaseResource(res.backingResource);
|
||||
_graphicsEngine.ResourceDatabase.ScheduleReleaseResource(res.backingResource);
|
||||
}
|
||||
|
||||
_graphicsEngine.ResourceDatabase.ReleaseResource(_resourceHeap);
|
||||
_graphicsEngine.ResourceDatabase.ScheduleReleaseResource(_resourceHeap);
|
||||
}
|
||||
|
||||
if (_aliasingManager.Heap.size == 0)
|
||||
@@ -380,11 +380,11 @@ internal sealed class RenderGraphCompiler
|
||||
{
|
||||
if (!res.isImported)
|
||||
{
|
||||
_graphicsEngine.ResourceDatabase.ReleaseResource(res.backingResource);
|
||||
_graphicsEngine.ResourceDatabase.ScheduleReleaseResource(res.backingResource);
|
||||
}
|
||||
}
|
||||
|
||||
_graphicsEngine.ResourceDatabase.ReleaseResource(_resourceHeap);
|
||||
_graphicsEngine.ResourceDatabase.ScheduleReleaseResource(_resourceHeap);
|
||||
_resourceHeap = Handle<GPUResource>.Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@ internal class MeshRenderPass : IRenderPass
|
||||
{
|
||||
foreach (var texture in _textures)
|
||||
{
|
||||
resourceDatabase.ReleaseResource(texture.AsResource());
|
||||
resourceDatabase.ScheduleReleaseResource(texture.AsResource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +265,6 @@ internal class RenderSystem : IRenderSystem
|
||||
// Sync the current frame resource to this new fence to keep state consistent
|
||||
frameResource.FenceValue = flushFence;
|
||||
|
||||
|
||||
foreach (var resource in _frameResources)
|
||||
{
|
||||
resource.CommandAllocator.Reset();
|
||||
|
||||
@@ -19,9 +19,9 @@ shader "Hidden/Blit"
|
||||
|
||||
includes
|
||||
{
|
||||
"F:/csharp/GhostEngine/src/Runtime//Ghost.Graphics/Shaders/Includes/Common.hlsl";
|
||||
"F:/csharp/GhostEngine/src/Runtime//Ghost.Graphics/Shaders/Includes/Color.hlsl";
|
||||
"F:/csharp/GhostEngine/src/Runtime//Ghost.Graphics/Shaders/Includes/Properties.hlsl";
|
||||
"F:/csharp/GhostEngine/src/Runtime/Ghost.Graphics/Shaders/Includes/Common.hlsl";
|
||||
"F:/csharp/GhostEngine/src/Runtime/Ghost.Graphics/Shaders/Includes/Color.hlsl";
|
||||
"F:/csharp/GhostEngine/src/Runtime/Ghost.Graphics/Shaders/Includes/Properties.hlsl";
|
||||
}
|
||||
|
||||
hlsl
|
||||
|
||||
Reference in New Issue
Block a user