fix(gpu): support Gen5 flat memory and 3D images (#587)

Vector-mesh UI text samples type-10 volume LUTs; treat MIMG DIM=2 as
Dim3D and transport depth through AGC and Vulkan so Z slices no longer
collapse into a single 2D plane.
This commit is contained in:
MarcelMediaDev
2026-07-24 13:44:58 +01:00
committed by GitHub
parent 21f964a0dc
commit 5228335f15
14 changed files with 1311 additions and 299 deletions
+119 -35
View File
@@ -8328,16 +8328,33 @@ public static partial class AgcExports
return tailLinear;
}
var volumeDepth = checked((int)GetTextureVolumeDepth(
descriptor.Type,
descriptor.Depth));
if (logicalByteCount % volumeDepth != 0 ||
source.Length % volumeDepth != 0)
{
return null;
}
var logicalSliceByteCount = logicalByteCount / volumeDepth;
var physicalSliceByteCount = source.Length / volumeDepth;
var linear = new byte[logicalByteCount];
return GnmTiling.TryDetile(
source,
linear,
descriptor.TileMode,
elementsWide,
elementsHigh,
bytesPerElement)
? linear
: null;
for (var slice = 0; slice < volumeDepth; slice++)
{
if (!GnmTiling.TryDetile(
source.AsSpan(slice * physicalSliceByteCount, physicalSliceByteCount),
linear.AsSpan(slice * logicalSliceByteCount, logicalSliceByteCount),
descriptor.TileMode,
elementsWide,
elementsHigh,
bytesPerElement))
{
return null;
}
}
return linear;
}
private static void TraceTextureFallback(TextureDescriptor descriptor, string reason)
@@ -8369,6 +8386,9 @@ public static partial class AgcExports
out GuestDrawTexture texture)
{
texture = default!;
var textureDepth = GetTextureVolumeDepth(
descriptor.Type,
descriptor.Depth);
if ((descriptor.Type != Gen5TextureType1D &&
descriptor.Type != Gen5TextureType2D &&
descriptor.Type != Gen5TextureType3D &&
@@ -8381,7 +8401,13 @@ public static partial class AgcExports
descriptor.Height > 8192)
{
TraceTextureFallback(descriptor, "invalid-descriptor");
texture = CreateFallbackGuestDrawTexture(isStorage, descriptor.Format, descriptor.NumberType, isArrayed);
texture = CreateFallbackGuestDrawTexture(
isStorage,
descriptor.Format,
descriptor.NumberType,
isArrayed,
descriptor.Type,
textureDepth);
return true;
}
@@ -8391,10 +8417,15 @@ public static partial class AgcExports
descriptor.Height,
descriptor.Format)
: descriptor.Width;
var sourceByteCount = GetTextureByteCount(
var sourceSliceByteCount = GetTextureByteCount(
descriptor.Format,
sourceWidth,
descriptor.Height);
var sourceByteCount = GetTextureByteCount(
descriptor.Format,
sourceWidth,
descriptor.Height,
textureDepth);
if (sourceByteCount == 0 ||
sourceByteCount > MaxPresentedTextureBytes ||
sourceByteCount > int.MaxValue)
@@ -8402,11 +8433,17 @@ public static partial class AgcExports
TraceTextureFallback(
descriptor,
$"invalid-byte-count:{sourceByteCount}");
texture = CreateFallbackGuestDrawTexture(isStorage, descriptor.Format, descriptor.NumberType, isArrayed);
texture = CreateFallbackGuestDrawTexture(
isStorage,
descriptor.Format,
descriptor.NumberType,
isArrayed,
descriptor.Type,
textureDepth);
return true;
}
var physicalSourceByteCount = sourceByteCount;
var physicalSourceByteCount = sourceSliceByteCount;
var elementsWide = 0;
var elementsHigh = 0;
var bytesPerElement = 0;
@@ -8428,13 +8465,6 @@ public static partial class AgcExports
physicalSourceByteCount = tiledByteCount;
}
if (physicalSourceByteCount > MaxPresentedTextureBytes ||
physicalSourceByteCount > int.MaxValue)
{
texture = CreateFallbackGuestDrawTexture(isStorage, descriptor.Format, descriptor.NumberType, isArrayed);
return true;
}
var resourceMipLevels = descriptor.HasExtendedDescriptor
? descriptor.ResourceMipLevels
: 1u;
@@ -8459,6 +8489,20 @@ public static partial class AgcExports
chainSliceBytes = placedChainSliceBytes;
}
physicalSourceByteCount = checked(physicalSourceByteCount * textureDepth);
if (physicalSourceByteCount > MaxPresentedTextureBytes ||
physicalSourceByteCount > int.MaxValue)
{
texture = CreateFallbackGuestDrawTexture(
isStorage,
descriptor.Format,
descriptor.NumberType,
isArrayed,
descriptor.Type,
textureDepth);
return true;
}
var wantsArrayUpload = isArrayed &&
!isStorage &&
descriptor.Address != 0 &&
@@ -8497,7 +8541,9 @@ public static partial class AgcExports
TileMode: descriptor.TileMode,
DstSelect: descriptor.DstSelect,
Sampler: ToGuestSampler(samplerDescriptor),
ArrayedView: isArrayed);
ArrayedView: isArrayed,
Type: descriptor.Type,
Depth: textureDepth);
return true;
}
@@ -8573,7 +8619,9 @@ public static partial class AgcExports
Pitch: sourceWidth,
TileMode: descriptor.TileMode,
DstSelect: descriptor.DstSelect,
Sampler: ToGuestSampler(samplerDescriptor));
Sampler: ToGuestSampler(samplerDescriptor),
Type: descriptor.Type,
Depth: textureDepth);
return true;
}
@@ -8614,7 +8662,9 @@ public static partial class AgcExports
sourceWidth,
sampler,
isArrayed,
arrayUploadLayers)))
arrayUploadLayers,
descriptor.Type,
textureDepth)))
{
texture = new GuestDrawTexture(
descriptor.Address,
@@ -8634,14 +8684,16 @@ public static partial class AgcExports
DstSelect: descriptor.DstSelect,
Sampler: sampler,
ArrayedView: isArrayed,
ArrayLayers: arrayUploadLayers);
ArrayLayers: arrayUploadLayers,
Type: descriptor.Type,
Depth: textureDepth);
return true;
}
if (wantsArrayUpload)
{
var arrayLayers = arrayUploadLayers;
var layerBytes = checked((int)sourceByteCount);
var layerBytes = checked((int)sourceSliceByteCount);
var totalBytes = (long)layerBytes * arrayLayers;
if (totalBytes <= int.MaxValue)
{
@@ -8649,7 +8701,7 @@ public static partial class AgcExports
var uploadedLayers = 0u;
for (var layer = 0u; layer < arrayLayers; layer++)
{
var sliceSource = new byte[(int)physicalSourceByteCount];
var sliceSource = new byte[(int)chainSliceBytes];
if (!ctx.Memory.TryRead(
descriptor.Address + layer * chainSliceBytes + baseMipByteOffset,
sliceSource))
@@ -8690,7 +8742,9 @@ public static partial class AgcExports
DstSelect: descriptor.DstSelect,
Sampler: sampler,
ArrayedView: true,
ArrayLayers: arrayLayers);
ArrayLayers: arrayLayers,
Type: descriptor.Type,
Depth: textureDepth);
return true;
}
}
@@ -8704,7 +8758,13 @@ public static partial class AgcExports
TraceTextureFallback(
descriptor,
$"guest-read-failed:{sourceByteCount}");
texture = CreateFallbackGuestDrawTexture(isStorage, descriptor.Format, descriptor.NumberType, isArrayed);
texture = CreateFallbackGuestDrawTexture(
isStorage,
descriptor.Format,
descriptor.NumberType,
isArrayed,
descriptor.Type,
textureDepth);
return true;
}
@@ -8759,7 +8819,9 @@ public static partial class AgcExports
DstSelect: descriptor.DstSelect,
Sampler: ToGuestSampler(samplerDescriptor),
WriteGeneration: hasWriteGeneration ? writeGeneration : -1,
ArrayedView: isArrayed);
ArrayedView: isArrayed,
Type: descriptor.Type,
Depth: textureDepth);
return true;
}
@@ -9039,7 +9101,9 @@ public static partial class AgcExports
bool isStorage,
uint format,
uint numberType,
bool isArrayed = false)
bool isArrayed = false,
uint type = Gen5TextureType2D,
uint depth = 1)
{
var fallbackFormat = format == 0 ? 10u : format;
var fallbackNumberType = numberType;
@@ -9054,7 +9118,9 @@ public static partial class AgcExports
IsStorage: isStorage,
MipLevels: 1,
MipLevel: 0,
ArrayedView: isArrayed);
ArrayedView: isArrayed,
Type: type,
Depth: GetTextureVolumeDepth(type, depth));
}
private static GuestSampler ToGuestSampler(IReadOnlyList<uint> descriptor) =>
@@ -10240,7 +10306,8 @@ public static partial class AgcExports
var totalBytes = GetTextureByteCount(
texture.Format,
texture.Width,
texture.Height);
texture.Height,
GetTextureVolumeDepth(texture.Type, texture.Depth));
if (totalBytes == 0)
{
return "probe=unsupported";
@@ -10323,20 +10390,37 @@ public static partial class AgcExports
_ => 0UL,
};
private static ulong GetTextureByteCount(uint format, uint width, uint height)
internal static ulong GetTextureByteCount(
uint format,
uint width,
uint height,
uint depth = 1)
{
var bytesPerTexel = GetTextureBytesPerTexel(format);
if (bytesPerTexel != 0)
{
return checked((ulong)width * height * bytesPerTexel);
return checked(
(ulong)width *
height *
Math.Max(depth, 1u) *
bytesPerTexel);
}
var blockBytes = (ulong)GetBlockCompressedBlockBytes(format);
return blockBytes == 0
? 0
: checked(((ulong)width + 3) / 4 * (((ulong)height + 3) / 4) * blockBytes);
: checked(
((ulong)width + 3) / 4 *
(((ulong)height + 3) / 4) *
Math.Max(depth, 1u) *
blockBytes);
}
internal static uint GetTextureVolumeDepth(uint type, uint depth) =>
type == Gen5TextureType3D
? Math.Max(depth, 1u)
: 1u;
private static uint GetLinearTexturePitch(uint pitch, uint height, uint format)
{
var bytesPerTexel = GetTextureBytesPerTexel(format);