aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu
diff options
context:
space:
mode:
authorgdk <gab.dark.100@gmail.com>2019-10-30 20:45:01 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commitd786d8d2b924da7cd116a2eb97d738a9f07b4e43 (patch)
tree0e84072c554066d20622d156d1394144ed5258bd /Ryujinx.Graphics.Gpu
parent3bcc395253e020df40763d36ba9401b126b17173 (diff)
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
Diffstat (limited to 'Ryujinx.Graphics.Gpu')
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/Methods.cs80
-rw-r--r--Ryujinx.Graphics.Gpu/Image/Texture.cs62
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureManager.cs67
3 files changed, 95 insertions, 114 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
index 5d90573c..5d156312 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
@@ -227,40 +227,29 @@ namespace Ryujinx.Graphics.Gpu.Engine
int samplesInX = msaaMode.SamplesInX();
int samplesInY = msaaMode.SamplesInY();
- Image.Texture color3D = Get3DRenderTarget(samplesInX, samplesInY);
-
- if (color3D == null)
+ for (int index = 0; index < Constants.TotalRenderTargets; index++)
{
- for (int index = 0; index < Constants.TotalRenderTargets; index++)
- {
- var colorState = _context.State.Get<RtColorState>(MethodOffset.RtColorState, index);
+ var colorState = _context.State.Get<RtColorState>(MethodOffset.RtColorState, index);
- if (!IsRtEnabled(colorState))
- {
- _textureManager.SetRenderTargetColor(index, null);
+ if (!IsRtEnabled(colorState))
+ {
+ _textureManager.SetRenderTargetColor(index, null);
- continue;
- }
+ continue;
+ }
- Image.Texture color = _textureManager.FindOrCreateTexture(
- colorState,
- samplesInX,
- samplesInY);
+ Image.Texture color = _textureManager.FindOrCreateTexture(
+ colorState,
+ samplesInX,
+ samplesInY);
- _textureManager.SetRenderTargetColor(index, color);
+ _textureManager.SetRenderTargetColor(index, color);
- if (color != null)
- {
- color.Modified = true;
- }
+ if (color != null)
+ {
+ color.Modified = true;
}
}
- else
- {
- _textureManager.SetRenderTargetColor3D(color3D);
-
- color3D.Modified = true;
- }
bool dsEnable = _context.State.Get<Boolean32>(MethodOffset.RtDepthStencilEnable);
@@ -286,45 +275,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
}
}
- private Image.Texture Get3DRenderTarget(int samplesInX, int samplesInY)
- {
- var colorState0 = _context.State.Get<RtColorState>(MethodOffset.RtColorState, 0);
-
- if (!IsRtEnabled(colorState0) || !colorState0.MemoryLayout.UnpackIsTarget3D() || colorState0.Depth != 1)
- {
- return null;
- }
-
- int slices = 1;
- int unused = 0;
-
- for (int index = 1; index < Constants.TotalRenderTargets; index++)
- {
- var colorState = _context.State.Get<RtColorState>(MethodOffset.RtColorState, index);
-
- if (!IsRtEnabled(colorState))
- {
- unused++;
-
- continue;
- }
-
- if (colorState.MemoryLayout.UnpackIsTarget3D() && colorState.Depth == 1)
- {
- slices++;
- }
- }
-
- if (slices + unused == Constants.TotalRenderTargets)
- {
- colorState0.Depth = slices;
-
- return _textureManager.FindOrCreateTexture(colorState0, samplesInX, samplesInY);
- }
-
- return null;
- }
-
private static bool IsRtEnabled(RtColorState colorState)
{
// Colors are disabled by writing 0 to the format.
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index c34ff1d3..cc7e7bf6 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -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();
}
}
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
index 7cf79d0f..2db1b4f2 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
@@ -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)
- {
- _context.Renderer.Pipeline.SetRenderTargets(_rtHostColors, _rtHostDs);
- }
- }
- else
- {
- if (_rtHostColors[0] != _rtColor3D.HostTexture)
+ if (_rtHostColors[index] != 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