Files
GhostEngine/Ghost.Graphics/Data/Texture.cs
Misaki 74bb2ccda5 Refactor descriptor handling and shader compilation
Refactored descriptor allocation and release logic by introducing `IDescriptorAllocator` and replacing `DescriptorHeapAllocator` with `D3D12DescriptorHeap`. Updated descriptor structs to include validation properties and improved memory management with `ReadOnlySpan`.

Enhanced shader compilation by introducing `ShaderStage` and `CompilerVersion` enums, enabling more flexible and maintainable shader handling.

Refactored `Mesh` to use `IBuffer` for vertex and index buffers, added bindless descriptor support, and improved resource cleanup.

Updated `RenderSystem` and other components for better initialization, error handling, and disposal logic. General improvements to code readability and maintainability.
2025-09-13 20:07:29 +09:00

147 lines
4.4 KiB
C#

using Ghost.Graphics.D3D12;
using Win32.Graphics.Direct3D12;
using Win32.Graphics.Dxgi.Common;
namespace Ghost.Graphics.Data;
/// <summary>
/// Base class for all texture types in the graphics pipeline.
/// Provides common functionality for texture dimensions, format, and GPU resource management.
/// </summary>
public abstract unsafe class Texture : GraphicsResource
{
private readonly BindlessDescriptor _bindlessDescriptor;
/// <summary>
/// Width of the texture in pixels.
/// </summary>
public uint Width
{
get;
}
/// <summary>
/// Height of the texture in pixels.
/// </summary>
public uint Height
{
get;
}
/// <summary>
/// Number of bytes per pixel for the texture format.
/// </summary>
public uint BytesPerPixel
{
get;
}
/// <summary>
/// Format of the texture.
/// </summary>
public Format Format
{
get;
}
/// <summary>
/// The index of this texture in the global bindless descriptor heap.
/// </summary>
public uint DescriptorIndex => _bindlessDescriptor.Index;
internal Texture(uint width, uint height, Format format, in TextureHandle handle, BindlessDescriptor bindlessDescriptor)
: base(handle.ResourceHandle)
{
Width = width;
Height = height;
BytesPerPixel = GetBytesPerPixel(format);
Format = format;
_bindlessDescriptor = bindlessDescriptor;
}
/// <summary>
/// Creates a bindless shader resource view descriptor for the texture.
/// </summary>
protected static BindlessDescriptor CreateBindlessShaderResourceView(ID3D12Resource* resource, Format format)
{
var device = GraphicsPipeline.GraphicsDevice.NativeDevice.Ptr;
var bindlessDescriptor = GraphicsPipeline.DescriptorAllocator.AllocateBindless();
var srvDesc = new ShaderResourceViewDescription
{
Format = format,
ViewDimension = SrvDimension.Texture2D,
Texture2D = new Texture2DSrv { MipLevels = 1 },
Shader4ComponentMapping = 0x1688 // D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING
};
device->CreateShaderResourceView(resource, &srvDesc, bindlessDescriptor.CpuHandle);
return bindlessDescriptor;
}
/// <summary>
/// Gets the bytes per pixel for the specified format.
/// </summary>
private static uint GetBytesPerPixel(Format format)
{
return format switch
{
Format.R8G8B8A8Unorm => 4,
Format.R8G8B8A8UnormSrgb => 4,
Format.B8G8R8A8Unorm => 4,
Format.B8G8R8A8UnormSrgb => 4,
Format.R8G8B8A8Uint => 4,
Format.R8G8B8A8Sint => 4,
Format.R8G8B8A8Snorm => 4,
Format.R8G8Unorm => 2,
Format.R8G8Uint => 2,
Format.R8G8Sint => 2,
Format.R8G8Snorm => 2,
Format.R8Unorm => 1,
Format.R8Uint => 1,
Format.R8Sint => 1,
Format.R8Snorm => 1,
Format.A8Unorm => 1,
Format.R16G16B16A16Float => 8,
Format.R16G16B16A16Unorm => 8,
Format.R16G16B16A16Uint => 8,
Format.R16G16B16A16Sint => 8,
Format.R16G16B16A16Snorm => 8,
Format.R32G32B32A32Float => 16,
Format.R32G32B32A32Uint => 16,
Format.R32G32B32A32Sint => 16,
Format.R32G32B32Float => 12,
Format.R32G32B32Uint => 12,
Format.R32G32B32Sint => 12,
Format.R32G32Float => 8,
Format.R32G32Uint => 8,
Format.R32G32Sint => 8,
Format.R32Float => 4,
Format.R32Uint => 4,
Format.R32Sint => 4,
Format.R16G16Float => 4,
Format.R16G16Unorm => 4,
Format.R16G16Uint => 4,
Format.R16G16Sint => 4,
Format.R16G16Snorm => 4,
Format.R16Float => 2,
Format.R16Unorm => 2,
Format.R16Uint => 2,
Format.R16Sint => 2,
Format.R16Snorm => 2,
Format.D32Float => 4,
Format.D24UnormS8Uint => 4,
Format.D16Unorm => 2,
_ => throw new NotSupportedException($"Format {format} is not supported.")
};
}
/// <summary>
/// Disposes the texture resources.
/// </summary>
public override void Dispose()
{
base.Dispose();
GraphicsPipeline.DescriptorAllocator.Release(_bindlessDescriptor);
}
}