mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Added support for Cube Textures, Improved dds import (and textures in general), Texture refactoring and DX11 DeviceContext synchronization
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
AssetLoader = "EditorTextureAssetLoader",
|
||||||
|
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
|
||||||
|
_isSrgb = true,
|
||||||
|
_samplerStateDescription = {
|
||||||
|
MinFilter = .Linear,
|
||||||
|
MagFilter = .Linear,
|
||||||
|
MipFilter = .Linear,
|
||||||
|
ComparisonFunction = .Never,
|
||||||
|
AddressModeU = .Clamp,
|
||||||
|
AddressModeV = .Clamp,
|
||||||
|
AddressModeW = .Clamp,
|
||||||
|
MipMinLOD = -Infinity,
|
||||||
|
MipMaxLOD = Infinity,
|
||||||
|
MaxAnisotropy = 1,
|
||||||
|
BorderColor = {
|
||||||
|
R = 1,
|
||||||
|
G = 1,
|
||||||
|
B = 1,
|
||||||
|
A = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,526 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using GlitchyEngine;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace GlitchyEditor.Assets.Importers;
|
||||||
|
|
||||||
|
// Based on https://github.com/Diron-P/DDSReader/blob/main/dds_loader.h
|
||||||
|
|
||||||
|
public struct LoadedSurface
|
||||||
|
{
|
||||||
|
public Span<uint8> Data;
|
||||||
|
public uint32 Pitch;
|
||||||
|
public uint32 SlicePitch;
|
||||||
|
|
||||||
|
public int ArrayIndex;
|
||||||
|
public int CubeFace;
|
||||||
|
public int MipLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct LoadedTextureInfo
|
||||||
|
{
|
||||||
|
public enum Dimension
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Texture1D,
|
||||||
|
Texture2D,
|
||||||
|
Texture3D
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint8[] PixelData = null;
|
||||||
|
public DirectX.DXGI.Format PixelFormat = .Unknown;
|
||||||
|
public int MipMapCount = 0;
|
||||||
|
public int ArraySize = 0;
|
||||||
|
public Dimension Dimension = .Unknown;
|
||||||
|
public bool IsCubeMap;
|
||||||
|
|
||||||
|
public int Width;
|
||||||
|
public int Height;
|
||||||
|
public int Depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DdsImporter
|
||||||
|
{
|
||||||
|
private const uint32 MagicWord = 0x20534444; // 'DDS
|
||||||
|
|
||||||
|
public enum LoadError
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
WrongMagicWord,
|
||||||
|
StreamReadFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum HeaderFlags : uint32
|
||||||
|
{
|
||||||
|
/// Required in every .dds file.
|
||||||
|
DDSD_CAPS = 0x1,
|
||||||
|
/// Required in every .dds file.
|
||||||
|
DDSD_HEIGHT = 0x2,
|
||||||
|
/// Required in every .dds file.
|
||||||
|
DDSD_WIDTH = 0x4,
|
||||||
|
/// Required in every .dds file.
|
||||||
|
DDSD_PITCH = 0x8,
|
||||||
|
/// Required in every .dds file.
|
||||||
|
DDSD_PIXELFORMAT = 0x1000,
|
||||||
|
/// Required in a mipmapped texture.
|
||||||
|
DDSD_MIPMAPCOUNT = 0x20000,
|
||||||
|
/// Required when pitch is provided for a compressed texture.
|
||||||
|
DDSD_LINEARSIZE = 0x80000,
|
||||||
|
/// Required in a depth texture.
|
||||||
|
DDSD_DEPTH = 0x800000
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum Caps1 : uint32
|
||||||
|
{
|
||||||
|
/// Should be set, when the file contains multiple surfaces (e.g. Cubemaps or Mipmaps).
|
||||||
|
Complex = 0x8,
|
||||||
|
/// Should be set, if the file contains mipmaps.
|
||||||
|
MipMap = 0x400000,
|
||||||
|
/// Should always be set.
|
||||||
|
Texture = 0x1000
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowDuplicates]
|
||||||
|
private enum Caps2 : uint32
|
||||||
|
{
|
||||||
|
Cubemap = 0x200,
|
||||||
|
Cubemap_PositiveX = 0x400,
|
||||||
|
Cubemap_NegativeX = 0x800,
|
||||||
|
Cubemap_X = Cubemap_PositiveX | Cubemap_NegativeX,
|
||||||
|
Cubemap_PositiveY = 0x1000,
|
||||||
|
Cubemap_NegativeY = 0x2000,
|
||||||
|
Cubemap_Y = Cubemap_PositiveY | Cubemap_NegativeY,
|
||||||
|
Cubemap_PositiveZ = 0x4000,
|
||||||
|
Cubemap_NegativeZ = 0x8000,
|
||||||
|
Cubemap_Z = Cubemap_PositiveZ | Cubemap_NegativeZ,
|
||||||
|
/// This is the flag that should be set for Cubemaps in DX10+
|
||||||
|
Cubemap_AllFaces = Cubemap | Cubemap_X | Cubemap_Y | Cubemap_Z,
|
||||||
|
|
||||||
|
Volume = 0x200000,
|
||||||
|
}
|
||||||
|
|
||||||
|
[CRepr]
|
||||||
|
private struct DdsHeader
|
||||||
|
{
|
||||||
|
/// Size of this structure. This member must be set to 124.
|
||||||
|
private uint32 Size;
|
||||||
|
/// Flags to indicate which members contain valid data.
|
||||||
|
public HeaderFlags Flags;
|
||||||
|
/// Surface height (in pixels).
|
||||||
|
public uint32 Height;
|
||||||
|
/// Surface width (in pixels).
|
||||||
|
public uint32 Width;
|
||||||
|
public uint32 PitchOrLinearSize;
|
||||||
|
/// Depth of a volume texture (in pixels), otherwise unused.
|
||||||
|
public uint32 Depth;
|
||||||
|
/// Number of mipmap levels, otherwise unused.
|
||||||
|
public uint32 MipMapCount;
|
||||||
|
/// Unused.
|
||||||
|
private uint32[11] Reserved1;
|
||||||
|
/// The pixel format.
|
||||||
|
public DdsPixelFormat PixelFormat;
|
||||||
|
public Caps1 Caps;
|
||||||
|
public Caps2 Caps2;
|
||||||
|
/// Unused.
|
||||||
|
private uint32 dwCaps3;
|
||||||
|
/// Unused.
|
||||||
|
private uint32 dwCaps4;
|
||||||
|
/// Unused.
|
||||||
|
private uint32 dwReserved2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum SurfaceType : uint32
|
||||||
|
{
|
||||||
|
/// Texture contains alpha data; dwRGBAlphaBitMask contains valid data.
|
||||||
|
AlphaPixels = 0x1,
|
||||||
|
/// Used in some older DDS files for alpha channel only uncompressed data (dwRGBBitCount contains the alpha channel bitcount; dwABitMask contains valid data)
|
||||||
|
Alpha = 0x2,
|
||||||
|
|
||||||
|
/// Texture contains compressed RGB data; dwFourCC contains valid data.
|
||||||
|
FourCC = 0x4,
|
||||||
|
/// Texture contains uncompressed RGB data; dwRGBBitCount and the RGB masks (dwRBitMask, dwGBitMask, dwBBitMask) contain valid data.
|
||||||
|
RGB = 0x40,
|
||||||
|
|
||||||
|
RGBA = RGB | AlphaPixels,
|
||||||
|
|
||||||
|
/// Used in some older DDS files for YUV uncompressed data (dwRGBBitCount contains the YUV bit count;
|
||||||
|
/// dwRBitMask contains the Y mask, dwGBitMask contains the U mask, dwBBitMask contains the V mask)
|
||||||
|
YUV = 0x200,
|
||||||
|
|
||||||
|
/// Used in some older DDS files for single channel color uncompressed data (dwRGBBitCount contains the luminance channel bit count;
|
||||||
|
/// dwRBitMask contains the channel mask). Can be combined with DDPF_ALPHAPIXELS for a two channel DDS file.
|
||||||
|
Luminance = 0x20000
|
||||||
|
}
|
||||||
|
|
||||||
|
private static uint32 MakeFourCC(char8 c0, char8 c1, char8 c2, char8 c3)
|
||||||
|
{
|
||||||
|
return ((uint32)c3 << 24 | (uint32) c2 << 16 | (uint32) c1 << 8 | (uint32) c0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*private enum FourCC : uint32
|
||||||
|
{
|
||||||
|
DXT1 = MakeFourCC('D', 'X', 'T', '1'),
|
||||||
|
DXT2 = MakeFourCC('D', 'X', 'T', '2'),
|
||||||
|
DXT3 = MakeFourCC('D', 'X', 'T', '3'),
|
||||||
|
DXT4 = MakeFourCC('D', 'X', 'T', '4'),
|
||||||
|
DXT5 = MakeFourCC('D', 'X', 'T', '5'),
|
||||||
|
/// indicates the prescense of the DDS_HEADER_DXT10 extended header
|
||||||
|
DX10 = MakeFourCC('D', 'X', '1', '0'),
|
||||||
|
}*/
|
||||||
|
|
||||||
|
[CRepr]
|
||||||
|
private struct DdsPixelFormat
|
||||||
|
{
|
||||||
|
/// Structure size; set to 32 (bytes).
|
||||||
|
private uint32 Size;
|
||||||
|
/// Values which indicate what type of data is in the surface.
|
||||||
|
public SurfaceType SurfaceType;
|
||||||
|
public uint32 FourCC;
|
||||||
|
/// Number of bits in an RGB (possibly including alpha) format. Valid when dwFlags includes DDPF_RGB, DDPF_LUMINANCE, or DDPF_YUV.
|
||||||
|
public uint32 RGBBitCount;
|
||||||
|
/// Red (or luminance or Y) mask for reading color data. For instance, given the A8R8G8B8 format, the red mask would be 0x00ff0000.
|
||||||
|
public uint32 RBitMask;
|
||||||
|
/// Green (or U) mask for reading color data. For instance, given the A8R8G8B8 format, the green mask would be 0x0000ff00.
|
||||||
|
public uint32 GBitMask;
|
||||||
|
/// Blue (or V) mask for reading color data. For instance, given the A8R8G8B8 format, the blue mask would be 0x000000ff.
|
||||||
|
public uint32 BBitMask;
|
||||||
|
/// Alpha mask for reading alpha data. dwFlags must include DDPF_ALPHAPIXELS or DDPF_ALPHA. For instance, given the A8R8G8B8 format, the alpha mask would be 0xff000000.
|
||||||
|
public uint32 ABitMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ResourceDimensions : uint32
|
||||||
|
{
|
||||||
|
Texture1D = 2,
|
||||||
|
Texture2D = 3,
|
||||||
|
Texture3D = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MiscFlags : uint32
|
||||||
|
{
|
||||||
|
TextureCube = 0x4,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AlphaMode : uint32
|
||||||
|
{
|
||||||
|
Unknown = 0x0,
|
||||||
|
Straight = 0x1,
|
||||||
|
Premultiplied = 0x2,
|
||||||
|
Opaque = 0x3,
|
||||||
|
/// Any alpha channel content is being used as a 4th channel and is not intended to represent transparency (straight or premultiplied).
|
||||||
|
Custom = 0x4
|
||||||
|
}
|
||||||
|
|
||||||
|
/// DDS header extension to handle resource arrays, DXGI pixel formats that don't map to the legacy Microsoft DirectDraw pixel format structures, and additional metadata.
|
||||||
|
[CRepr]
|
||||||
|
private struct DdsDxt10Header
|
||||||
|
{
|
||||||
|
public DirectX.DXGI.Format PixelFormat;
|
||||||
|
public ResourceDimensions ResourceDimension;
|
||||||
|
public MiscFlags MiscFlags;
|
||||||
|
/// Number of elements in the array. For a 2D cubemap this is the number of cubes, so the file contains ArraySize * 6 2D textures.
|
||||||
|
/// For a 3D Texture this must be 1.
|
||||||
|
public uint32 ArraySize;
|
||||||
|
|
||||||
|
public AlphaMode AlphaMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Result<void, LoadError> DecodeHeader(Stream data, out DdsHeader header, out DdsDxt10Header? extendedHeader)
|
||||||
|
{
|
||||||
|
header = ?;
|
||||||
|
extendedHeader = null;
|
||||||
|
|
||||||
|
// Check the magic word
|
||||||
|
Result<uint32> magicWord = data.Read<uint32>();
|
||||||
|
|
||||||
|
if (magicWord case .Err)
|
||||||
|
return .Err(.StreamReadFailed);
|
||||||
|
|
||||||
|
if (magicWord != MagicWord)
|
||||||
|
return .Err(.WrongMagicWord);
|
||||||
|
|
||||||
|
// Load the header
|
||||||
|
Result<DdsHeader> headerResult = data.Read<DdsHeader>();
|
||||||
|
|
||||||
|
if (headerResult case .Err)
|
||||||
|
return .Err(.StreamReadFailed);
|
||||||
|
|
||||||
|
header = headerResult;
|
||||||
|
|
||||||
|
// If available, load the extended header
|
||||||
|
if (header.PixelFormat.SurfaceType.HasFlag(.FourCC) && header.PixelFormat.FourCC == MakeFourCC('D', 'X', '1', '0'))
|
||||||
|
{
|
||||||
|
Result<DdsDxt10Header> extendedHeaderResult = data.Read<DdsDxt10Header>();
|
||||||
|
|
||||||
|
if (headerResult case .Err)
|
||||||
|
return .Err(.StreamReadFailed);
|
||||||
|
|
||||||
|
extendedHeader = extendedHeaderResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsBitMask(DdsPixelFormat ddspf, uint32 rBitMask, uint32 gBitMask, uint32 bBitMask, uint32 aBitMask)
|
||||||
|
{
|
||||||
|
return ddspf.RBitMask == rBitMask && ddspf.GBitMask == gBitMask && ddspf.BBitMask == bBitMask && ddspf.ABitMask == aBitMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DirectX.DXGI.Format GetFormat(in DdsHeader header, in DdsDxt10Header? extendedheader, bool isSrgb)
|
||||||
|
{
|
||||||
|
if (extendedheader != null)
|
||||||
|
return extendedheader.Value.PixelFormat;
|
||||||
|
|
||||||
|
DdsPixelFormat pixelFormat = header.PixelFormat;
|
||||||
|
|
||||||
|
// Currently supports only basic dxgi formats.
|
||||||
|
if (pixelFormat.SurfaceType.HasFlag(.RGBA))
|
||||||
|
{
|
||||||
|
switch (pixelFormat.RGBBitCount)
|
||||||
|
{
|
||||||
|
case 32:
|
||||||
|
if (IsBitMask(pixelFormat, 0xFF, 0xFF00, 0xFF0000, 0xFF000000))
|
||||||
|
return isSrgb ? .R8G8B8A8_UNorm_SRGB : .R8G8B8A8_UNorm;
|
||||||
|
|
||||||
|
if (IsBitMask(pixelFormat, 0xffff, 0xffff0000, 0x0, 0x0))
|
||||||
|
return .R16G16_UNorm;
|
||||||
|
|
||||||
|
if (IsBitMask(pixelFormat, 0x3ff, 0xffc00, 0x3ff00000, 0x0))
|
||||||
|
return .R10G10B10A2_UNorm;
|
||||||
|
case 16:
|
||||||
|
if (IsBitMask(pixelFormat, 0x7c00, 0x3e0, 0x1f, 0x8000))
|
||||||
|
return .B5G5R5A1_UNorm;
|
||||||
|
default:
|
||||||
|
return .Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pixelFormat.SurfaceType.HasFlag(.RGB))
|
||||||
|
{
|
||||||
|
switch (pixelFormat.RGBBitCount)
|
||||||
|
{
|
||||||
|
case 32:
|
||||||
|
if (IsBitMask(pixelFormat, 0xffff, 0xffff0000, 0x0, 0x0))
|
||||||
|
return .R16G16_UNorm;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
if (IsBitMask(pixelFormat, 0xf800, 0x7e0, 0x1f, 0x0))
|
||||||
|
return .B5G6R5_UNorm;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return .Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pixelFormat.SurfaceType.HasFlag(.FourCC))
|
||||||
|
{
|
||||||
|
switch (pixelFormat.FourCC)
|
||||||
|
{
|
||||||
|
case MakeFourCC('D', 'X', 'T', '1'):
|
||||||
|
return isSrgb ? .BC1_UNorm_SRGB : .BC1_UNorm;
|
||||||
|
case MakeFourCC('D', 'X', 'T', '3'):
|
||||||
|
return isSrgb ? .BC2_UNorm_SRGB : .BC2_UNorm;
|
||||||
|
case MakeFourCC('D', 'X', 'T', '5'):
|
||||||
|
return isSrgb ? .BC3_UNorm_SRGB : .BC3_UNorm;
|
||||||
|
// Legacy compression formats.
|
||||||
|
case MakeFourCC('B', 'C', '4', 'U'), MakeFourCC('A', 'T', 'I', '1'):
|
||||||
|
return .BC4_UNorm;
|
||||||
|
case MakeFourCC('A', 'T', 'I', '2'):
|
||||||
|
return .BC5_UNorm;
|
||||||
|
case MakeFourCC('R', 'G', 'B', 'G'):
|
||||||
|
return .R8G8_B8G8_UNorm;
|
||||||
|
case MakeFourCC('G', 'R', 'G', 'B'):
|
||||||
|
return .G8R8_G8B8_UNorm;
|
||||||
|
case 36:
|
||||||
|
return .R16G16B16A16_UNorm;
|
||||||
|
case 111:
|
||||||
|
return .R16_Float;
|
||||||
|
case 112:
|
||||||
|
return .R16G16_Float;
|
||||||
|
case 113:
|
||||||
|
return .R16G16B16A16_Float;
|
||||||
|
case 114:
|
||||||
|
return .R32_Float;
|
||||||
|
case 115:
|
||||||
|
return .R32G32_Float;
|
||||||
|
case 116:
|
||||||
|
return .R32G32B32A32_Float;
|
||||||
|
default:
|
||||||
|
return .Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result<void, LoadError> LoadDds(Stream data, bool isSrgb, List<LoadedSurface> surfaces, out LoadedTextureInfo textureInfo)
|
||||||
|
{
|
||||||
|
textureInfo = .();
|
||||||
|
|
||||||
|
var headerResult = DecodeHeader(data, let header, let extendedHeader);
|
||||||
|
|
||||||
|
if (headerResult case .Err)
|
||||||
|
return headerResult;
|
||||||
|
|
||||||
|
int surfaceCount = 1;
|
||||||
|
|
||||||
|
if (header.Flags.HasFlag(.DDSD_MIPMAPCOUNT) || header.MipMapCount != 0)
|
||||||
|
{
|
||||||
|
if (header.MipMapCount == 0)
|
||||||
|
Log.EngineLogger.Warning("Mipmap count is zero, even though the flags say it shouldn't.");
|
||||||
|
|
||||||
|
if (!header.Flags.HasFlag(.DDSD_MIPMAPCOUNT))
|
||||||
|
Log.EngineLogger.Warning("Mipmap count is not zero, even though the mipmap count flag isn't set.");
|
||||||
|
|
||||||
|
textureInfo.MipMapCount = header.MipMapCount;
|
||||||
|
surfaceCount *= textureInfo.MipMapCount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textureInfo.MipMapCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extendedHeader != null)
|
||||||
|
{
|
||||||
|
textureInfo.ArraySize = extendedHeader.Value.ArraySize;
|
||||||
|
surfaceCount *= textureInfo.ArraySize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textureInfo.ArraySize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.Caps2.HasFlag(.Cubemap))
|
||||||
|
{
|
||||||
|
if (!header.Caps2.HasFlag(.Cubemap_AllFaces))
|
||||||
|
Log.EngineLogger.Warning("Texture might only contains partial cubemap, this is not allowed. (Defined Cubemap-Flag, but not all cubemap faces)");
|
||||||
|
|
||||||
|
surfaceCount *= 6;
|
||||||
|
textureInfo.IsCubeMap = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
textureInfo.PixelFormat = GetFormat(header, extendedHeader, isSrgb);
|
||||||
|
|
||||||
|
textureInfo.Width = header.Width;
|
||||||
|
textureInfo.Height = header.Height;
|
||||||
|
textureInfo.Depth = header.Depth;
|
||||||
|
|
||||||
|
switch (extendedHeader?.ResourceDimension)
|
||||||
|
{
|
||||||
|
case .Texture1D:
|
||||||
|
textureInfo.Dimension = .Texture1D;
|
||||||
|
case .Texture2D:
|
||||||
|
textureInfo.Dimension = .Texture2D;
|
||||||
|
case .Texture3D:
|
||||||
|
textureInfo.Dimension = .Texture3D;
|
||||||
|
case null:
|
||||||
|
if (header.Flags.HasFlag(.DDSD_DEPTH))
|
||||||
|
textureInfo.Dimension = .Texture3D;
|
||||||
|
else
|
||||||
|
textureInfo.Dimension = .Texture2D;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have enough space in the list (avoid allocations later)
|
||||||
|
surfaces.Reserve(surfaceCount);
|
||||||
|
|
||||||
|
uint32 scanLineSize = 0;
|
||||||
|
uint32 slicePitch = 0;
|
||||||
|
uint32 numBytes = 0;
|
||||||
|
uint32 blockSize = 0; // Block size in bytes.
|
||||||
|
|
||||||
|
switch (textureInfo.PixelFormat)
|
||||||
|
{
|
||||||
|
case .BC1_UNorm, .BC1_UNorm_SRGB, .BC4_UNorm:
|
||||||
|
blockSize = 8;
|
||||||
|
case .BC2_UNorm, .BC2_UNorm_SRGB, .BC3_UNorm, .BC3_UNorm_SRGB, .BC5_UNorm:
|
||||||
|
blockSize = 16;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 width = 0;
|
||||||
|
uint32 height = 0;
|
||||||
|
uint32 depth = 0;
|
||||||
|
|
||||||
|
uint32 index = 0;
|
||||||
|
|
||||||
|
uint offset = 0;
|
||||||
|
|
||||||
|
for (uint32 arrayIndex = 0; arrayIndex < textureInfo.ArraySize; arrayIndex++)
|
||||||
|
{
|
||||||
|
for (uint32 cubeFace = 0; cubeFace < (textureInfo.IsCubeMap ? 6 : 1); cubeFace++)
|
||||||
|
{
|
||||||
|
width = header.Width;
|
||||||
|
height = header.Height;
|
||||||
|
depth = header.Depth;
|
||||||
|
|
||||||
|
for (uint32 mipLevel = 0; mipLevel < textureInfo.MipMapCount; ++mipLevel)
|
||||||
|
{
|
||||||
|
// This will recalculate te pitch of the main image as well.
|
||||||
|
if (header.Flags.HasFlag(.DDSD_LINEARSIZE))
|
||||||
|
{
|
||||||
|
// compressed textures
|
||||||
|
scanLineSize = Math.Max(1, ((width + 3u) / 4u)) * blockSize;
|
||||||
|
uint32 numScanLines = Math.Max(1, ((height + 3u) / 4u));
|
||||||
|
numBytes = scanLineSize * numScanLines;
|
||||||
|
}
|
||||||
|
else if (header.Flags.HasFlag(.DDSD_PITCH))
|
||||||
|
{
|
||||||
|
// uncompressed data
|
||||||
|
scanLineSize = (width * header.PixelFormat.RGBBitCount + 7u) / 8u;
|
||||||
|
numBytes = scanLineSize * height;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadedSurface surface = .();
|
||||||
|
// We don't know how large data-array is, so we don't have one yet.
|
||||||
|
// Only save the offset, we will adjust the pointer later.
|
||||||
|
surface.Data = Span<uint8>((uint8*)(void*)offset, numBytes);
|
||||||
|
surface.Pitch = scanLineSize;
|
||||||
|
surface.SlicePitch = slicePitch;
|
||||||
|
|
||||||
|
surface.ArrayIndex = arrayIndex;
|
||||||
|
surface.CubeFace = cubeFace;
|
||||||
|
surface.MipLevel = mipLevel;
|
||||||
|
|
||||||
|
surfaces.Add(surface);
|
||||||
|
|
||||||
|
++index;
|
||||||
|
|
||||||
|
width >>= 1;
|
||||||
|
height >>= 1;
|
||||||
|
depth >>= 1;
|
||||||
|
|
||||||
|
if (width == 0)
|
||||||
|
{
|
||||||
|
width = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height == 0)
|
||||||
|
{
|
||||||
|
height = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += numBytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textureInfo.PixelData = new uint8[offset];
|
||||||
|
|
||||||
|
Result<int> pixelDataResult = data.TryRead(textureInfo.PixelData);
|
||||||
|
|
||||||
|
if (pixelDataResult case .Err)
|
||||||
|
{
|
||||||
|
delete textureInfo.PixelData;
|
||||||
|
return .Err(.StreamReadFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ref LoadedSurface surface in ref surfaces)
|
||||||
|
{
|
||||||
|
// Data pointer so far only has the offset inside the array.
|
||||||
|
// Move the pointer, so that it is inside the array.
|
||||||
|
surface.Data.Ptr += (uint)(void*)textureInfo.PixelData.Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -347,6 +347,7 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
|
|||||||
|
|
||||||
for (let (slotName, textureIdentifier) in materialFile.Textures)
|
for (let (slotName, textureIdentifier) in materialFile.Textures)
|
||||||
{
|
{
|
||||||
|
|
||||||
AssetHandle<Texture> texture = contentManager.LoadAsset(textureIdentifier);
|
AssetHandle<Texture> texture = contentManager.LoadAsset(textureIdentifier);
|
||||||
|
|
||||||
if (texture.IsInvalid)
|
if (texture.IsInvalid)
|
||||||
@@ -402,7 +403,7 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
|
|||||||
|
|
||||||
for (let (slotName, texture) in material.[Friend]_textures)
|
for (let (slotName, texture) in material.[Friend]_textures)
|
||||||
{
|
{
|
||||||
Texture textureAsset = texture.Get();
|
Texture textureAsset = texture.Handle.Get();
|
||||||
|
|
||||||
materialFile.Textures.Add(new String(slotName), new String(textureAsset?.Identifier ?? ""));
|
materialFile.Textures.Add(new String(slotName), new String(textureAsset?.Identifier ?? ""));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using GlitchyEngine.Renderer;
|
|||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
using DirectXTK;
|
using DirectXTK;
|
||||||
using ImGui;
|
using ImGui;
|
||||||
|
using GlitchyEditor.Assets.Importers;
|
||||||
|
|
||||||
namespace GlitchyEditor.Assets;
|
namespace GlitchyEditor.Assets;
|
||||||
|
|
||||||
@@ -234,19 +235,34 @@ class EditorTextureAssetLoader : IAssetLoader//, IReloadingAssetLoader
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
Texture texture = null;
|
List<LoadedSurface> surfaces = scope .();
|
||||||
|
LoadedTextureInfo textureInfo;
|
||||||
|
|
||||||
|
// Make sure we clean up the pixel data
|
||||||
|
defer { delete textureInfo.PixelData; }
|
||||||
|
|
||||||
|
|
||||||
switch(GetTextureType(data))
|
switch(GetTextureType(data))
|
||||||
{
|
{
|
||||||
case .DDS:
|
case .DDS:
|
||||||
texture = LoadDds(data, config);
|
Result<void> result = LoadDds(data, config, surfaces, out textureInfo);
|
||||||
|
|
||||||
|
if (result case .Err)
|
||||||
|
return null;
|
||||||
|
|
||||||
case .PNG:
|
case .PNG:
|
||||||
texture = LoadPng(data, config);
|
Result<void> result = LoadPng(data, config, surfaces, out textureInfo);
|
||||||
|
|
||||||
|
if (result case .Err)
|
||||||
|
return null;
|
||||||
|
|
||||||
case .Unknown:
|
case .Unknown:
|
||||||
Log.EngineLogger.Error("Unknown texture format.");
|
Log.EngineLogger.Error("Unknown texture format.");
|
||||||
texture = null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Texture texture = CreateTexture(surfaces, textureInfo);
|
||||||
|
|
||||||
if (texture != null)
|
if (texture != null)
|
||||||
{
|
{
|
||||||
SetSampler(texture, config);
|
SetSampler(texture, config);
|
||||||
@@ -256,10 +272,75 @@ class EditorTextureAssetLoader : IAssetLoader//, IReloadingAssetLoader
|
|||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Texture2D LoadPng(Stream data, EditorTextureAssetLoaderConfig config)
|
private static Texture CreateTexture(List<LoadedSurface> surfaces, LoadedTextureInfo textureInfo)
|
||||||
|
{
|
||||||
|
switch (textureInfo.Dimension)
|
||||||
|
{
|
||||||
|
//case .Texture1D:
|
||||||
|
case .Texture2D:
|
||||||
|
if (textureInfo.IsCubeMap)
|
||||||
|
{
|
||||||
|
Texture2DDesc staging = .();
|
||||||
|
|
||||||
|
staging.Width = (.)textureInfo.Width;
|
||||||
|
staging.Height = (.)textureInfo.Height;
|
||||||
|
|
||||||
|
staging.MipLevels = (.)textureInfo.MipMapCount;
|
||||||
|
staging.ArraySize = (.)textureInfo.ArraySize;
|
||||||
|
|
||||||
|
staging.Format = textureInfo.PixelFormat;
|
||||||
|
|
||||||
|
// TODO: allow enabling read/write
|
||||||
|
staging.CpuAccess = .None;
|
||||||
|
staging.Usage = .Default;
|
||||||
|
|
||||||
|
TextureCube cubeTexture = new TextureCube(staging);
|
||||||
|
|
||||||
|
for (let surface in surfaces)
|
||||||
|
{
|
||||||
|
cubeTexture.SetData(surface.Data.Ptr, surface.Pitch / staging.Width, (TextureCubeFace)surface.CubeFace, (.)surface.ArrayIndex, (.)surface.MipLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cubeTexture;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Texture2DDesc staging = .();
|
||||||
|
|
||||||
|
staging.Width = (.)textureInfo.Width;
|
||||||
|
staging.Height = (.)textureInfo.Height;
|
||||||
|
|
||||||
|
staging.MipLevels = (.)textureInfo.MipMapCount;
|
||||||
|
staging.ArraySize = (.)textureInfo.ArraySize;
|
||||||
|
|
||||||
|
staging.Format = textureInfo.PixelFormat;
|
||||||
|
|
||||||
|
// TODO: allow enabling read/write
|
||||||
|
staging.CpuAccess = .None;
|
||||||
|
staging.Usage = .Default;
|
||||||
|
|
||||||
|
Texture2D stagingTexture = new Texture2D(staging);
|
||||||
|
|
||||||
|
for (let surface in surfaces)
|
||||||
|
{
|
||||||
|
stagingTexture.[Friend]PlatformSetData(surface.Data.Ptr, surface.Pitch / staging.Width, 0, 0, staging.Width, staging.Height, (.)surface.ArrayIndex, (.)surface.MipLevel, .Write);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stagingTexture;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Runtime.NotImplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Result<void> LoadPng(Stream data, EditorTextureAssetLoaderConfig config, List<LoadedSurface> surfaces, out LoadedTextureInfo textureInfo)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
textureInfo = .();
|
||||||
|
|
||||||
uint8[] pngData = new:ScopedAlloc! uint8[data.Length];
|
uint8[] pngData = new:ScopedAlloc! uint8[data.Length];
|
||||||
|
|
||||||
var result = data.TryRead(pngData);
|
var result = data.TryRead(pngData);
|
||||||
@@ -267,7 +348,7 @@ class EditorTextureAssetLoader : IAssetLoader//, IReloadingAssetLoader
|
|||||||
if (result case .Err(let err))
|
if (result case .Err(let err))
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Failed to read data from stream. Texture: Error: {err}");
|
Log.EngineLogger.Error($"Failed to read data from stream. Texture: Error: {err}");
|
||||||
return null;
|
return .Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8* rawData = null;
|
uint8* rawData = null;
|
||||||
@@ -285,25 +366,55 @@ class EditorTextureAssetLoader : IAssetLoader//, IReloadingAssetLoader
|
|||||||
if (errorCode != 0)
|
if (errorCode != 0)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Failed to decode PNG file {errorCode}.");
|
Log.EngineLogger.Error($"Failed to decode PNG file {errorCode}.");
|
||||||
return null;
|
return .Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture2DDesc desc = .(width, height, config.IsSRGB ? .R8G8B8A8_UNorm_SRGB : .R8G8B8A8_UNorm, 1, 1, .Immutable);
|
uint8[] pixelData = new uint8[4 * width * height];
|
||||||
Texture2D texture = new Texture2D(desc);
|
Internal.MemCpy(pixelData.Ptr, rawData, pixelData.Count);
|
||||||
texture.SetData<Color>((.)rawData);
|
|
||||||
|
LoadedSurface surface = .();
|
||||||
|
surface.Data = Span<uint8>(pixelData);
|
||||||
|
surface.Pitch = 4 * width;
|
||||||
|
surface.SlicePitch = 0;
|
||||||
|
surface.ArrayIndex = 0;
|
||||||
|
surface.MipLevel = 0;
|
||||||
|
|
||||||
|
surfaces.Add(surface);
|
||||||
|
|
||||||
|
//Texture2DDesc desc = .(width, height, config.IsSRGB ? .R8G8B8A8_UNorm_SRGB : .R8G8B8A8_UNorm, 1, 1, .Immutable);
|
||||||
|
//Texture2D texture = new Texture2D(desc);
|
||||||
|
//texture.SetData<Color>((.)rawData);
|
||||||
|
|
||||||
// TODO: Generate mip maps
|
// TODO: Generate mip maps
|
||||||
|
|
||||||
return texture;
|
textureInfo.PixelData = pixelData;
|
||||||
|
textureInfo.Width = width;
|
||||||
|
textureInfo.Height = height;
|
||||||
|
textureInfo.Depth = 1;
|
||||||
|
|
||||||
|
textureInfo.ArraySize = 1;
|
||||||
|
textureInfo.MipMapCount = 1;
|
||||||
|
|
||||||
|
textureInfo.Dimension = .Texture2D;
|
||||||
|
|
||||||
|
textureInfo.IsCubeMap = false;
|
||||||
|
|
||||||
|
textureInfo.PixelFormat = config.IsSRGB ? .R8G8B8A8_UNorm_SRGB : .R8G8B8A8_UNorm;
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
|
||||||
|
//return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Texture LoadDds(Stream data, EditorTextureAssetLoaderConfig config)
|
private static Result<void> LoadDds(Stream data, EditorTextureAssetLoaderConfig config, List<LoadedSurface> surfaces, out LoadedTextureInfo textureInfo)
|
||||||
{
|
{
|
||||||
// TODO: Move the loading of Dds files here.
|
var result = DdsImporter.LoadDds(data, config.IsSRGB, surfaces, out textureInfo);
|
||||||
Texture2D texture = new [Friend]Texture2D(data);
|
|
||||||
|
|
||||||
return texture;
|
if (result case .Err)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetSampler(Texture texture, EditorTextureAssetLoaderConfig config)
|
private static void SetSampler(Texture texture, EditorTextureAssetLoaderConfig config)
|
||||||
@@ -315,12 +426,38 @@ class EditorTextureAssetLoader : IAssetLoader//, IReloadingAssetLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Texture2D _placeholder2D;
|
private static Texture2D _placeholder2D;
|
||||||
|
private static TextureCube _placeholderCube;
|
||||||
|
|
||||||
private static Texture2D _error2D;
|
private static Texture2D _error2D;
|
||||||
|
private static TextureCube _errorCube;
|
||||||
|
|
||||||
public Asset GetPlaceholderAsset(Type assetType)
|
public Asset GetPlaceholderAsset(Type assetType)
|
||||||
{
|
{
|
||||||
switch (assetType)
|
switch (assetType)
|
||||||
{
|
{
|
||||||
|
case typeof(TextureCube):
|
||||||
|
if (_placeholderCube == null)
|
||||||
|
{
|
||||||
|
// TODO: immutable
|
||||||
|
Texture2DDesc desc = .(1, 1, .R8G8B8A8_UNorm, 1, 1, .Default, .None);
|
||||||
|
|
||||||
|
_placeholderCube = new TextureCube(desc);
|
||||||
|
_placeholderCube.SamplerState = SamplerStateManager.PointWrap;
|
||||||
|
Color color = Color.Cyan;
|
||||||
|
_placeholderCube.SetData<Color>(&color, .PositiveX);
|
||||||
|
_placeholderCube.SetData<Color>(&color, .NegativeX);
|
||||||
|
_placeholderCube.SetData<Color>(&color, .PositiveY);
|
||||||
|
_placeholderCube.SetData<Color>(&color, .NegativeY);
|
||||||
|
_placeholderCube.SetData<Color>(&color, .PositiveZ);
|
||||||
|
_placeholderCube.SetData<Color>(&color, .NegativeZ);
|
||||||
|
|
||||||
|
Content.ManageAsset(_placeholderCube);
|
||||||
|
_placeholderCube.ReleaseRef();
|
||||||
|
|
||||||
|
_placeholderCube.[Friend]Complete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _placeholderCube;
|
||||||
case typeof(Texture2D):
|
case typeof(Texture2D):
|
||||||
fallthrough;
|
fallthrough;
|
||||||
default:
|
default:
|
||||||
@@ -347,6 +484,31 @@ class EditorTextureAssetLoader : IAssetLoader//, IReloadingAssetLoader
|
|||||||
{
|
{
|
||||||
switch (assetType)
|
switch (assetType)
|
||||||
{
|
{
|
||||||
|
case typeof(TextureCube):
|
||||||
|
if (_placeholderCube == null)
|
||||||
|
{
|
||||||
|
// TODO: immutable
|
||||||
|
Texture2DDesc desc = .(2, 2, .R8G8B8A8_UNorm, 1, 1, .Default, .None);
|
||||||
|
|
||||||
|
_errorCube = new TextureCube(desc);
|
||||||
|
_errorCube.SamplerState = SamplerStateManager.PointWrap;
|
||||||
|
|
||||||
|
Color[4] color = .(Color.HotPink, Color.Black, Color.Black, Color.HotPink);
|
||||||
|
|
||||||
|
_errorCube.SetData<Color>(&color, .PositiveX);
|
||||||
|
_errorCube.SetData<Color>(&color, .NegativeX);
|
||||||
|
_errorCube.SetData<Color>(&color, .PositiveY);
|
||||||
|
_errorCube.SetData<Color>(&color, .NegativeY);
|
||||||
|
_errorCube.SetData<Color>(&color, .PositiveZ);
|
||||||
|
_errorCube.SetData<Color>(&color, .NegativeZ);
|
||||||
|
|
||||||
|
Content.ManageAsset(_errorCube);
|
||||||
|
_errorCube.ReleaseRef();
|
||||||
|
|
||||||
|
_errorCube.[Friend]Complete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _placeholderCube;
|
||||||
case typeof(Texture2D):
|
case typeof(Texture2D):
|
||||||
fallthrough;
|
fallthrough;
|
||||||
default:
|
default:
|
||||||
@@ -356,7 +518,9 @@ class EditorTextureAssetLoader : IAssetLoader//, IReloadingAssetLoader
|
|||||||
|
|
||||||
_error2D = new Texture2D(desc);
|
_error2D = new Texture2D(desc);
|
||||||
_error2D.SamplerState = SamplerStateManager.PointWrap;
|
_error2D.SamplerState = SamplerStateManager.PointWrap;
|
||||||
|
|
||||||
Color[4] color = .(Color.HotPink, Color.Black, Color.Black, Color.HotPink);
|
Color[4] color = .(Color.HotPink, Color.Black, Color.Black, Color.HotPink);
|
||||||
|
|
||||||
_error2D.SetData<Color>(&color);
|
_error2D.SetData<Color>(&color);
|
||||||
|
|
||||||
Content.ManageAsset(_error2D);
|
Content.ManageAsset(_error2D);
|
||||||
|
|||||||
@@ -142,7 +142,11 @@ namespace GlitchyEngine.ImGui
|
|||||||
RenderCommand.BindRenderTargets();
|
RenderCommand.BindRenderTargets();
|
||||||
|
|
||||||
#if GE_GRAPHICS_DX11
|
#if GE_GRAPHICS_DX11
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
ImGuiImplDX11.RenderDrawData(ImGui.GetDrawData());
|
ImGuiImplDX11.RenderDrawData(ImGui.GetDrawData());
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ImGui.CleanupFrame();
|
ImGui.CleanupFrame();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using DirectX.Common;
|
|||||||
using DirectX.D3D11;
|
using DirectX.D3D11;
|
||||||
using DirectX.D3D11.SDKLayers;
|
using DirectX.D3D11.SDKLayers;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace GlitchyEngine.Platform.DX11
|
namespace GlitchyEngine.Platform.DX11
|
||||||
{
|
{
|
||||||
@@ -18,6 +19,8 @@ namespace GlitchyEngine.Platform.DX11
|
|||||||
protected internal static ID3D11Device* NativeDevice;
|
protected internal static ID3D11Device* NativeDevice;
|
||||||
protected internal static ID3D11DeviceContext* NativeContext;
|
protected internal static ID3D11DeviceContext* NativeContext;
|
||||||
|
|
||||||
|
protected internal static Monitor ContextMonitor = new Monitor() ~ delete _;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
protected internal static ID3D11Debug* DebugDevice;
|
protected internal static ID3D11Debug* DebugDevice;
|
||||||
#endif
|
#endif
|
||||||
@@ -42,8 +45,11 @@ namespace GlitchyEngine.Platform.DX11
|
|||||||
HResult deviceResult;
|
HResult deviceResult;
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileScope!("D3D11.CreateDevice");
|
Debug.Profiler.ProfileScope!("D3D11.CreateDevice");
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
deviceResult = D3D11.CreateDevice(null, .Hardware, 0, deviceFlags, levels, &NativeDevice, &deviceLevel, &NativeContext);
|
deviceResult = D3D11.CreateDevice(null, .Hardware, 0, deviceFlags, levels, &NativeDevice, &deviceLevel, &NativeContext);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Log.EngineLogger.Assert(deviceResult.Succeeded, scope $"Failed to create D3D11 Device. Message({(int32)deviceResult}): {deviceResult}");
|
Log.EngineLogger.Assert(deviceResult.Succeeded, scope $"Failed to create D3D11 Device. Message({(int32)deviceResult}): {deviceResult}");
|
||||||
|
|
||||||
|
|||||||
@@ -100,14 +100,24 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
case .Default:
|
case .Default:
|
||||||
Box dataBox = .(dstByteOffset, 0, 0, dstByteOffset + byteLength, 1, 1);
|
Box dataBox = .(dstByteOffset, 0, 0, dstByteOffset + byteLength, 1, 1);
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.UpdateSubresource(nativeBuffer, 0, &dataBox, data, byteLength, byteLength);
|
NativeContext.UpdateSubresource(nativeBuffer, 0, &dataBox, data, byteLength, byteLength);
|
||||||
|
}
|
||||||
case .Dynamic:
|
case .Dynamic:
|
||||||
Log.EngineLogger.Assert(mapType == .WriteDiscard || mapType == .WriteNoOverwrite, scope $"When writing to dynamic resources the map type must be {nameof(Renderer.MapType.WriteDiscard)} or {nameof(Renderer.MapType.WriteNoOverwrite)}.");
|
Log.EngineLogger.Assert(mapType == .WriteDiscard || mapType == .WriteNoOverwrite, scope $"When writing to dynamic resources the map type must be {nameof(Renderer.MapType.WriteDiscard)} or {nameof(Renderer.MapType.WriteNoOverwrite)}.");
|
||||||
// Todo: DoNotWaitFlag
|
// Todo: DoNotWaitFlag
|
||||||
MappedSubresource map = ?;
|
MappedSubresource map = ?;
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.Map(nativeBuffer, 0, (.)mapType, .None, &map);
|
NativeContext.Map(nativeBuffer, 0, (.)mapType, .None, &map);
|
||||||
|
}
|
||||||
Internal.MemCpy(((uint8*)map.Data) + dstByteOffset, data, byteLength);
|
Internal.MemCpy(((uint8*)map.Data) + dstByteOffset, data, byteLength);
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.Unmap(nativeBuffer, 0);
|
NativeContext.Unmap(nativeBuffer, 0);
|
||||||
|
}
|
||||||
case .Immutable:
|
case .Immutable:
|
||||||
Log.EngineLogger.Error("Can't set the data of an immutable resource.");
|
Log.EngineLogger.Error("Can't set the data of an immutable resource.");
|
||||||
return .Err;
|
return .Err;
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.InputAssembler.SetVertexBuffers(0, nativeBuffers.Count, &nativeBuffers, &bufferStrides, &bufferOffsets);
|
NativeContext.InputAssembler.SetVertexBuffers(0, nativeBuffers.Count, &nativeBuffers, &bufferStrides, &bufferOffsets);
|
||||||
GraphicsContext.Get().SetVertexLayout(_vertexLayout);
|
GraphicsContext.Get().SetVertexLayout(_vertexLayout);
|
||||||
NativeContext.InputAssembler.SetPrimitiveTopology((.)_primitiveTopology);
|
NativeContext.InputAssembler.SetPrimitiveTopology((.)_primitiveTopology);
|
||||||
@@ -88,6 +90,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
if(_indexBuffer != null)
|
if(_indexBuffer != null)
|
||||||
NativeContext.InputAssembler.SetIndexBuffer(_indexBuffer.nativeBuffer, _indexBuffer.Format == .Index32Bit ? .R32_UInt : .R16_UInt, _indexByteOffset);
|
NativeContext.InputAssembler.SetIndexBuffer(_indexBuffer.nativeBuffer, _indexBuffer.Format == .Index32Bit ? .R32_UInt : .R16_UInt, _indexByteOffset);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Unbind()
|
public override void Unbind()
|
||||||
{
|
{
|
||||||
@@ -97,6 +100,8 @@ namespace GlitchyEngine.Renderer
|
|||||||
uint32[nativeBuffers.Count] zeroStrides = .();
|
uint32[nativeBuffers.Count] zeroStrides = .();
|
||||||
uint32[nativeBuffers.Count] zeroOffsets = .();
|
uint32[nativeBuffers.Count] zeroOffsets = .();
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.InputAssembler.SetVertexBuffers(0, nativeBuffers.Count, &nullBuffers, &zeroStrides, &zeroOffsets);
|
NativeContext.InputAssembler.SetVertexBuffers(0, nativeBuffers.Count, &nullBuffers, &zeroStrides, &zeroOffsets);
|
||||||
NativeContext.InputAssembler.SetInputLayout(null);
|
NativeContext.InputAssembler.SetInputLayout(null);
|
||||||
NativeContext.InputAssembler.SetPrimitiveTopology(.Undefined);
|
NativeContext.InputAssembler.SetPrimitiveTopology(.Undefined);
|
||||||
@@ -104,6 +109,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
NativeContext.InputAssembler.SetIndexBuffer(null, .R16_UNorm, 0);
|
NativeContext.InputAssembler.SetIndexBuffer(null, .R16_UNorm, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -157,21 +157,30 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override void BindRenderTargets()
|
public override void BindRenderTargets()
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
NativeContext.OutputMerger.SetRenderTargets(MaxRTVCount, &_renderTargets, _depthStencilTarget);
|
NativeContext.OutputMerger.SetRenderTargets(MaxRTVCount, &_renderTargets, _depthStencilTarget);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void ClearRenderTarget(RenderTarget2D renderTarget, ColorRGBA color)
|
public override void ClearRenderTarget(RenderTarget2D renderTarget, ColorRGBA color)
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
NativeContext.ClearRenderTargetView((renderTarget ?? _swapChain.BackBuffer)._nativeRenderTargetView, color);
|
NativeContext.ClearRenderTargetView((renderTarget ?? _swapChain.BackBuffer)._nativeRenderTargetView, color);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetVertexBuffer(uint32 slot, Buffer buffer, uint32 stride, uint32 offset = 0)
|
public override void SetVertexBuffer(uint32 slot, Buffer buffer, uint32 stride, uint32 offset = 0)
|
||||||
{
|
{
|
||||||
// make stride and offset mutable so that we can take their pointers.
|
// make stride and offset mutable so that we can take their pointers.
|
||||||
var stride, offset;
|
var stride, offset;
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.InputAssembler.SetVertexBuffers(slot, 1, &buffer.nativeBuffer, &stride, &offset);
|
NativeContext.InputAssembler.SetVertexBuffers(slot, 1, &buffer.nativeBuffer, &stride, &offset);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Inline]
|
[Inline]
|
||||||
private void BindInputLayout()
|
private void BindInputLayout()
|
||||||
@@ -181,9 +190,12 @@ namespace GlitchyEngine.Renderer
|
|||||||
_currentInputLayout = _currentVertexLayout.GetNativeVertexLayout(_currentVertexShader.nativeCode);
|
_currentInputLayout = _currentVertexLayout.GetNativeVertexLayout(_currentVertexShader.nativeCode);
|
||||||
_currentInputLayout.AddRef();
|
_currentInputLayout.AddRef();
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.InputAssembler.SetInputLayout(_currentInputLayout);
|
NativeContext.InputAssembler.SetInputLayout(_currentInputLayout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void BindState()
|
private void BindState()
|
||||||
{
|
{
|
||||||
@@ -199,35 +211,50 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw(uint32 vertexCount, uint32 startVertexIndex = 0)
|
public override void Draw(uint32 vertexCount, uint32 startVertexIndex = 0)
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
BindState();
|
BindState();
|
||||||
|
|
||||||
NativeContext.Draw(vertexCount, startVertexIndex);
|
NativeContext.Draw(vertexCount, startVertexIndex);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void DrawIndexed(uint32 indexCount, uint32 startIndexLocation = 0, int32 vertexOffset = 0)
|
public override void DrawIndexed(uint32 indexCount, uint32 startIndexLocation = 0, int32 vertexOffset = 0)
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
BindState();
|
BindState();
|
||||||
|
|
||||||
NativeContext.DrawIndexed(indexCount, startIndexLocation, vertexOffset);
|
NativeContext.DrawIndexed(indexCount, startIndexLocation, vertexOffset);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void DrawIndexedInstanced(uint32 indexCountPerInstance, uint32 instanceCount, uint32 startIndexLocation, int32 baseVertexLocation, uint32 startInstanceLocation)
|
public override void DrawIndexedInstanced(uint32 indexCountPerInstance, uint32 instanceCount, uint32 startIndexLocation, int32 baseVertexLocation, uint32 startInstanceLocation)
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
BindState();
|
BindState();
|
||||||
|
|
||||||
NativeContext.DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation);
|
NativeContext.DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetIndexBuffer(Buffer buffer, IndexFormat indexFormat = .Index16Bit, uint32 byteOffset = 0)
|
public override void SetIndexBuffer(Buffer buffer, IndexFormat indexFormat = .Index16Bit, uint32 byteOffset = 0)
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
NativeContext.InputAssembler.SetIndexBuffer(buffer.nativeBuffer, indexFormat == .Index32Bit ? .R32_UInt : .R16_UInt, byteOffset);
|
NativeContext.InputAssembler.SetIndexBuffer(buffer.nativeBuffer, indexFormat == .Index32Bit ? .R32_UInt : .R16_UInt, byteOffset);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetViewports(uint32 viewportsCount, GlitchyEngine.Renderer.Viewport* viewports)
|
public override void SetViewports(uint32 viewportsCount, GlitchyEngine.Renderer.Viewport* viewports)
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
NativeContext.Rasterizer.SetViewports(viewportsCount, (.)viewports);
|
NativeContext.Rasterizer.SetViewports(viewportsCount, (.)viewports);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetVertexLayout(VertexLayout vertexLayout)
|
public override void SetVertexLayout(VertexLayout vertexLayout)
|
||||||
{
|
{
|
||||||
@@ -240,9 +267,12 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override void SetPrimitiveTopology(GlitchyEngine.Renderer.PrimitiveTopology primitiveTopology)
|
public override void SetPrimitiveTopology(GlitchyEngine.Renderer.PrimitiveTopology primitiveTopology)
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
NativeContext.InputAssembler.SetPrimitiveTopology((DirectX.Common.PrimitiveTopology)primitiveTopology);
|
NativeContext.InputAssembler.SetPrimitiveTopology((DirectX.Common.PrimitiveTopology)primitiveTopology);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private uint32 _ps_FirstTexture;
|
private uint32 _ps_FirstTexture;
|
||||||
private uint32 _ps_BoundTextures;
|
private uint32 _ps_BoundTextures;
|
||||||
@@ -344,19 +374,28 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
void** voidArray = scope void*[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]*;
|
void** voidArray = scope void*[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT]*;
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.PixelShader.SetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, (.)voidArray);
|
NativeContext.PixelShader.SetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, (.)voidArray);
|
||||||
NativeContext.VertexShader.SetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, (.)voidArray);
|
NativeContext.VertexShader.SetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, (.)voidArray);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void BindVertexShader(VertexShader vertexShader)
|
public override void BindVertexShader(VertexShader vertexShader)
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
BindShaderToStage(vertexShader);
|
BindShaderToStage(vertexShader);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void BindPixelShader(PixelShader pixelShader)
|
public override void BindPixelShader(PixelShader pixelShader)
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
BindShaderToStage(pixelShader);
|
BindShaderToStage(pixelShader);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void BindConstantBuffer(Buffer buffer, int slot, ShaderStage stage)
|
public override void BindConstantBuffer(Buffer buffer, int slot, ShaderStage stage)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -444,11 +444,24 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
Box srcBox = .(x, y, arraySlice, x + width, y + height, arraySlice + 1);
|
Box srcBox = .(x, y, arraySlice, x + width, y + height, arraySlice + 1);
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, texture, srcSubResource, &srcBox);
|
NativeContext.CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, texture, srcSubResource, &srcBox);
|
||||||
|
}
|
||||||
|
|
||||||
MappedSubresource subresource = ?;
|
MappedSubresource subresource = ?;
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
result = NativeContext.Map(stagingTexture, 0, .Read, .None, &subresource);
|
result = NativeContext.Map(stagingTexture, 0, .Read, .None, &subresource);
|
||||||
defer NativeContext.Unmap(stagingTexture, 0);
|
}
|
||||||
|
|
||||||
|
defer
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
|
NativeContext.Unmap(stagingTexture, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
return .Err;
|
return .Err;
|
||||||
@@ -475,9 +488,12 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
Box srcBox = .((.)srcTopLeft.X, (.)srcTopLeft.Y, 0, (.)(srcTopLeft.X + size.X), (.)(srcTopLeft.Y + size.Y), 1);
|
Box srcBox = .((.)srcTopLeft.X, (.)srcTopLeft.Y, 0, (.)(srcTopLeft.X + size.X), (.)(srcTopLeft.Y + size.Y), 1);
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.CopySubresourceRegion(dstTexture, 0, (.)dstTopLeft.X, (.)dstTopLeft.Y, 0, srcTexture, 0, &srcBox);
|
NativeContext.CopySubresourceRegion(dstTexture, 0, (.)dstTopLeft.X, (.)dstTopLeft.Y, 0, srcTexture, 0, &srcBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -45,8 +45,11 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.ClearRenderTargetView(RtOrBackbuffer!(renderTarget)._nativeRenderTargetView, color);
|
NativeContext.ClearRenderTargetView(RtOrBackbuffer!(renderTarget)._nativeRenderTargetView, color);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Clear(DepthStencilTarget target, ClearOptions clearOptions, float depth, uint8 stencil)
|
public override void Clear(DepthStencilTarget target, ClearOptions clearOptions, float depth, uint8 stencil)
|
||||||
{
|
{
|
||||||
@@ -67,17 +70,22 @@ namespace GlitchyEngine.Renderer
|
|||||||
flags |= .Stencil;
|
flags |= .Stencil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.ClearDepthStencilView(target.nativeView, flags, depth, stencil);
|
NativeContext.ClearDepthStencilView(target.nativeView, flags, depth, stencil);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ClearRtv(DirectX.D3D11.ID3D11RenderTargetView* rtv, ClearColor clearColor)
|
private void ClearRtv(DirectX.D3D11.ID3D11RenderTargetView* rtv, ClearColor clearColor)
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
switch(clearColor)
|
switch(clearColor)
|
||||||
{
|
{
|
||||||
case .Color(let color):
|
case .Color(let color):
|
||||||
NativeContext.ClearRenderTargetView(rtv, color);
|
NativeContext.ClearRenderTargetView(rtv, color);
|
||||||
case .UInt(let value):
|
case .UInt(let value):
|
||||||
#unwarn
|
#unwarn
|
||||||
NativeContext.OutputMerger.SetRenderTargets(1, &rtv, null);
|
NativeContext.OutputMerger.SetRenderTargets(1, &rtv, null);
|
||||||
|
|
||||||
using (BlendState lastBlendState = _currentBlendState..AddRef())
|
using (BlendState lastBlendState = _currentBlendState..AddRef())
|
||||||
@@ -99,6 +107,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
Runtime.NotImplemented();
|
Runtime.NotImplemented();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Clear(RenderTargetGroup renderTarget, ClearOptions options, ClearColor? color = null, float? depth = null, uint8? stencil = null)
|
public override void Clear(RenderTargetGroup renderTarget, ClearOptions options, ClearColor? color = null, float? depth = null, uint8? stencil = null)
|
||||||
{
|
{
|
||||||
@@ -143,10 +152,13 @@ namespace GlitchyEngine.Renderer
|
|||||||
clearDepth = depth ?? clearDepth;
|
clearDepth = depth ?? clearDepth;
|
||||||
clearStencil = stencil ?? clearStencil;
|
clearStencil = stencil ?? clearStencil;
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.ClearDepthStencilView(renderTarget._nativeDepthTargetView, flags, clearDepth, clearStencil);
|
NativeContext.ClearDepthStencilView(renderTarget._nativeDepthTargetView, flags, clearDepth, clearStencil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetRenderTarget(RenderTarget2D renderTarget, int slot, bool setDepthBuffer)
|
public override void SetRenderTarget(RenderTarget2D renderTarget, int slot, bool setDepthBuffer)
|
||||||
{
|
{
|
||||||
@@ -199,8 +211,11 @@ namespace GlitchyEngine.Renderer
|
|||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
SetReference!(_currentRasterizerState, rasterizerState);
|
SetReference!(_currentRasterizerState, rasterizerState);
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.Rasterizer.SetState(_currentRasterizerState.nativeRasterizerState);
|
NativeContext.Rasterizer.SetState(_currentRasterizerState.nativeRasterizerState);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private BlendState _currentBlendState ~ _?.ReleaseRef();
|
private BlendState _currentBlendState ~ _?.ReleaseRef();
|
||||||
|
|
||||||
@@ -209,8 +224,12 @@ namespace GlitchyEngine.Renderer
|
|||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
SetReference!(_currentBlendState, blendState);
|
SetReference!(_currentBlendState, blendState);
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.OutputMerger.SetBlendState(_currentBlendState.nativeBlendState, blendFactor);
|
NativeContext.OutputMerger.SetBlendState(_currentBlendState.nativeBlendState, blendFactor);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private DepthStencilState _currentDepthStencilState ~ _?.ReleaseRef();
|
private DepthStencilState _currentDepthStencilState ~ _?.ReleaseRef();
|
||||||
|
|
||||||
@@ -219,8 +238,12 @@ namespace GlitchyEngine.Renderer
|
|||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
SetReference!(_currentDepthStencilState, depthStencilState);
|
SetReference!(_currentDepthStencilState, depthStencilState);
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.OutputMerger.SetDepthStencilState(_currentDepthStencilState.nativeDepthStencilState, stencilReference);
|
NativeContext.OutputMerger.SetDepthStencilState(_currentDepthStencilState.nativeDepthStencilState, stencilReference);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void DrawIndexed(GeometryBinding geometry)
|
public override void DrawIndexed(GeometryBinding geometry)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -121,11 +121,14 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override void Bind(uint32 slot)
|
public override void Bind(uint32 slot)
|
||||||
|
{
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
{
|
{
|
||||||
NativeContext.VertexShader.SetSamplers(slot, 1, &nativeSamplerState);
|
NativeContext.VertexShader.SetSamplers(slot, 1, &nativeSamplerState);
|
||||||
NativeContext.PixelShader.SetSamplers(slot, 1, &nativeSamplerState);
|
NativeContext.PixelShader.SetSamplers(slot, 1, &nativeSamplerState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -205,7 +205,30 @@ namespace GlitchyEngine.Renderer
|
|||||||
buffer.ReleaseRef();
|
buffer.ReleaseRef();
|
||||||
}
|
}
|
||||||
case .Texture:
|
case .Texture:
|
||||||
_textures.Add(scope String(bindDesc.Name), bindDesc.BindPoint, TextureViewBinding(null, null));
|
|
||||||
|
TextureDimension texDim;
|
||||||
|
|
||||||
|
switch (bindDesc.Dimension)
|
||||||
|
{
|
||||||
|
case .Texture1D:
|
||||||
|
texDim = .Texture1D;
|
||||||
|
case .Texture1DArray:
|
||||||
|
texDim = .Texture1DArray;
|
||||||
|
case .Texture2D:
|
||||||
|
texDim = .Texture2D;
|
||||||
|
case .Texture2DArray:
|
||||||
|
texDim = .Texture2DArray;
|
||||||
|
case .Texture3D:
|
||||||
|
texDim = .Texture3D;
|
||||||
|
case .TextureCube:
|
||||||
|
texDim = .TextureCube;
|
||||||
|
case .TextureCubeArray:
|
||||||
|
texDim = .TextureCubeArray;
|
||||||
|
default:
|
||||||
|
texDim = .Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
_textures.Add(scope String(bindDesc.Name), bindDesc.BindPoint, TextureViewBinding(null, null), texDim);
|
||||||
case .Sampler:
|
case .Sampler:
|
||||||
// TODO: do we have to do something for samplers?
|
// TODO: do we have to do something for samplers?
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -19,43 +19,6 @@ namespace GlitchyEngine.Renderer
|
|||||||
extension Texture
|
extension Texture
|
||||||
{
|
{
|
||||||
protected internal ID3D11ShaderResourceView* _nativeResourceView ~ _?.Release();
|
protected internal ID3D11ShaderResourceView* _nativeResourceView ~ _?.Release();
|
||||||
|
|
||||||
/** \brief Loads the texture from the specified path.
|
|
||||||
* @param path The path of the texture to load.
|
|
||||||
* @param texture The reference to the pointer that will hold the texture.
|
|
||||||
* @returns true if the texture was loaded successfully; false otherwise.
|
|
||||||
*/
|
|
||||||
protected bool LoadDdsResourcePlatform<T>(Stream stream, ref T* texture) where T : ID3D11Resource
|
|
||||||
{
|
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
|
||||||
|
|
||||||
uint8[] ddsData = new:ScopedAlloc! uint8[stream.Length];
|
|
||||||
|
|
||||||
var result = stream.TryRead(ddsData);
|
|
||||||
|
|
||||||
if (result case .Err(let err))
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"Failed to read texture data from stream. Error: {err}");
|
|
||||||
}
|
|
||||||
|
|
||||||
((ID3D11Resource*)texture)?.Release();
|
|
||||||
_nativeResourceView?.Release();
|
|
||||||
|
|
||||||
HResult loadResult = DDSTextureLoader.CreateDDSTextureFromMemory(NativeDevice,
|
|
||||||
ddsData.Ptr, (uint)ddsData.Count, (.)&texture, &_nativeResourceView);
|
|
||||||
|
|
||||||
if(loadResult.Failed)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"Failed to load texture. Error({(int)loadResult}): {loadResult}");
|
|
||||||
|
|
||||||
ReleaseAndNullify!(texture);
|
|
||||||
ReleaseAndNullify!(_nativeResourceView);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Texture2DDesc
|
extension Texture2DDesc
|
||||||
@@ -94,18 +57,6 @@ namespace GlitchyEngine.Renderer
|
|||||||
public override uint32 ArraySize => nativeDesc.ArraySize;
|
public override uint32 ArraySize => nativeDesc.ArraySize;
|
||||||
public override uint32 MipLevels => nativeDesc.MipLevels;
|
public override uint32 MipLevels => nativeDesc.MipLevels;
|
||||||
|
|
||||||
protected override void LoadDdsPlatform(Stream stream)
|
|
||||||
{
|
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
|
||||||
|
|
||||||
LoadDdsResourcePlatform(stream, ref nativeTexture);
|
|
||||||
|
|
||||||
let resType = nativeTexture.GetResourceType();
|
|
||||||
Log.EngineLogger.Assert(resType == .Texture2D, scope $"The texture is not a 2D texture (it is {resType}).");
|
|
||||||
|
|
||||||
nativeTexture.GetDescription(out nativeDesc);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void CreateTexturePlatform(Texture2DDesc desc, bool isRenderTarget, void* data, uint32 linePitch)
|
protected override void CreateTexturePlatform(Texture2DDesc desc, bool isRenderTarget, void* data, uint32 linePitch)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
@@ -177,7 +128,12 @@ namespace GlitchyEngine.Renderer
|
|||||||
case .Default:
|
case .Default:
|
||||||
Box dataBox = .(destX, destY, 0, destX + destWidth, destY + destHeight, 1);
|
Box dataBox = .(destX, destY, 0, destX + destWidth, destY + destHeight, 1);
|
||||||
var rowPitch = elementSize * destWidth;
|
var rowPitch = elementSize * destWidth;
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
NativeContext.UpdateSubresource(nativeTexture, subresourceIndex, &dataBox, data, rowPitch, rowPitch * destHeight);
|
NativeContext.UpdateSubresource(nativeTexture, subresourceIndex, &dataBox, data, rowPitch, rowPitch * destHeight);
|
||||||
|
}
|
||||||
|
|
||||||
case .Dynamic:
|
case .Dynamic:
|
||||||
Runtime.NotImplemented();
|
Runtime.NotImplemented();
|
||||||
/*
|
/*
|
||||||
@@ -220,6 +176,186 @@ namespace GlitchyEngine.Renderer
|
|||||||
sourceBox.Back = 1;
|
sourceBox.Back = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure the destination was initialized
|
||||||
|
if(destination.nativeTexture == null)
|
||||||
|
destination.InternalCreateTexture(null, 0, 0);
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
|
NativeContext.CopySubresourceRegion(destination.nativeTexture,
|
||||||
|
D3D11.CalcSubresource(destMipSlice, destArraySlice, destination.MipLevels), destX, destY, 0,
|
||||||
|
source.nativeTexture, D3D11.CalcSubresource(srcMipSlice, srcArraySlice, source.MipLevels), (.)&sourceBox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CopyTo(Texture2D destination)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
if(nativeTexture == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Log.EngineLogger.AssertDebug(nativeDesc.Format == destination.nativeDesc.Format,
|
||||||
|
"Source and destination resources must have the same texel-format.");
|
||||||
|
|
||||||
|
// Make sure the destination was initialized
|
||||||
|
if(destination.nativeTexture == null)
|
||||||
|
destination.InternalCreateTexture(null, 0, 0);
|
||||||
|
|
||||||
|
uint32 arraySlices = Math.Min(ArraySize, destination.ArraySize);
|
||||||
|
uint32 mipSlices = Math.Min(MipLevels, destination.MipLevels);
|
||||||
|
|
||||||
|
for(uint32 arraySlice < arraySlices)
|
||||||
|
for(uint32 mipSlice < mipSlices)
|
||||||
|
{
|
||||||
|
Box sourceBox = .(0, 0, 0, Width, Height, 1);
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
|
NativeContext.CopySubresourceRegion(destination.nativeTexture,
|
||||||
|
D3D11.CalcSubresource(mipSlice, arraySlice, destination.MipLevels), 0, 0, 0,
|
||||||
|
nativeTexture, D3D11.CalcSubresource(mipSlice, arraySlice, MipLevels), (.)&sourceBox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TextureViewBinding PlatformGetViewBinding()
|
||||||
|
{
|
||||||
|
return .(_nativeResourceView, _samplerState?.nativeSamplerState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TextureCube
|
||||||
|
{
|
||||||
|
protected internal ID3D11Texture2D* nativeTexture ~ _?.Release();
|
||||||
|
protected internal NativeTex2DDesc nativeDesc;
|
||||||
|
|
||||||
|
public override uint32 Width => nativeDesc.Width;
|
||||||
|
public override uint32 Height => nativeDesc.Height;
|
||||||
|
public override uint32 ArraySize => nativeDesc.ArraySize / 6;
|
||||||
|
public override uint32 MipLevels => nativeDesc.MipLevels;
|
||||||
|
|
||||||
|
protected override void CreateTexturePlatform(Texture2DDesc desc, bool isRenderTarget, void* data, uint32 linePitch)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
PrepareTexturePlatform(desc, isRenderTarget);
|
||||||
|
InternalCreateTexture(data, linePitch, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PrepareTexturePlatform(Texture2DDesc desc, bool isRenderTarget)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
nativeTexture?.Release();
|
||||||
|
nativeTexture = null;
|
||||||
|
_nativeResourceView?.Release();
|
||||||
|
_nativeResourceView = null;
|
||||||
|
|
||||||
|
nativeDesc = (NativeTex2DDesc)desc;
|
||||||
|
// Make it a texture cube
|
||||||
|
nativeDesc.MiscFlags |= .TextureCube;
|
||||||
|
nativeDesc.ArraySize *= 6;
|
||||||
|
|
||||||
|
if(isRenderTarget)
|
||||||
|
nativeDesc.BindFlags |= .RenderTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InternalCreateTexture(void* data, uint32 linePitch, uint32 slicePitch)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
SubresourceData resData = .(data, linePitch, slicePitch);
|
||||||
|
|
||||||
|
// If data is null, set subresourceData null
|
||||||
|
SubresourceData* resDataPtr = null;//data == null ? null : &resData;
|
||||||
|
|
||||||
|
var result = NativeDevice.CreateTexture2D(ref nativeDesc, resDataPtr, &nativeTexture);
|
||||||
|
Log.EngineLogger.Assert(result.Succeeded, scope $"Failed to create texture 2D. Error ({result.Underlying}): {result}");
|
||||||
|
|
||||||
|
result = NativeDevice.CreateShaderResourceView(nativeTexture, null, &_nativeResourceView);
|
||||||
|
Log.EngineLogger.Assert(result.Succeeded, scope $"Failed to create texture view. Error ({result.Underlying}): {result}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Update Texture Arrays!
|
||||||
|
protected override Result<void> PlatformSetData(void* data, uint32 elementSize, uint32 destX,
|
||||||
|
uint32 destY, uint32 destWidth, uint32 destHeight, uint32 arraySlice, uint32 mipLevel, GlitchyEngine.Renderer.MapType mapType)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
if(nativeTexture == null)
|
||||||
|
{
|
||||||
|
if(destX == 0 && destY == 0 && destWidth == nativeDesc.Width && destHeight == nativeDesc.Height)
|
||||||
|
{
|
||||||
|
// We can pass the data while creating the buffer, so we can return here.
|
||||||
|
var rowPitch = elementSize * destWidth;
|
||||||
|
InternalCreateTexture(data, rowPitch, rowPitch * destHeight);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we don't set the entire texture we need to create the texture with unknown content and set it manually
|
||||||
|
Log.EngineLogger.Assert(nativeDesc.Usage != .Immutable, "The entire immutable texture has to be initialized.");
|
||||||
|
InternalCreateTexture(null, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Log.EngineLogger.AssertDebug();
|
||||||
|
// TODO: Debug.Assert(dstByteOffset + byteLength <= _description.Size, "The destination offset and byte length are too long for the target buffer.");
|
||||||
|
|
||||||
|
uint32 subresourceIndex = D3D11.CalcSubresource(mipLevel, arraySlice, nativeDesc.MipLevels);
|
||||||
|
|
||||||
|
switch(nativeDesc.Usage)
|
||||||
|
{
|
||||||
|
case .Default:
|
||||||
|
Box dataBox = .(destX, destY, 0, destX + destWidth, destY + destHeight, 1);
|
||||||
|
var rowPitch = elementSize * destWidth;
|
||||||
|
|
||||||
|
using (ContextMonitor.Enter())
|
||||||
|
{
|
||||||
|
NativeContext.UpdateSubresource(nativeTexture, subresourceIndex, &dataBox, data, rowPitch, rowPitch * destHeight);
|
||||||
|
}
|
||||||
|
case .Dynamic:
|
||||||
|
Runtime.NotImplemented();
|
||||||
|
/*
|
||||||
|
Log.EngineLogger.Assert(mapType.CanWrite, "The map type has to have write access.");
|
||||||
|
// Todo: DoNotWaitFlag
|
||||||
|
MappedSubresource map = ?;
|
||||||
|
_context.nativeContext.Map(nativeBuffer, 0, (.)mapType, .None, &map);
|
||||||
|
Internal.MemCpy(((uint8*)map.Data) + dstByteOffset, data, byteLength);
|
||||||
|
_context.nativeContext.Unmap(nativeBuffer, 0);
|
||||||
|
*/
|
||||||
|
case .Immutable:
|
||||||
|
Log.EngineLogger.Error("Can't set the data of an immutable resource.");
|
||||||
|
return .Err;
|
||||||
|
default:
|
||||||
|
Log.EngineLogger.Error($"Unknown resource usage: {nativeDesc.Usage}");
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public static override void CopySubresourceRegion(Texture2D source, Texture2D destination,
|
||||||
|
ResourceBox sourceBox = default, uint32 destX = 0, uint32 destY = 0,
|
||||||
|
uint32 srcArraySlice = 0, uint32 srcMipSlice = 0, uint32 destArraySlice = 0, uint32 destMipSlice = 0)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
Log.EngineLogger.AssertDebug(source != destination || srcArraySlice != destArraySlice
|
||||||
|
|| srcMipSlice != destMipSlice, "Cannot copy from and to the same sub resource.");
|
||||||
|
|
||||||
|
Log.EngineLogger.AssertDebug(source.nativeDesc.Format == destination.nativeDesc.Format,
|
||||||
|
"Source and destination resources must have the same texel-format.");
|
||||||
|
|
||||||
|
var sourceBox;
|
||||||
|
|
||||||
|
if(sourceBox.Right == 0)
|
||||||
|
{
|
||||||
|
sourceBox.Right = source.Width;
|
||||||
|
sourceBox.Bottom = source.Height;
|
||||||
|
sourceBox.Back = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure the destination was initialized
|
// Make sure the destination was initialized
|
||||||
if(destination.nativeTexture == null)
|
if(destination.nativeTexture == null)
|
||||||
destination.InternalCreateTexture(null, 0, 0);
|
destination.InternalCreateTexture(null, 0, 0);
|
||||||
@@ -255,44 +391,13 @@ namespace GlitchyEngine.Renderer
|
|||||||
D3D11.CalcSubresource(mipSlice, arraySlice, destination.MipLevels), 0, 0, 0,
|
D3D11.CalcSubresource(mipSlice, arraySlice, destination.MipLevels), 0, 0, 0,
|
||||||
nativeTexture, D3D11.CalcSubresource(mipSlice, arraySlice, MipLevels), (.)&sourceBox);
|
nativeTexture, D3D11.CalcSubresource(mipSlice, arraySlice, MipLevels), (.)&sourceBox);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
protected override TextureViewBinding PlatformGetViewBinding()
|
protected override TextureViewBinding PlatformGetViewBinding()
|
||||||
{
|
{
|
||||||
return .(_nativeResourceView, _samplerState?.nativeSamplerState);
|
return .(_nativeResourceView, _samplerState?.nativeSamplerState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TextureCube
|
|
||||||
{
|
|
||||||
protected internal ID3D11Texture2D* nativeTexture ~ _?.Release();
|
|
||||||
protected internal NativeTex2DDesc nativeDesc;
|
|
||||||
|
|
||||||
public override uint32 Width => nativeDesc.Width;
|
|
||||||
public override uint32 Height => nativeDesc.Height;
|
|
||||||
public override uint32 ArraySize => nativeDesc.ArraySize / 6;
|
|
||||||
public override uint32 MipLevels => nativeDesc.MipLevels;
|
|
||||||
|
|
||||||
protected override void LoadTexturePlatform(Stream stream)
|
|
||||||
{
|
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
|
||||||
|
|
||||||
LoadDdsResourcePlatform(stream, ref nativeTexture);
|
|
||||||
|
|
||||||
let resType = nativeTexture.GetResourceType();
|
|
||||||
Log.EngineLogger.Assert(resType == .Texture2D, scope $"The texture \"{_path}\" is not a texture cube (it is {resType}).");
|
|
||||||
|
|
||||||
nativeTexture.GetDescription(out nativeDesc);
|
|
||||||
|
|
||||||
Log.EngineLogger.Assert(nativeDesc.MiscFlags.HasFlag(.TextureCube), scope $"The texture \"{_path}\" is not a texture cube.");
|
|
||||||
// TODO: load fallback texture
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override TextureViewBinding PlatformGetViewBinding()
|
|
||||||
{
|
|
||||||
return .(_nativeResourceView, _samplerState.nativeSamplerState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -104,6 +104,18 @@ public class EffectLibrary
|
|||||||
public bool Exists(String effectName) => _effects.ContainsKey(effectName);
|
public bool Exists(String effectName) => _effects.ContainsKey(effectName);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
public enum TextureDimension
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Texture1D,
|
||||||
|
Texture1DArray,
|
||||||
|
Texture2D,
|
||||||
|
Texture2DArray,
|
||||||
|
Texture3D,
|
||||||
|
TextureCube,
|
||||||
|
TextureCubeArray
|
||||||
|
}
|
||||||
|
|
||||||
public class Effect : Asset
|
public class Effect : Asset
|
||||||
{
|
{
|
||||||
internal VertexShader _vs ~ _?.ReleaseRef();
|
internal VertexShader _vs ~ _?.ReleaseRef();
|
||||||
@@ -137,14 +149,16 @@ public class Effect : Asset
|
|||||||
public struct TextureEntry
|
public struct TextureEntry
|
||||||
{
|
{
|
||||||
public TextureViewBinding BoundTexture;
|
public TextureViewBinding BoundTexture;
|
||||||
|
public TextureDimension TextureDimension;
|
||||||
public ShaderTextureCollection.ResourceEntry* VsSlot;
|
public ShaderTextureCollection.ResourceEntry* VsSlot;
|
||||||
public ShaderTextureCollection.ResourceEntry* PsSlot;
|
public ShaderTextureCollection.ResourceEntry* PsSlot;
|
||||||
|
|
||||||
public this(TextureViewBinding boundTexture, ShaderTextureCollection.ResourceEntry* vsSlot, ShaderTextureCollection.ResourceEntry* psSlot)
|
public this(TextureViewBinding boundTexture, TextureDimension textureDimension, ShaderTextureCollection.ResourceEntry* vsSlot, ShaderTextureCollection.ResourceEntry* psSlot)
|
||||||
{
|
{
|
||||||
BoundTexture = boundTexture;
|
BoundTexture = boundTexture;
|
||||||
VsSlot = vsSlot;
|
VsSlot = vsSlot;
|
||||||
PsSlot = psSlot;
|
PsSlot = psSlot;
|
||||||
|
TextureDimension = textureDimension;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,7 +755,7 @@ public class Effect : Asset
|
|||||||
// Get existing entry or create new
|
// Get existing entry or create new
|
||||||
if(!_textures.TryGetValue(shaderEntry.Name, out entry))
|
if(!_textures.TryGetValue(shaderEntry.Name, out entry))
|
||||||
{
|
{
|
||||||
entry = .(shaderEntry.BoundTexture, null, null);
|
entry = .(shaderEntry.BoundTexture, shaderEntry.Dimension, null, null);
|
||||||
entry.BoundTexture.AddRef();
|
entry.BoundTexture.AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class Material : Asset
|
|||||||
|
|
||||||
private uint8[] _rawVariables ~ delete _;
|
private uint8[] _rawVariables ~ delete _;
|
||||||
|
|
||||||
private Dictionary<String, AssetHandle<Texture>> _textures = new .() ~ delete _;
|
private Dictionary<String, (AssetHandle<Texture> Handle, TextureDimension Dimension)> _textures = new .() ~ delete _;
|
||||||
|
|
||||||
private Dictionary<String, (uint32 Offset, BufferVariable Variable)> _variables = new .() ~ delete _;
|
private Dictionary<String, (uint32 Offset, BufferVariable Variable)> _variables = new .() ~ delete _;
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ public class Material : Asset
|
|||||||
// At best whole paths. Shouldn't be that hard to do...
|
// At best whole paths. Shouldn't be that hard to do...
|
||||||
/*var texture = entry.BoundTexture;*/
|
/*var texture = entry.BoundTexture;*/
|
||||||
|
|
||||||
_textures.Add(name, .Invalid);
|
_textures.Add(name, (AssetHandle<Texture>.Invalid, entry.TextureDimension));
|
||||||
}
|
}
|
||||||
|
|
||||||
InitRawData();
|
InitRawData();
|
||||||
@@ -66,7 +66,19 @@ public class Material : Asset
|
|||||||
|
|
||||||
for(let (name, texture) in _textures)
|
for(let (name, texture) in _textures)
|
||||||
{
|
{
|
||||||
_effect.SetTexture(name, texture);
|
switch (texture.Dimension)
|
||||||
|
{
|
||||||
|
//case .Texture1D, .Texture1DArray:
|
||||||
|
case .Texture2D, .Texture2DArray:
|
||||||
|
AssetHandle<Texture2D> handle2D = .(texture.Handle);
|
||||||
|
_effect.SetTexture(name, handle2D);
|
||||||
|
case .TextureCube, .TextureCubeArray:
|
||||||
|
AssetHandle<TextureCube> cubeHandle = .(texture.Handle);
|
||||||
|
_effect.SetTexture(name, cubeHandle);
|
||||||
|
//case .Texture3D:
|
||||||
|
default:
|
||||||
|
Log.EngineLogger.Error("Tryied to bind undefined texture dimension!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(let (name, variable) in _variables)
|
for(let (name, variable) in _variables)
|
||||||
@@ -86,13 +98,27 @@ public class Material : Asset
|
|||||||
{
|
{
|
||||||
if(_textures.TryGetValue(name, var entry))
|
if(_textures.TryGetValue(name, var entry))
|
||||||
{
|
{
|
||||||
|
/*switch (texture.Get().GetType())
|
||||||
|
{
|
||||||
|
//case .Texture1D:
|
||||||
|
// _textures[name].Dimension = .Texture1D;
|
||||||
|
case typeof(Texture2D):
|
||||||
|
_textures[name].Dimension = .Texture2D;
|
||||||
|
case typeof(TextureCube):
|
||||||
|
_textures[name].Dimension = .TextureCube;
|
||||||
|
//case .Texture3D:
|
||||||
|
// _textures[name].Dimension = .Texture3D;
|
||||||
|
default:
|
||||||
|
_textures[name].Dimension = .Unknown;
|
||||||
|
}*/
|
||||||
//entry?.ReleaseRef();
|
//entry?.ReleaseRef();
|
||||||
_textures[name] = texture;
|
_textures[name].Handle = texture;
|
||||||
//texture?.AddRef();
|
//texture?.AddRef();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Assert(false);
|
Log.EngineLogger.Error($"Material doesn't have the texture slot \"{name}\"");
|
||||||
|
//Log.EngineLogger.Assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,15 +79,6 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
protected extern TextureViewBinding PlatformGetViewBinding();
|
protected extern TextureViewBinding PlatformGetViewBinding();
|
||||||
|
|
||||||
protected internal override void SneakySwappyTexture(Texture otherTexture)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.AssertDebug(otherTexture is RenderTarget2D, "Swapping texture must be a RenderTarget2D!");
|
|
||||||
|
|
||||||
SamplerState = otherTexture.SamplerState;
|
|
||||||
|
|
||||||
PlatformSneakySwappyTexture(otherTexture as RenderTarget2D);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected extern void PlatformSneakySwappyTexture(RenderTarget2D otherTexture);
|
protected extern void PlatformSneakySwappyTexture(RenderTarget2D otherTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ using System.Collections;
|
|||||||
|
|
||||||
namespace GlitchyEngine.Renderer
|
namespace GlitchyEngine.Renderer
|
||||||
{
|
{
|
||||||
public class ShaderTextureCollection : IEnumerable<(String Name, uint32 Index, TextureViewBinding BoundTexture)>
|
public class ShaderTextureCollection : IEnumerable<(String Name, uint32 Index, TextureViewBinding BoundTexture, TextureDimension Dimension)>
|
||||||
{
|
{
|
||||||
public typealias ResourceEntry = (String Name, uint32 Index, TextureViewBinding BoundTexture);
|
public typealias ResourceEntry = (String Name, uint32 Index, TextureViewBinding BoundTexture, TextureDimension Dimension);
|
||||||
|
|
||||||
List<ResourceEntry> _textures ~ DeleteTextureEntries!(_);
|
List<ResourceEntry> _textures ~ DeleteTextureEntries!(_);
|
||||||
|
|
||||||
@@ -39,14 +39,14 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
// TODO: finish implementation (like BufferCollection)
|
// TODO: finish implementation (like BufferCollection)
|
||||||
|
|
||||||
public void Add(String name, uint32 index, TextureViewBinding texture)
|
public void Add(String name, uint32 index, TextureViewBinding texture, TextureDimension dimension)
|
||||||
{
|
{
|
||||||
Add((name, index, texture));
|
Add((name, index, texture, dimension));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(ResourceEntry entry)
|
public void Add(ResourceEntry entry)
|
||||||
{
|
{
|
||||||
ResourceEntry copy = (new String(entry.Name), entry.Index, entry.BoundTexture);
|
ResourceEntry copy = (new String(entry.Name), entry.Index, entry.BoundTexture, entry.Dimension);
|
||||||
entry.BoundTexture.AddRef();
|
entry.BoundTexture.AddRef();
|
||||||
|
|
||||||
_textures.Add(copy);
|
_textures.Add(copy);
|
||||||
|
|||||||
@@ -30,11 +30,6 @@ namespace GlitchyEngine.Renderer
|
|||||||
public abstract uint32 MipLevels {get;}
|
public abstract uint32 MipLevels {get;}
|
||||||
|
|
||||||
public abstract TextureViewBinding GetViewBinding();
|
public abstract TextureViewBinding GetViewBinding();
|
||||||
|
|
||||||
/// Very dirtily swaps the internals with the given texture.
|
|
||||||
/// TODO: Please do this differently!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
/// This is for texture hot reloading POC, I know... it's bad...
|
|
||||||
protected internal abstract void SneakySwappyTexture(Texture otherTexture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Texture2DDesc
|
public struct Texture2DDesc
|
||||||
@@ -69,17 +64,6 @@ namespace GlitchyEngine.Renderer
|
|||||||
//public override extern uint32 ArraySize {get;}
|
//public override extern uint32 ArraySize {get;}
|
||||||
//public override extern uint32 MipLevels {get;}
|
//public override extern uint32 MipLevels {get;}
|
||||||
|
|
||||||
// TODO: remove
|
|
||||||
private this(Stream data)
|
|
||||||
{
|
|
||||||
LoadDds(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void LoadDds(Stream stream)
|
|
||||||
{
|
|
||||||
LoadDdsPlatform(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public this(Texture2DDesc desc)
|
public this(Texture2DDesc desc)
|
||||||
{
|
{
|
||||||
PrepareTexturePlatform(desc, false);
|
PrepareTexturePlatform(desc, false);
|
||||||
@@ -100,8 +84,6 @@ namespace GlitchyEngine.Renderer
|
|||||||
uint32 mipLevels = 1, uint32 arraySize = 1, Usage usage = .Default, CPUAccessFlags cpuAccess = .None
|
uint32 mipLevels = 1, uint32 arraySize = 1, Usage usage = .Default, CPUAccessFlags cpuAccess = .None
|
||||||
*/
|
*/
|
||||||
|
|
||||||
protected extern void LoadDdsPlatform(Stream stream);
|
|
||||||
|
|
||||||
protected extern void CreateTexturePlatform(Texture2DDesc desc, bool isRenderTarget, void* data, uint32 linePitch);
|
protected extern void CreateTexturePlatform(Texture2DDesc desc, bool isRenderTarget, void* data, uint32 linePitch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -130,17 +112,16 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected extern TextureViewBinding PlatformGetViewBinding();
|
protected extern TextureViewBinding PlatformGetViewBinding();
|
||||||
|
|
||||||
protected internal override void SneakySwappyTexture(Texture otherTexture)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.AssertDebug(otherTexture is Texture2D, "Swapping texture must be a Texture2D!");
|
|
||||||
|
|
||||||
SamplerState = otherTexture.SamplerState;
|
|
||||||
|
|
||||||
PlatformSneakySwappyTexture(otherTexture as Texture2D);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected extern void PlatformSneakySwappyTexture(Texture2D otherTexture);
|
public enum TextureCubeFace
|
||||||
|
{
|
||||||
|
PositiveX = 0,
|
||||||
|
NegativeX = 1,
|
||||||
|
PositiveY = 2,
|
||||||
|
NegativeY = 3,
|
||||||
|
PositiveZ = 4,
|
||||||
|
NegativeZ = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TextureCube : Texture
|
public class TextureCube : Texture
|
||||||
@@ -153,23 +134,47 @@ namespace GlitchyEngine.Renderer
|
|||||||
// public override extern uint32 ArraySize {get;}
|
// public override extern uint32 ArraySize {get;}
|
||||||
// public override extern uint32 MipLevels {get;}
|
// public override extern uint32 MipLevels {get;}
|
||||||
|
|
||||||
public this(String path)
|
public this(Texture2DDesc desc)
|
||||||
{
|
{
|
||||||
this._path = new String(path);
|
PrepareTexturePlatform(desc, false);
|
||||||
LoadTexture();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadTexture()
|
public void SetData(void* data, int elementSize, TextureCubeFace cubeFace, uint32 arraySlice = 0, uint32 mipSlice = 0)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
PlatformSetData(data, (.)elementSize, 0, 0, Width, Height, arraySlice * 6 + (uint32)cubeFace, mipSlice, .Write);
|
||||||
|
|
||||||
Stream data = Application.Get().ContentManager.GetStream(_path);
|
|
||||||
defer delete data;
|
|
||||||
|
|
||||||
LoadTexturePlatform(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected extern void LoadTexturePlatform(Stream stream);
|
public void SetData<T>(T* data, TextureCubeFace cubeFace, uint32 arraySlice = 0, uint32 mipSlice = 0)
|
||||||
|
{
|
||||||
|
PlatformSetData(data, (.)sizeof(T), 0, 0, Width, Height, arraySlice * 6 + (uint32)cubeFace, mipSlice, .Write);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetData<T>(T* data, uint32 x, uint32 y, uint32 width, uint32 height, TextureCubeFace cubeFace, uint32 arraySlice = 0, uint32 mipSlice = 0)
|
||||||
|
{
|
||||||
|
PlatformSetData(data, (.)sizeof(T), x, y, width, height, arraySlice * 6 + (uint32)cubeFace, mipSlice, .Write);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected extern void CreateTexturePlatform(Texture2DDesc desc, bool isRenderTarget, void* data, uint32 linePitch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the texture so that a call to SetData can successfully upload the data to the gpu.
|
||||||
|
*/
|
||||||
|
protected extern void PrepareTexturePlatform(Texture2DDesc desc, bool isRenderTarget);
|
||||||
|
|
||||||
|
protected extern Result<void> PlatformSetData(void* data, uint32 elementSize, uint32 destX,
|
||||||
|
uint32 destY, uint32 destWidth, uint32 destHeight, uint32 arraySlice, uint32 mipLevel, GlitchyEngine.Renderer.MapType mapType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the texel-data of this texture to the given destination texture.
|
||||||
|
*/
|
||||||
|
public static extern void CopySubresourceRegion(Texture2D source, Texture2D destination,
|
||||||
|
ResourceBox sourceBox = default, uint32 destX = 0, uint32 destY = 0,
|
||||||
|
uint32 srcArraySlice = 0, uint32 srcMipSlice = 0, uint32 destArraySlice = 0, uint32 destMipSlice = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the data to the given destination.
|
||||||
|
*/
|
||||||
|
//public extern void CopyTo(TextureCube destination);
|
||||||
|
|
||||||
public override TextureViewBinding GetViewBinding()
|
public override TextureViewBinding GetViewBinding()
|
||||||
{
|
{
|
||||||
@@ -177,10 +182,5 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected extern TextureViewBinding PlatformGetViewBinding();
|
protected extern TextureViewBinding PlatformGetViewBinding();
|
||||||
|
|
||||||
protected internal override void SneakySwappyTexture(Texture otherTexture)
|
|
||||||
{
|
|
||||||
Runtime.NotImplemented();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user