Support copy of slices to 3D textures, remove old 3D render target layered render support, do not delete textures with existing views created from them
This commit is contained in:
parent
3bcc395253
commit
d786d8d2b9
9 changed files with 131 additions and 160 deletions
|
@ -6,6 +6,7 @@ using Ryujinx.Graphics.Texture;
|
|||
using Ryujinx.Graphics.Texture.Astc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Image
|
||||
{
|
||||
|
@ -116,6 +117,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
_views.Remove(texture);
|
||||
|
||||
texture._viewStorage = null;
|
||||
|
||||
DeleteIfNotUsed();
|
||||
}
|
||||
|
||||
public void ChangeSize(int width, int height, int depthOrLayers)
|
||||
|
@ -187,7 +190,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
{
|
||||
ITexture newStorage = _context.Renderer.CreateTexture(createInfo);
|
||||
|
||||
HostTexture.CopyTo(newStorage);
|
||||
HostTexture.CopyTo(newStorage, 0, 0);
|
||||
|
||||
ReplaceStorage(newStorage);
|
||||
}
|
||||
|
@ -413,7 +416,21 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
_info.SamplesInY == info.SamplesInY;
|
||||
}
|
||||
|
||||
public bool IsViewCompatible(TextureInfo info, ulong size, out int firstLayer, out int firstLevel)
|
||||
public bool IsViewCompatible(
|
||||
TextureInfo info,
|
||||
ulong size,
|
||||
out int firstLayer,
|
||||
out int firstLevel)
|
||||
{
|
||||
return IsViewCompatible(info, size, isCopy: false, out firstLayer, out firstLevel);
|
||||
}
|
||||
|
||||
public bool IsViewCompatible(
|
||||
TextureInfo info,
|
||||
ulong size,
|
||||
bool isCopy,
|
||||
out int firstLayer,
|
||||
out int firstLevel)
|
||||
{
|
||||
// Out of range.
|
||||
if (info.Address < Address || info.Address + size > EndAddress)
|
||||
|
@ -441,12 +458,12 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!ViewSizeMatches(info, firstLevel))
|
||||
if (!ViewSizeMatches(info, firstLevel, isCopy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ViewTargetCompatible(info))
|
||||
if (!ViewTargetCompatible(info, isCopy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -496,18 +513,24 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
return TextureCompatibility.FormatCompatible(_info.FormatInfo, info.FormatInfo);
|
||||
}
|
||||
|
||||
private bool ViewSizeMatches(TextureInfo info, int level)
|
||||
private bool ViewSizeMatches(TextureInfo info, int level, bool isCopy)
|
||||
{
|
||||
Size size = GetAlignedSize(_info, level);
|
||||
|
||||
Size otherSize = GetAlignedSize(info);
|
||||
|
||||
return size.Width == otherSize.Width &&
|
||||
size.Height == otherSize.Height &&
|
||||
size.Depth == otherSize.Depth;
|
||||
// For copies, we can copy a subset of the 3D texture slices,
|
||||
// so the depth may be different in this case.
|
||||
if (!isCopy && info.Target == Target.Texture3D && size.Depth != otherSize.Depth)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return size.Width == otherSize.Width &&
|
||||
size.Height == otherSize.Height;
|
||||
}
|
||||
|
||||
private bool ViewTargetCompatible(TextureInfo info)
|
||||
private bool ViewTargetCompatible(TextureInfo info, bool isCopy)
|
||||
{
|
||||
switch (_info.Target)
|
||||
{
|
||||
|
@ -534,7 +557,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
info.Target == Target.Texture2DMultisampleArray;
|
||||
|
||||
case Target.Texture3D:
|
||||
return info.Target == Target.Texture3D;
|
||||
return info.Target == Target.Texture3D ||
|
||||
(info.Target == Target.Texture2D && isCopy);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -686,7 +710,9 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
public void DecrementReferenceCount()
|
||||
{
|
||||
if (--_referenceCount == 0)
|
||||
int newRefCount = --_referenceCount;
|
||||
|
||||
if (newRefCount == 0)
|
||||
{
|
||||
if (_viewStorage != this)
|
||||
{
|
||||
|
@ -694,7 +720,21 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
}
|
||||
|
||||
_context.Methods.TextureManager.RemoveTextureFromCache(this);
|
||||
}
|
||||
|
||||
Debug.Assert(newRefCount >= 0);
|
||||
|
||||
DeleteIfNotUsed();
|
||||
}
|
||||
|
||||
private void DeleteIfNotUsed()
|
||||
{
|
||||
// We can delete the texture as long it is not being used
|
||||
// in any cache (the reference count is 0 in this case), and
|
||||
// also all views that may be created from this texture were
|
||||
// already deleted (views count is 0).
|
||||
if (_referenceCount == 0 && _views.Count == 0)
|
||||
{
|
||||
DisposeTextures();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,10 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
private TextureBindingsManager _gpBindingsManager;
|
||||
|
||||
private Texture[] _rtColors;
|
||||
private Texture _rtColor3D;
|
||||
|
||||
private Texture _rtDepthStencil;
|
||||
private Texture _rtDepthStencil;
|
||||
|
||||
private ITexture[] _rtHostColors;
|
||||
|
||||
private ITexture _rtHostDs;
|
||||
private ITexture _rtHostDs;
|
||||
|
||||
private RangeList<Texture> _textures;
|
||||
|
||||
|
@ -98,13 +95,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
public void SetRenderTargetColor(int index, Texture color)
|
||||
{
|
||||
_rtColors[index] = color;
|
||||
|
||||
_rtColor3D = null;
|
||||
}
|
||||
|
||||
public void SetRenderTargetColor3D(Texture color)
|
||||
{
|
||||
_rtColor3D = color;
|
||||
}
|
||||
|
||||
public void SetRenderTargetDepthStencil(Texture depthStencil)
|
||||
|
@ -141,38 +131,21 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
anyChanged = true;
|
||||
}
|
||||
|
||||
if (_rtColor3D == null)
|
||||
for (int index = 0; index < _rtColors.Length; index++)
|
||||
{
|
||||
for (int index = 0; index < _rtColors.Length; index++)
|
||||
{
|
||||
ITexture hostTexture = _rtColors[index]?.HostTexture;
|
||||
ITexture hostTexture = _rtColors[index]?.HostTexture;
|
||||
|
||||
if (_rtHostColors[index] != hostTexture)
|
||||
{
|
||||
_rtHostColors[index] = hostTexture;
|
||||
|
||||
anyChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (anyChanged)
|
||||
if (_rtHostColors[index] != hostTexture)
|
||||
{
|
||||
_context.Renderer.Pipeline.SetRenderTargets(_rtHostColors, _rtHostDs);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_rtHostColors[0] != _rtColor3D.HostTexture)
|
||||
{
|
||||
_rtHostColors[0] = _rtColor3D.HostTexture;
|
||||
_rtHostColors[index] = hostTexture;
|
||||
|
||||
anyChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (anyChanged)
|
||||
{
|
||||
_context.Renderer.Pipeline.SetRenderTargets(_rtColor3D.HostTexture, _rtHostDs);
|
||||
}
|
||||
if (anyChanged)
|
||||
{
|
||||
_context.Renderer.Pipeline.SetRenderTargets(_rtHostColors, _rtHostDs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -447,11 +420,29 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
ITexture newView = texture.HostTexture.CreateView(createInfo, firstLayer, firstLevel);
|
||||
|
||||
overlap.HostTexture.CopyTo(newView);
|
||||
overlap.HostTexture.CopyTo(newView, 0, 0);
|
||||
|
||||
overlap.ReplaceView(texture, overlapInfo, newView);
|
||||
}
|
||||
}
|
||||
|
||||
// If the texture is a 3D texture, we need to additionally copy any slice
|
||||
// of the 3D texture to the newly created 3D texture.
|
||||
if (info.Target == Target.Texture3D)
|
||||
{
|
||||
foreach (Texture overlap in overlaps)
|
||||
{
|
||||
if (texture.IsViewCompatible(
|
||||
overlap.Info,
|
||||
overlap.Size,
|
||||
isCopy: true,
|
||||
out int firstLayer,
|
||||
out int firstLevel))
|
||||
{
|
||||
overlap.HostTexture.CopyTo(texture.HostTexture, firstLayer, firstLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sampler textures are managed by the texture pool, all other textures
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue