Support Array/3D depth-stencil render target, and single layer clears (#3400)
* Support Array/3D depth-stencil render target, and single layer clears * Alignment
This commit is contained in:
parent
b1bd6a50b5
commit
851f56b08a
10 changed files with 157 additions and 34 deletions
|
@ -10,9 +10,10 @@ namespace Ryujinx.Graphics.GAL
|
||||||
|
|
||||||
void ClearBuffer(BufferHandle destination, int offset, int size, uint value);
|
void ClearBuffer(BufferHandle destination, int offset, int size, uint value);
|
||||||
|
|
||||||
void ClearRenderTargetColor(int index, uint componentMask, ColorF color);
|
void ClearRenderTargetColor(int index, int layer, uint componentMask, ColorF color);
|
||||||
|
|
||||||
void ClearRenderTargetDepthStencil(
|
void ClearRenderTargetDepthStencil(
|
||||||
|
int layer,
|
||||||
float depthValue,
|
float depthValue,
|
||||||
bool depthMask,
|
bool depthMask,
|
||||||
int stencilValue,
|
int stencilValue,
|
||||||
|
|
|
@ -4,19 +4,21 @@
|
||||||
{
|
{
|
||||||
public CommandType CommandType => CommandType.ClearRenderTargetColor;
|
public CommandType CommandType => CommandType.ClearRenderTargetColor;
|
||||||
private int _index;
|
private int _index;
|
||||||
|
private int _layer;
|
||||||
private uint _componentMask;
|
private uint _componentMask;
|
||||||
private ColorF _color;
|
private ColorF _color;
|
||||||
|
|
||||||
public void Set(int index, uint componentMask, ColorF color)
|
public void Set(int index, int layer, uint componentMask, ColorF color)
|
||||||
{
|
{
|
||||||
_index = index;
|
_index = index;
|
||||||
|
_layer = layer;
|
||||||
_componentMask = componentMask;
|
_componentMask = componentMask;
|
||||||
_color = color;
|
_color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Run(ref ClearRenderTargetColorCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
public static void Run(ref ClearRenderTargetColorCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||||
{
|
{
|
||||||
renderer.Pipeline.ClearRenderTargetColor(command._index, command._componentMask, command._color);
|
renderer.Pipeline.ClearRenderTargetColor(command._index, command._layer, command._componentMask, command._color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,15 @@
|
||||||
struct ClearRenderTargetDepthStencilCommand : IGALCommand
|
struct ClearRenderTargetDepthStencilCommand : IGALCommand
|
||||||
{
|
{
|
||||||
public CommandType CommandType => CommandType.ClearRenderTargetDepthStencil;
|
public CommandType CommandType => CommandType.ClearRenderTargetDepthStencil;
|
||||||
|
private int _layer;
|
||||||
private float _depthValue;
|
private float _depthValue;
|
||||||
private bool _depthMask;
|
private bool _depthMask;
|
||||||
private int _stencilValue;
|
private int _stencilValue;
|
||||||
private int _stencilMask;
|
private int _stencilMask;
|
||||||
|
|
||||||
public void Set(float depthValue, bool depthMask, int stencilValue, int stencilMask)
|
public void Set(int layer, float depthValue, bool depthMask, int stencilValue, int stencilMask)
|
||||||
{
|
{
|
||||||
|
_layer = layer;
|
||||||
_depthValue = depthValue;
|
_depthValue = depthValue;
|
||||||
_depthMask = depthMask;
|
_depthMask = depthMask;
|
||||||
_stencilValue = stencilValue;
|
_stencilValue = stencilValue;
|
||||||
|
@ -18,7 +20,7 @@
|
||||||
|
|
||||||
public static void Run(ref ClearRenderTargetDepthStencilCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
public static void Run(ref ClearRenderTargetDepthStencilCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||||
{
|
{
|
||||||
renderer.Pipeline.ClearRenderTargetDepthStencil(command._depthValue, command._depthMask, command._stencilValue, command._stencilMask);
|
renderer.Pipeline.ClearRenderTargetDepthStencil(command._layer, command._depthValue, command._depthMask, command._stencilValue, command._stencilMask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,15 +40,15 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||||
_renderer.QueueCommand();
|
_renderer.QueueCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearRenderTargetColor(int index, uint componentMask, ColorF color)
|
public void ClearRenderTargetColor(int index, int layer, uint componentMask, ColorF color)
|
||||||
{
|
{
|
||||||
_renderer.New<ClearRenderTargetColorCommand>().Set(index, componentMask, color);
|
_renderer.New<ClearRenderTargetColorCommand>().Set(index, layer, componentMask, color);
|
||||||
_renderer.QueueCommand();
|
_renderer.QueueCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearRenderTargetDepthStencil(float depthValue, bool depthMask, int stencilValue, int stencilMask)
|
public void ClearRenderTargetDepthStencil(int layer, float depthValue, bool depthMask, int stencilValue, int stencilMask)
|
||||||
{
|
{
|
||||||
_renderer.New<ClearRenderTargetDepthStencilCommand>().Set(depthValue, depthMask, stencilValue, stencilMask);
|
_renderer.New<ClearRenderTargetDepthStencilCommand>().Set(layer, depthValue, depthMask, stencilValue, stencilMask);
|
||||||
_renderer.QueueCommand();
|
_renderer.QueueCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -505,8 +505,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = (argument >> 6) & 0xf;
|
int index = (argument >> 6) & 0xf;
|
||||||
|
int layer = (argument >> 10) & 0x3ff;
|
||||||
|
|
||||||
engine.UpdateRenderTargetState(useControl: false, singleUse: index);
|
engine.UpdateRenderTargetState(useControl: false, layered: layer != 0, singleUse: index);
|
||||||
|
|
||||||
// If there is a mismatch on the host clip region and the one explicitly defined by the guest
|
// If there is a mismatch on the host clip region and the one explicitly defined by the guest
|
||||||
// on the screen scissor state, then we need to force only one texture to be bound to avoid
|
// on the screen scissor state, then we need to force only one texture to be bound to avoid
|
||||||
|
@ -581,7 +582,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
|
|
||||||
ColorF color = new ColorF(clearColor.Red, clearColor.Green, clearColor.Blue, clearColor.Alpha);
|
ColorF color = new ColorF(clearColor.Red, clearColor.Green, clearColor.Blue, clearColor.Alpha);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.ClearRenderTargetColor(index, componentMask, color);
|
_context.Renderer.Pipeline.ClearRenderTargetColor(index, layer, componentMask, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clearDepth || clearStencil)
|
if (clearDepth || clearStencil)
|
||||||
|
@ -602,6 +603,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
}
|
}
|
||||||
|
|
||||||
_context.Renderer.Pipeline.ClearRenderTargetDepthStencil(
|
_context.Renderer.Pipeline.ClearRenderTargetDepthStencil(
|
||||||
|
layer,
|
||||||
depthValue,
|
depthValue,
|
||||||
clearDepth,
|
clearDepth,
|
||||||
stencilValue,
|
stencilValue,
|
||||||
|
|
|
@ -362,8 +362,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
/// Updates render targets (color and depth-stencil buffers) based on current render target state.
|
/// Updates render targets (color and depth-stencil buffers) based on current render target state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="useControl">Use draw buffers information from render target control register</param>
|
/// <param name="useControl">Use draw buffers information from render target control register</param>
|
||||||
|
/// <param name="layered">Indicates if the texture is layered</param>
|
||||||
/// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param>
|
/// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param>
|
||||||
public void UpdateRenderTargetState(bool useControl, int singleUse = -1)
|
public void UpdateRenderTargetState(bool useControl, bool layered = false, int singleUse = -1)
|
||||||
{
|
{
|
||||||
var memoryManager = _channel.MemoryManager;
|
var memoryManager = _channel.MemoryManager;
|
||||||
var rtControl = _state.State.RtControl;
|
var rtControl = _state.State.RtControl;
|
||||||
|
@ -399,7 +400,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
Image.Texture color = memoryManager.Physical.TextureCache.FindOrCreateTexture(
|
Image.Texture color = memoryManager.Physical.TextureCache.FindOrCreateTexture(
|
||||||
memoryManager,
|
memoryManager,
|
||||||
colorState,
|
colorState,
|
||||||
_vtgWritesRtLayer,
|
_vtgWritesRtLayer || layered,
|
||||||
samplesInX,
|
samplesInX,
|
||||||
samplesInY,
|
samplesInY,
|
||||||
sizeHint);
|
sizeHint);
|
||||||
|
@ -433,6 +434,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
memoryManager,
|
memoryManager,
|
||||||
dsState,
|
dsState,
|
||||||
dsSize,
|
dsSize,
|
||||||
|
_vtgWritesRtLayer || layered,
|
||||||
samplesInX,
|
samplesInX,
|
||||||
samplesInY,
|
samplesInY,
|
||||||
sizeHint);
|
sizeHint);
|
||||||
|
|
|
@ -131,10 +131,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
/// Updates render targets (color and depth-stencil buffers) based on current render target state.
|
/// Updates render targets (color and depth-stencil buffers) based on current render target state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="useControl">Use draw buffers information from render target control register</param>
|
/// <param name="useControl">Use draw buffers information from render target control register</param>
|
||||||
|
/// <param name="layered">Indicates if the texture is layered</param>
|
||||||
/// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param>
|
/// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param>
|
||||||
public void UpdateRenderTargetState(bool useControl, int singleUse = -1)
|
public void UpdateRenderTargetState(bool useControl, bool layered = false, int singleUse = -1)
|
||||||
{
|
{
|
||||||
_stateUpdater.UpdateRenderTargetState(useControl, singleUse);
|
_stateUpdater.UpdateRenderTargetState(useControl, layered, singleUse);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -349,6 +349,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// <param name="memoryManager">GPU memory manager where the texture is mapped</param>
|
/// <param name="memoryManager">GPU memory manager where the texture is mapped</param>
|
||||||
/// <param name="dsState">Depth-stencil buffer texture to find or create</param>
|
/// <param name="dsState">Depth-stencil buffer texture to find or create</param>
|
||||||
/// <param name="size">Size of the depth-stencil texture</param>
|
/// <param name="size">Size of the depth-stencil texture</param>
|
||||||
|
/// <param name="layered">Indicates if the texture might be accessed with a non-zero layer index</param>
|
||||||
/// <param name="samplesInX">Number of samples in the X direction, for MSAA</param>
|
/// <param name="samplesInX">Number of samples in the X direction, for MSAA</param>
|
||||||
/// <param name="samplesInY">Number of samples in the Y direction, for MSAA</param>
|
/// <param name="samplesInY">Number of samples in the Y direction, for MSAA</param>
|
||||||
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
|
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
|
||||||
|
@ -357,6 +358,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
MemoryManager memoryManager,
|
MemoryManager memoryManager,
|
||||||
RtDepthStencilState dsState,
|
RtDepthStencilState dsState,
|
||||||
Size3D size,
|
Size3D size,
|
||||||
|
bool layered,
|
||||||
int samplesInX,
|
int samplesInX,
|
||||||
int samplesInY,
|
int samplesInY,
|
||||||
Size sizeHint)
|
Size sizeHint)
|
||||||
|
@ -364,9 +366,24 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
int gobBlocksInY = dsState.MemoryLayout.UnpackGobBlocksInY();
|
int gobBlocksInY = dsState.MemoryLayout.UnpackGobBlocksInY();
|
||||||
int gobBlocksInZ = dsState.MemoryLayout.UnpackGobBlocksInZ();
|
int gobBlocksInZ = dsState.MemoryLayout.UnpackGobBlocksInZ();
|
||||||
|
|
||||||
Target target = (samplesInX | samplesInY) != 1
|
Target target;
|
||||||
? Target.Texture2DMultisample
|
|
||||||
: Target.Texture2D;
|
if (dsState.MemoryLayout.UnpackIsTarget3D())
|
||||||
|
{
|
||||||
|
target = Target.Texture3D;
|
||||||
|
}
|
||||||
|
else if ((samplesInX | samplesInY) != 1)
|
||||||
|
{
|
||||||
|
target = size.Depth > 1 && layered
|
||||||
|
? Target.Texture2DMultisampleArray
|
||||||
|
: Target.Texture2DMultisample;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
target = size.Depth > 1 && layered
|
||||||
|
? Target.Texture2DArray
|
||||||
|
: Target.Texture2D;
|
||||||
|
}
|
||||||
|
|
||||||
FormatInfo formatInfo = dsState.Format.Convert();
|
FormatInfo formatInfo = dsState.Format.Convert();
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,13 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
class Framebuffer : IDisposable
|
class Framebuffer : IDisposable
|
||||||
{
|
{
|
||||||
public int Handle { get; private set; }
|
public int Handle { get; private set; }
|
||||||
|
private int _clearFbHandle;
|
||||||
|
private bool _clearFbInitialized;
|
||||||
|
|
||||||
private FramebufferAttachment _lastDsAttachment;
|
private FramebufferAttachment _lastDsAttachment;
|
||||||
|
|
||||||
private readonly TextureView[] _colors;
|
private readonly TextureView[] _colors;
|
||||||
|
private TextureView _depthStencil;
|
||||||
|
|
||||||
private int _colorsCount;
|
private int _colorsCount;
|
||||||
private bool _dualSourceBlend;
|
private bool _dualSourceBlend;
|
||||||
|
@ -20,6 +23,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
public Framebuffer()
|
public Framebuffer()
|
||||||
{
|
{
|
||||||
Handle = GL.GenFramebuffer();
|
Handle = GL.GenFramebuffer();
|
||||||
|
_clearFbHandle = GL.GenFramebuffer();
|
||||||
|
|
||||||
_colors = new TextureView[8];
|
_colors = new TextureView[8];
|
||||||
}
|
}
|
||||||
|
@ -55,20 +59,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
|
|
||||||
if (depthStencil != null)
|
if (depthStencil != null)
|
||||||
{
|
{
|
||||||
FramebufferAttachment attachment;
|
FramebufferAttachment attachment = GetAttachment(depthStencil.Format);
|
||||||
|
|
||||||
if (IsPackedDepthStencilFormat(depthStencil.Format))
|
|
||||||
{
|
|
||||||
attachment = FramebufferAttachment.DepthStencilAttachment;
|
|
||||||
}
|
|
||||||
else if (IsDepthOnlyFormat(depthStencil.Format))
|
|
||||||
{
|
|
||||||
attachment = FramebufferAttachment.DepthAttachment;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
attachment = FramebufferAttachment.StencilAttachment;
|
|
||||||
}
|
|
||||||
|
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
FramebufferTarget.Framebuffer,
|
FramebufferTarget.Framebuffer,
|
||||||
|
@ -82,6 +73,8 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
{
|
{
|
||||||
_lastDsAttachment = 0;
|
_lastDsAttachment = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_depthStencil = depthStencil;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetDualSourceBlend(bool enable)
|
public void SetDualSourceBlend(bool enable)
|
||||||
|
@ -124,6 +117,22 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
GL.DrawBuffers(colorsCount, drawBuffers);
|
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)
|
private static bool IsPackedDepthStencilFormat(Format format)
|
||||||
{
|
{
|
||||||
return format == Format.D24UnormS8Uint ||
|
return format == Format.D24UnormS8Uint ||
|
||||||
|
@ -136,6 +145,78 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
return format == Format.D16Unorm || format == Format.D32Float;
|
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()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (Handle != 0)
|
if (Handle != 0)
|
||||||
|
@ -144,6 +225,13 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
|
|
||||||
Handle = 0;
|
Handle = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_clearFbHandle != 0)
|
||||||
|
{
|
||||||
|
GL.DeleteFramebuffer(_clearFbHandle);
|
||||||
|
|
||||||
|
_clearFbHandle = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
Buffer.Clear(destination, offset, size, value);
|
Buffer.Clear(destination, offset, size, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearRenderTargetColor(int index, uint componentMask, ColorF color)
|
public void ClearRenderTargetColor(int index, int layer, uint componentMask, ColorF color)
|
||||||
{
|
{
|
||||||
GL.ColorMask(
|
GL.ColorMask(
|
||||||
index,
|
index,
|
||||||
|
@ -119,14 +119,18 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
(componentMask & 4) != 0,
|
(componentMask & 4) != 0,
|
||||||
(componentMask & 8) != 0);
|
(componentMask & 8) != 0);
|
||||||
|
|
||||||
|
_framebuffer.AttachColorLayerForClear(index, layer);
|
||||||
|
|
||||||
float[] colors = new float[] { color.Red, color.Green, color.Blue, color.Alpha };
|
float[] colors = new float[] { color.Red, color.Green, color.Blue, color.Alpha };
|
||||||
|
|
||||||
GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Color, index, colors);
|
GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Color, index, colors);
|
||||||
|
|
||||||
|
_framebuffer.DetachColorLayerForClear(index);
|
||||||
|
|
||||||
RestoreComponentMask(index);
|
RestoreComponentMask(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearRenderTargetDepthStencil(float depthValue, bool depthMask, int stencilValue, int stencilMask)
|
public void ClearRenderTargetDepthStencil(int layer, float depthValue, bool depthMask, int stencilValue, int stencilMask)
|
||||||
{
|
{
|
||||||
bool stencilMaskChanged =
|
bool stencilMaskChanged =
|
||||||
stencilMask != 0 &&
|
stencilMask != 0 &&
|
||||||
|
@ -144,6 +148,8 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
GL.DepthMask(depthMask);
|
GL.DepthMask(depthMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_framebuffer.AttachDepthStencilLayerForClear(layer);
|
||||||
|
|
||||||
if (depthMask && stencilMask != 0)
|
if (depthMask && stencilMask != 0)
|
||||||
{
|
{
|
||||||
GL.ClearBuffer(ClearBufferCombined.DepthStencil, 0, depthValue, stencilValue);
|
GL.ClearBuffer(ClearBufferCombined.DepthStencil, 0, depthValue, stencilValue);
|
||||||
|
@ -157,6 +163,8 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Stencil, 0, ref stencilValue);
|
GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Stencil, 0, ref stencilValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_framebuffer.DetachDepthStencilLayerForClear();
|
||||||
|
|
||||||
if (stencilMaskChanged)
|
if (stencilMaskChanged)
|
||||||
{
|
{
|
||||||
GL.StencilMaskSeparate(StencilFace.Front, _stencilFrontMask);
|
GL.StencilMaskSeparate(StencilFace.Front, _stencilFrontMask);
|
||||||
|
|
Reference in a new issue