mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-31 23:19:44 +08:00
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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user