Fix multiple rendertargets (#427)
* Simplify render target bindings * Implement multiple viewports * Pack glViewportIndexed calls into a single glViewportArray * Use ARB_viewport_array when available * Cache framebuffer attachments * Use get accessors in OGLExtension * Address feedback
This commit is contained in:
parent
7de7b559ad
commit
2562ca6c3f
8 changed files with 185 additions and 155 deletions
|
@ -2,15 +2,17 @@ namespace Ryujinx.Graphics.Gal
|
||||||
{
|
{
|
||||||
public interface IGalRenderTarget
|
public interface IGalRenderTarget
|
||||||
{
|
{
|
||||||
void BindColor(long Key, int Attachment, GalImage Image);
|
void Bind();
|
||||||
|
|
||||||
|
void BindColor(long Key, int Attachment);
|
||||||
|
|
||||||
void UnbindColor(int Attachment);
|
void UnbindColor(int Attachment);
|
||||||
|
|
||||||
void BindZeta(long Key, GalImage Image);
|
void BindZeta(long Key);
|
||||||
|
|
||||||
void UnbindZeta();
|
void UnbindZeta();
|
||||||
|
|
||||||
void Set(long Key);
|
void Present(long Key);
|
||||||
|
|
||||||
void SetMap(int[] Map);
|
void SetMap(int[] Map);
|
||||||
|
|
||||||
|
@ -18,7 +20,7 @@ namespace Ryujinx.Graphics.Gal
|
||||||
|
|
||||||
void SetWindowSize(int Width, int Height);
|
void SetWindowSize(int Width, int Height);
|
||||||
|
|
||||||
void SetViewport(int X, int Y, int Width, int Height);
|
void SetViewport(int Attachment, int X, int Y, int Width, int Height);
|
||||||
|
|
||||||
void Render();
|
void Render();
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
case GalTextureWrap.Clamp: return TextureWrapMode.Clamp;
|
case GalTextureWrap.Clamp: return TextureWrapMode.Clamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OGLExtension.HasTextureMirrorClamp())
|
if (OGLExtension.TextureMirrorClamp)
|
||||||
{
|
{
|
||||||
switch (Wrap)
|
switch (Wrap)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,40 +1,17 @@
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
static class OGLExtension
|
static class OGLExtension
|
||||||
{
|
{
|
||||||
private static bool Initialized = false;
|
private static Lazy<bool> s_EnhancedLayouts = new Lazy<bool>(() => HasExtension("GL_ARB_enhanced_layouts"));
|
||||||
|
private static Lazy<bool> s_TextureMirrorClamp = new Lazy<bool>(() => HasExtension("GL_EXT_texture_mirror_clamp"));
|
||||||
|
private static Lazy<bool> s_ViewportArray = new Lazy<bool>(() => HasExtension("GL_ARB_viewport_array"));
|
||||||
|
|
||||||
private static bool EnhancedLayouts;
|
public static bool EnhancedLayouts => s_EnhancedLayouts.Value;
|
||||||
|
public static bool TextureMirrorClamp => s_TextureMirrorClamp.Value;
|
||||||
private static bool TextureMirrorClamp;
|
public static bool ViewportArray => s_ViewportArray.Value;
|
||||||
|
|
||||||
public static bool HasEnhancedLayouts()
|
|
||||||
{
|
|
||||||
EnsureInitialized();
|
|
||||||
|
|
||||||
return EnhancedLayouts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasTextureMirrorClamp()
|
|
||||||
{
|
|
||||||
EnsureInitialized();
|
|
||||||
|
|
||||||
return TextureMirrorClamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void EnsureInitialized()
|
|
||||||
{
|
|
||||||
if (Initialized)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnhancedLayouts = HasExtension("GL_ARB_enhanced_layouts");
|
|
||||||
|
|
||||||
TextureMirrorClamp = HasExtension("GL_EXT_texture_mirror_clamp");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool HasExtension(string Name)
|
private static bool HasExtension(string Name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,16 +22,52 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class FrameBufferAttachments
|
||||||
|
{
|
||||||
|
public long[] Colors;
|
||||||
|
public long Zeta;
|
||||||
|
|
||||||
|
public int MapCount;
|
||||||
|
public DrawBuffersEnum[] Map;
|
||||||
|
|
||||||
|
public FrameBufferAttachments()
|
||||||
|
{
|
||||||
|
Colors = new long[RenderTargetsCount];
|
||||||
|
|
||||||
|
Map = new DrawBuffersEnum[RenderTargetsCount];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAndClear(FrameBufferAttachments Source)
|
||||||
|
{
|
||||||
|
Zeta = Source.Zeta;
|
||||||
|
MapCount = Source.MapCount;
|
||||||
|
|
||||||
|
Source.Zeta = 0;
|
||||||
|
Source.MapCount = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < RenderTargetsCount; i++)
|
||||||
|
{
|
||||||
|
Colors[i] = Source.Colors[i];
|
||||||
|
Map[i] = Source.Map[i];
|
||||||
|
|
||||||
|
Source.Colors[i] = 0;
|
||||||
|
Source.Map[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private const int NativeWidth = 1280;
|
private const int NativeWidth = 1280;
|
||||||
private const int NativeHeight = 720;
|
private const int NativeHeight = 720;
|
||||||
|
|
||||||
|
private const int RenderTargetsCount = 8;
|
||||||
|
|
||||||
private const GalImageFormat RawFormat = GalImageFormat.A8B8G8R8 | GalImageFormat.Unorm;
|
private const GalImageFormat RawFormat = GalImageFormat.A8B8G8R8 | GalImageFormat.Unorm;
|
||||||
|
|
||||||
private OGLTexture Texture;
|
private OGLTexture Texture;
|
||||||
|
|
||||||
private ImageHandler ReadTex;
|
private ImageHandler ReadTex;
|
||||||
|
|
||||||
private Rect Viewport;
|
private float[] Viewports;
|
||||||
private Rect Window;
|
private Rect Window;
|
||||||
|
|
||||||
private bool FlipX;
|
private bool FlipX;
|
||||||
|
@ -50,138 +86,164 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
private int SrcFb;
|
private int SrcFb;
|
||||||
private int DstFb;
|
private int DstFb;
|
||||||
|
|
||||||
//Holds current attachments, used to avoid unnecesary calls to OpenGL
|
private FrameBufferAttachments Attachments;
|
||||||
private int[] ColorAttachments;
|
private FrameBufferAttachments OldAttachments;
|
||||||
|
|
||||||
private int DepthAttachment;
|
|
||||||
private int StencilAttachment;
|
|
||||||
|
|
||||||
private int CopyPBO;
|
private int CopyPBO;
|
||||||
|
|
||||||
public OGLRenderTarget(OGLTexture Texture)
|
public OGLRenderTarget(OGLTexture Texture)
|
||||||
{
|
{
|
||||||
ColorAttachments = new int[8];
|
Attachments = new FrameBufferAttachments();
|
||||||
|
|
||||||
|
OldAttachments = new FrameBufferAttachments();
|
||||||
|
|
||||||
|
Viewports = new float[RenderTargetsCount * 4];
|
||||||
|
|
||||||
this.Texture = Texture;
|
this.Texture = Texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BindColor(long Key, int Attachment, GalImage Image)
|
public void Bind()
|
||||||
{
|
{
|
||||||
if (Texture.TryGetImageHandler(Key, out ImageHandler CachedImage))
|
if (DummyFrameBuffer == 0)
|
||||||
{
|
{
|
||||||
EnsureFrameBuffer();
|
DummyFrameBuffer = GL.GenFramebuffer();
|
||||||
|
|
||||||
Attach(ref ColorAttachments[Attachment], CachedImage.Handle, FramebufferAttachment.ColorAttachment0 + Attachment);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DummyFrameBuffer);
|
||||||
|
|
||||||
|
ImageHandler CachedImage;
|
||||||
|
|
||||||
|
for (int Attachment = 0; Attachment < RenderTargetsCount; Attachment++)
|
||||||
{
|
{
|
||||||
UnbindColor(Attachment);
|
if (Attachments.Colors[Attachment] == OldAttachments.Colors[Attachment])
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UnbindColor(int Attachment)
|
|
||||||
{
|
|
||||||
EnsureFrameBuffer();
|
|
||||||
|
|
||||||
Attach(ref ColorAttachments[Attachment], 0, FramebufferAttachment.ColorAttachment0 + Attachment);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void BindZeta(long Key, GalImage Image)
|
|
||||||
{
|
|
||||||
if (Texture.TryGetImageHandler(Key, out ImageHandler CachedImage))
|
|
||||||
{
|
|
||||||
EnsureFrameBuffer();
|
|
||||||
|
|
||||||
if (CachedImage.HasDepth && CachedImage.HasStencil)
|
|
||||||
{
|
{
|
||||||
if (DepthAttachment != CachedImage.Handle ||
|
continue;
|
||||||
StencilAttachment != CachedImage.Handle)
|
}
|
||||||
|
|
||||||
|
int Handle = 0;
|
||||||
|
|
||||||
|
if (Attachments.Colors[Attachment] != 0 &&
|
||||||
|
Texture.TryGetImageHandler(Attachments.Colors[Attachment], out CachedImage))
|
||||||
|
{
|
||||||
|
Handle = CachedImage.Handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
GL.FramebufferTexture(
|
||||||
|
FramebufferTarget.DrawFramebuffer,
|
||||||
|
FramebufferAttachment.ColorAttachment0 + Attachment,
|
||||||
|
Handle,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Attachments.Zeta != OldAttachments.Zeta)
|
||||||
|
{
|
||||||
|
if (Attachments.Zeta != 0 && Texture.TryGetImageHandler(Attachments.Zeta, out CachedImage))
|
||||||
|
{
|
||||||
|
if (CachedImage.HasDepth && CachedImage.HasStencil)
|
||||||
{
|
{
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
FramebufferTarget.DrawFramebuffer,
|
FramebufferTarget.DrawFramebuffer,
|
||||||
FramebufferAttachment.DepthStencilAttachment,
|
FramebufferAttachment.DepthStencilAttachment,
|
||||||
CachedImage.Handle,
|
CachedImage.Handle,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
DepthAttachment = CachedImage.Handle;
|
|
||||||
StencilAttachment = CachedImage.Handle;
|
|
||||||
}
|
}
|
||||||
}
|
else if (CachedImage.HasDepth)
|
||||||
else if (CachedImage.HasDepth)
|
{
|
||||||
{
|
GL.FramebufferTexture(
|
||||||
Attach(ref DepthAttachment, CachedImage.Handle, FramebufferAttachment.DepthAttachment);
|
FramebufferTarget.DrawFramebuffer,
|
||||||
|
FramebufferAttachment.DepthAttachment,
|
||||||
|
CachedImage.Handle,
|
||||||
|
0);
|
||||||
|
|
||||||
Attach(ref StencilAttachment, 0, FramebufferAttachment.StencilAttachment);
|
GL.FramebufferTexture(
|
||||||
}
|
FramebufferTarget.DrawFramebuffer,
|
||||||
else if (CachedImage.HasStencil)
|
FramebufferAttachment.StencilAttachment,
|
||||||
{
|
0,
|
||||||
Attach(ref DepthAttachment, 0, FramebufferAttachment.DepthAttachment);
|
0);
|
||||||
|
}
|
||||||
Attach(ref StencilAttachment, CachedImage.Handle, FramebufferAttachment.StencilAttachment);
|
else
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
GL.FramebufferTexture(
|
||||||
|
FramebufferTarget.DrawFramebuffer,
|
||||||
|
FramebufferAttachment.DepthStencilAttachment,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (OGLExtension.ViewportArray)
|
||||||
|
{
|
||||||
|
GL.ViewportArray(0, 8, Viewports);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UnbindZeta();
|
GL.Viewport(
|
||||||
|
(int)Viewports[0],
|
||||||
|
(int)Viewports[1],
|
||||||
|
(int)Viewports[2],
|
||||||
|
(int)Viewports[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Attachments.MapCount > 1)
|
||||||
|
{
|
||||||
|
GL.DrawBuffers(Attachments.MapCount, Attachments.Map);
|
||||||
|
}
|
||||||
|
else if (Attachments.MapCount == 1)
|
||||||
|
{
|
||||||
|
GL.DrawBuffer((DrawBufferMode)Attachments.Map[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL.DrawBuffer(DrawBufferMode.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
OldAttachments.SetAndClear(Attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Attach(ref int OldHandle, int NewHandle, FramebufferAttachment FbAttachment)
|
public void BindColor(long Key, int Attachment)
|
||||||
{
|
{
|
||||||
if (OldHandle != NewHandle)
|
Attachments.Colors[Attachment] = Key;
|
||||||
{
|
}
|
||||||
GL.FramebufferTexture(
|
|
||||||
FramebufferTarget.DrawFramebuffer,
|
|
||||||
FbAttachment,
|
|
||||||
NewHandle,
|
|
||||||
0);
|
|
||||||
|
|
||||||
OldHandle = NewHandle;
|
public void UnbindColor(int Attachment)
|
||||||
}
|
{
|
||||||
|
Attachments.Colors[Attachment] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BindZeta(long Key)
|
||||||
|
{
|
||||||
|
Attachments.Zeta = Key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnbindZeta()
|
public void UnbindZeta()
|
||||||
{
|
{
|
||||||
EnsureFrameBuffer();
|
Attachments.Zeta = 0;
|
||||||
|
|
||||||
if (DepthAttachment != 0 || StencilAttachment != 0)
|
|
||||||
{
|
|
||||||
GL.FramebufferTexture(
|
|
||||||
FramebufferTarget.DrawFramebuffer,
|
|
||||||
FramebufferAttachment.DepthStencilAttachment,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
|
|
||||||
DepthAttachment = 0;
|
|
||||||
StencilAttachment = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Set(long Key)
|
public void Present(long Key)
|
||||||
{
|
{
|
||||||
Texture.TryGetImageHandler(Key, out ReadTex);
|
Texture.TryGetImageHandler(Key, out ReadTex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetMap(int[] Map)
|
public void SetMap(int[] Map)
|
||||||
{
|
{
|
||||||
if (Map != null && Map.Length > 0)
|
if (Map != null)
|
||||||
{
|
{
|
||||||
DrawBuffersEnum[] Mode = new DrawBuffersEnum[Map.Length];
|
Attachments.MapCount = Map.Length;
|
||||||
|
|
||||||
for (int i = 0; i < Map.Length; i++)
|
for (int Attachment = 0; Attachment < Attachments.MapCount; Attachment++)
|
||||||
{
|
{
|
||||||
Mode[i] = DrawBuffersEnum.ColorAttachment0 + Map[i];
|
Attachments.Map[Attachment] = DrawBuffersEnum.ColorAttachment0 + Map[Attachment];
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.DrawBuffers(Mode.Length, Mode);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
Attachments.MapCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,20 +263,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
Window = new Rect(0, 0, Width, Height);
|
Window = new Rect(0, 0, Width, Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetViewport(int X, int Y, int Width, int Height)
|
public void SetViewport(int Attachment, int X, int Y, int Width, int Height)
|
||||||
{
|
{
|
||||||
Viewport = new Rect(X, Y, Width, Height);
|
int Offset = Attachment * 4;
|
||||||
|
|
||||||
SetViewport(Viewport);
|
Viewports[Offset + 0] = X;
|
||||||
}
|
Viewports[Offset + 1] = Y;
|
||||||
|
Viewports[Offset + 2] = Width;
|
||||||
private void SetViewport(Rect Viewport)
|
Viewports[Offset + 3] = Height;
|
||||||
{
|
|
||||||
GL.Viewport(
|
|
||||||
Viewport.X,
|
|
||||||
Viewport.Y,
|
|
||||||
Viewport.Width,
|
|
||||||
Viewport.Height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render()
|
public void Render()
|
||||||
|
@ -276,7 +332,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, ReadTex.Handle, 0);
|
GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, ReadTex.Handle, 0);
|
||||||
|
|
||||||
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
|
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
|
||||||
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
|
||||||
|
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||||
|
|
||||||
|
@ -285,8 +340,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
DstX0, DstY0, DstX1, DstY1,
|
DstX0, DstY0, DstX1, DstY1,
|
||||||
ClearBufferMask.ColorBufferBit,
|
ClearBufferMask.ColorBufferBit,
|
||||||
BlitFramebufferFilter.Linear);
|
BlitFramebufferFilter.Linear);
|
||||||
|
|
||||||
EnsureFrameBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Copy(
|
public void Copy(
|
||||||
|
@ -343,8 +396,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
GL.Clear(Mask);
|
GL.Clear(Mask);
|
||||||
|
|
||||||
GL.BlitFramebuffer(SrcX0, SrcY0, SrcX1, SrcY1, DstX0, DstY0, DstX1, DstY1, Mask, Filter);
|
GL.BlitFramebuffer(SrcX0, SrcY0, SrcX1, SrcY1, DstX0, DstY0, DstX1, DstY1, Mask, Filter);
|
||||||
|
|
||||||
EnsureFrameBuffer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,15 +470,5 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
(CachedImage.HasDepth ? ClearBufferMask.DepthBufferBit : 0) |
|
(CachedImage.HasDepth ? ClearBufferMask.DepthBufferBit : 0) |
|
||||||
(CachedImage.HasStencil ? ClearBufferMask.StencilBufferBit : 0);
|
(CachedImage.HasStencil ? ClearBufferMask.StencilBufferBit : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureFrameBuffer()
|
|
||||||
{
|
|
||||||
if (DummyFrameBuffer == 0)
|
|
||||||
{
|
|
||||||
DummyFrameBuffer = GL.GenFramebuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DummyFrameBuffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
//Enhanced layouts are required for Geometry shaders
|
//Enhanced layouts are required for Geometry shaders
|
||||||
//skip this stage if current driver has no ARB_enhanced_layouts
|
//skip this stage if current driver has no ARB_enhanced_layouts
|
||||||
if (!OGLExtension.HasEnhancedLayouts())
|
if (!OGLExtension.EnhancedLayouts)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace Ryujinx.Graphics
|
||||||
Gpu.Renderer.Texture.Create(Position, (int)Size, NewImage);
|
Gpu.Renderer.Texture.Create(Position, (int)Size, NewImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gpu.Renderer.RenderTarget.BindColor(Position, Attachment, NewImage);
|
Gpu.Renderer.RenderTarget.BindColor(Position, Attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendZetaBuffer(NvGpuVmm Vmm, long Position, GalImage NewImage)
|
public void SendZetaBuffer(NvGpuVmm Vmm, long Position, GalImage NewImage)
|
||||||
|
@ -60,7 +60,7 @@ namespace Ryujinx.Graphics
|
||||||
Gpu.Renderer.Texture.Create(Position, (int)Size, NewImage);
|
Gpu.Renderer.Texture.Create(Position, (int)Size, NewImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gpu.Renderer.RenderTarget.BindZeta(Position, NewImage);
|
Gpu.Renderer.RenderTarget.BindZeta(Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendTexture(NvGpuVmm Vmm, long Position, GalImage NewImage, int TexIndex = -1)
|
public void SendTexture(NvGpuVmm Vmm, long Position, GalImage NewImage, int TexIndex = -1)
|
||||||
|
|
|
@ -100,7 +100,10 @@ namespace Ryujinx.Graphics
|
||||||
SetAlphaBlending(State);
|
SetAlphaBlending(State);
|
||||||
SetPrimitiveRestart(State);
|
SetPrimitiveRestart(State);
|
||||||
|
|
||||||
SetFrameBuffer(Vmm, 0);
|
for (int FbIndex = 0; FbIndex < 8; FbIndex++)
|
||||||
|
{
|
||||||
|
SetFrameBuffer(Vmm, FbIndex);
|
||||||
|
}
|
||||||
|
|
||||||
SetZeta(Vmm);
|
SetZeta(Vmm);
|
||||||
|
|
||||||
|
@ -154,6 +157,10 @@ namespace Ryujinx.Graphics
|
||||||
|
|
||||||
SetZeta(Vmm);
|
SetZeta(Vmm);
|
||||||
|
|
||||||
|
SetRenderTargets();
|
||||||
|
|
||||||
|
Gpu.Renderer.RenderTarget.Bind();
|
||||||
|
|
||||||
Gpu.Renderer.Rasterizer.ClearBuffers(
|
Gpu.Renderer.Rasterizer.ClearBuffers(
|
||||||
Flags,
|
Flags,
|
||||||
FbIndex,
|
FbIndex,
|
||||||
|
@ -204,7 +211,7 @@ namespace Ryujinx.Graphics
|
||||||
|
|
||||||
Gpu.ResourceManager.SendColorBuffer(Vmm, Key, FbIndex, Image);
|
Gpu.ResourceManager.SendColorBuffer(Vmm, Key, FbIndex, Image);
|
||||||
|
|
||||||
Gpu.Renderer.RenderTarget.SetViewport(VpX, VpY, VpW, VpH);
|
Gpu.Renderer.RenderTarget.SetViewport(FbIndex, VpX, VpY, VpW, VpH);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetFrameBuffer(GalPipelineState State)
|
private void SetFrameBuffer(GalPipelineState State)
|
||||||
|
@ -426,14 +433,15 @@ namespace Ryujinx.Graphics
|
||||||
|
|
||||||
private void SetRenderTargets()
|
private void SetRenderTargets()
|
||||||
{
|
{
|
||||||
bool SeparateFragData = ReadRegisterBool(NvGpuEngine3dReg.RTSeparateFragData);
|
//Commercial games do not seem to
|
||||||
|
//bool SeparateFragData = ReadRegisterBool(NvGpuEngine3dReg.RTSeparateFragData);
|
||||||
|
|
||||||
if (SeparateFragData)
|
uint Control = (uint)(ReadRegister(NvGpuEngine3dReg.RTControl));
|
||||||
|
|
||||||
|
uint Count = Control & 0xf;
|
||||||
|
|
||||||
|
if (Count > 0)
|
||||||
{
|
{
|
||||||
uint Control = (uint)(ReadRegister(NvGpuEngine3dReg.RTControl));
|
|
||||||
|
|
||||||
uint Count = Control & 0xf;
|
|
||||||
|
|
||||||
int[] Map = new int[Count];
|
int[] Map = new int[Count];
|
||||||
|
|
||||||
for (int i = 0; i < Count; i++)
|
for (int i = 0; i < Count; i++)
|
||||||
|
@ -702,6 +710,8 @@ namespace Ryujinx.Graphics
|
||||||
|
|
||||||
Gpu.Renderer.Pipeline.Bind(State);
|
Gpu.Renderer.Pipeline.Bind(State);
|
||||||
|
|
||||||
|
Gpu.Renderer.RenderTarget.Bind();
|
||||||
|
|
||||||
if (IndexCount != 0)
|
if (IndexCount != 0)
|
||||||
{
|
{
|
||||||
int IndexEntryFmt = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat);
|
int IndexEntryFmt = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat);
|
||||||
|
|
|
@ -328,7 +328,7 @@ namespace Ryujinx.HLE.HOS.Services.Android
|
||||||
Context.Device.Gpu.ResourceManager.SendTexture(Vmm, FbAddr, Image);
|
Context.Device.Gpu.ResourceManager.SendTexture(Vmm, FbAddr, Image);
|
||||||
|
|
||||||
Renderer.RenderTarget.SetTransform(FlipX, FlipY, Top, Left, Right, Bottom);
|
Renderer.RenderTarget.SetTransform(FlipX, FlipY, Top, Left, Right, Bottom);
|
||||||
Renderer.RenderTarget.Set(FbAddr);
|
Renderer.RenderTarget.Present(FbAddr);
|
||||||
|
|
||||||
ReleaseBuffer(Slot);
|
ReleaseBuffer(Slot);
|
||||||
});
|
});
|
||||||
|
|
Reference in a new issue