aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.OpenGL/Framebuffer.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2022-06-14 13:30:39 -0300
committerGitHub <noreply@github.com>2022-06-14 13:30:39 -0300
commit851f56b08a0c3b420f91143b6c6c007b429174a8 (patch)
treed4f331d1de9f4715a22abdc9b1b90b5ce5a3b4ae /Ryujinx.Graphics.OpenGL/Framebuffer.cs
parentb1bd6a50b5341f444ceb31bbb0fb64f685828d75 (diff)
Support Array/3D depth-stencil render target, and single layer clears (#3400)1.1.147
* Support Array/3D depth-stencil render target, and single layer clears * Alignment
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Framebuffer.cs')
-rw-r--r--Ryujinx.Graphics.OpenGL/Framebuffer.cs116
1 files changed, 102 insertions, 14 deletions
diff --git a/Ryujinx.Graphics.OpenGL/Framebuffer.cs b/Ryujinx.Graphics.OpenGL/Framebuffer.cs
index da928b4c..dafa7672 100644
--- a/Ryujinx.Graphics.OpenGL/Framebuffer.cs
+++ b/Ryujinx.Graphics.OpenGL/Framebuffer.cs
@@ -9,10 +9,13 @@ namespace Ryujinx.Graphics.OpenGL
class Framebuffer : IDisposable
{
public int Handle { get; private set; }
+ private int _clearFbHandle;
+ private bool _clearFbInitialized;
private FramebufferAttachment _lastDsAttachment;
private readonly TextureView[] _colors;
+ private TextureView _depthStencil;
private int _colorsCount;
private bool _dualSourceBlend;
@@ -20,6 +23,7 @@ namespace Ryujinx.Graphics.OpenGL
public Framebuffer()
{
Handle = GL.GenFramebuffer();
+ _clearFbHandle = GL.GenFramebuffer();
_colors = new TextureView[8];
}
@@ -55,20 +59,7 @@ namespace Ryujinx.Graphics.OpenGL
if (depthStencil != null)
{
- FramebufferAttachment attachment;
-
- if (IsPackedDepthStencilFormat(depthStencil.Format))
- {
- attachment = FramebufferAttachment.DepthStencilAttachment;
- }
- else if (IsDepthOnlyFormat(depthStencil.Format))
- {
- attachment = FramebufferAttachment.DepthAttachment;
- }
- else
- {
- attachment = FramebufferAttachment.StencilAttachment;
- }
+ FramebufferAttachment attachment = GetAttachment(depthStencil.Format);
GL.FramebufferTexture(
FramebufferTarget.Framebuffer,
@@ -82,6 +73,8 @@ namespace Ryujinx.Graphics.OpenGL
{
_lastDsAttachment = 0;
}
+
+ _depthStencil = depthStencil;
}
public void SetDualSourceBlend(bool enable)
@@ -124,6 +117,22 @@ namespace Ryujinx.Graphics.OpenGL
GL.DrawBuffers(colorsCount, drawBuffers);
}
+ private static FramebufferAttachment GetAttachment(Format format)
+ {
+ if (IsPackedDepthStencilFormat(format))
+ {
+ return FramebufferAttachment.DepthStencilAttachment;
+ }
+ else if (IsDepthOnlyFormat(format))
+ {
+ return FramebufferAttachment.DepthAttachment;
+ }
+ else
+ {
+ return FramebufferAttachment.StencilAttachment;
+ }
+ }
+
private static bool IsPackedDepthStencilFormat(Format format)
{
return format == Format.D24UnormS8Uint ||
@@ -136,6 +145,78 @@ namespace Ryujinx.Graphics.OpenGL
return format == Format.D16Unorm || format == Format.D32Float;
}
+ public void AttachColorLayerForClear(int index, int layer)
+ {
+ TextureView color = _colors[index];
+
+ if (!IsLayered(color))
+ {
+ return;
+ }
+
+ BindClearFb();
+ GL.FramebufferTextureLayer(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0 + index, color.Handle, 0, layer);
+ }
+
+ public void DetachColorLayerForClear(int index)
+ {
+ TextureView color = _colors[index];
+
+ if (!IsLayered(color))
+ {
+ return;
+ }
+
+ GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0 + index, 0, 0);
+ Bind();
+ }
+
+ public void AttachDepthStencilLayerForClear(int layer)
+ {
+ TextureView depthStencil = _depthStencil;
+
+ if (!IsLayered(depthStencil))
+ {
+ return;
+ }
+
+ BindClearFb();
+ GL.FramebufferTextureLayer(FramebufferTarget.Framebuffer, GetAttachment(depthStencil.Format), depthStencil.Handle, 0, layer);
+ }
+
+ public void DetachDepthStencilLayerForClear()
+ {
+ TextureView depthStencil = _depthStencil;
+
+ if (!IsLayered(depthStencil))
+ {
+ return;
+ }
+
+ GL.FramebufferTexture(FramebufferTarget.Framebuffer, GetAttachment(depthStencil.Format), 0, 0);
+ Bind();
+ }
+
+ private void BindClearFb()
+ {
+ GL.BindFramebuffer(FramebufferTarget.Framebuffer, _clearFbHandle);
+
+ if (!_clearFbInitialized)
+ {
+ SetDrawBuffersImpl(Constants.MaxRenderTargets);
+ _clearFbInitialized = true;
+ }
+ }
+
+ private static bool IsLayered(TextureView view)
+ {
+ return view != null &&
+ view.Target != Target.Texture1D &&
+ view.Target != Target.Texture2D &&
+ view.Target != Target.Texture2DMultisample &&
+ view.Target != Target.TextureBuffer;
+ }
+
public void Dispose()
{
if (Handle != 0)
@@ -144,6 +225,13 @@ namespace Ryujinx.Graphics.OpenGL
Handle = 0;
}
+
+ if (_clearFbHandle != 0)
+ {
+ GL.DeleteFramebuffer(_clearFbHandle);
+
+ _clearFbHandle = 0;
+ }
}
}
}