| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- using Ryujinx.Graphics.GAL;
- using Ryujinx.Graphics.GAL.Texture;
- using Ryujinx.Graphics.Gpu.Memory;
- using System;
- using System.Collections.Generic;
- using System.Runtime.InteropServices;
- namespace Ryujinx.Graphics.Gpu.Image
- {
- class TexturePool : Pool<Texture>
- {
- public LinkedListNode<TexturePool> CacheNode { get; set; }
- private struct TextureContainer
- {
- public Texture Texture0 { get; set; }
- public Texture Texture1 { get; set; }
- }
- public TexturePool(
- GpuContext context,
- ulong address,
- int maximumId) : base(context, address, maximumId) { }
- public override Texture Get(int id)
- {
- if ((uint)id >= Items.Length)
- {
- return null;
- }
- SynchronizeMemory();
- Texture texture = Items[id];
- if (texture == null)
- {
- ulong address = Address + (ulong)(uint)id * DescriptorSize;
- Span<byte> data = Context.PhysicalMemory.Read(address, DescriptorSize);
- TextureDescriptor descriptor = MemoryMarshal.Cast<byte, TextureDescriptor>(data)[0];
- TextureInfo info = GetInfo(descriptor);
- // Bad address. We can't add a texture with a invalid address
- // to the cache.
- if (info.Address == MemoryManager.BadAddress)
- {
- return null;
- }
- texture = Context.Methods.TextureManager.FindOrCreateTexture(info, TextureSearchFlags.Sampler);
- texture.IncrementReferenceCount();
- Items[id] = texture;
- }
- else
- {
- // Memory is automatically synchronized on texture creation.
- texture.SynchronizeMemory();
- }
- return texture;
- }
- protected override void InvalidateRangeImpl(ulong address, ulong size)
- {
- ulong endAddress = address + size;
- for (; address < endAddress; address += DescriptorSize)
- {
- int id = (int)((address - Address) / DescriptorSize);
- Texture texture = Items[id];
- if (texture != null)
- {
- Span<byte> data = Context.PhysicalMemory.Read(address, DescriptorSize);
- TextureDescriptor descriptor = MemoryMarshal.Cast<byte, TextureDescriptor>(data)[0];
- // If the descriptors are the same, the texture is the same,
- // we don't need to remove as it was not modified. Just continue.
- if (texture.IsPerfectMatch(GetInfo(descriptor), TextureSearchFlags.Strict))
- {
- continue;
- }
- texture.DecrementReferenceCount();
- Items[id] = null;
- }
- }
- }
- private TextureInfo GetInfo(TextureDescriptor descriptor)
- {
- ulong address = Context.MemoryManager.Translate(descriptor.UnpackAddress());
- int width = descriptor.UnpackWidth();
- int height = descriptor.UnpackHeight();
- int depthOrLayers = descriptor.UnpackDepth();
- int levels = descriptor.UnpackLevels();
- TextureMsaaMode msaaMode = descriptor.UnpackTextureMsaaMode();
- int samplesInX = msaaMode.SamplesInX();
- int samplesInY = msaaMode.SamplesInY();
- int stride = descriptor.UnpackStride();
- TextureDescriptorType descriptorType = descriptor.UnpackTextureDescriptorType();
- bool isLinear = descriptorType == TextureDescriptorType.Linear;
- Target target = descriptor.UnpackTextureTarget().Convert((samplesInX | samplesInY) != 1);
- uint format = descriptor.UnpackFormat();
- bool srgb = descriptor.UnpackSrgb();
- if (!FormatTable.TryGetTextureFormat(format, srgb, out FormatInfo formatInfo))
- {
- // TODO: Warning.
- formatInfo = FormatInfo.Default;
- }
- int gobBlocksInY = descriptor.UnpackGobBlocksInY();
- int gobBlocksInZ = descriptor.UnpackGobBlocksInZ();
- int gobBlocksInTileX = descriptor.UnpackGobBlocksInTileX();
- SwizzleComponent swizzleR = descriptor.UnpackSwizzleR().Convert();
- SwizzleComponent swizzleG = descriptor.UnpackSwizzleG().Convert();
- SwizzleComponent swizzleB = descriptor.UnpackSwizzleB().Convert();
- SwizzleComponent swizzleA = descriptor.UnpackSwizzleA().Convert();
- DepthStencilMode depthStencilMode = GetDepthStencilMode(
- formatInfo.Format,
- swizzleR,
- swizzleG,
- swizzleB,
- swizzleA);
- return new TextureInfo(
- address,
- width,
- height,
- depthOrLayers,
- levels,
- samplesInX,
- samplesInY,
- stride,
- isLinear,
- gobBlocksInY,
- gobBlocksInZ,
- gobBlocksInTileX,
- target,
- formatInfo,
- depthStencilMode,
- swizzleR,
- swizzleG,
- swizzleB,
- swizzleA);
- }
- private static DepthStencilMode GetDepthStencilMode(Format format, params SwizzleComponent[] components)
- {
- // R = Depth, G = Stencil.
- // On 24-bits depth formats, this is inverted (Stencil is R etc).
- // NVN setup:
- // For depth, A is set to 1.0f, the other components are set to Depth.
- // For stencil, all components are set to Stencil.
- SwizzleComponent component = components[0];
- for (int index = 1; index < 4 && !IsRG(component); index++)
- {
- component = components[index];
- }
- if (!IsRG(component))
- {
- return DepthStencilMode.Depth;
- }
- if (format == Format.D24X8Unorm || format == Format.D24UnormS8Uint)
- {
- return component == SwizzleComponent.Red
- ? DepthStencilMode.Stencil
- : DepthStencilMode.Depth;
- }
- else
- {
- return component == SwizzleComponent.Red
- ? DepthStencilMode.Depth
- : DepthStencilMode.Stencil;
- }
- }
- private static bool IsRG(SwizzleComponent component)
- {
- return component == SwizzleComponent.Red ||
- component == SwizzleComponent.Green;
- }
- protected override void Delete(Texture item)
- {
- item?.DecrementReferenceCount();
- }
- }
- }
|