aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-04-17 05:13:53 -0300
committerGitHub <noreply@github.com>2023-04-17 08:13:53 +0000
commitd9b63353b019e1f1775370154f4f045ff14184ce (patch)
treeef4909c3da741eb9c498fcd57891c857a5cabe5a /Ryujinx.Graphics.OpenGL/Image/TextureView.cs
parenteabd0ec93f903fb39605a29b35db4c6290bc9c88 (diff)
Support copy between multisample and non-multisample depth textures (#4676)1.1.721
* Support copy between multisample and non-multisample depth textures * PR feedback
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Image/TextureView.cs')
-rw-r--r--Ryujinx.Graphics.OpenGL/Image/TextureView.cs78
1 files changed, 74 insertions, 4 deletions
diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
index ddc5f9a3..804b3b03 100644
--- a/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
+++ b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
@@ -117,12 +117,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
TextureView destinationView = (TextureView)destination;
- if (!destinationView.Target.IsMultisample() && Target.IsMultisample())
+ bool srcIsMultisample = Target.IsMultisample();
+ bool dstIsMultisample = destinationView.Target.IsMultisample();
+
+ if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil())
+ {
+ int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
+ CopyWithBlitForDepthMS(destinationView, 0, firstLayer, layers);
+ }
+ else if (!dstIsMultisample && srcIsMultisample)
{
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_renderer.TextureCopyMS.CopyMSToNonMS(this, destinationView, 0, firstLayer, layers);
}
- else if (destinationView.Target.IsMultisample() && !Target.IsMultisample())
+ else if (dstIsMultisample && !srcIsMultisample)
{
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_renderer.TextureCopyMS.CopyNonMSToMS(this, destinationView, 0, firstLayer, layers);
@@ -143,11 +151,18 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
TextureView destinationView = (TextureView)destination;
- if (!destinationView.Target.IsMultisample() && Target.IsMultisample())
+ bool srcIsMultisample = Target.IsMultisample();
+ bool dstIsMultisample = destinationView.Target.IsMultisample();
+
+ if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil())
+ {
+ CopyWithBlitForDepthMS(destinationView, srcLayer, dstLayer, 1);
+ }
+ else if (!dstIsMultisample && srcIsMultisample)
{
_renderer.TextureCopyMS.CopyMSToNonMS(this, destinationView, srcLayer, dstLayer, 1);
}
- else if (destinationView.Target.IsMultisample() && !Target.IsMultisample())
+ else if (dstIsMultisample && !srcIsMultisample)
{
_renderer.TextureCopyMS.CopyNonMSToMS(this, destinationView, srcLayer, dstLayer, 1);
}
@@ -161,6 +176,61 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
}
+ private void CopyWithBlitForDepthMS(TextureView destinationView, int srcLayer, int dstLayer, int layers)
+ {
+ // This is currently used for multisample <-> non-multisample copies.
+ // We can't do that with compute because it's not possible to write depth textures on compute.
+ // It can be done with draws, but we don't have support for saving and restoring the OpenGL state
+ // for a draw with different state right now.
+ // This approach uses blit, which causes a resolution loss since some samples will be lost
+ // in the process.
+
+ Extents2D srcRegion = new Extents2D(0, 0, Width, Height);
+ Extents2D dstRegion = new Extents2D(0, 0, destinationView.Width, destinationView.Height);
+
+ if (destinationView.Target.IsMultisample())
+ {
+ TextureView intermmediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
+ Info.Target,
+ Info.BlockWidth,
+ Info.BlockHeight,
+ Info.BytesPerPixel,
+ Format,
+ destinationView.Width,
+ destinationView.Height,
+ Info.Depth,
+ 1,
+ 1);
+
+ _renderer.TextureCopy.Copy(this, intermmediate, srcRegion, dstRegion, false);
+ _renderer.TextureCopy.Copy(intermmediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
+ }
+ else
+ {
+ Target target = Target switch
+ {
+ Target.Texture2DMultisample => Target.Texture2D,
+ Target.Texture2DMultisampleArray => Target.Texture2DArray,
+ _ => Target
+ };
+
+ TextureView intermmediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
+ target,
+ Info.BlockWidth,
+ Info.BlockHeight,
+ Info.BytesPerPixel,
+ Format,
+ Width,
+ Height,
+ Info.Depth,
+ 1,
+ 1);
+
+ _renderer.TextureCopy.Copy(this, intermmediate, srcRegion, srcRegion, false);
+ _renderer.TextureCopy.Copy(intermmediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
+ }
+ }
+
public void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter)
{
_renderer.TextureCopy.Copy(this, (TextureView)destination, srcRegion, dstRegion, linearFilter);