|
|
@@ -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;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|