Support copy between multisample and non-multisample depth textures (#4676)
* Support copy between multisample and non-multisample depth textures * PR feedback
This commit is contained in:
parent
eabd0ec93f
commit
d9b63353b0
12 changed files with 947 additions and 66 deletions
103
Ryujinx.Graphics.OpenGL/Image/IntermmediatePool.cs
Normal file
103
Ryujinx.Graphics.OpenGL/Image/IntermmediatePool.cs
Normal file
|
@ -0,0 +1,103 @@
|
|||
using Ryujinx.Graphics.GAL;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.OpenGL.Image
|
||||
{
|
||||
class IntermediatePool : IDisposable
|
||||
{
|
||||
private readonly OpenGLRenderer _renderer;
|
||||
private readonly List<TextureView> _entries;
|
||||
|
||||
public IntermediatePool(OpenGLRenderer renderer)
|
||||
{
|
||||
_renderer = renderer;
|
||||
_entries = new List<TextureView>();
|
||||
}
|
||||
|
||||
public TextureView GetOrCreateWithAtLeast(
|
||||
Target target,
|
||||
int blockWidth,
|
||||
int blockHeight,
|
||||
int bytesPerPixel,
|
||||
Format format,
|
||||
int width,
|
||||
int height,
|
||||
int depth,
|
||||
int levels,
|
||||
int samples)
|
||||
{
|
||||
TextureView entry;
|
||||
|
||||
for (int i = 0; i < _entries.Count; i++)
|
||||
{
|
||||
entry = _entries[i];
|
||||
|
||||
if (entry.Target == target && entry.Format == format && entry.Info.Samples == samples)
|
||||
{
|
||||
if (entry.Width < width ||
|
||||
entry.Height < height ||
|
||||
entry.Info.Depth < depth ||
|
||||
entry.Info.Levels < levels)
|
||||
{
|
||||
width = Math.Max(width, entry.Width);
|
||||
height = Math.Max(height, entry.Height);
|
||||
depth = Math.Max(depth, entry.Info.Depth);
|
||||
levels = Math.Max(levels, entry.Info.Levels);
|
||||
|
||||
entry.Dispose();
|
||||
entry = CreateNew(target, blockWidth, blockHeight, bytesPerPixel, format, width, height, depth, levels, samples);
|
||||
_entries[i] = entry;
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
entry = CreateNew(target, blockWidth, blockHeight, bytesPerPixel, format, width, height, depth, levels, samples);
|
||||
_entries.Add(entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
private TextureView CreateNew(
|
||||
Target target,
|
||||
int blockWidth,
|
||||
int blockHeight,
|
||||
int bytesPerPixel,
|
||||
Format format,
|
||||
int width,
|
||||
int height,
|
||||
int depth,
|
||||
int levels,
|
||||
int samples)
|
||||
{
|
||||
return (TextureView)_renderer.CreateTexture(new TextureCreateInfo(
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
levels,
|
||||
samples,
|
||||
blockWidth,
|
||||
blockHeight,
|
||||
bytesPerPixel,
|
||||
format,
|
||||
DepthStencilMode.Depth,
|
||||
target,
|
||||
SwizzleComponent.Red,
|
||||
SwizzleComponent.Green,
|
||||
SwizzleComponent.Blue,
|
||||
SwizzleComponent.Alpha), 1f);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (TextureView entry in _entries)
|
||||
{
|
||||
entry.Dispose();
|
||||
}
|
||||
|
||||
_entries.Clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,9 +15,12 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
private int _copyPboHandle;
|
||||
private int _copyPboSize;
|
||||
|
||||
public IntermediatePool IntermediatePool { get; }
|
||||
|
||||
public TextureCopy(OpenGLRenderer renderer)
|
||||
{
|
||||
_renderer = renderer;
|
||||
IntermediatePool = new IntermediatePool(renderer);
|
||||
}
|
||||
|
||||
public void Copy(
|
||||
|
@ -514,6 +517,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
|
||||
_copyPboHandle = 0;
|
||||
}
|
||||
|
||||
IntermediatePool.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue