326 lines
8.6 KiB
C#
326 lines
8.6 KiB
C#
using System;
|
|
using RefreshCS;
|
|
|
|
namespace Nerfed.Runtime.Graphics;
|
|
|
|
/// <summary>
|
|
/// A multi-dimensional data container that can be efficiently used by the GPU.
|
|
/// </summary>
|
|
public class Texture : RefreshResource
|
|
{
|
|
public uint Width { get; internal set; }
|
|
public uint Height { get; internal set; }
|
|
public uint Depth { get; }
|
|
public TextureFormat Format { get; internal set; }
|
|
public bool IsCube { get; }
|
|
public uint LayerCount { get; }
|
|
public uint LevelCount { get; }
|
|
public SampleCount SampleCount { get; }
|
|
public TextureUsageFlags UsageFlags { get; }
|
|
public uint Size { get; }
|
|
|
|
private string name;
|
|
public string Name
|
|
{
|
|
get => name;
|
|
|
|
set
|
|
{
|
|
if (Device.DebugMode)
|
|
{
|
|
Refresh.Refresh_SetTextureName(
|
|
Device.Handle,
|
|
Handle,
|
|
value
|
|
);
|
|
}
|
|
|
|
name = value;
|
|
}
|
|
}
|
|
|
|
// FIXME: this allocates a delegate instance
|
|
protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_ReleaseTexture;
|
|
|
|
/// <summary>
|
|
/// Creates a 2D texture.
|
|
/// </summary>
|
|
/// <param name="device">An initialized GraphicsDevice.</param>
|
|
/// <param name="width">The width of the texture.</param>
|
|
/// <param name="height">The height of the texture.</param>
|
|
/// <param name="format">The format of the texture.</param>
|
|
/// <param name="usageFlags">Specifies how the texture will be used.</param>
|
|
/// <param name="levelCount">Specifies the number of mip levels.</param>
|
|
public static Texture CreateTexture2D(
|
|
GraphicsDevice device,
|
|
uint width,
|
|
uint height,
|
|
TextureFormat format,
|
|
TextureUsageFlags usageFlags,
|
|
uint levelCount = 1,
|
|
SampleCount sampleCount = SampleCount.One
|
|
) {
|
|
TextureCreateInfo textureCreateInfo = new TextureCreateInfo
|
|
{
|
|
Width = width,
|
|
Height = height,
|
|
Depth = 1,
|
|
IsCube = false,
|
|
LayerCount = 1,
|
|
LevelCount = levelCount,
|
|
SampleCount = sampleCount,
|
|
Format = format,
|
|
UsageFlags = usageFlags
|
|
};
|
|
|
|
return new Texture(device, textureCreateInfo);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a 2D texture array.
|
|
/// </summary>
|
|
/// <param name="device">An initialized GraphicsDevice.</param>
|
|
/// <param name="width">The width of the texture.</param>
|
|
/// <param name="height">The height of the texture.</param>
|
|
/// <param name="layerCount">The layer count of the texture.</param>
|
|
/// <param name="format">The format of the texture.</param>
|
|
/// <param name="usageFlags">Specifies how the texture will be used.</param>
|
|
/// <param name="levelCount">Specifies the number of mip levels.</param>
|
|
public static Texture CreateTexture2DArray(
|
|
GraphicsDevice device,
|
|
uint width,
|
|
uint height,
|
|
uint layerCount,
|
|
TextureFormat format,
|
|
TextureUsageFlags usageFlags,
|
|
uint levelCount = 1
|
|
) {
|
|
TextureCreateInfo textureCreateInfo = new TextureCreateInfo
|
|
{
|
|
Width = width,
|
|
Height = height,
|
|
Depth = 1,
|
|
IsCube = false,
|
|
LayerCount = layerCount,
|
|
LevelCount = levelCount,
|
|
Format = format,
|
|
UsageFlags = usageFlags
|
|
};
|
|
|
|
return new Texture(device, textureCreateInfo);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a 3D texture.
|
|
/// Note that the width, height and depth all form one slice and cannot be subdivided in a texture slice.
|
|
/// </summary>
|
|
public static Texture CreateTexture3D(
|
|
GraphicsDevice device,
|
|
uint width,
|
|
uint height,
|
|
uint depth,
|
|
TextureFormat format,
|
|
TextureUsageFlags usageFlags,
|
|
uint levelCount = 1
|
|
) {
|
|
TextureCreateInfo textureCreateInfo = new TextureCreateInfo
|
|
{
|
|
Width = width,
|
|
Height = height,
|
|
Depth = depth,
|
|
IsCube = false,
|
|
LayerCount = 1,
|
|
LevelCount = levelCount,
|
|
Format = format,
|
|
UsageFlags = usageFlags
|
|
};
|
|
|
|
return new Texture(device, textureCreateInfo);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a cube texture.
|
|
/// </summary>
|
|
/// <param name="device">An initialized GraphicsDevice.</param>
|
|
/// <param name="size">The length of one side of the cube.</param>
|
|
/// <param name="format">The format of the texture.</param>
|
|
/// <param name="usageFlags">Specifies how the texture will be used.</param>
|
|
/// <param name="levelCount">Specifies the number of mip levels.</param>
|
|
public static Texture CreateTextureCube(
|
|
GraphicsDevice device,
|
|
uint size,
|
|
TextureFormat format,
|
|
TextureUsageFlags usageFlags,
|
|
uint levelCount = 1
|
|
) {
|
|
TextureCreateInfo textureCreateInfo = new TextureCreateInfo
|
|
{
|
|
Width = size,
|
|
Height = size,
|
|
Depth = 1,
|
|
IsCube = true,
|
|
LayerCount = 6,
|
|
LevelCount = levelCount,
|
|
Format = format,
|
|
UsageFlags = usageFlags
|
|
};
|
|
|
|
return new Texture(device, textureCreateInfo);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new texture using a TextureCreateInfo struct.
|
|
/// </summary>
|
|
/// <param name="device">An initialized GraphicsDevice.</param>
|
|
/// <param name="textureCreateInfo">The parameters to use when creating the texture.</param>
|
|
public Texture(
|
|
GraphicsDevice device,
|
|
in TextureCreateInfo textureCreateInfo
|
|
) : base(device)
|
|
{
|
|
Handle = Refresh.Refresh_CreateTexture(
|
|
device.Handle,
|
|
textureCreateInfo.ToRefresh()
|
|
);
|
|
|
|
Format = textureCreateInfo.Format;
|
|
Width = textureCreateInfo.Width;
|
|
Height = textureCreateInfo.Height;
|
|
Depth = textureCreateInfo.Depth;
|
|
IsCube = textureCreateInfo.IsCube;
|
|
LayerCount = textureCreateInfo.LayerCount;
|
|
LevelCount = textureCreateInfo.LevelCount;
|
|
SampleCount = textureCreateInfo.SampleCount;
|
|
UsageFlags = textureCreateInfo.UsageFlags;
|
|
Size = Width * Height * BytesPerPixel(Format) / BlockSizeSquared(Format);
|
|
name = "";
|
|
}
|
|
|
|
// Used by Window. Swapchain texture handles are managed by the driver backend.
|
|
internal Texture(
|
|
GraphicsDevice device,
|
|
TextureFormat format
|
|
) : base(device)
|
|
{
|
|
Handle = IntPtr.Zero;
|
|
|
|
Format = format;
|
|
Width = 0;
|
|
Height = 0;
|
|
Depth = 1;
|
|
IsCube = false;
|
|
LevelCount = 1;
|
|
SampleCount = SampleCount.One;
|
|
UsageFlags = TextureUsageFlags.ColorTarget;
|
|
Size = Width * Height * BytesPerPixel(Format) / BlockSizeSquared(Format);
|
|
}
|
|
|
|
public static uint BytesPerPixel(TextureFormat format)
|
|
{
|
|
switch (format)
|
|
{
|
|
case TextureFormat.R8:
|
|
case TextureFormat.R8_UINT:
|
|
return 1;
|
|
case TextureFormat.R5G6B5:
|
|
case TextureFormat.B4G4R4A4:
|
|
case TextureFormat.A1R5G5B5:
|
|
case TextureFormat.R16_SFLOAT:
|
|
case TextureFormat.R8G8_SNORM:
|
|
case TextureFormat.R8G8_UINT:
|
|
case TextureFormat.R16_UINT:
|
|
case TextureFormat.D16_UNORM:
|
|
return 2;
|
|
case TextureFormat.R8G8B8A8:
|
|
case TextureFormat.B8G8R8A8:
|
|
case TextureFormat.R32_SFLOAT:
|
|
case TextureFormat.R16G16:
|
|
case TextureFormat.R16G16_SFLOAT:
|
|
case TextureFormat.R8G8B8A8_SNORM:
|
|
case TextureFormat.A2R10G10B10:
|
|
case TextureFormat.R8G8B8A8_UINT:
|
|
case TextureFormat.R16G16_UINT:
|
|
case TextureFormat.D24_UNORM_S8_UINT:
|
|
case TextureFormat.D32_SFLOAT:
|
|
return 4;
|
|
case TextureFormat.D32_SFLOAT_S8_UINT:
|
|
return 5;
|
|
case TextureFormat.R16G16B16A16_SFLOAT:
|
|
case TextureFormat.R16G16B16A16:
|
|
case TextureFormat.R32G32_SFLOAT:
|
|
case TextureFormat.R16G16B16A16_UINT:
|
|
case TextureFormat.BC1:
|
|
return 8;
|
|
case TextureFormat.R32G32B32A32_SFLOAT:
|
|
case TextureFormat.BC2:
|
|
case TextureFormat.BC3:
|
|
case TextureFormat.BC7:
|
|
return 16;
|
|
default:
|
|
Log.Error("Texture format not recognized!");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public static uint TexelSize(TextureFormat format)
|
|
{
|
|
switch (format)
|
|
{
|
|
case TextureFormat.BC2:
|
|
case TextureFormat.BC3:
|
|
case TextureFormat.BC7:
|
|
return 16;
|
|
case TextureFormat.BC1:
|
|
return 8;
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
public static uint BlockSizeSquared(TextureFormat format)
|
|
{
|
|
switch (format)
|
|
{
|
|
case TextureFormat.BC1:
|
|
case TextureFormat.BC2:
|
|
case TextureFormat.BC3:
|
|
case TextureFormat.BC7:
|
|
return 16;
|
|
case TextureFormat.R8G8B8A8:
|
|
case TextureFormat.B8G8R8A8:
|
|
case TextureFormat.R5G6B5:
|
|
case TextureFormat.A1R5G5B5:
|
|
case TextureFormat.B4G4R4A4:
|
|
case TextureFormat.A2R10G10B10:
|
|
case TextureFormat.R16G16:
|
|
case TextureFormat.R16G16B16A16:
|
|
case TextureFormat.R8:
|
|
case TextureFormat.R8G8_SNORM:
|
|
case TextureFormat.R8G8B8A8_SNORM:
|
|
case TextureFormat.R16_SFLOAT:
|
|
case TextureFormat.R16G16_SFLOAT:
|
|
case TextureFormat.R16G16B16A16_SFLOAT:
|
|
case TextureFormat.R32_SFLOAT:
|
|
case TextureFormat.R32G32_SFLOAT:
|
|
case TextureFormat.R32G32B32A32_SFLOAT:
|
|
case TextureFormat.R8_UINT:
|
|
case TextureFormat.R8G8_UINT:
|
|
case TextureFormat.R8G8B8A8_UINT:
|
|
case TextureFormat.R16_UINT:
|
|
case TextureFormat.R16G16_UINT:
|
|
case TextureFormat.R16G16B16A16_UINT:
|
|
case TextureFormat.D16_UNORM:
|
|
case TextureFormat.D24_UNORM:
|
|
case TextureFormat.D24_UNORM_S8_UINT:
|
|
case TextureFormat.D32_SFLOAT:
|
|
case TextureFormat.D32_SFLOAT_S8_UINT:
|
|
return 1;
|
|
default:
|
|
Log.Error("Texture format not recognized!");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public static implicit operator TextureSlice(Texture t) => new TextureSlice(t);
|
|
public static implicit operator TextureRegion(Texture t) => new TextureRegion(t);
|
|
} |