Workaround for AMD and Intel view format bug (#1050)

* Workaround for Intel view format bug

* Dispose of the intermmediate texture aswell

* Apply workaround on AMD aswell
This commit is contained in:
gdkchan 2020-03-29 09:48:39 -03:00 committed by GitHub
parent 5c1757f7c2
commit b18ef8e3a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 222 additions and 119 deletions

View file

@ -14,24 +14,19 @@ namespace Ryujinx.Graphics.OpenGL
private TextureView _emulatedViewParent;
private TextureView _incompatibleFormatView;
private readonly TextureCreateInfo _info;
private int _firstLayer;
private int _firstLevel;
public int FirstLayer { get; private set; }
public int FirstLevel { get; private set; }
public int Width => _info.Width;
public int Height => _info.Height;
public int DepthOrLayers => _info.GetDepthOrLayers();
public int Levels => _info.Levels;
public int Width => _info.Width;
public int Height => _info.Height;
public Target Target => _info.Target;
public Format Format => _info.Format;
public int BlockWidth => _info.BlockWidth;
public int BlockHeight => _info.BlockHeight;
public bool IsCompressed => _info.IsCompressed;
public TextureView(
Renderer renderer,
TextureStorage parent,
@ -43,8 +38,8 @@ namespace Ryujinx.Graphics.OpenGL
_parent = parent;
_info = info;
_firstLayer = firstLayer;
_firstLevel = firstLevel;
FirstLayer = firstLayer;
FirstLevel = firstLevel;
Handle = GL.GenTexture();
@ -73,9 +68,9 @@ namespace Ryujinx.Graphics.OpenGL
target,
_parent.Handle,
pixelInternalFormat,
_firstLevel,
FirstLevel,
_info.Levels,
_firstLayer,
FirstLayer,
_info.GetLayers());
GL.ActiveTexture(TextureUnit.Texture0);
@ -107,8 +102,8 @@ namespace Ryujinx.Graphics.OpenGL
{
if (_info.IsCompressed == info.IsCompressed)
{
firstLayer += _firstLayer;
firstLevel += _firstLevel;
firstLayer += FirstLayer;
firstLevel += FirstLevel;
return _parent.CreateView(info, firstLayer, firstLevel);
}
@ -123,26 +118,59 @@ namespace Ryujinx.Graphics.OpenGL
emulatedView._emulatedViewParent = this;
emulatedView._firstLayer = firstLayer;
emulatedView._firstLevel = firstLevel;
emulatedView.FirstLayer = firstLayer;
emulatedView.FirstLevel = firstLevel;
return emulatedView;
}
}
public int GetIncompatibleFormatViewHandle()
{
// AMD and Intel has a bug where the view format is always ignored,
// it uses the parent format instead.
// As workaround we create a new texture with the correct
// format, and then do a copy after the draw.
if (_parent.Info.Format != Format)
{
if (_incompatibleFormatView == null)
{
_incompatibleFormatView = (TextureView)_renderer.CreateTexture(_info);
}
TextureCopyUnscaled.Copy(_parent.Info, _incompatibleFormatView._info, _parent.Handle, _incompatibleFormatView.Handle, FirstLayer, 0, FirstLevel, 0);
return _incompatibleFormatView.Handle;
}
return Handle;
}
public void SignalModified()
{
if (_incompatibleFormatView != null)
{
TextureCopyUnscaled.Copy(_incompatibleFormatView._info, _parent.Info, _incompatibleFormatView.Handle, _parent.Handle, 0, FirstLayer, 0, FirstLevel);
}
}
public void CopyTo(ITexture destination, int firstLayer, int firstLevel)
{
TextureView destinationView = (TextureView)destination;
TextureCopyUnscaled.Copy(this, destinationView, firstLayer, firstLevel);
TextureCopyUnscaled.Copy(_info, destinationView._info, Handle, destinationView.Handle, 0, firstLayer, 0, firstLevel);
if (destinationView._emulatedViewParent != null)
{
TextureCopyUnscaled.Copy(
this,
destinationView._emulatedViewParent,
destinationView._firstLayer,
destinationView._firstLevel);
_info,
destinationView._emulatedViewParent._info,
Handle,
destinationView._emulatedViewParent.Handle,
0,
destinationView.FirstLayer,
0,
destinationView.FirstLevel);
}
}
@ -405,6 +433,13 @@ namespace Ryujinx.Graphics.OpenGL
public void Dispose()
{
if (_incompatibleFormatView != null)
{
_incompatibleFormatView.Dispose();
_incompatibleFormatView = null;
}
if (Handle != 0)
{
GL.DeleteTexture(Handle);