[GPU] Track DCC metadata coverage for color targets and volume textures
Co-authored-by: Sekai <140012992+SekaixX@users.noreply.github.com>
This commit is contained in:
parent
7be8a4b389
commit
ef10b4a1d8
|
|
@ -43,24 +43,38 @@ public static partial class ImageRequestBuilders
|
|||
|
||||
public static uint SampleCount(uint encodedLog2) => encodedLog2 <= 3 ? 1u << (int)encodedLog2 : 0;
|
||||
|
||||
private static bool DccAlphaOnMsb(in ColorTargetWords words)
|
||||
{
|
||||
switch (words.Layout)
|
||||
{
|
||||
case ChannelLayout.Bits10_10_10_2:
|
||||
case ChannelLayout.Bits10_10_10_2Float:
|
||||
case ChannelLayout.Bits5_5_5_1:
|
||||
return true;
|
||||
case ChannelLayout.Bits2_10_10_10:
|
||||
case ChannelLayout.Bits1_5_5_5:
|
||||
return false;
|
||||
}
|
||||
|
||||
var components = GuestPixelFormats.ResolveRenderTargetEncoding(words.Layout, words.NumberType).Components;
|
||||
if (components == 1)
|
||||
{
|
||||
return words.Order != ChannelOrder.Standard;
|
||||
}
|
||||
|
||||
return components == 3 || words.Order is ChannelOrder.Standard or ChannelOrder.Alternate;
|
||||
}
|
||||
|
||||
// DCC clears use the target's packed clear word; the fixed-clear set is a format allow-list.
|
||||
private static (bool Supported, bool FixedSupported, ClearColorValue Value) DccClearInfo(Format format, bool hasDcc, uint packedClear)
|
||||
{
|
||||
ClearColorValue value = default;
|
||||
var supported = hasDcc && PackedClearValue.TryDecodeColor(format, packedClear, out value);
|
||||
var fixedSupported = hasDcc && SupportsDccFixedClear(format);
|
||||
var fixedSupported = hasDcc && PackedClearValue.SupportsDccFixedColor(format);
|
||||
return (supported, fixedSupported, supported ? value : default);
|
||||
}
|
||||
|
||||
public static bool SupportsDccFixedClear(Format format) => format switch
|
||||
{
|
||||
Format.R8Unorm or Format.R8G8Unorm or Format.R8G8B8A8Unorm or Format.R8G8B8A8Srgb or Format.B8G8R8A8Unorm or Format.B8G8R8A8Srgb or
|
||||
Format.A2B10G10R10UnormPack32 or Format.A2R10G10B10UnormPack32 or Format.R5G6B5UnormPack16 or Format.A1R5G5B5UnormPack16 or
|
||||
Format.R4G4B4A4UnormPack16 or Format.R16Unorm or Format.R16G16Unorm or Format.R16G16B16A16Unorm or Format.R16Sfloat or
|
||||
Format.R16G16Sfloat or Format.R16G16B16A16Sfloat or Format.R32Sfloat or Format.R32G32Sfloat or Format.R32G32B32A32Sfloat or
|
||||
Format.B10G11R11UfloatPack32 => true,
|
||||
_ => false,
|
||||
};
|
||||
public static bool SupportsDccFixedClear(Format format) => PackedClearValue.SupportsDccFixedColor(format);
|
||||
|
||||
// Builds the request for a bound color target. Null when the slot carries no target.
|
||||
public static ColorTargetResolution? ColorTarget(in ColorTargetWords words, uint targetMask, uint drawLayerOffset, bool ignoreTargetMask)
|
||||
|
|
@ -324,8 +338,14 @@ public static partial class ImageRequestBuilders
|
|||
if (hasDcc)
|
||||
{
|
||||
// DCC lives in its own allocation; the address lets the cache match fills seen before the target.
|
||||
_ = TileGeometry.TryGetDccSize(
|
||||
width, height, volume ? depth : view.ImageLayers, bytesPerElement, levels, tileMode,
|
||||
out var metadataSize, words.FragmentsLog2);
|
||||
description.Metadata.Kind = MetadataKind.Dcc;
|
||||
description.Metadata.Range = new GuestSpan(words.DccAddress, 0);
|
||||
description.Metadata.Range = new GuestSpan(words.DccAddress, metadataSize.Size);
|
||||
description.Metadata.DccClearWord = words.ClearWord0;
|
||||
description.Metadata.DccClearRegisterValid = true;
|
||||
description.Metadata.DccAlphaMsb = DccAlphaOnMsb(words);
|
||||
}
|
||||
|
||||
for (var level = 0; level < levels; level++)
|
||||
|
|
|
|||
|
|
@ -300,12 +300,15 @@ public static partial class ImageRequestBuilders
|
|||
description.BytesPerBlock = blockBytes != 0 ? blockBytes : GuestPixelFormats.BytesPerElement(format);
|
||||
description.Samples = samples;
|
||||
description.TileMode = tile;
|
||||
var metadataAddress = descriptor.MetadataAddress << 8;
|
||||
if (!storage && type == GuestImageType.Color2D && samples == 1 && levels == 1 && tile == GuestTileMode.RenderTarget && descriptor.MetadataCompress &&
|
||||
metadataAddress != 0 && metadataAddress < TrackerLayout.SpaceBytes)
|
||||
if (!shape.R128 && words.Length >= 8 && descriptor.MetadataCompress &&
|
||||
tile != GuestTileMode.Depth && !description.IsDepth)
|
||||
{
|
||||
_ = TileGeometry.TryGetDccSize(
|
||||
width, height, volume ? depth : imageLayers, description.BytesPerBlock, levels, tile,
|
||||
out var metadataSize, (uint)System.Numerics.BitOperations.TrailingZeroCount(samples));
|
||||
description.Metadata.Kind = MetadataKind.Dcc;
|
||||
description.Metadata.Range = new GuestSpan(metadataAddress, 0);
|
||||
description.Metadata.Range = new GuestSpan(descriptor.MetadataAddress << 8, metadataSize.Size);
|
||||
description.Metadata.DccAlphaMsb = descriptor.DccAlphaMsb;
|
||||
}
|
||||
|
||||
if (samples > 1)
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ public readonly struct TextureDescriptorWords
|
|||
|
||||
public bool MetadataCompress => ((Fields[6] >> 21) & 0x1) == 1;
|
||||
|
||||
public bool DccAlphaMsb => ((Fields[6] >> 22) & 0x1) == 1;
|
||||
|
||||
public ulong MetadataAddress => ((Fields[6] >> 24) & 0xFF) | ((ulong)Fields[7] << 8);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -608,6 +608,39 @@ public static partial class TileGeometry
|
|||
return true;
|
||||
}
|
||||
|
||||
public static bool TryGetDccSize(
|
||||
uint width,
|
||||
uint height,
|
||||
uint slices,
|
||||
uint bytesPerElement,
|
||||
uint levels,
|
||||
GuestTileMode tile,
|
||||
out TileSizeAndAlignment totalSize,
|
||||
uint fragmentsLog2 = 0)
|
||||
{
|
||||
totalSize = default;
|
||||
if (width == 0 || height == 0 || slices == 0 || levels != 1 || fragmentsLog2 != 0 ||
|
||||
!BitOperations.IsPow2(bytesPerElement) || bytesPerElement > 16 ||
|
||||
tile is not (GuestTileMode.RenderTarget or GuestTileMode.Depth))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var coverageBits = 20 - BitOperations.TrailingZeroCount(bytesPerElement);
|
||||
var blockWidth = 1u << ((coverageBits + 1) / 2);
|
||||
var blockHeight = 1u << (coverageBits / 2);
|
||||
var blocksX = ((ulong)width + blockWidth - 1) / blockWidth;
|
||||
var blocksY = ((ulong)height + blockHeight - 1) / blockHeight;
|
||||
var blocks = blocksX * blocksY;
|
||||
if (blocks == 0 || blocks > uint.MaxValue / 4096u / slices)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
totalSize = new TileSizeAndAlignment((uint)(blocks * slices * 4096u), 4096);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryGetRenderTargetMipLayout(uint width, uint height, uint pitch, uint bytesPerElement, uint levels, out TileSizeAndAlignment totalSize, TileLevelSpan[]? levelSpans, TilePaddedSize[]? paddedSizes)
|
||||
{
|
||||
totalSize = default;
|
||||
|
|
|
|||
Loading…
Reference in New Issue