GPU: Discard data when getting texture before full clear (#5719)
* GPU: Discard data when getting texture before full clear * Fix rules and order of clear checks * Fix formatting
This commit is contained in:
parent
8026e1c804
commit
f6c3f1cdfd
@ -335,6 +335,45 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the texture format is a depth or depth-stencil format.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">Texture format</param>
|
||||||
|
/// <returns>True if the format is a depth or depth-stencil format, false otherwise</returns>
|
||||||
|
public static bool HasDepth(this Format format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case Format.D16Unorm:
|
||||||
|
case Format.D24UnormS8Uint:
|
||||||
|
case Format.S8UintD24Unorm:
|
||||||
|
case Format.D32Float:
|
||||||
|
case Format.D32FloatS8Uint:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the texture format is a stencil or depth-stencil format.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">Texture format</param>
|
||||||
|
/// <returns>True if the format is a stencil or depth-stencil format, false otherwise</returns>
|
||||||
|
public static bool HasStencil(this Format format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case Format.D24UnormS8Uint:
|
||||||
|
case Format.S8UintD24Unorm:
|
||||||
|
case Format.D32FloatS8Uint:
|
||||||
|
case Format.S8Uint:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the texture format is valid to use as image format.
|
/// Checks if the texture format is valid to use as image format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw;
|
using Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.Types;
|
using Ryujinx.Graphics.Gpu.Engine.Types;
|
||||||
|
using Ryujinx.Graphics.Gpu.Image;
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
using Ryujinx.Graphics.Gpu.Memory;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
@ -806,25 +807,69 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
updateFlags |= RenderTargetUpdateFlags.Layered;
|
updateFlags |= RenderTargetUpdateFlags.Layered;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clearDepth || clearStencil)
|
bool clearDS = clearDepth || clearStencil;
|
||||||
|
|
||||||
|
if (clearDS)
|
||||||
{
|
{
|
||||||
updateFlags |= RenderTargetUpdateFlags.UpdateDepthStencil;
|
updateFlags |= RenderTargetUpdateFlags.UpdateDepthStencil;
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.UpdateRenderTargetState(updateFlags, singleUse: componentMask != 0 ? index : -1);
|
|
||||||
|
|
||||||
// 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
|
||||||
// host clipping.
|
// host clipping.
|
||||||
var screenScissorState = _state.State.ScreenScissorState;
|
var screenScissorState = _state.State.ScreenScissorState;
|
||||||
|
|
||||||
|
bool clearAffectedByStencilMask = (_state.State.ClearFlags & 1) != 0;
|
||||||
|
bool clearAffectedByScissor = (_state.State.ClearFlags & 0x100) != 0;
|
||||||
|
|
||||||
|
if (clearDS || componentMask == 15)
|
||||||
|
{
|
||||||
|
// A full clear if scissor is disabled, or it matches the screen scissor state.
|
||||||
|
|
||||||
|
bool fullClear = screenScissorState.X == 0 && screenScissorState.Y == 0;
|
||||||
|
|
||||||
|
if (fullClear && clearAffectedByScissor && _state.State.ScissorState[0].Enable)
|
||||||
|
{
|
||||||
|
ref var scissorState = ref _state.State.ScissorState[0];
|
||||||
|
|
||||||
|
fullClear = scissorState.X1 == screenScissorState.X &&
|
||||||
|
scissorState.Y1 == screenScissorState.Y &&
|
||||||
|
scissorState.X2 >= screenScissorState.X + screenScissorState.Width &&
|
||||||
|
scissorState.Y2 >= screenScissorState.Y + screenScissorState.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fullClear && clearDS)
|
||||||
|
{
|
||||||
|
// Must clear all aspects of the depth-stencil format.
|
||||||
|
|
||||||
|
FormatInfo dsFormat = _state.State.RtDepthStencilState.Format.Convert();
|
||||||
|
|
||||||
|
bool hasDepth = dsFormat.Format.HasDepth();
|
||||||
|
bool hasStencil = dsFormat.Format.HasStencil();
|
||||||
|
|
||||||
|
if (hasStencil && (!clearStencil || (clearAffectedByStencilMask && _state.State.StencilTestState.FrontMask != 0xff)))
|
||||||
|
{
|
||||||
|
fullClear = false;
|
||||||
|
}
|
||||||
|
else if (hasDepth && !clearDepth)
|
||||||
|
{
|
||||||
|
fullClear = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fullClear)
|
||||||
|
{
|
||||||
|
updateFlags |= RenderTargetUpdateFlags.DiscardClip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
engine.UpdateRenderTargetState(updateFlags, singleUse: componentMask != 0 ? index : -1);
|
||||||
|
|
||||||
// Must happen after UpdateRenderTargetState to have up-to-date clip region values.
|
// Must happen after UpdateRenderTargetState to have up-to-date clip region values.
|
||||||
bool clipMismatch = (screenScissorState.X | screenScissorState.Y) != 0 ||
|
bool clipMismatch = (screenScissorState.X | screenScissorState.Y) != 0 ||
|
||||||
screenScissorState.Width != _channel.TextureManager.ClipRegionWidth ||
|
screenScissorState.Width != _channel.TextureManager.ClipRegionWidth ||
|
||||||
screenScissorState.Height != _channel.TextureManager.ClipRegionHeight;
|
screenScissorState.Height != _channel.TextureManager.ClipRegionHeight;
|
||||||
|
|
||||||
bool clearAffectedByStencilMask = (_state.State.ClearFlags & 1) != 0;
|
|
||||||
bool clearAffectedByScissor = (_state.State.ClearFlags & 0x100) != 0;
|
|
||||||
bool needsCustomScissor = !clearAffectedByScissor || clipMismatch;
|
bool needsCustomScissor = !clearAffectedByScissor || clipMismatch;
|
||||||
|
|
||||||
// Scissor and rasterizer discard also affect clears.
|
// Scissor and rasterizer discard also affect clears.
|
||||||
|
@ -33,6 +33,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
UpdateDepthStencil = 1 << 3,
|
UpdateDepthStencil = 1 << 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the data in the clip region can be discarded for the next use.
|
||||||
|
/// </summary>
|
||||||
|
DiscardClip = 1 << 4,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default update flags for draw.
|
/// Default update flags for draw.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -447,6 +447,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
bool useControl = updateFlags.HasFlag(RenderTargetUpdateFlags.UseControl);
|
bool useControl = updateFlags.HasFlag(RenderTargetUpdateFlags.UseControl);
|
||||||
bool layered = updateFlags.HasFlag(RenderTargetUpdateFlags.Layered);
|
bool layered = updateFlags.HasFlag(RenderTargetUpdateFlags.Layered);
|
||||||
bool singleColor = updateFlags.HasFlag(RenderTargetUpdateFlags.SingleColor);
|
bool singleColor = updateFlags.HasFlag(RenderTargetUpdateFlags.SingleColor);
|
||||||
|
bool discard = updateFlags.HasFlag(RenderTargetUpdateFlags.DiscardClip);
|
||||||
|
|
||||||
int count = useControl ? rtControl.UnpackCount() : Constants.TotalRenderTargets;
|
int count = useControl ? rtControl.UnpackCount() : Constants.TotalRenderTargets;
|
||||||
|
|
||||||
@ -486,6 +487,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
memoryManager,
|
memoryManager,
|
||||||
colorState,
|
colorState,
|
||||||
_vtgWritesRtLayer || layered,
|
_vtgWritesRtLayer || layered,
|
||||||
|
discard,
|
||||||
samplesInX,
|
samplesInX,
|
||||||
samplesInY,
|
samplesInY,
|
||||||
sizeHint);
|
sizeHint);
|
||||||
@ -525,6 +527,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
dsState,
|
dsState,
|
||||||
dsSize,
|
dsSize,
|
||||||
_vtgWritesRtLayer || layered,
|
_vtgWritesRtLayer || layered,
|
||||||
|
discard,
|
||||||
samplesInX,
|
samplesInX,
|
||||||
samplesInY,
|
samplesInY,
|
||||||
sizeHint);
|
sizeHint);
|
||||||
|
@ -570,6 +570,18 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
return Group.CheckDirty(this, consume);
|
return Group.CheckDirty(this, consume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Discards all data for this texture.
|
||||||
|
/// This clears all dirty flags, modified flags, and pending copies from other textures.
|
||||||
|
/// It should be used if the texture data will be fully overwritten by the next use.
|
||||||
|
/// </summary>
|
||||||
|
public void DiscardData()
|
||||||
|
{
|
||||||
|
Group.DiscardData(this);
|
||||||
|
|
||||||
|
_dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Synchronizes guest and host memory.
|
/// Synchronizes guest and host memory.
|
||||||
/// This will overwrite the texture data with the texture data on the guest memory, if a CPU
|
/// This will overwrite the texture data with the texture data on the guest memory, if a CPU
|
||||||
|
@ -311,7 +311,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
flags |= TextureSearchFlags.NoCreate;
|
flags |= TextureSearchFlags.NoCreate;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture texture = FindOrCreateTexture(memoryManager, flags, info, 0);
|
Texture texture = FindOrCreateTexture(memoryManager, flags, info, 0, sizeHint: sizeHint);
|
||||||
|
|
||||||
texture?.SynchronizeMemory();
|
texture?.SynchronizeMemory();
|
||||||
|
|
||||||
@ -324,6 +324,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="colorState">Color buffer texture to find or create</param>
|
/// <param name="colorState">Color buffer texture to find or create</param>
|
||||||
/// <param name="layered">Indicates if the texture might be accessed with a non-zero layer index</param>
|
/// <param name="layered">Indicates if the texture might be accessed with a non-zero layer index</param>
|
||||||
|
/// <param name="discard">Indicates that the sizeHint region's data will be overwritten</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>
|
||||||
@ -332,6 +333,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
MemoryManager memoryManager,
|
MemoryManager memoryManager,
|
||||||
RtColorState colorState,
|
RtColorState colorState,
|
||||||
bool layered,
|
bool layered,
|
||||||
|
bool discard,
|
||||||
int samplesInX,
|
int samplesInX,
|
||||||
int samplesInY,
|
int samplesInY,
|
||||||
Size sizeHint)
|
Size sizeHint)
|
||||||
@ -398,7 +400,14 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
int layerSize = !isLinear ? colorState.LayerSize * 4 : 0;
|
int layerSize = !isLinear ? colorState.LayerSize * 4 : 0;
|
||||||
|
|
||||||
Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, layerSize);
|
var flags = TextureSearchFlags.WithUpscale;
|
||||||
|
|
||||||
|
if (discard)
|
||||||
|
{
|
||||||
|
flags |= TextureSearchFlags.DiscardData;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture texture = FindOrCreateTexture(memoryManager, flags, info, layerSize, sizeHint: sizeHint);
|
||||||
|
|
||||||
texture?.SynchronizeMemory();
|
texture?.SynchronizeMemory();
|
||||||
|
|
||||||
@ -412,6 +421,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// <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="layered">Indicates if the texture might be accessed with a non-zero layer index</param>
|
||||||
|
/// <param name="discard">Indicates that the sizeHint region's data will be overwritten</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>
|
||||||
@ -421,6 +431,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
RtDepthStencilState dsState,
|
RtDepthStencilState dsState,
|
||||||
Size3D size,
|
Size3D size,
|
||||||
bool layered,
|
bool layered,
|
||||||
|
bool discard,
|
||||||
int samplesInX,
|
int samplesInX,
|
||||||
int samplesInY,
|
int samplesInY,
|
||||||
Size sizeHint)
|
Size sizeHint)
|
||||||
@ -465,7 +476,14 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
target,
|
target,
|
||||||
formatInfo);
|
formatInfo);
|
||||||
|
|
||||||
Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, dsState.LayerSize * 4);
|
var flags = TextureSearchFlags.WithUpscale;
|
||||||
|
|
||||||
|
if (discard)
|
||||||
|
{
|
||||||
|
flags |= TextureSearchFlags.DiscardData;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture texture = FindOrCreateTexture(memoryManager, flags, info, dsState.LayerSize * 4, sizeHint: sizeHint);
|
||||||
|
|
||||||
texture?.SynchronizeMemory();
|
texture?.SynchronizeMemory();
|
||||||
|
|
||||||
@ -500,6 +518,37 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
return Math.Clamp(widthAligned - alignment + 1, minimumWidth, widthAligned);
|
return Math.Clamp(widthAligned - alignment + 1, minimumWidth, widthAligned);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if texture data should be fully discarded
|
||||||
|
/// based on the size hint region and whether it is set to be discarded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="discard">Whether the size hint region should be discarded</param>
|
||||||
|
/// <param name="texture">The texture being discarded</param>
|
||||||
|
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
|
||||||
|
/// <returns>True if the data should be discarded, false otherwise</returns>
|
||||||
|
private static bool ShouldDiscard(bool discard, Texture texture, Size? sizeHint)
|
||||||
|
{
|
||||||
|
return discard &&
|
||||||
|
texture.Info.DepthOrLayers == 1 &&
|
||||||
|
sizeHint != null &&
|
||||||
|
texture.Width <= sizeHint.Value.Width &&
|
||||||
|
texture.Height <= sizeHint.Value.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Discards texture data if requested and possible.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="discard">Whether the size hint region should be discarded</param>
|
||||||
|
/// <param name="texture">The texture being discarded</param>
|
||||||
|
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
|
||||||
|
private static void DiscardIfNeeded(bool discard, Texture texture, Size? sizeHint)
|
||||||
|
{
|
||||||
|
if (ShouldDiscard(discard, texture, sizeHint))
|
||||||
|
{
|
||||||
|
texture.DiscardData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to find an existing texture, or create a new one if not found.
|
/// Tries to find an existing texture, or create a new one if not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -507,6 +556,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// <param name="flags">The texture search flags, defines texture comparison rules</param>
|
/// <param name="flags">The texture search flags, defines texture comparison rules</param>
|
||||||
/// <param name="info">Texture information of the texture to be found or created</param>
|
/// <param name="info">Texture information of the texture to be found or created</param>
|
||||||
/// <param name="layerSize">Size in bytes of a single texture layer</param>
|
/// <param name="layerSize">Size in bytes of a single texture layer</param>
|
||||||
|
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
|
||||||
/// <param name="range">Optional ranges of physical memory where the texture data is located</param>
|
/// <param name="range">Optional ranges of physical memory where the texture data is located</param>
|
||||||
/// <returns>The texture</returns>
|
/// <returns>The texture</returns>
|
||||||
public Texture FindOrCreateTexture(
|
public Texture FindOrCreateTexture(
|
||||||
@ -514,9 +564,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
TextureSearchFlags flags,
|
TextureSearchFlags flags,
|
||||||
TextureInfo info,
|
TextureInfo info,
|
||||||
int layerSize = 0,
|
int layerSize = 0,
|
||||||
|
Size? sizeHint = null,
|
||||||
MultiRange? range = null)
|
MultiRange? range = null)
|
||||||
{
|
{
|
||||||
bool isSamplerTexture = (flags & TextureSearchFlags.ForSampler) != 0;
|
bool isSamplerTexture = (flags & TextureSearchFlags.ForSampler) != 0;
|
||||||
|
bool discard = (flags & TextureSearchFlags.DiscardData) != 0;
|
||||||
|
|
||||||
TextureScaleMode scaleMode = IsUpscaleCompatible(info, (flags & TextureSearchFlags.WithUpscale) != 0);
|
TextureScaleMode scaleMode = IsUpscaleCompatible(info, (flags & TextureSearchFlags.WithUpscale) != 0);
|
||||||
|
|
||||||
@ -612,6 +664,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
if (texture != null)
|
if (texture != null)
|
||||||
{
|
{
|
||||||
|
DiscardIfNeeded(discard, texture, sizeHint);
|
||||||
|
|
||||||
texture.SynchronizeMemory();
|
texture.SynchronizeMemory();
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
@ -907,7 +961,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
// We need to synchronize before copying the old view data to the texture,
|
// We need to synchronize before copying the old view data to the texture,
|
||||||
// otherwise the copied data would be overwritten by a future synchronization.
|
// otherwise the copied data would be overwritten by a future synchronization.
|
||||||
texture.InitializeData(false, setData);
|
texture.InitializeData(false, setData && !ShouldDiscard(discard, texture, sizeHint));
|
||||||
|
|
||||||
texture.Group.InitializeOverlaps();
|
texture.Group.InitializeOverlaps();
|
||||||
|
|
||||||
|
@ -278,6 +278,24 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
return dirty;
|
return dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Discards all data for a given texture.
|
||||||
|
/// This clears all dirty flags, modified flags, and pending copies from other textures.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="texture">The texture being discarded</param>
|
||||||
|
public void DiscardData(Texture texture)
|
||||||
|
{
|
||||||
|
EvaluateRelevantHandles(texture, (baseHandle, regionCount, split) =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < regionCount; i++)
|
||||||
|
{
|
||||||
|
TextureGroupHandle group = _handles[baseHandle + i];
|
||||||
|
|
||||||
|
group.DiscardData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Synchronize memory for a given texture.
|
/// Synchronize memory for a given texture.
|
||||||
/// If overlapping tracking handles are dirty, fully or partially synchronize the texture data.
|
/// If overlapping tracking handles are dirty, fully or partially synchronize the texture data.
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using Ryujinx.Memory.Tracking;
|
using Ryujinx.Memory.Tracking;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Image
|
namespace Ryujinx.Graphics.Gpu.Image
|
||||||
@ -155,6 +154,24 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Discards all data for this handle.
|
||||||
|
/// This clears all dirty flags, modified flags, and pending copies from other handles.
|
||||||
|
/// </summary>
|
||||||
|
public void DiscardData()
|
||||||
|
{
|
||||||
|
Modified = false;
|
||||||
|
DeferredCopy = null;
|
||||||
|
|
||||||
|
foreach (RegionHandle handle in Handles)
|
||||||
|
{
|
||||||
|
if (handle.Dirty)
|
||||||
|
{
|
||||||
|
handle.Reprotect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculate a list of which views overlap this handle.
|
/// Calculate a list of which views overlap this handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -14,5 +14,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
DepthAlias = 1 << 3,
|
DepthAlias = 1 << 3,
|
||||||
WithUpscale = 1 << 4,
|
WithUpscale = 1 << 4,
|
||||||
NoCreate = 1 << 5,
|
NoCreate = 1 << 5,
|
||||||
|
DiscardData = 1 << 6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
{
|
{
|
||||||
pt.AcquireCallback(_context, pt.UserObj);
|
pt.AcquireCallback(_context, pt.UserObj);
|
||||||
|
|
||||||
Image.Texture texture = pt.Cache.FindOrCreateTexture(null, TextureSearchFlags.WithUpscale, pt.Info, 0, pt.Range);
|
Image.Texture texture = pt.Cache.FindOrCreateTexture(null, TextureSearchFlags.WithUpscale, pt.Info, 0, range: pt.Range);
|
||||||
|
|
||||||
pt.Cache.Tick();
|
pt.Cache.Tick();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user