Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
618c8edc79 | ||
|
99fc4fa61b | ||
|
f6d5499a16 | ||
|
26bf13a65d | ||
|
96cf242bcf | ||
|
59755818ef | ||
|
f8beeeb7d3 | ||
|
cb250162cb | ||
|
7528f94536 |
@@ -44,7 +44,7 @@
|
|||||||
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
|
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
|
||||||
<PackageVersion Include="SPB" Version="0.0.4-build28" />
|
<PackageVersion Include="SPB" Version="0.0.4-build28" />
|
||||||
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
|
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
|
||||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.26.0" />
|
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.26.1" />
|
||||||
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
|
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
|
||||||
<PackageVersion Include="System.Management" Version="7.0.0" />
|
<PackageVersion Include="System.Management" Version="7.0.0" />
|
||||||
<PackageVersion Include="System.Net.NameResolution" Version="4.3.0" />
|
<PackageVersion Include="System.Net.NameResolution" Version="4.3.0" />
|
||||||
|
@@ -53,7 +53,6 @@ using Key = Ryujinx.Input.Key;
|
|||||||
using MouseButton = Ryujinx.Input.MouseButton;
|
using MouseButton = Ryujinx.Input.MouseButton;
|
||||||
using Size = Avalonia.Size;
|
using Size = Avalonia.Size;
|
||||||
using Switch = Ryujinx.HLE.Switch;
|
using Switch = Ryujinx.HLE.Switch;
|
||||||
using WindowState = Avalonia.Controls.WindowState;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava
|
namespace Ryujinx.Ava
|
||||||
{
|
{
|
||||||
@@ -766,7 +765,7 @@ namespace Ryujinx.Ava
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void RenderLoop()
|
private void RenderLoop()
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
@@ -802,6 +801,8 @@ namespace Ryujinx.Ava
|
|||||||
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
|
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
|
||||||
Translator.IsReadyForTranslation.Set();
|
Translator.IsReadyForTranslation.Set();
|
||||||
|
|
||||||
|
_renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
|
||||||
|
|
||||||
while (_isActive)
|
while (_isActive)
|
||||||
{
|
{
|
||||||
_ticks += _chrono.ElapsedTicks;
|
_ticks += _chrono.ElapsedTicks;
|
||||||
|
@@ -725,10 +725,25 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool clearDepth = (argument & 1) != 0;
|
||||||
|
bool clearStencil = (argument & 2) != 0;
|
||||||
|
uint componentMask = (uint)((argument >> 2) & 0xf);
|
||||||
int index = (argument >> 6) & 0xf;
|
int index = (argument >> 6) & 0xf;
|
||||||
int layer = (argument >> 10) & 0x3ff;
|
int layer = (argument >> 10) & 0x3ff;
|
||||||
|
|
||||||
engine.UpdateRenderTargetState(useControl: false, layered: layer != 0 || layerCount > 1, singleUse: index);
|
RenderTargetUpdateFlags updateFlags = RenderTargetUpdateFlags.SingleColor;
|
||||||
|
|
||||||
|
if (layer != 0 || layerCount > 1)
|
||||||
|
{
|
||||||
|
updateFlags |= RenderTargetUpdateFlags.Layered;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clearDepth || clearStencil)
|
||||||
|
{
|
||||||
|
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
|
||||||
@@ -788,18 +803,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
_context.Renderer.Pipeline.SetScissors(scissors);
|
_context.Renderer.Pipeline.SetScissors(scissors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clipMismatch)
|
_channel.TextureManager.UpdateRenderTargets();
|
||||||
{
|
|
||||||
_channel.TextureManager.UpdateRenderTarget(index);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_channel.TextureManager.UpdateRenderTargets();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool clearDepth = (argument & 1) != 0;
|
|
||||||
bool clearStencil = (argument & 2) != 0;
|
|
||||||
uint componentMask = (uint)((argument >> 2) & 0xf);
|
|
||||||
|
|
||||||
if (componentMask != 0)
|
if (componentMask != 0)
|
||||||
{
|
{
|
||||||
@@ -841,7 +845,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
engine.UpdateScissorState();
|
engine.UpdateScissorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.UpdateRenderTargetState(useControl: true);
|
engine.UpdateRenderTargetState(RenderTargetUpdateFlags.UpdateAll);
|
||||||
|
|
||||||
if (renderEnable == ConditionalRenderEnabled.Host)
|
if (renderEnable == ConditionalRenderEnabled.Host)
|
||||||
{
|
{
|
||||||
|
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Flags indicating how the render targets should be updated.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
enum RenderTargetUpdateFlags
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// No flags.
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get render target index from the control register.
|
||||||
|
/// </summary>
|
||||||
|
UseControl = 1 << 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that all render targets are 2D array textures.
|
||||||
|
/// </summary>
|
||||||
|
Layered = 1 << 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that only a single color target will be used.
|
||||||
|
/// </summary>
|
||||||
|
SingleColor = 1 << 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the depth-stencil target will be used.
|
||||||
|
/// </summary>
|
||||||
|
UpdateDepthStencil = 1 << 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default update flags for draw.
|
||||||
|
/// </summary>
|
||||||
|
UpdateAll = UseControl | UpdateDepthStencil
|
||||||
|
}
|
||||||
|
}
|
@@ -402,20 +402,23 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateRenderTargetState()
|
private void UpdateRenderTargetState()
|
||||||
{
|
{
|
||||||
UpdateRenderTargetState(true);
|
UpdateRenderTargetState(RenderTargetUpdateFlags.UpdateAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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="updateFlags">Flags indicating which render targets should be updated and how</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, bool layered = false, int singleUse = -1)
|
public void UpdateRenderTargetState(RenderTargetUpdateFlags updateFlags, int singleUse = -1)
|
||||||
{
|
{
|
||||||
var memoryManager = _channel.MemoryManager;
|
var memoryManager = _channel.MemoryManager;
|
||||||
var rtControl = _state.State.RtControl;
|
var rtControl = _state.State.RtControl;
|
||||||
|
|
||||||
|
bool useControl = updateFlags.HasFlag(RenderTargetUpdateFlags.UseControl);
|
||||||
|
bool layered = updateFlags.HasFlag(RenderTargetUpdateFlags.Layered);
|
||||||
|
bool singleColor = updateFlags.HasFlag(RenderTargetUpdateFlags.SingleColor);
|
||||||
|
|
||||||
int count = useControl ? rtControl.UnpackCount() : Constants.TotalRenderTargets;
|
int count = useControl ? rtControl.UnpackCount() : Constants.TotalRenderTargets;
|
||||||
|
|
||||||
var msaaMode = _state.State.RtMsaaMode;
|
var msaaMode = _state.State.RtMsaaMode;
|
||||||
@@ -438,7 +441,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
var colorState = _state.State.RtColorState[rtIndex];
|
var colorState = _state.State.RtColorState[rtIndex];
|
||||||
|
|
||||||
if (index >= count || !IsRtEnabled(colorState))
|
if (index >= count || !IsRtEnabled(colorState) || (singleColor && index != singleUse))
|
||||||
{
|
{
|
||||||
changedScale |= _channel.TextureManager.SetRenderTargetColor(index, null);
|
changedScale |= _channel.TextureManager.SetRenderTargetColor(index, null);
|
||||||
|
|
||||||
@@ -478,7 +481,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
Image.Texture depthStencil = null;
|
Image.Texture depthStencil = null;
|
||||||
|
|
||||||
if (dsEnable)
|
if (dsEnable && updateFlags.HasFlag(RenderTargetUpdateFlags.UpdateDepthStencil))
|
||||||
{
|
{
|
||||||
var dsState = _state.State.RtDepthStencilState;
|
var dsState = _state.State.RtDepthStencilState;
|
||||||
var dsSize = _state.State.RtDepthStencilSize;
|
var dsSize = _state.State.RtDepthStencilSize;
|
||||||
|
@@ -139,12 +139,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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="updateFlags">Flags indicating which render targets should be updated and how</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, bool layered = false, int singleUse = -1)
|
public void UpdateRenderTargetState(RenderTargetUpdateFlags updateFlags, int singleUse = -1)
|
||||||
{
|
{
|
||||||
_stateUpdater.UpdateRenderTargetState(useControl, layered, singleUse);
|
_stateUpdater.UpdateRenderTargetState(updateFlags, singleUse);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -33,10 +33,12 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class AutoDeleteCache : IEnumerable<Texture>
|
class AutoDeleteCache : IEnumerable<Texture>
|
||||||
{
|
{
|
||||||
|
private const int MinCountForDeletion = 32;
|
||||||
private const int MaxCapacity = 2048;
|
private const int MaxCapacity = 2048;
|
||||||
|
private const ulong MaxTextureSizeCapacity = 512 * 1024 * 1024; // MB;
|
||||||
|
|
||||||
private readonly LinkedList<Texture> _textures;
|
private readonly LinkedList<Texture> _textures;
|
||||||
private readonly ConcurrentQueue<Texture> _deferredRemovals;
|
private ulong _totalSize;
|
||||||
|
|
||||||
private HashSet<ShortTextureCacheEntry> _shortCacheBuilder;
|
private HashSet<ShortTextureCacheEntry> _shortCacheBuilder;
|
||||||
private HashSet<ShortTextureCacheEntry> _shortCache;
|
private HashSet<ShortTextureCacheEntry> _shortCache;
|
||||||
@@ -49,7 +51,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
public AutoDeleteCache()
|
public AutoDeleteCache()
|
||||||
{
|
{
|
||||||
_textures = new LinkedList<Texture>();
|
_textures = new LinkedList<Texture>();
|
||||||
_deferredRemovals = new ConcurrentQueue<Texture>();
|
|
||||||
|
|
||||||
_shortCacheBuilder = new HashSet<ShortTextureCacheEntry>();
|
_shortCacheBuilder = new HashSet<ShortTextureCacheEntry>();
|
||||||
_shortCache = new HashSet<ShortTextureCacheEntry>();
|
_shortCache = new HashSet<ShortTextureCacheEntry>();
|
||||||
@@ -67,37 +68,15 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// <param name="texture">The texture to be added to the cache</param>
|
/// <param name="texture">The texture to be added to the cache</param>
|
||||||
public void Add(Texture texture)
|
public void Add(Texture texture)
|
||||||
{
|
{
|
||||||
texture.IncrementReferenceCount();
|
_totalSize += texture.Size;
|
||||||
|
|
||||||
|
texture.IncrementReferenceCount();
|
||||||
texture.CacheNode = _textures.AddLast(texture);
|
texture.CacheNode = _textures.AddLast(texture);
|
||||||
|
|
||||||
if (_textures.Count > MaxCapacity)
|
if (_textures.Count > MaxCapacity ||
|
||||||
|
(_totalSize > MaxTextureSizeCapacity && _textures.Count >= MinCountForDeletion))
|
||||||
{
|
{
|
||||||
Texture oldestTexture = _textures.First.Value;
|
RemoveLeastUsedTexture();
|
||||||
|
|
||||||
if (!oldestTexture.CheckModified(false))
|
|
||||||
{
|
|
||||||
// The texture must be flushed if it falls out of the auto delete cache.
|
|
||||||
// Flushes out of the auto delete cache do not trigger write tracking,
|
|
||||||
// as it is expected that other overlapping textures exist that have more up-to-date contents.
|
|
||||||
|
|
||||||
oldestTexture.Group.SynchronizeDependents(oldestTexture);
|
|
||||||
oldestTexture.FlushModified(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
_textures.RemoveFirst();
|
|
||||||
|
|
||||||
oldestTexture.DecrementReferenceCount();
|
|
||||||
|
|
||||||
oldestTexture.CacheNode = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_deferredRemovals.Count > 0)
|
|
||||||
{
|
|
||||||
while (_deferredRemovals.TryDequeue(out Texture textureToRemove))
|
|
||||||
{
|
|
||||||
Remove(textureToRemove, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +99,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
texture.CacheNode = _textures.AddLast(texture);
|
texture.CacheNode = _textures.AddLast(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_totalSize > MaxTextureSizeCapacity && _textures.Count >= MinCountForDeletion)
|
||||||
|
{
|
||||||
|
RemoveLeastUsedTexture();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -127,6 +111,31 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the least used texture from the cache.
|
||||||
|
/// </summary>
|
||||||
|
private void RemoveLeastUsedTexture()
|
||||||
|
{
|
||||||
|
Texture oldestTexture = _textures.First.Value;
|
||||||
|
|
||||||
|
_totalSize -= oldestTexture.Size;
|
||||||
|
|
||||||
|
if (!oldestTexture.CheckModified(false))
|
||||||
|
{
|
||||||
|
// The texture must be flushed if it falls out of the auto delete cache.
|
||||||
|
// Flushes out of the auto delete cache do not trigger write tracking,
|
||||||
|
// as it is expected that other overlapping textures exist that have more up-to-date contents.
|
||||||
|
|
||||||
|
oldestTexture.Group.SynchronizeDependents(oldestTexture);
|
||||||
|
oldestTexture.FlushModified(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
_textures.RemoveFirst();
|
||||||
|
|
||||||
|
oldestTexture.DecrementReferenceCount();
|
||||||
|
oldestTexture.CacheNode = null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes a texture from the cache.
|
/// Removes a texture from the cache.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -148,20 +157,13 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
_textures.Remove(texture.CacheNode);
|
_textures.Remove(texture.CacheNode);
|
||||||
|
|
||||||
|
_totalSize -= texture.Size;
|
||||||
|
|
||||||
texture.CacheNode = null;
|
texture.CacheNode = null;
|
||||||
|
|
||||||
return texture.DecrementReferenceCount();
|
return texture.DecrementReferenceCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Queues removal of a texture from the cache in a thread safe way.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="texture">The texture to be removed from the cache</param>
|
|
||||||
public void RemoveDeferred(Texture texture)
|
|
||||||
{
|
|
||||||
_deferredRemovals.Enqueue(texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempt to find a texture on the short duration cache.
|
/// Attempt to find a texture on the short duration cache.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
@@ -89,12 +88,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public TextureGroup Group { get; private set; }
|
public TextureGroup Group { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set when a texture has been changed size. This indicates that it may need to be
|
|
||||||
/// changed again when obtained as a sampler.
|
|
||||||
/// </summary>
|
|
||||||
public bool ChangedSize { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set when a texture's GPU VA has ever been partially or fully unmapped.
|
/// Set when a texture's GPU VA has ever been partially or fully unmapped.
|
||||||
/// This indicates that the range must be fully checked when matching the texture.
|
/// This indicates that the range must be fully checked when matching the texture.
|
||||||
@@ -410,122 +403,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
Group.CreateCopyDependency(contained, FirstLayer + layer, FirstLevel + level, copyTo);
|
Group.CreateCopyDependency(contained, FirstLayer + layer, FirstLevel + level, copyTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Changes the texture size.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This operation may also change the size of all mipmap levels, including from the parent
|
|
||||||
/// and other possible child textures, to ensure that all sizes are consistent.
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="width">The new texture width</param>
|
|
||||||
/// <param name="height">The new texture height</param>
|
|
||||||
/// <param name="depthOrLayers">The new texture depth (for 3D textures) or layers (for layered textures)</param>
|
|
||||||
public void ChangeSize(int width, int height, int depthOrLayers)
|
|
||||||
{
|
|
||||||
int blockWidth = Info.FormatInfo.BlockWidth;
|
|
||||||
int blockHeight = Info.FormatInfo.BlockHeight;
|
|
||||||
|
|
||||||
width <<= FirstLevel;
|
|
||||||
height <<= FirstLevel;
|
|
||||||
|
|
||||||
if (Target == Target.Texture3D)
|
|
||||||
{
|
|
||||||
depthOrLayers <<= FirstLevel;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
depthOrLayers = _viewStorage.Info.DepthOrLayers;
|
|
||||||
}
|
|
||||||
|
|
||||||
_viewStorage.RecreateStorageOrView(width, height, blockWidth, blockHeight, depthOrLayers);
|
|
||||||
|
|
||||||
foreach (Texture view in _viewStorage._views)
|
|
||||||
{
|
|
||||||
int viewWidth = Math.Max(1, width >> view.FirstLevel);
|
|
||||||
int viewHeight = Math.Max(1, height >> view.FirstLevel);
|
|
||||||
|
|
||||||
int viewDepthOrLayers;
|
|
||||||
|
|
||||||
if (view.Info.Target == Target.Texture3D)
|
|
||||||
{
|
|
||||||
viewDepthOrLayers = Math.Max(1, depthOrLayers >> view.FirstLevel);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
viewDepthOrLayers = view.Info.DepthOrLayers;
|
|
||||||
}
|
|
||||||
|
|
||||||
view.RecreateStorageOrView(viewWidth, viewHeight, blockWidth, blockHeight, viewDepthOrLayers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Recreates the texture storage (or view, in the case of child textures) of this texture.
|
|
||||||
/// This allows recreating the texture with a new size.
|
|
||||||
/// A copy is automatically performed from the old to the new texture.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="width">The new texture width</param>
|
|
||||||
/// <param name="height">The new texture height</param>
|
|
||||||
/// <param name="width">The block width related to the given width</param>
|
|
||||||
/// <param name="height">The block height related to the given height</param>
|
|
||||||
/// <param name="depthOrLayers">The new texture depth (for 3D textures) or layers (for layered textures)</param>
|
|
||||||
private void RecreateStorageOrView(int width, int height, int blockWidth, int blockHeight, int depthOrLayers)
|
|
||||||
{
|
|
||||||
RecreateStorageOrView(
|
|
||||||
BitUtils.DivRoundUp(width * Info.FormatInfo.BlockWidth, blockWidth),
|
|
||||||
BitUtils.DivRoundUp(height * Info.FormatInfo.BlockHeight, blockHeight),
|
|
||||||
depthOrLayers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Recreates the texture storage (or view, in the case of child textures) of this texture.
|
|
||||||
/// This allows recreating the texture with a new size.
|
|
||||||
/// A copy is automatically performed from the old to the new texture.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="width">The new texture width</param>
|
|
||||||
/// <param name="height">The new texture height</param>
|
|
||||||
/// <param name="depthOrLayers">The new texture depth (for 3D textures) or layers (for layered textures)</param>
|
|
||||||
private void RecreateStorageOrView(int width, int height, int depthOrLayers)
|
|
||||||
{
|
|
||||||
ChangedSize = true;
|
|
||||||
|
|
||||||
SetInfo(new TextureInfo(
|
|
||||||
Info.GpuAddress,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
depthOrLayers,
|
|
||||||
Info.Levels,
|
|
||||||
Info.SamplesInX,
|
|
||||||
Info.SamplesInY,
|
|
||||||
Info.Stride,
|
|
||||||
Info.IsLinear,
|
|
||||||
Info.GobBlocksInY,
|
|
||||||
Info.GobBlocksInZ,
|
|
||||||
Info.GobBlocksInTileX,
|
|
||||||
Info.Target,
|
|
||||||
Info.FormatInfo,
|
|
||||||
Info.DepthStencilMode,
|
|
||||||
Info.SwizzleR,
|
|
||||||
Info.SwizzleG,
|
|
||||||
Info.SwizzleB,
|
|
||||||
Info.SwizzleA));
|
|
||||||
|
|
||||||
TextureCreateInfo createInfo = TextureCache.GetCreateInfo(Info, _context.Capabilities, ScaleFactor);
|
|
||||||
|
|
||||||
if (_viewStorage != this)
|
|
||||||
{
|
|
||||||
ReplaceStorage(_viewStorage.HostTexture.CreateView(createInfo, FirstLayer, FirstLevel));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ITexture newStorage = _context.Renderer.CreateTexture(createInfo, ScaleFactor);
|
|
||||||
|
|
||||||
HostTexture.CopyTo(newStorage, 0, 0);
|
|
||||||
|
|
||||||
ReplaceStorage(newStorage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers when a texture has had its data set after being scaled, and
|
/// Registers when a texture has had its data set after being scaled, and
|
||||||
/// determines if it should be blacklisted from scaling to improve performance.
|
/// determines if it should be blacklisted from scaling to improve performance.
|
||||||
@@ -1215,7 +1092,9 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// <returns>A value indicating how well this texture matches the given info</returns>
|
/// <returns>A value indicating how well this texture matches the given info</returns>
|
||||||
public TextureMatchQuality IsExactMatch(TextureInfo info, TextureSearchFlags flags)
|
public TextureMatchQuality IsExactMatch(TextureInfo info, TextureSearchFlags flags)
|
||||||
{
|
{
|
||||||
TextureMatchQuality matchQuality = TextureCompatibility.FormatMatches(Info, info, (flags & TextureSearchFlags.ForSampler) != 0, (flags & TextureSearchFlags.ForCopy) != 0);
|
bool forSampler = (flags & TextureSearchFlags.ForSampler) != 0;
|
||||||
|
|
||||||
|
TextureMatchQuality matchQuality = TextureCompatibility.FormatMatches(Info, info, forSampler, (flags & TextureSearchFlags.ForCopy) != 0);
|
||||||
|
|
||||||
if (matchQuality == TextureMatchQuality.NoMatch)
|
if (matchQuality == TextureMatchQuality.NoMatch)
|
||||||
{
|
{
|
||||||
@@ -1227,12 +1106,12 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
return TextureMatchQuality.NoMatch;
|
return TextureMatchQuality.NoMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TextureCompatibility.SizeMatches(Info, info, (flags & TextureSearchFlags.Strict) == 0, FirstLevel))
|
if (!TextureCompatibility.SizeMatches(Info, info, forSampler))
|
||||||
{
|
{
|
||||||
return TextureMatchQuality.NoMatch;
|
return TextureMatchQuality.NoMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & TextureSearchFlags.ForSampler) != 0 || (flags & TextureSearchFlags.Strict) != 0)
|
if ((flags & TextureSearchFlags.ForSampler) != 0)
|
||||||
{
|
{
|
||||||
if (!TextureCompatibility.SamplerParamsMatches(Info, info))
|
if (!TextureCompatibility.SamplerParamsMatches(Info, info))
|
||||||
{
|
{
|
||||||
@@ -1262,12 +1141,20 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="info">Texture view information</param>
|
/// <param name="info">Texture view information</param>
|
||||||
/// <param name="range">Texture view physical memory ranges</param>
|
/// <param name="range">Texture view physical memory ranges</param>
|
||||||
|
/// <param name="exactSize">Indicates if the texture sizes must be exactly equal, or width is allowed to differ</param>
|
||||||
/// <param name="layerSize">Layer size on the given texture</param>
|
/// <param name="layerSize">Layer size on the given texture</param>
|
||||||
/// <param name="caps">Host GPU capabilities</param>
|
/// <param name="caps">Host GPU capabilities</param>
|
||||||
/// <param name="firstLayer">Texture view initial layer on this texture</param>
|
/// <param name="firstLayer">Texture view initial layer on this texture</param>
|
||||||
/// <param name="firstLevel">Texture view first mipmap level on this texture</param>
|
/// <param name="firstLevel">Texture view first mipmap level on this texture</param>
|
||||||
/// <returns>The level of compatiblilty a view with the given parameters created from this texture has</returns>
|
/// <returns>The level of compatiblilty a view with the given parameters created from this texture has</returns>
|
||||||
public TextureViewCompatibility IsViewCompatible(TextureInfo info, MultiRange range, int layerSize, Capabilities caps, out int firstLayer, out int firstLevel)
|
public TextureViewCompatibility IsViewCompatible(
|
||||||
|
TextureInfo info,
|
||||||
|
MultiRange range,
|
||||||
|
bool exactSize,
|
||||||
|
int layerSize,
|
||||||
|
Capabilities caps,
|
||||||
|
out int firstLayer,
|
||||||
|
out int firstLevel)
|
||||||
{
|
{
|
||||||
TextureViewCompatibility result = TextureViewCompatibility.Full;
|
TextureViewCompatibility result = TextureViewCompatibility.Full;
|
||||||
|
|
||||||
@@ -1317,7 +1204,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
return TextureViewCompatibility.LayoutIncompatible;
|
return TextureViewCompatibility.LayoutIncompatible;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewSizeMatches(Info, info, firstLevel));
|
result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewSizeMatches(Info, info, exactSize, firstLevel));
|
||||||
result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewSubImagesInBounds(Info, info, firstLayer, firstLevel));
|
result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewSubImagesInBounds(Info, info, firstLayer, firstLevel));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -1750,13 +1637,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
|
|
||||||
RemoveFromPools(true);
|
RemoveFromPools(true);
|
||||||
|
|
||||||
// We only want to remove if there's no mapped region of the texture that was modified by the GPU,
|
|
||||||
// otherwise we could lose data.
|
|
||||||
if (!Group.AnyModified(this))
|
|
||||||
{
|
|
||||||
_physicalMemory.TextureCache.QueueAutoDeleteCacheRemoval(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -210,8 +210,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
ulong offset,
|
ulong offset,
|
||||||
FormatInfo formatInfo,
|
FormatInfo formatInfo,
|
||||||
bool shouldCreate,
|
bool shouldCreate,
|
||||||
bool preferScaling = true,
|
bool preferScaling,
|
||||||
Size? sizeHint = null)
|
Size sizeHint)
|
||||||
{
|
{
|
||||||
int gobBlocksInY = copyTexture.MemoryLayout.UnpackGobBlocksInY();
|
int gobBlocksInY = copyTexture.MemoryLayout.UnpackGobBlocksInY();
|
||||||
int gobBlocksInZ = copyTexture.MemoryLayout.UnpackGobBlocksInZ();
|
int gobBlocksInZ = copyTexture.MemoryLayout.UnpackGobBlocksInZ();
|
||||||
@@ -229,7 +229,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
TextureInfo info = new TextureInfo(
|
TextureInfo info = new TextureInfo(
|
||||||
copyTexture.Address.Pack() + offset,
|
copyTexture.Address.Pack() + offset,
|
||||||
width,
|
GetMinimumWidthInGob(width, sizeHint.Width, formatInfo.BytesPerPixel, copyTexture.LinearLayout),
|
||||||
copyTexture.Height,
|
copyTexture.Height,
|
||||||
copyTexture.Depth,
|
copyTexture.Depth,
|
||||||
1,
|
1,
|
||||||
@@ -255,7 +255,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
flags |= TextureSearchFlags.NoCreate;
|
flags |= TextureSearchFlags.NoCreate;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture texture = FindOrCreateTexture(memoryManager, flags, info, 0, sizeHint);
|
Texture texture = FindOrCreateTexture(memoryManager, flags, info, 0);
|
||||||
|
|
||||||
texture?.SynchronizeMemory();
|
texture?.SynchronizeMemory();
|
||||||
|
|
||||||
@@ -326,7 +326,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
TextureInfo info = new TextureInfo(
|
TextureInfo info = new TextureInfo(
|
||||||
colorState.Address.Pack(),
|
colorState.Address.Pack(),
|
||||||
width,
|
GetMinimumWidthInGob(width, sizeHint.Width, formatInfo.BytesPerPixel, isLinear),
|
||||||
colorState.Height,
|
colorState.Height,
|
||||||
colorState.Depth,
|
colorState.Depth,
|
||||||
1,
|
1,
|
||||||
@@ -342,7 +342,7 @@ 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, sizeHint);
|
Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, layerSize);
|
||||||
|
|
||||||
texture?.SynchronizeMemory();
|
texture?.SynchronizeMemory();
|
||||||
|
|
||||||
@@ -395,7 +395,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
TextureInfo info = new TextureInfo(
|
TextureInfo info = new TextureInfo(
|
||||||
dsState.Address.Pack(),
|
dsState.Address.Pack(),
|
||||||
size.Width,
|
GetMinimumWidthInGob(size.Width, sizeHint.Width, formatInfo.BytesPerPixel, false),
|
||||||
size.Height,
|
size.Height,
|
||||||
size.Depth,
|
size.Depth,
|
||||||
1,
|
1,
|
||||||
@@ -409,13 +409,41 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
target,
|
target,
|
||||||
formatInfo);
|
formatInfo);
|
||||||
|
|
||||||
Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, dsState.LayerSize * 4, sizeHint);
|
Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, dsState.LayerSize * 4);
|
||||||
|
|
||||||
texture?.SynchronizeMemory();
|
texture?.SynchronizeMemory();
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For block linear textures, gets the minimum width of the texture
|
||||||
|
/// that would still have the same number of GOBs per row as the original width.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="width">The possibly aligned texture width</param>
|
||||||
|
/// <param name="minimumWidth">The minimum width that the texture may have without losing data</param>
|
||||||
|
/// <param name="bytesPerPixel">Bytes per pixel of the texture format</param>
|
||||||
|
/// <param name="isLinear">True if the texture is linear, false for block linear</param>
|
||||||
|
/// <returns>The minimum width of the texture with the same amount of GOBs per row</returns>
|
||||||
|
private static int GetMinimumWidthInGob(int width, int minimumWidth, int bytesPerPixel, bool isLinear)
|
||||||
|
{
|
||||||
|
if (isLinear || (uint)minimumWidth >= (uint)width)
|
||||||
|
{
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the minimum possible that would not cause data loss
|
||||||
|
// and would be still within the same GOB (aligned size would be the same).
|
||||||
|
// This is useful for render and copy operations, where we don't know the
|
||||||
|
// exact width of the texture, but it doesn't matter, as long the texture is
|
||||||
|
// at least as large as the region being rendered or copied.
|
||||||
|
|
||||||
|
int alignment = 64 / bytesPerPixel;
|
||||||
|
int widthAligned = BitUtils.AlignUp(width, alignment);
|
||||||
|
|
||||||
|
return Math.Clamp(widthAligned - alignment + 1, minimumWidth, widthAligned);
|
||||||
|
}
|
||||||
|
|
||||||
/// <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>
|
||||||
@@ -423,7 +451,6 @@ 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(
|
||||||
@@ -431,7 +458,6 @@ 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;
|
||||||
@@ -512,8 +538,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
if (texture != null)
|
if (texture != null)
|
||||||
{
|
{
|
||||||
ChangeSizeIfNeeded(info, texture, isSamplerTexture, sizeHint);
|
|
||||||
|
|
||||||
texture.SynchronizeMemory();
|
texture.SynchronizeMemory();
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
@@ -568,6 +592,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
TextureViewCompatibility overlapCompatibility = overlap.IsViewCompatible(
|
TextureViewCompatibility overlapCompatibility = overlap.IsViewCompatible(
|
||||||
info,
|
info,
|
||||||
range.Value,
|
range.Value,
|
||||||
|
isSamplerTexture,
|
||||||
sizeInfo.LayerSize,
|
sizeInfo.LayerSize,
|
||||||
_context.Capabilities,
|
_context.Capabilities,
|
||||||
out int firstLayer,
|
out int firstLayer,
|
||||||
@@ -598,17 +623,15 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
if (oInfo.Compatibility == TextureViewCompatibility.Full)
|
if (oInfo.Compatibility == TextureViewCompatibility.Full)
|
||||||
{
|
{
|
||||||
TextureInfo adjInfo = AdjustSizes(overlap, info, oInfo.FirstLevel);
|
|
||||||
|
|
||||||
if (!isSamplerTexture)
|
if (!isSamplerTexture)
|
||||||
{
|
{
|
||||||
info = adjInfo;
|
// If this is not a sampler texture, the size might be different from the requested size,
|
||||||
|
// so we need to make sure the texture information has the correct size for this base texture,
|
||||||
|
// before creating the view.
|
||||||
|
info = info.CreateInfoForLevelView(overlap, oInfo.FirstLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
texture = overlap.CreateView(adjInfo, sizeInfo, range.Value, oInfo.FirstLayer, oInfo.FirstLevel);
|
texture = overlap.CreateView(info, sizeInfo, range.Value, oInfo.FirstLayer, oInfo.FirstLevel);
|
||||||
|
|
||||||
ChangeSizeIfNeeded(info, texture, isSamplerTexture, sizeHint);
|
|
||||||
|
|
||||||
texture.SynchronizeMemory();
|
texture.SynchronizeMemory();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -682,6 +705,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
TextureViewCompatibility compatibility = texture.IsViewCompatible(
|
TextureViewCompatibility compatibility = texture.IsViewCompatible(
|
||||||
overlap.Info,
|
overlap.Info,
|
||||||
overlap.Range,
|
overlap.Range,
|
||||||
|
exactSize: true,
|
||||||
overlap.LayerSize,
|
overlap.LayerSize,
|
||||||
_context.Capabilities,
|
_context.Capabilities,
|
||||||
out int firstLayer,
|
out int firstLayer,
|
||||||
@@ -792,7 +816,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureInfo overlapInfo = AdjustSizes(texture, overlap.Info, oInfo.FirstLevel);
|
// Note: If we allow different sizes for those overlaps,
|
||||||
|
// we need to make sure that the "info" has the correct size for the parent texture here.
|
||||||
|
// Since this is not allowed right now, we don't need to do it.
|
||||||
|
|
||||||
|
TextureInfo overlapInfo = overlap.Info;
|
||||||
|
|
||||||
if (texture.ScaleFactor != overlap.ScaleFactor)
|
if (texture.ScaleFactor != overlap.ScaleFactor)
|
||||||
{
|
{
|
||||||
@@ -856,44 +884,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Changes a texture's size to match the desired size for samplers,
|
|
||||||
/// or increases a texture's size to fit the region indicated by a size hint.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="info">The desired texture info</param>
|
|
||||||
/// <param name="texture">The texture to resize</param>
|
|
||||||
/// <param name="isSamplerTexture">True if the texture will be used for a sampler, false otherwise</param>
|
|
||||||
/// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
|
|
||||||
private void ChangeSizeIfNeeded(TextureInfo info, Texture texture, bool isSamplerTexture, Size? sizeHint)
|
|
||||||
{
|
|
||||||
if (isSamplerTexture)
|
|
||||||
{
|
|
||||||
// If this is used for sampling, the size must match,
|
|
||||||
// otherwise the shader would sample garbage data.
|
|
||||||
// To fix that, we create a new texture with the correct
|
|
||||||
// size, and copy the data from the old one to the new one.
|
|
||||||
|
|
||||||
if (!TextureCompatibility.SizeMatches(texture.Info, info))
|
|
||||||
{
|
|
||||||
texture.ChangeSize(info.Width, info.Height, info.DepthOrLayers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (sizeHint != null)
|
|
||||||
{
|
|
||||||
// A size hint indicates that data will be used within that range, at least.
|
|
||||||
// If the texture is smaller than the size hint, it must be enlarged to meet it.
|
|
||||||
// The maximum size is provided by the requested info, which generally has an aligned size.
|
|
||||||
|
|
||||||
int width = Math.Max(texture.Info.Width, Math.Min(sizeHint.Value.Width, info.Width));
|
|
||||||
int height = Math.Max(texture.Info.Height, Math.Min(sizeHint.Value.Height, info.Height));
|
|
||||||
|
|
||||||
if (texture.Info.Width != width || texture.Info.Height != height)
|
|
||||||
{
|
|
||||||
texture.ChangeSize(width, height, info.DepthOrLayers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempt to find a texture on the short duration cache.
|
/// Attempt to find a texture on the short duration cache.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1000,92 +990,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adjusts the size of the texture information for a given mipmap level,
|
|
||||||
/// based on the size of a parent texture.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="parent">The parent texture</param>
|
|
||||||
/// <param name="info">The texture information to be adjusted</param>
|
|
||||||
/// <param name="firstLevel">The first level of the texture view</param>
|
|
||||||
/// <returns>The adjusted texture information with the new size</returns>
|
|
||||||
private static TextureInfo AdjustSizes(Texture parent, TextureInfo info, int firstLevel)
|
|
||||||
{
|
|
||||||
// When the texture is used as view of another texture, we must
|
|
||||||
// ensure that the sizes are valid, otherwise data uploads would fail
|
|
||||||
// (and the size wouldn't match the real size used on the host API).
|
|
||||||
// Given a parent texture from where the view is created, we have the
|
|
||||||
// following rules:
|
|
||||||
// - The view size must be equal to the parent size, divided by (2 ^ l),
|
|
||||||
// where l is the first mipmap level of the view. The division result must
|
|
||||||
// be rounded down, and the result must be clamped to 1.
|
|
||||||
// - If the parent format is compressed, and the view format isn't, the
|
|
||||||
// view size is calculated as above, but the width and height of the
|
|
||||||
// view must be also divided by the compressed format block width and height.
|
|
||||||
// - If the parent format is not compressed, and the view is, the view
|
|
||||||
// size is calculated as described on the first point, but the width and height
|
|
||||||
// of the view must be also multiplied by the block width and height.
|
|
||||||
int width = Math.Max(1, parent.Info.Width >> firstLevel);
|
|
||||||
int height = Math.Max(1, parent.Info.Height >> firstLevel);
|
|
||||||
|
|
||||||
if (parent.Info.FormatInfo.IsCompressed && !info.FormatInfo.IsCompressed)
|
|
||||||
{
|
|
||||||
width = BitUtils.DivRoundUp(width, parent.Info.FormatInfo.BlockWidth);
|
|
||||||
height = BitUtils.DivRoundUp(height, parent.Info.FormatInfo.BlockHeight);
|
|
||||||
}
|
|
||||||
else if (!parent.Info.FormatInfo.IsCompressed && info.FormatInfo.IsCompressed)
|
|
||||||
{
|
|
||||||
width *= info.FormatInfo.BlockWidth;
|
|
||||||
height *= info.FormatInfo.BlockHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
int depthOrLayers;
|
|
||||||
|
|
||||||
if (info.Target == Target.Texture3D)
|
|
||||||
{
|
|
||||||
depthOrLayers = Math.Max(1, parent.Info.DepthOrLayers >> firstLevel);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
depthOrLayers = info.DepthOrLayers;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2D and 2D multisample textures are not considered compatible.
|
|
||||||
// This specific case is required for copies, where the source texture might be multisample.
|
|
||||||
// In this case, we inherit the parent texture multisample state.
|
|
||||||
Target target = info.Target;
|
|
||||||
int samplesInX = info.SamplesInX;
|
|
||||||
int samplesInY = info.SamplesInY;
|
|
||||||
|
|
||||||
if (target == Target.Texture2D && parent.Target == Target.Texture2DMultisample)
|
|
||||||
{
|
|
||||||
target = Target.Texture2DMultisample;
|
|
||||||
samplesInX = parent.Info.SamplesInX;
|
|
||||||
samplesInY = parent.Info.SamplesInY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TextureInfo(
|
|
||||||
info.GpuAddress,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
depthOrLayers,
|
|
||||||
info.Levels,
|
|
||||||
samplesInX,
|
|
||||||
samplesInY,
|
|
||||||
info.Stride,
|
|
||||||
info.IsLinear,
|
|
||||||
info.GobBlocksInY,
|
|
||||||
info.GobBlocksInZ,
|
|
||||||
info.GobBlocksInTileX,
|
|
||||||
target,
|
|
||||||
info.FormatInfo,
|
|
||||||
info.DepthStencilMode,
|
|
||||||
info.SwizzleR,
|
|
||||||
info.SwizzleG,
|
|
||||||
info.SwizzleB,
|
|
||||||
info.SwizzleA);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a texture creation information from texture information.
|
/// Gets a texture creation information from texture information.
|
||||||
/// This can be used to create new host textures.
|
/// This can be used to create new host textures.
|
||||||
@@ -1175,19 +1079,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Queues the removal of a texture from the auto delete cache.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This function is thread safe and can be called from any thread.
|
|
||||||
/// The texture will be deleted on the next time the cache is used.
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="texture">The texture to be removed</param>
|
|
||||||
public void QueueAutoDeleteCacheRemoval(Texture texture)
|
|
||||||
{
|
|
||||||
_cache.RemoveDeferred(texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a texture to the short duration cache. This typically keeps it alive for two ticks.
|
/// Adds a texture to the short duration cache. This typically keeps it alive for two ticks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -380,42 +380,37 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lhs">Texture information of the texture view</param>
|
/// <param name="lhs">Texture information of the texture view</param>
|
||||||
/// <param name="rhs">Texture information of the texture view to match against</param>
|
/// <param name="rhs">Texture information of the texture view to match against</param>
|
||||||
|
/// <param name="exact">Indicates if the sizes must be exactly equal</param>
|
||||||
/// <param name="level">Mipmap level of the texture view in relation to this texture</param>
|
/// <param name="level">Mipmap level of the texture view in relation to this texture</param>
|
||||||
/// <returns>The view compatibility level of the view sizes</returns>
|
/// <returns>The view compatibility level of the view sizes</returns>
|
||||||
public static TextureViewCompatibility ViewSizeMatches(TextureInfo lhs, TextureInfo rhs, int level)
|
public static TextureViewCompatibility ViewSizeMatches(TextureInfo lhs, TextureInfo rhs, bool exact, int level)
|
||||||
{
|
{
|
||||||
Size size = GetAlignedSize(lhs, level);
|
Size lhsAlignedSize = GetAlignedSize(lhs, level);
|
||||||
|
Size rhsAlignedSize = GetAlignedSize(rhs);
|
||||||
|
|
||||||
Size otherSize = GetAlignedSize(rhs);
|
Size lhsSize = GetSizeInBlocks(lhs, level);
|
||||||
|
Size rhsSize = GetSizeInBlocks(rhs);
|
||||||
|
|
||||||
TextureViewCompatibility result = TextureViewCompatibility.Full;
|
TextureViewCompatibility result = TextureViewCompatibility.Full;
|
||||||
|
|
||||||
// For copies, we can copy a subset of the 3D texture slices,
|
// For copies, we can copy a subset of the 3D texture slices,
|
||||||
// so the depth may be different in this case.
|
// so the depth may be different in this case.
|
||||||
if (rhs.Target == Target.Texture3D && size.Depth != otherSize.Depth)
|
if (rhs.Target == Target.Texture3D && lhsSize.Depth != rhsSize.Depth)
|
||||||
{
|
{
|
||||||
result = TextureViewCompatibility.CopyOnly;
|
result = TextureViewCompatibility.CopyOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size.Width == otherSize.Width && size.Height == otherSize.Height)
|
// Some APIs align the width for copy and render target textures,
|
||||||
|
// so the width may not match in this case for different uses of the same texture.
|
||||||
|
// To account for this, we compare the aligned width here.
|
||||||
|
// We expect height to always match exactly, if the texture is the same.
|
||||||
|
if (lhsAlignedSize.Width == rhsAlignedSize.Width && lhsSize.Height == rhsSize.Height)
|
||||||
{
|
{
|
||||||
if (level > 0 && result == TextureViewCompatibility.Full)
|
return (exact && lhsSize.Width != rhsSize.Width) || lhsSize.Width < rhsSize.Width
|
||||||
{
|
? TextureViewCompatibility.CopyOnly
|
||||||
// A resize should not change the aligned size of the largest mip.
|
: result;
|
||||||
// If it would, then create a copy dependency rather than a full view.
|
|
||||||
|
|
||||||
Size mip0SizeLhs = GetAlignedSize(lhs);
|
|
||||||
Size mip0SizeRhs = GetLargestAlignedSize(rhs, level);
|
|
||||||
|
|
||||||
if (mip0SizeLhs.Width != mip0SizeRhs.Width || mip0SizeLhs.Height != mip0SizeRhs.Height)
|
|
||||||
{
|
|
||||||
result = TextureViewCompatibility.CopyOnly;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
else if (lhs.IsLinear && rhs.IsLinear)
|
else if (lhs.IsLinear && rhs.IsLinear && lhsSize.Height == rhsSize.Height)
|
||||||
{
|
{
|
||||||
// Copy between linear textures with matching stride.
|
// Copy between linear textures with matching stride.
|
||||||
int stride = BitUtils.AlignUp(Math.Max(1, lhs.Stride >> level), Constants.StrideAlignment);
|
int stride = BitUtils.AlignUp(Math.Max(1, lhs.Stride >> level), Constants.StrideAlignment);
|
||||||
@@ -454,57 +449,33 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lhs">Texture information to compare</param>
|
/// <param name="lhs">Texture information to compare</param>
|
||||||
/// <param name="rhs">Texture information to compare with</param>
|
/// <param name="rhs">Texture information to compare with</param>
|
||||||
/// <returns>True if the size matches, false otherwise</returns>
|
/// <param name="exact">Indicates if the size must be exactly equal between the textures, or if <paramref name="rhs"/> is allowed to be larger</param>
|
||||||
public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs)
|
|
||||||
{
|
|
||||||
return SizeMatches(lhs, rhs, alignSizes: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if the texture sizes of the supplied texture informations match the given level
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="lhs">Texture information to compare</param>
|
|
||||||
/// <param name="rhs">Texture information to compare with</param>
|
|
||||||
/// <param name="level">Mipmap level of this texture to compare with</param>
|
|
||||||
/// <returns>True if the size matches with the level, false otherwise</returns>
|
|
||||||
public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs, int level)
|
|
||||||
{
|
|
||||||
return Math.Max(1, lhs.Width >> level) == rhs.Width &&
|
|
||||||
Math.Max(1, lhs.Height >> level) == rhs.Height &&
|
|
||||||
Math.Max(1, lhs.GetDepth() >> level) == rhs.GetDepth();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if the texture sizes of the supplied texture informations match.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="lhs">Texture information to compare</param>
|
|
||||||
/// <param name="rhs">Texture information to compare with</param>
|
|
||||||
/// <param name="alignSizes">True to align the sizes according to the texture layout for comparison</param>
|
|
||||||
/// <param name="lhsLevel">Mip level of the lhs texture. Aligned sizes are compared for the largest mip</param>
|
|
||||||
/// <returns>True if the sizes matches, false otherwise</returns>
|
/// <returns>True if the sizes matches, false otherwise</returns>
|
||||||
public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs, bool alignSizes, int lhsLevel = 0)
|
public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs, bool exact)
|
||||||
{
|
{
|
||||||
if (lhs.GetLayers() != rhs.GetLayers())
|
if (lhs.GetLayers() != rhs.GetLayers())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isTextureBuffer = lhs.Target == Target.TextureBuffer || rhs.Target == Target.TextureBuffer;
|
Size lhsSize = GetSizeInBlocks(lhs);
|
||||||
|
Size rhsSize = GetSizeInBlocks(rhs);
|
||||||
|
|
||||||
if (alignSizes && !isTextureBuffer)
|
if (exact || lhs.IsLinear || rhs.IsLinear)
|
||||||
{
|
{
|
||||||
Size size0 = GetLargestAlignedSize(lhs, lhsLevel);
|
return lhsSize.Width == rhsSize.Width &&
|
||||||
Size size1 = GetLargestAlignedSize(rhs, lhsLevel);
|
lhsSize.Height == rhsSize.Height &&
|
||||||
|
lhsSize.Depth == rhsSize.Depth;
|
||||||
return size0.Width == size1.Width &&
|
|
||||||
size0.Height == size1.Height &&
|
|
||||||
size0.Depth == size1.Depth;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return lhs.Width == rhs.Width &&
|
Size lhsAlignedSize = GetAlignedSize(lhs);
|
||||||
lhs.Height == rhs.Height &&
|
Size rhsAlignedSize = GetAlignedSize(rhs);
|
||||||
lhs.GetDepth() == rhs.GetDepth();
|
|
||||||
|
return lhsAlignedSize.Width == rhsAlignedSize.Width &&
|
||||||
|
lhsSize.Width >= rhsSize.Width &&
|
||||||
|
lhsSize.Height == rhsSize.Height &&
|
||||||
|
lhsSize.Depth == rhsSize.Depth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,22 +514,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the aligned sizes of the specified texture information, shifted to the largest mip from a given level.
|
|
||||||
/// The alignment depends on the texture layout and format bytes per pixel.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="info">Texture information to calculate the aligned size from</param>
|
|
||||||
/// <param name="level">Mipmap level for texture views. Shifts the aligned size to represent the largest mip level</param>
|
|
||||||
/// <returns>The aligned texture size of the largest mip level</returns>
|
|
||||||
public static Size GetLargestAlignedSize(TextureInfo info, int level)
|
|
||||||
{
|
|
||||||
int width = info.Width << level;
|
|
||||||
int height = info.Height << level;
|
|
||||||
int depth = info.GetDepth() << level;
|
|
||||||
|
|
||||||
return GetAlignedSize(info, width, height, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the aligned sizes of the specified texture information.
|
/// Gets the aligned sizes of the specified texture information.
|
||||||
/// The alignment depends on the texture layout and format bytes per pixel.
|
/// The alignment depends on the texture layout and format bytes per pixel.
|
||||||
@@ -575,6 +530,25 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
return GetAlignedSize(info, width, height, depth);
|
return GetAlignedSize(info, width, height, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the size in blocks for the given texture information.
|
||||||
|
/// For non-compressed formats, that's the same as the regular size.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">Texture information to calculate the aligned size from</param>
|
||||||
|
/// <param name="level">Mipmap level for texture views</param>
|
||||||
|
/// <returns>The texture size in blocks</returns>
|
||||||
|
public static Size GetSizeInBlocks(TextureInfo info, int level = 0)
|
||||||
|
{
|
||||||
|
int width = Math.Max(1, info.Width >> level);
|
||||||
|
int height = Math.Max(1, info.Height >> level);
|
||||||
|
int depth = Math.Max(1, info.GetDepth() >> level);
|
||||||
|
|
||||||
|
return new Size(
|
||||||
|
BitUtils.DivRoundUp(width, info.FormatInfo.BlockWidth),
|
||||||
|
BitUtils.DivRoundUp(height, info.FormatInfo.BlockHeight),
|
||||||
|
depth);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if it's possible to create a view with the layout of the second texture information from the first.
|
/// Check if it's possible to create a view with the layout of the second texture information from the first.
|
||||||
/// The layout information is composed of the Stride for linear textures, or GOB block size
|
/// The layout information is composed of the Stride for linear textures, or GOB block size
|
||||||
|
@@ -434,32 +434,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if a texture was modified by the GPU.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="texture">The texture to be checked</param>
|
|
||||||
/// <returns>True if any region of the texture was modified by the GPU, false otherwise</returns>
|
|
||||||
public bool AnyModified(Texture texture)
|
|
||||||
{
|
|
||||||
bool anyModified = false;
|
|
||||||
|
|
||||||
EvaluateRelevantHandles(texture, (baseHandle, regionCount, split) =>
|
|
||||||
{
|
|
||||||
for (int i = 0; i < regionCount; i++)
|
|
||||||
{
|
|
||||||
TextureGroupHandle group = _handles[baseHandle + i];
|
|
||||||
|
|
||||||
if (group.Modified)
|
|
||||||
{
|
|
||||||
anyModified = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return anyModified;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flush modified ranges for a given texture.
|
/// Flush modified ranges for a given texture.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Texture;
|
using Ryujinx.Graphics.Texture;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Image
|
namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
@@ -292,5 +294,88 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
layerSize);
|
layerSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates texture information for a given mipmap level of the specified parent texture and this information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parent">The parent texture</param>
|
||||||
|
/// <param name="firstLevel">The first level of the texture view</param>
|
||||||
|
/// <returns>The adjusted texture information with the new size</returns>
|
||||||
|
public TextureInfo CreateInfoForLevelView(Texture parent, int firstLevel)
|
||||||
|
{
|
||||||
|
// When the texture is used as view of another texture, we must
|
||||||
|
// ensure that the sizes are valid, otherwise data uploads would fail
|
||||||
|
// (and the size wouldn't match the real size used on the host API).
|
||||||
|
// Given a parent texture from where the view is created, we have the
|
||||||
|
// following rules:
|
||||||
|
// - The view size must be equal to the parent size, divided by (2 ^ l),
|
||||||
|
// where l is the first mipmap level of the view. The division result must
|
||||||
|
// be rounded down, and the result must be clamped to 1.
|
||||||
|
// - If the parent format is compressed, and the view format isn't, the
|
||||||
|
// view size is calculated as above, but the width and height of the
|
||||||
|
// view must be also divided by the compressed format block width and height.
|
||||||
|
// - If the parent format is not compressed, and the view is, the view
|
||||||
|
// size is calculated as described on the first point, but the width and height
|
||||||
|
// of the view must be also multiplied by the block width and height.
|
||||||
|
int width = Math.Max(1, parent.Info.Width >> firstLevel);
|
||||||
|
int height = Math.Max(1, parent.Info.Height >> firstLevel);
|
||||||
|
|
||||||
|
if (parent.Info.FormatInfo.IsCompressed && !FormatInfo.IsCompressed)
|
||||||
|
{
|
||||||
|
width = BitUtils.DivRoundUp(width, parent.Info.FormatInfo.BlockWidth);
|
||||||
|
height = BitUtils.DivRoundUp(height, parent.Info.FormatInfo.BlockHeight);
|
||||||
|
}
|
||||||
|
else if (!parent.Info.FormatInfo.IsCompressed && FormatInfo.IsCompressed)
|
||||||
|
{
|
||||||
|
width *= FormatInfo.BlockWidth;
|
||||||
|
height *= FormatInfo.BlockHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
int depthOrLayers;
|
||||||
|
|
||||||
|
if (Target == Target.Texture3D)
|
||||||
|
{
|
||||||
|
depthOrLayers = Math.Max(1, parent.Info.DepthOrLayers >> firstLevel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
depthOrLayers = DepthOrLayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2D and 2D multisample textures are not considered compatible.
|
||||||
|
// This specific case is required for copies, where the source texture might be multisample.
|
||||||
|
// In this case, we inherit the parent texture multisample state.
|
||||||
|
Target target = Target;
|
||||||
|
int samplesInX = SamplesInX;
|
||||||
|
int samplesInY = SamplesInY;
|
||||||
|
|
||||||
|
if (target == Target.Texture2D && parent.Target == Target.Texture2DMultisample)
|
||||||
|
{
|
||||||
|
target = Target.Texture2DMultisample;
|
||||||
|
samplesInX = parent.Info.SamplesInX;
|
||||||
|
samplesInY = parent.Info.SamplesInY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TextureInfo(
|
||||||
|
GpuAddress,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
depthOrLayers,
|
||||||
|
Levels,
|
||||||
|
samplesInX,
|
||||||
|
samplesInY,
|
||||||
|
Stride,
|
||||||
|
IsLinear,
|
||||||
|
GobBlocksInY,
|
||||||
|
GobBlocksInZ,
|
||||||
|
GobBlocksInTileX,
|
||||||
|
target,
|
||||||
|
FormatInfo,
|
||||||
|
DepthStencilMode,
|
||||||
|
SwizzleR,
|
||||||
|
SwizzleG,
|
||||||
|
SwizzleB,
|
||||||
|
SwizzleA);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -437,22 +437,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Update host framebuffer attachments based on currently bound render target buffers.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// All attachments other than <paramref name="index"/> will be unbound.
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="index">Index of the render target color to be updated</param>
|
|
||||||
public void UpdateRenderTarget(int index)
|
|
||||||
{
|
|
||||||
new Span<ITexture>(_rtHostColors).Fill(null);
|
|
||||||
_rtHostColors[index] = _rtColors[index]?.HostTexture;
|
|
||||||
_rtHostDs = null;
|
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetRenderTargets(_rtHostColors, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update host framebuffer attachments based on currently bound render target buffers.
|
/// Update host framebuffer attachments based on currently bound render target buffers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -77,22 +77,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (texture.ChangedSize)
|
// On the path above (texture not yet in the pool), memory is automatically synchronized on texture creation.
|
||||||
{
|
|
||||||
// Texture changed size at one point - it may be a different size than the sampler expects.
|
|
||||||
// This can be triggered when the size is changed by a size hint on copy or draw, but the texture has been sampled before.
|
|
||||||
|
|
||||||
int baseLevel = descriptor.UnpackBaseLevel();
|
|
||||||
int width = Math.Max(1, descriptor.UnpackWidth() >> baseLevel);
|
|
||||||
int height = Math.Max(1, descriptor.UnpackHeight() >> baseLevel);
|
|
||||||
|
|
||||||
if (texture.Info.Width != width || texture.Info.Height != height)
|
|
||||||
{
|
|
||||||
texture.ChangeSize(width, height, texture.Info.DepthOrLayers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory is automatically synchronized on texture creation.
|
|
||||||
texture.SynchronizeMemory();
|
texture.SynchronizeMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,7 +9,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
enum TextureSearchFlags
|
enum TextureSearchFlags
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
Strict = 1 << 0,
|
|
||||||
ForSampler = 1 << 1,
|
ForSampler = 1 << 1,
|
||||||
ForCopy = 1 << 2,
|
ForCopy = 1 << 2,
|
||||||
WithUpscale = 1 << 3,
|
WithUpscale = 1 << 3,
|
||||||
|
@@ -202,7 +202,7 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
{
|
{
|
||||||
pt.AcquireCallback(_context, pt.UserObj);
|
pt.AcquireCallback(_context, pt.UserObj);
|
||||||
|
|
||||||
Texture texture = pt.Cache.FindOrCreateTexture(null, TextureSearchFlags.WithUpscale, pt.Info, 0, null, pt.Range);
|
Texture texture = pt.Cache.FindOrCreateTexture(null, TextureSearchFlags.WithUpscale, pt.Info, 0, pt.Range);
|
||||||
|
|
||||||
pt.Cache.Tick();
|
pt.Cache.Tick();
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.Intrinsics;
|
using System.Runtime.Intrinsics;
|
||||||
|
using System.Runtime.Intrinsics.Arm;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vic
|
namespace Ryujinx.Graphics.Vic
|
||||||
@@ -17,10 +18,18 @@ namespace Ryujinx.Graphics.Vic
|
|||||||
int x2 = Math.Min(src.Width, x1 + targetRect.Width);
|
int x2 = Math.Min(src.Width, x1 + targetRect.Width);
|
||||||
int y2 = Math.Min(src.Height, y1 + targetRect.Height);
|
int y2 = Math.Min(src.Height, y1 + targetRect.Height);
|
||||||
|
|
||||||
if (Sse41.IsSupported && ((x1 | x2) & 3) == 0)
|
if (((x1 | x2) & 3) == 0)
|
||||||
{
|
{
|
||||||
BlendOneSse41(dst, src, ref slot, x1, y1, x2, y2);
|
if (Sse41.IsSupported)
|
||||||
return;
|
{
|
||||||
|
BlendOneSse41(dst, src, ref slot, x1, y1, x2, y2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (AdvSimd.IsSupported)
|
||||||
|
{
|
||||||
|
BlendOneAdvSimd(dst, src, ref slot, x1, y1, x2, y2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int y = y1; y < y2; y++)
|
for (int y = y1; y < y2; y++)
|
||||||
@@ -105,6 +114,84 @@ namespace Ryujinx.Graphics.Vic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unsafe static void BlendOneAdvSimd(Surface dst, Surface src, ref SlotStruct slot, int x1, int y1, int x2, int y2)
|
||||||
|
{
|
||||||
|
Debug.Assert(((x1 | x2) & 3) == 0);
|
||||||
|
|
||||||
|
ref MatrixStruct mtx = ref slot.ColorMatrixStruct;
|
||||||
|
|
||||||
|
Vector128<int> col1 = Vector128.Create(mtx.MatrixCoeff00, mtx.MatrixCoeff10, mtx.MatrixCoeff20, 0);
|
||||||
|
Vector128<int> col2 = Vector128.Create(mtx.MatrixCoeff01, mtx.MatrixCoeff11, mtx.MatrixCoeff21, 0);
|
||||||
|
Vector128<int> col3 = Vector128.Create(mtx.MatrixCoeff02, mtx.MatrixCoeff12, mtx.MatrixCoeff22, 0);
|
||||||
|
Vector128<int> col4 = Vector128.Create(mtx.MatrixCoeff03, mtx.MatrixCoeff13, mtx.MatrixCoeff23, 0);
|
||||||
|
|
||||||
|
Vector128<int> rShift = Vector128.Create(-mtx.MatrixRShift);
|
||||||
|
Vector128<int> selMask = Vector128.Create(0, 0, 0, -1);
|
||||||
|
Vector128<ushort> clMin = Vector128.Create((ushort)slot.SlotConfig.SoftClampLow);
|
||||||
|
Vector128<ushort> clMax = Vector128.Create((ushort)slot.SlotConfig.SoftClampHigh);
|
||||||
|
|
||||||
|
fixed (Pixel* srcPtr = src.Data, dstPtr = dst.Data)
|
||||||
|
{
|
||||||
|
Pixel* ip = srcPtr;
|
||||||
|
Pixel* op = dstPtr;
|
||||||
|
|
||||||
|
if (mtx.MatrixEnable)
|
||||||
|
{
|
||||||
|
for (int y = y1; y < y2; y++, ip += src.Width, op += dst.Width)
|
||||||
|
{
|
||||||
|
for (int x = x1; x < x2; x += 4)
|
||||||
|
{
|
||||||
|
Vector128<ushort> pixel12 = AdvSimd.LoadVector128((ushort*)(ip + (uint)x));
|
||||||
|
Vector128<ushort> pixel34 = AdvSimd.LoadVector128((ushort*)(ip + (uint)x + 2));
|
||||||
|
|
||||||
|
Vector128<uint> pixel1 = AdvSimd.ZeroExtendWideningLower(pixel12.GetLower());
|
||||||
|
Vector128<uint> pixel2 = AdvSimd.ZeroExtendWideningUpper(pixel12);
|
||||||
|
Vector128<uint> pixel3 = AdvSimd.ZeroExtendWideningLower(pixel34.GetLower());
|
||||||
|
Vector128<uint> pixel4 = AdvSimd.ZeroExtendWideningUpper(pixel34);
|
||||||
|
|
||||||
|
Vector128<int> t1 = MatrixMultiplyAdvSimd(pixel1.AsInt32(), col1, col2, col3, col4, rShift, selMask);
|
||||||
|
Vector128<int> t2 = MatrixMultiplyAdvSimd(pixel2.AsInt32(), col1, col2, col3, col4, rShift, selMask);
|
||||||
|
Vector128<int> t3 = MatrixMultiplyAdvSimd(pixel3.AsInt32(), col1, col2, col3, col4, rShift, selMask);
|
||||||
|
Vector128<int> t4 = MatrixMultiplyAdvSimd(pixel4.AsInt32(), col1, col2, col3, col4, rShift, selMask);
|
||||||
|
|
||||||
|
Vector64<ushort> lower1 = AdvSimd.ExtractNarrowingSaturateUnsignedLower(t1);
|
||||||
|
Vector64<ushort> lower3 = AdvSimd.ExtractNarrowingSaturateUnsignedLower(t3);
|
||||||
|
|
||||||
|
pixel12 = AdvSimd.ExtractNarrowingSaturateUnsignedUpper(lower1, t2);
|
||||||
|
pixel34 = AdvSimd.ExtractNarrowingSaturateUnsignedUpper(lower3, t4);
|
||||||
|
|
||||||
|
pixel12 = AdvSimd.Min(pixel12, clMax);
|
||||||
|
pixel34 = AdvSimd.Min(pixel34, clMax);
|
||||||
|
pixel12 = AdvSimd.Max(pixel12, clMin);
|
||||||
|
pixel34 = AdvSimd.Max(pixel34, clMin);
|
||||||
|
|
||||||
|
AdvSimd.Store((ushort*)(op + (uint)x + 0), pixel12);
|
||||||
|
AdvSimd.Store((ushort*)(op + (uint)x + 2), pixel34);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int y = y1; y < y2; y++, ip += src.Width, op += dst.Width)
|
||||||
|
{
|
||||||
|
for (int x = x1; x < x2; x += 4)
|
||||||
|
{
|
||||||
|
Vector128<ushort> pixel12 = AdvSimd.LoadVector128((ushort*)(ip + (uint)x));
|
||||||
|
Vector128<ushort> pixel34 = AdvSimd.LoadVector128((ushort*)(ip + (uint)x + 2));
|
||||||
|
|
||||||
|
pixel12 = AdvSimd.Min(pixel12, clMax);
|
||||||
|
pixel34 = AdvSimd.Min(pixel34, clMax);
|
||||||
|
pixel12 = AdvSimd.Max(pixel12, clMin);
|
||||||
|
pixel34 = AdvSimd.Max(pixel34, clMin);
|
||||||
|
|
||||||
|
AdvSimd.Store((ushort*)(op + (uint)x + 0), pixel12);
|
||||||
|
AdvSimd.Store((ushort*)(op + (uint)x + 2), pixel34);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static void MatrixMultiply(ref MatrixStruct mtx, int x, int y, int z, out int r, out int g, out int b)
|
private static void MatrixMultiply(ref MatrixStruct mtx, int x, int y, int z, out int r, out int g, out int b)
|
||||||
{
|
{
|
||||||
@@ -159,5 +246,33 @@ namespace Ryujinx.Graphics.Vic
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static Vector128<int> MatrixMultiplyAdvSimd(
|
||||||
|
Vector128<int> pixel,
|
||||||
|
Vector128<int> col1,
|
||||||
|
Vector128<int> col2,
|
||||||
|
Vector128<int> col3,
|
||||||
|
Vector128<int> col4,
|
||||||
|
Vector128<int> rShift,
|
||||||
|
Vector128<int> selectMask)
|
||||||
|
{
|
||||||
|
Vector128<int> x = AdvSimd.DuplicateSelectedScalarToVector128(pixel, 0);
|
||||||
|
Vector128<int> y = AdvSimd.DuplicateSelectedScalarToVector128(pixel, 1);
|
||||||
|
Vector128<int> z = AdvSimd.DuplicateSelectedScalarToVector128(pixel, 2);
|
||||||
|
|
||||||
|
col1 = AdvSimd.Multiply(col1, x);
|
||||||
|
col2 = AdvSimd.Multiply(col2, y);
|
||||||
|
col3 = AdvSimd.Multiply(col3, z);
|
||||||
|
|
||||||
|
Vector128<int> res = AdvSimd.Add(col3, AdvSimd.Add(col1, col2));
|
||||||
|
|
||||||
|
res = AdvSimd.ShiftArithmetic(res, rShift);
|
||||||
|
res = AdvSimd.Add(res, col4);
|
||||||
|
res = AdvSimd.ShiftRightArithmetic(res, 8);
|
||||||
|
res = AdvSimd.BitwiseSelect(selectMask, pixel, res);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@ using Ryujinx.Graphics.Vic.Types;
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.Intrinsics;
|
using System.Runtime.Intrinsics;
|
||||||
|
using System.Runtime.Intrinsics.Arm;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
using static Ryujinx.Graphics.Vic.Image.SurfaceCommon;
|
using static Ryujinx.Graphics.Vic.Image.SurfaceCommon;
|
||||||
|
|
||||||
@@ -54,7 +55,7 @@ namespace Ryujinx.Graphics.Vic.Image
|
|||||||
(byte)4, (byte)6, (byte)7, (byte)5,
|
(byte)4, (byte)6, (byte)7, (byte)5,
|
||||||
(byte)8, (byte)10, (byte)11, (byte)9,
|
(byte)8, (byte)10, (byte)11, (byte)9,
|
||||||
(byte)12, (byte)14, (byte)15, (byte)13);
|
(byte)12, (byte)14, (byte)15, (byte)13);
|
||||||
Vector128<short> alphaMask = Vector128.Create(0xffUL << 48).AsInt16();
|
Vector128<short> alphaMask = Vector128.Create(0xff << 24).AsInt16();
|
||||||
|
|
||||||
int yStrideGap = yStride - width;
|
int yStrideGap = yStride - width;
|
||||||
int uvStrideGap = uvStride - input.UvWidth;
|
int uvStrideGap = uvStride - input.UvWidth;
|
||||||
@@ -95,6 +96,11 @@ namespace Ryujinx.Graphics.Vic.Image
|
|||||||
rgba2 = Ssse3.Shuffle(rgba2.AsByte(), shufMask).AsInt16();
|
rgba2 = Ssse3.Shuffle(rgba2.AsByte(), shufMask).AsInt16();
|
||||||
rgba3 = Ssse3.Shuffle(rgba3.AsByte(), shufMask).AsInt16();
|
rgba3 = Ssse3.Shuffle(rgba3.AsByte(), shufMask).AsInt16();
|
||||||
|
|
||||||
|
rgba0 = Sse2.Or(rgba0, alphaMask);
|
||||||
|
rgba1 = Sse2.Or(rgba1, alphaMask);
|
||||||
|
rgba2 = Sse2.Or(rgba2, alphaMask);
|
||||||
|
rgba3 = Sse2.Or(rgba3, alphaMask);
|
||||||
|
|
||||||
Vector128<short> rgba16_0 = Sse41.ConvertToVector128Int16(rgba0.AsByte());
|
Vector128<short> rgba16_0 = Sse41.ConvertToVector128Int16(rgba0.AsByte());
|
||||||
Vector128<short> rgba16_1 = Sse41.ConvertToVector128Int16(HighToLow(rgba0.AsByte()));
|
Vector128<short> rgba16_1 = Sse41.ConvertToVector128Int16(HighToLow(rgba0.AsByte()));
|
||||||
Vector128<short> rgba16_2 = Sse41.ConvertToVector128Int16(rgba1.AsByte());
|
Vector128<short> rgba16_2 = Sse41.ConvertToVector128Int16(rgba1.AsByte());
|
||||||
@@ -104,15 +110,6 @@ namespace Ryujinx.Graphics.Vic.Image
|
|||||||
Vector128<short> rgba16_6 = Sse41.ConvertToVector128Int16(rgba3.AsByte());
|
Vector128<short> rgba16_6 = Sse41.ConvertToVector128Int16(rgba3.AsByte());
|
||||||
Vector128<short> rgba16_7 = Sse41.ConvertToVector128Int16(HighToLow(rgba3.AsByte()));
|
Vector128<short> rgba16_7 = Sse41.ConvertToVector128Int16(HighToLow(rgba3.AsByte()));
|
||||||
|
|
||||||
rgba16_0 = Sse2.Or(rgba16_0, alphaMask);
|
|
||||||
rgba16_1 = Sse2.Or(rgba16_1, alphaMask);
|
|
||||||
rgba16_2 = Sse2.Or(rgba16_2, alphaMask);
|
|
||||||
rgba16_3 = Sse2.Or(rgba16_3, alphaMask);
|
|
||||||
rgba16_4 = Sse2.Or(rgba16_4, alphaMask);
|
|
||||||
rgba16_5 = Sse2.Or(rgba16_5, alphaMask);
|
|
||||||
rgba16_6 = Sse2.Or(rgba16_6, alphaMask);
|
|
||||||
rgba16_7 = Sse2.Or(rgba16_7, alphaMask);
|
|
||||||
|
|
||||||
rgba16_0 = Sse2.ShiftLeftLogical(rgba16_0, 2);
|
rgba16_0 = Sse2.ShiftLeftLogical(rgba16_0, 2);
|
||||||
rgba16_1 = Sse2.ShiftLeftLogical(rgba16_1, 2);
|
rgba16_1 = Sse2.ShiftLeftLogical(rgba16_1, 2);
|
||||||
rgba16_2 = Sse2.ShiftLeftLogical(rgba16_2, 2);
|
rgba16_2 = Sse2.ShiftLeftLogical(rgba16_2, 2);
|
||||||
@@ -149,6 +146,98 @@ namespace Ryujinx.Graphics.Vic.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (AdvSimd.Arm64.IsSupported)
|
||||||
|
{
|
||||||
|
Vector128<int> alphaMask = Vector128.Create(0xffu << 24).AsInt32();
|
||||||
|
|
||||||
|
int yStrideGap = yStride - width;
|
||||||
|
int uvStrideGap = uvStride - input.UvWidth;
|
||||||
|
|
||||||
|
int widthTrunc = width & ~0xf;
|
||||||
|
|
||||||
|
fixed (Pixel* dstPtr = output.Data)
|
||||||
|
{
|
||||||
|
Pixel* op = dstPtr;
|
||||||
|
|
||||||
|
fixed (byte* src0Ptr = input.Buffer0, src1Ptr = input.Buffer1)
|
||||||
|
{
|
||||||
|
byte* i0p = src0Ptr;
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
byte* i1p = src1Ptr + (y >> 1) * uvStride;
|
||||||
|
|
||||||
|
int x = 0;
|
||||||
|
|
||||||
|
for (; x < widthTrunc; x += 16, i0p += 16, i1p += 16)
|
||||||
|
{
|
||||||
|
Vector128<byte> ya = AdvSimd.LoadVector128(i0p);
|
||||||
|
Vector128<byte> uv = AdvSimd.LoadVector128(i1p);
|
||||||
|
|
||||||
|
Vector128<short> ya0 = AdvSimd.ZeroExtendWideningLower(ya.GetLower()).AsInt16();
|
||||||
|
Vector128<short> ya1 = AdvSimd.ZeroExtendWideningUpper(ya).AsInt16();
|
||||||
|
|
||||||
|
Vector128<short> uv0 = AdvSimd.Arm64.ZipLow(uv.AsInt16(), uv.AsInt16());
|
||||||
|
Vector128<short> uv1 = AdvSimd.Arm64.ZipHigh(uv.AsInt16(), uv.AsInt16());
|
||||||
|
|
||||||
|
ya0 = AdvSimd.ShiftLeftLogical(ya0, 8);
|
||||||
|
ya1 = AdvSimd.ShiftLeftLogical(ya1, 8);
|
||||||
|
|
||||||
|
Vector128<short> rgba0 = AdvSimd.Arm64.ZipLow(ya0, uv0);
|
||||||
|
Vector128<short> rgba1 = AdvSimd.Arm64.ZipHigh(ya0, uv0);
|
||||||
|
Vector128<short> rgba2 = AdvSimd.Arm64.ZipLow(ya1, uv1);
|
||||||
|
Vector128<short> rgba3 = AdvSimd.Arm64.ZipHigh(ya1, uv1);
|
||||||
|
|
||||||
|
rgba0 = AdvSimd.ShiftRightLogicalAdd(alphaMask, rgba0.AsInt32(), 8).AsInt16();
|
||||||
|
rgba1 = AdvSimd.ShiftRightLogicalAdd(alphaMask, rgba1.AsInt32(), 8).AsInt16();
|
||||||
|
rgba2 = AdvSimd.ShiftRightLogicalAdd(alphaMask, rgba2.AsInt32(), 8).AsInt16();
|
||||||
|
rgba3 = AdvSimd.ShiftRightLogicalAdd(alphaMask, rgba3.AsInt32(), 8).AsInt16();
|
||||||
|
|
||||||
|
Vector128<short> rgba16_0 = AdvSimd.ZeroExtendWideningLower(rgba0.AsByte().GetLower()).AsInt16();
|
||||||
|
Vector128<short> rgba16_1 = AdvSimd.ZeroExtendWideningUpper(rgba0.AsByte()).AsInt16();
|
||||||
|
Vector128<short> rgba16_2 = AdvSimd.ZeroExtendWideningLower(rgba1.AsByte().GetLower()).AsInt16();
|
||||||
|
Vector128<short> rgba16_3 = AdvSimd.ZeroExtendWideningUpper(rgba1.AsByte()).AsInt16();
|
||||||
|
Vector128<short> rgba16_4 = AdvSimd.ZeroExtendWideningLower(rgba2.AsByte().GetLower()).AsInt16();
|
||||||
|
Vector128<short> rgba16_5 = AdvSimd.ZeroExtendWideningUpper(rgba2.AsByte()).AsInt16();
|
||||||
|
Vector128<short> rgba16_6 = AdvSimd.ZeroExtendWideningLower(rgba3.AsByte().GetLower()).AsInt16();
|
||||||
|
Vector128<short> rgba16_7 = AdvSimd.ZeroExtendWideningUpper(rgba3.AsByte()).AsInt16();
|
||||||
|
|
||||||
|
rgba16_0 = AdvSimd.ShiftLeftLogical(rgba16_0, 2);
|
||||||
|
rgba16_1 = AdvSimd.ShiftLeftLogical(rgba16_1, 2);
|
||||||
|
rgba16_2 = AdvSimd.ShiftLeftLogical(rgba16_2, 2);
|
||||||
|
rgba16_3 = AdvSimd.ShiftLeftLogical(rgba16_3, 2);
|
||||||
|
rgba16_4 = AdvSimd.ShiftLeftLogical(rgba16_4, 2);
|
||||||
|
rgba16_5 = AdvSimd.ShiftLeftLogical(rgba16_5, 2);
|
||||||
|
rgba16_6 = AdvSimd.ShiftLeftLogical(rgba16_6, 2);
|
||||||
|
rgba16_7 = AdvSimd.ShiftLeftLogical(rgba16_7, 2);
|
||||||
|
|
||||||
|
AdvSimd.Store((short*)(op + (uint)x + 0), rgba16_0);
|
||||||
|
AdvSimd.Store((short*)(op + (uint)x + 2), rgba16_1);
|
||||||
|
AdvSimd.Store((short*)(op + (uint)x + 4), rgba16_2);
|
||||||
|
AdvSimd.Store((short*)(op + (uint)x + 6), rgba16_3);
|
||||||
|
AdvSimd.Store((short*)(op + (uint)x + 8), rgba16_4);
|
||||||
|
AdvSimd.Store((short*)(op + (uint)x + 10), rgba16_5);
|
||||||
|
AdvSimd.Store((short*)(op + (uint)x + 12), rgba16_6);
|
||||||
|
AdvSimd.Store((short*)(op + (uint)x + 14), rgba16_7);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; x < width; x++, i1p += (x & 1) * 2)
|
||||||
|
{
|
||||||
|
Pixel* px = op + (uint)x;
|
||||||
|
|
||||||
|
px->R = Upsample(*i0p++);
|
||||||
|
px->G = Upsample(*i1p);
|
||||||
|
px->B = Upsample(*(i1p + 1));
|
||||||
|
px->A = 0x3ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
op += width;
|
||||||
|
i0p += yStrideGap;
|
||||||
|
i1p += uvStrideGap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int y = 0; y < height; y++)
|
for (int y = 0; y < height; y++)
|
||||||
|
@@ -3,6 +3,7 @@ using Ryujinx.Graphics.Texture;
|
|||||||
using Ryujinx.Graphics.Vic.Types;
|
using Ryujinx.Graphics.Vic.Types;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.Intrinsics;
|
using System.Runtime.Intrinsics;
|
||||||
|
using System.Runtime.Intrinsics.Arm;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
using static Ryujinx.Graphics.Vic.Image.SurfaceCommon;
|
using static Ryujinx.Graphics.Vic.Image.SurfaceCommon;
|
||||||
|
|
||||||
@@ -93,6 +94,64 @@ namespace Ryujinx.Graphics.Vic.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (AdvSimd.IsSupported)
|
||||||
|
{
|
||||||
|
int widthTrunc = width & ~7;
|
||||||
|
int strideGap = stride - width * 4;
|
||||||
|
|
||||||
|
fixed (Pixel* srcPtr = input.Data)
|
||||||
|
{
|
||||||
|
Pixel* ip = srcPtr;
|
||||||
|
|
||||||
|
fixed (byte* dstPtr = dst)
|
||||||
|
{
|
||||||
|
byte* op = dstPtr;
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++, ip += input.Width)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
|
||||||
|
for (; x < widthTrunc; x += 8)
|
||||||
|
{
|
||||||
|
Vector128<ushort> pixel12 = AdvSimd.LoadVector128((ushort*)(ip + (uint)x));
|
||||||
|
Vector128<ushort> pixel34 = AdvSimd.LoadVector128((ushort*)(ip + (uint)x + 2));
|
||||||
|
Vector128<ushort> pixel56 = AdvSimd.LoadVector128((ushort*)(ip + (uint)x + 4));
|
||||||
|
Vector128<ushort> pixel78 = AdvSimd.LoadVector128((ushort*)(ip + (uint)x + 6));
|
||||||
|
|
||||||
|
pixel12 = AdvSimd.ShiftRightLogical(pixel12, 2);
|
||||||
|
pixel34 = AdvSimd.ShiftRightLogical(pixel34, 2);
|
||||||
|
pixel56 = AdvSimd.ShiftRightLogical(pixel56, 2);
|
||||||
|
pixel78 = AdvSimd.ShiftRightLogical(pixel78, 2);
|
||||||
|
|
||||||
|
Vector64<byte> lower12 = AdvSimd.ExtractNarrowingLower(pixel12.AsUInt16());
|
||||||
|
Vector64<byte> lower56 = AdvSimd.ExtractNarrowingLower(pixel56.AsUInt16());
|
||||||
|
|
||||||
|
Vector128<byte> pixel1234 = AdvSimd.ExtractNarrowingUpper(lower12, pixel34.AsUInt16());
|
||||||
|
Vector128<byte> pixel5678 = AdvSimd.ExtractNarrowingUpper(lower56, pixel78.AsUInt16());
|
||||||
|
|
||||||
|
AdvSimd.Store(op + 0x00, pixel1234);
|
||||||
|
AdvSimd.Store(op + 0x10, pixel5678);
|
||||||
|
|
||||||
|
op += 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; x < width; x++)
|
||||||
|
{
|
||||||
|
Pixel* px = ip + (uint)x;
|
||||||
|
|
||||||
|
*(op + 0) = Downsample(px->R);
|
||||||
|
*(op + 1) = Downsample(px->G);
|
||||||
|
*(op + 2) = Downsample(px->B);
|
||||||
|
*(op + 3) = Downsample(px->A);
|
||||||
|
|
||||||
|
op += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
op += strideGap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int y = 0; y < height; y++)
|
for (int y = 0; y < height; y++)
|
||||||
@@ -302,6 +361,87 @@ namespace Ryujinx.Graphics.Vic.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (AdvSimd.IsSupported)
|
||||||
|
{
|
||||||
|
Vector128<ushort> mask = Vector128.Create(0xffffUL).AsUInt16();
|
||||||
|
|
||||||
|
int widthTrunc = width & ~0xf;
|
||||||
|
int strideGap = yStride - width;
|
||||||
|
|
||||||
|
fixed (Pixel* srcPtr = input.Data)
|
||||||
|
{
|
||||||
|
Pixel* ip = srcPtr;
|
||||||
|
|
||||||
|
fixed (byte* dstPtr = dstY)
|
||||||
|
{
|
||||||
|
byte* op = dstPtr;
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++, ip += input.Width)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
|
||||||
|
for (; x < widthTrunc; x += 16)
|
||||||
|
{
|
||||||
|
byte* baseOffset = (byte*)(ip + (ulong)(uint)x);
|
||||||
|
|
||||||
|
Vector128<ushort> pixelp1 = AdvSimd.LoadVector128((ushort*)baseOffset);
|
||||||
|
Vector128<ushort> pixelp2 = AdvSimd.LoadVector128((ushort*)(baseOffset + 0x10));
|
||||||
|
Vector128<ushort> pixelp3 = AdvSimd.LoadVector128((ushort*)(baseOffset + 0x20));
|
||||||
|
Vector128<ushort> pixelp4 = AdvSimd.LoadVector128((ushort*)(baseOffset + 0x30));
|
||||||
|
Vector128<ushort> pixelp5 = AdvSimd.LoadVector128((ushort*)(baseOffset + 0x40));
|
||||||
|
Vector128<ushort> pixelp6 = AdvSimd.LoadVector128((ushort*)(baseOffset + 0x50));
|
||||||
|
Vector128<ushort> pixelp7 = AdvSimd.LoadVector128((ushort*)(baseOffset + 0x60));
|
||||||
|
Vector128<ushort> pixelp8 = AdvSimd.LoadVector128((ushort*)(baseOffset + 0x70));
|
||||||
|
|
||||||
|
pixelp1 = AdvSimd.And(pixelp1, mask);
|
||||||
|
pixelp2 = AdvSimd.And(pixelp2, mask);
|
||||||
|
pixelp3 = AdvSimd.And(pixelp3, mask);
|
||||||
|
pixelp4 = AdvSimd.And(pixelp4, mask);
|
||||||
|
pixelp5 = AdvSimd.And(pixelp5, mask);
|
||||||
|
pixelp6 = AdvSimd.And(pixelp6, mask);
|
||||||
|
pixelp7 = AdvSimd.And(pixelp7, mask);
|
||||||
|
pixelp8 = AdvSimd.And(pixelp8, mask);
|
||||||
|
|
||||||
|
Vector64<ushort> lowerp1 = AdvSimd.ExtractNarrowingLower(pixelp1.AsUInt32());
|
||||||
|
Vector64<ushort> lowerp3 = AdvSimd.ExtractNarrowingLower(pixelp3.AsUInt32());
|
||||||
|
Vector64<ushort> lowerp5 = AdvSimd.ExtractNarrowingLower(pixelp5.AsUInt32());
|
||||||
|
Vector64<ushort> lowerp7 = AdvSimd.ExtractNarrowingLower(pixelp7.AsUInt32());
|
||||||
|
|
||||||
|
Vector128<ushort> pixelq1 = AdvSimd.ExtractNarrowingUpper(lowerp1, pixelp2.AsUInt32());
|
||||||
|
Vector128<ushort> pixelq2 = AdvSimd.ExtractNarrowingUpper(lowerp3, pixelp4.AsUInt32());
|
||||||
|
Vector128<ushort> pixelq3 = AdvSimd.ExtractNarrowingUpper(lowerp5, pixelp6.AsUInt32());
|
||||||
|
Vector128<ushort> pixelq4 = AdvSimd.ExtractNarrowingUpper(lowerp7, pixelp8.AsUInt32());
|
||||||
|
|
||||||
|
Vector64<ushort> lowerq1 = AdvSimd.ExtractNarrowingLower(pixelq1.AsUInt32());
|
||||||
|
Vector64<ushort> lowerq3 = AdvSimd.ExtractNarrowingLower(pixelq3.AsUInt32());
|
||||||
|
|
||||||
|
pixelq1 = AdvSimd.ExtractNarrowingUpper(lowerq1, pixelq2.AsUInt32());
|
||||||
|
pixelq2 = AdvSimd.ExtractNarrowingUpper(lowerq3, pixelq4.AsUInt32());
|
||||||
|
|
||||||
|
pixelq1 = AdvSimd.ShiftRightLogical(pixelq1, 2);
|
||||||
|
pixelq2 = AdvSimd.ShiftRightLogical(pixelq2, 2);
|
||||||
|
|
||||||
|
Vector64<byte> pixelLower = AdvSimd.ExtractNarrowingLower(pixelq1.AsUInt16());
|
||||||
|
|
||||||
|
Vector128<byte> pixel = AdvSimd.ExtractNarrowingUpper(pixelLower, pixelq2.AsUInt16());
|
||||||
|
|
||||||
|
AdvSimd.Store(op, pixel);
|
||||||
|
|
||||||
|
op += 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; x < width; x++)
|
||||||
|
{
|
||||||
|
Pixel* px = ip + (uint)x;
|
||||||
|
|
||||||
|
*op++ = Downsample(px->R);
|
||||||
|
}
|
||||||
|
|
||||||
|
op += strideGap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int y = 0; y < height; y++)
|
for (int y = 0; y < height; y++)
|
||||||
@@ -392,6 +532,69 @@ namespace Ryujinx.Graphics.Vic.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (AdvSimd.Arm64.IsSupported)
|
||||||
|
{
|
||||||
|
int widthTrunc = uvWidth & ~7;
|
||||||
|
int strideGap = uvStride - uvWidth * 2;
|
||||||
|
|
||||||
|
fixed (Pixel* srcPtr = input.Data)
|
||||||
|
{
|
||||||
|
Pixel* ip = srcPtr;
|
||||||
|
|
||||||
|
fixed (byte* dstPtr = dstUv)
|
||||||
|
{
|
||||||
|
byte* op = dstPtr;
|
||||||
|
|
||||||
|
for (int y = 0; y < uvHeight; y++, ip += input.Width * 2)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
|
||||||
|
for (; x < widthTrunc; x += 8)
|
||||||
|
{
|
||||||
|
byte* baseOffset = (byte*)ip + (ulong)(uint)x * 16;
|
||||||
|
|
||||||
|
Vector128<uint> pixel1 = AdvSimd.LoadAndReplicateToVector128((uint*)(baseOffset + 0x02));
|
||||||
|
Vector128<uint> pixel2 = AdvSimd.LoadAndReplicateToVector128((uint*)(baseOffset + 0x12));
|
||||||
|
Vector128<uint> pixel3 = AdvSimd.LoadAndReplicateToVector128((uint*)(baseOffset + 0x22));
|
||||||
|
Vector128<uint> pixel4 = AdvSimd.LoadAndReplicateToVector128((uint*)(baseOffset + 0x32));
|
||||||
|
Vector128<uint> pixel5 = AdvSimd.LoadAndReplicateToVector128((uint*)(baseOffset + 0x42));
|
||||||
|
Vector128<uint> pixel6 = AdvSimd.LoadAndReplicateToVector128((uint*)(baseOffset + 0x52));
|
||||||
|
Vector128<uint> pixel7 = AdvSimd.LoadAndReplicateToVector128((uint*)(baseOffset + 0x62));
|
||||||
|
Vector128<uint> pixel8 = AdvSimd.LoadAndReplicateToVector128((uint*)(baseOffset + 0x72));
|
||||||
|
|
||||||
|
Vector128<uint> pixel12 = AdvSimd.Arm64.ZipLow(pixel1, pixel2);
|
||||||
|
Vector128<uint> pixel34 = AdvSimd.Arm64.ZipLow(pixel3, pixel4);
|
||||||
|
Vector128<uint> pixel56 = AdvSimd.Arm64.ZipLow(pixel5, pixel6);
|
||||||
|
Vector128<uint> pixel78 = AdvSimd.Arm64.ZipLow(pixel7, pixel8);
|
||||||
|
|
||||||
|
Vector128<ulong> pixel1234 = AdvSimd.Arm64.ZipLow(pixel12.AsUInt64(), pixel34.AsUInt64());
|
||||||
|
Vector128<ulong> pixel5678 = AdvSimd.Arm64.ZipLow(pixel56.AsUInt64(), pixel78.AsUInt64());
|
||||||
|
|
||||||
|
pixel1234 = AdvSimd.ShiftRightLogical(pixel1234, 2);
|
||||||
|
pixel5678 = AdvSimd.ShiftRightLogical(pixel5678, 2);
|
||||||
|
|
||||||
|
Vector64<byte> pixelLower = AdvSimd.ExtractNarrowingLower(pixel1234.AsUInt16());
|
||||||
|
|
||||||
|
Vector128<byte> pixel = AdvSimd.ExtractNarrowingUpper(pixelLower, pixel5678.AsUInt16());
|
||||||
|
|
||||||
|
AdvSimd.Store(op, pixel);
|
||||||
|
|
||||||
|
op += 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; x < uvWidth; x++)
|
||||||
|
{
|
||||||
|
Pixel* px = ip + (uint)(x << 1);
|
||||||
|
|
||||||
|
*op++ = Downsample(px->G);
|
||||||
|
*op++ = Downsample(px->B);
|
||||||
|
}
|
||||||
|
|
||||||
|
op += strideGap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int y = 0; y < uvHeight; y++)
|
for (int y = 0; y < uvHeight; y++)
|
||||||
|
@@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
_attachments = new[] { view };
|
_attachments = new[] { view };
|
||||||
_validColorAttachments = 1u;
|
_validColorAttachments = isDepthStencil ? 0u : 1u;
|
||||||
|
|
||||||
Width = width;
|
Width = width;
|
||||||
Height = height;
|
Height = height;
|
||||||
@@ -46,7 +46,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
AttachmentSamples = new[] { samples };
|
AttachmentSamples = new[] { samples };
|
||||||
AttachmentFormats = new[] { format };
|
AttachmentFormats = new[] { format };
|
||||||
AttachmentIndices = new[] { 0 };
|
AttachmentIndices = isDepthStencil ? Array.Empty<int>() : new[] { 0 };
|
||||||
|
|
||||||
AttachmentsCount = 1;
|
AttachmentsCount = 1;
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
public readonly bool SupportsGeometryShaderPassthrough;
|
public readonly bool SupportsGeometryShaderPassthrough;
|
||||||
public readonly bool SupportsSubgroupSizeControl;
|
public readonly bool SupportsSubgroupSizeControl;
|
||||||
public readonly bool SupportsShaderInt8;
|
public readonly bool SupportsShaderInt8;
|
||||||
|
public readonly bool SupportsShaderStencilExport;
|
||||||
public readonly bool SupportsConditionalRendering;
|
public readonly bool SupportsConditionalRendering;
|
||||||
public readonly bool SupportsExtendedDynamicState;
|
public readonly bool SupportsExtendedDynamicState;
|
||||||
public readonly bool SupportsMultiView;
|
public readonly bool SupportsMultiView;
|
||||||
@@ -48,6 +49,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
bool supportsGeometryShaderPassthrough,
|
bool supportsGeometryShaderPassthrough,
|
||||||
bool supportsSubgroupSizeControl,
|
bool supportsSubgroupSizeControl,
|
||||||
bool supportsShaderInt8,
|
bool supportsShaderInt8,
|
||||||
|
bool supportsShaderStencilExport,
|
||||||
bool supportsConditionalRendering,
|
bool supportsConditionalRendering,
|
||||||
bool supportsExtendedDynamicState,
|
bool supportsExtendedDynamicState,
|
||||||
bool supportsMultiView,
|
bool supportsMultiView,
|
||||||
@@ -71,6 +73,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
|
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
|
||||||
SupportsSubgroupSizeControl = supportsSubgroupSizeControl;
|
SupportsSubgroupSizeControl = supportsSubgroupSizeControl;
|
||||||
SupportsShaderInt8 = supportsShaderInt8;
|
SupportsShaderInt8 = supportsShaderInt8;
|
||||||
|
SupportsShaderStencilExport = supportsShaderStencilExport;
|
||||||
SupportsConditionalRendering = supportsConditionalRendering;
|
SupportsConditionalRendering = supportsConditionalRendering;
|
||||||
SupportsExtendedDynamicState = supportsExtendedDynamicState;
|
SupportsExtendedDynamicState = supportsExtendedDynamicState;
|
||||||
SupportsMultiView = supportsMultiView;
|
SupportsMultiView = supportsMultiView;
|
||||||
|
@@ -24,6 +24,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private readonly ISampler _samplerLinear;
|
private readonly ISampler _samplerLinear;
|
||||||
private readonly ISampler _samplerNearest;
|
private readonly ISampler _samplerNearest;
|
||||||
private readonly IProgram _programColorBlit;
|
private readonly IProgram _programColorBlit;
|
||||||
|
private readonly IProgram _programColorBlitMs;
|
||||||
private readonly IProgram _programColorBlitClearAlpha;
|
private readonly IProgram _programColorBlitClearAlpha;
|
||||||
private readonly IProgram _programColorClearF;
|
private readonly IProgram _programColorClearF;
|
||||||
private readonly IProgram _programColorClearSI;
|
private readonly IProgram _programColorClearSI;
|
||||||
@@ -33,6 +34,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private readonly IProgram _programConvertIndirectData;
|
private readonly IProgram _programConvertIndirectData;
|
||||||
private readonly IProgram _programColorCopyToNonMs;
|
private readonly IProgram _programColorCopyToNonMs;
|
||||||
private readonly IProgram _programColorDrawToMs;
|
private readonly IProgram _programColorDrawToMs;
|
||||||
|
private readonly IProgram _programDepthBlit;
|
||||||
|
private readonly IProgram _programDepthBlitMs;
|
||||||
|
private readonly IProgram _programStencilBlit;
|
||||||
|
private readonly IProgram _programStencilBlitMs;
|
||||||
|
|
||||||
public HelperShader(VulkanRenderer gd, Device device)
|
public HelperShader(VulkanRenderer gd, Device device)
|
||||||
{
|
{
|
||||||
@@ -42,13 +47,13 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_samplerLinear = gd.CreateSampler(GAL.SamplerCreateInfo.Create(MinFilter.Linear, MagFilter.Linear));
|
_samplerLinear = gd.CreateSampler(GAL.SamplerCreateInfo.Create(MinFilter.Linear, MagFilter.Linear));
|
||||||
_samplerNearest = gd.CreateSampler(GAL.SamplerCreateInfo.Create(MinFilter.Nearest, MagFilter.Nearest));
|
_samplerNearest = gd.CreateSampler(GAL.SamplerCreateInfo.Create(MinFilter.Nearest, MagFilter.Nearest));
|
||||||
|
|
||||||
var colorBlitVertexBindings = new ShaderBindings(
|
var blitVertexBindings = new ShaderBindings(
|
||||||
new[] { 1 },
|
new[] { 1 },
|
||||||
Array.Empty<int>(),
|
Array.Empty<int>(),
|
||||||
Array.Empty<int>(),
|
Array.Empty<int>(),
|
||||||
Array.Empty<int>());
|
Array.Empty<int>());
|
||||||
|
|
||||||
var colorBlitFragmentBindings = new ShaderBindings(
|
var blitFragmentBindings = new ShaderBindings(
|
||||||
Array.Empty<int>(),
|
Array.Empty<int>(),
|
||||||
Array.Empty<int>(),
|
Array.Empty<int>(),
|
||||||
new[] { 0 },
|
new[] { 0 },
|
||||||
@@ -56,14 +61,20 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
_programColorBlit = gd.CreateProgramWithMinimalLayout(new[]
|
_programColorBlit = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
{
|
{
|
||||||
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, colorBlitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
||||||
new ShaderSource(ShaderBinaries.ColorBlitFragmentShaderSource, colorBlitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ColorBlitFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
||||||
|
});
|
||||||
|
|
||||||
|
_programColorBlitMs = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
|
{
|
||||||
|
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
||||||
|
new ShaderSource(ShaderBinaries.ColorBlitMsFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
||||||
});
|
});
|
||||||
|
|
||||||
_programColorBlitClearAlpha = gd.CreateProgramWithMinimalLayout(new[]
|
_programColorBlitClearAlpha = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
{
|
{
|
||||||
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, colorBlitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
||||||
new ShaderSource(ShaderBinaries.ColorBlitClearAlphaFragmentShaderSource, colorBlitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ColorBlitClearAlphaFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
||||||
});
|
});
|
||||||
|
|
||||||
var colorClearFragmentBindings = new ShaderBindings(
|
var colorClearFragmentBindings = new ShaderBindings(
|
||||||
@@ -74,19 +85,19 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
_programColorClearF = gd.CreateProgramWithMinimalLayout(new[]
|
_programColorClearF = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
{
|
{
|
||||||
new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, colorBlitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
||||||
new ShaderSource(ShaderBinaries.ColorClearFFragmentShaderSource, colorClearFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ColorClearFFragmentShaderSource, colorClearFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
||||||
});
|
});
|
||||||
|
|
||||||
_programColorClearSI = gd.CreateProgramWithMinimalLayout(new[]
|
_programColorClearSI = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
{
|
{
|
||||||
new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, colorBlitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
||||||
new ShaderSource(ShaderBinaries.ColorClearSIFragmentShaderSource, colorClearFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ColorClearSIFragmentShaderSource, colorClearFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
||||||
});
|
});
|
||||||
|
|
||||||
_programColorClearUI = gd.CreateProgramWithMinimalLayout(new[]
|
_programColorClearUI = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
{
|
{
|
||||||
new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, colorBlitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
||||||
new ShaderSource(ShaderBinaries.ColorClearUIFragmentShaderSource, colorClearFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ColorClearUIFragmentShaderSource, colorClearFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -151,17 +162,44 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
new ShaderSource(ShaderBinaries.ConvertIndirectDataShaderSource, convertIndirectDataBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ConvertIndirectDataShaderSource, convertIndirectDataBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_programDepthBlit = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
|
{
|
||||||
|
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
||||||
|
new ShaderSource(ShaderBinaries.DepthBlitFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
||||||
|
});
|
||||||
|
|
||||||
|
_programDepthBlitMs = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
|
{
|
||||||
|
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
||||||
|
new ShaderSource(ShaderBinaries.DepthBlitMsFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (gd.Capabilities.SupportsShaderStencilExport)
|
||||||
|
{
|
||||||
|
_programStencilBlit = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
|
{
|
||||||
|
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
||||||
|
new ShaderSource(ShaderBinaries.StencilBlitFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
||||||
|
});
|
||||||
|
|
||||||
|
_programStencilBlitMs = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
|
{
|
||||||
|
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv),
|
||||||
|
new ShaderSource(ShaderBinaries.StencilBlitMsFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Blit(
|
public void Blit(
|
||||||
VulkanRenderer gd,
|
VulkanRenderer gd,
|
||||||
TextureView src,
|
TextureView src,
|
||||||
Auto<DisposableImageView> dst,
|
TextureView dst,
|
||||||
int dstWidth,
|
|
||||||
int dstHeight,
|
|
||||||
VkFormat dstFormat,
|
|
||||||
Extents2D srcRegion,
|
Extents2D srcRegion,
|
||||||
Extents2D dstRegion,
|
Extents2D dstRegion,
|
||||||
|
int layers,
|
||||||
|
int levels,
|
||||||
|
bool isDepthOrStencil,
|
||||||
bool linearFilter,
|
bool linearFilter,
|
||||||
bool clearAlpha = false)
|
bool clearAlpha = false)
|
||||||
{
|
{
|
||||||
@@ -169,17 +207,150 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
using var cbs = gd.CommandBufferPool.Rent();
|
using var cbs = gd.CommandBufferPool.Rent();
|
||||||
|
|
||||||
Blit(gd, cbs, src, dst, dstWidth, dstHeight, dstFormat, srcRegion, dstRegion, linearFilter, clearAlpha);
|
var dstFormat = dst.VkFormat;
|
||||||
|
var dstSamples = dst.Info.Samples;
|
||||||
|
|
||||||
|
for (int l = 0; l < levels; l++)
|
||||||
|
{
|
||||||
|
int srcWidth = Math.Max(1, src.Width >> l);
|
||||||
|
int srcHeight = Math.Max(1, src.Height >> l);
|
||||||
|
|
||||||
|
int dstWidth = Math.Max(1, dst.Width >> l);
|
||||||
|
int dstHeight = Math.Max(1, dst.Height >> l);
|
||||||
|
|
||||||
|
var mipSrcRegion = new Extents2D(
|
||||||
|
srcRegion.X1 >> l,
|
||||||
|
srcRegion.Y1 >> l,
|
||||||
|
srcRegion.X2 >> l,
|
||||||
|
srcRegion.Y2 >> l);
|
||||||
|
|
||||||
|
var mipDstRegion = new Extents2D(
|
||||||
|
dstRegion.X1 >> l,
|
||||||
|
dstRegion.Y1 >> l,
|
||||||
|
dstRegion.X2 >> l,
|
||||||
|
dstRegion.Y2 >> l);
|
||||||
|
|
||||||
|
for (int z = 0; z < layers; z++)
|
||||||
|
{
|
||||||
|
var srcView = Create2DLayerView(src, z, l);
|
||||||
|
var dstView = Create2DLayerView(dst, z, l);
|
||||||
|
|
||||||
|
if (isDepthOrStencil)
|
||||||
|
{
|
||||||
|
BlitDepthStencil(
|
||||||
|
gd,
|
||||||
|
cbs,
|
||||||
|
srcView,
|
||||||
|
dst.GetImageViewForAttachment(),
|
||||||
|
dstWidth,
|
||||||
|
dstHeight,
|
||||||
|
dstSamples,
|
||||||
|
dstFormat,
|
||||||
|
mipSrcRegion,
|
||||||
|
mipDstRegion);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BlitColor(
|
||||||
|
gd,
|
||||||
|
cbs,
|
||||||
|
srcView,
|
||||||
|
dst.GetImageViewForAttachment(),
|
||||||
|
dstWidth,
|
||||||
|
dstHeight,
|
||||||
|
dstSamples,
|
||||||
|
dstFormat,
|
||||||
|
false,
|
||||||
|
mipSrcRegion,
|
||||||
|
mipDstRegion,
|
||||||
|
linearFilter,
|
||||||
|
clearAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcView != src)
|
||||||
|
{
|
||||||
|
srcView.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dstView != dst)
|
||||||
|
{
|
||||||
|
dstView.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Blit(
|
public void CopyColor(
|
||||||
|
VulkanRenderer gd,
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
TextureView src,
|
||||||
|
TextureView dst,
|
||||||
|
int srcLayer,
|
||||||
|
int dstLayer,
|
||||||
|
int srcLevel,
|
||||||
|
int dstLevel,
|
||||||
|
int depth,
|
||||||
|
int levels)
|
||||||
|
{
|
||||||
|
for (int l = 0; l < levels; l++)
|
||||||
|
{
|
||||||
|
int mipSrcLevel = srcLevel + l;
|
||||||
|
int mipDstLevel = dstLevel + l;
|
||||||
|
|
||||||
|
int srcWidth = Math.Max(1, src.Width >> mipSrcLevel);
|
||||||
|
int srcHeight = Math.Max(1, src.Height >> mipSrcLevel);
|
||||||
|
|
||||||
|
int dstWidth = Math.Max(1, dst.Width >> mipDstLevel);
|
||||||
|
int dstHeight = Math.Max(1, dst.Height >> mipDstLevel);
|
||||||
|
|
||||||
|
var extents = new Extents2D(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
Math.Min(srcWidth, dstWidth),
|
||||||
|
Math.Min(srcHeight, dstHeight));
|
||||||
|
|
||||||
|
for (int z = 0; z < depth; z++)
|
||||||
|
{
|
||||||
|
var srcView = Create2DLayerView(src, srcLayer + z, mipSrcLevel);
|
||||||
|
var dstView = Create2DLayerView(dst, dstLayer + z, mipDstLevel);
|
||||||
|
|
||||||
|
BlitColor(
|
||||||
|
gd,
|
||||||
|
cbs,
|
||||||
|
srcView,
|
||||||
|
dstView.GetImageViewForAttachment(),
|
||||||
|
dstView.Width,
|
||||||
|
dstView.Height,
|
||||||
|
dstView.Info.Samples,
|
||||||
|
dstView.VkFormat,
|
||||||
|
dstView.Info.Format.IsDepthOrStencil(),
|
||||||
|
extents,
|
||||||
|
extents,
|
||||||
|
false);
|
||||||
|
|
||||||
|
if (srcView != src)
|
||||||
|
{
|
||||||
|
srcView.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dstView != dst)
|
||||||
|
{
|
||||||
|
dstView.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BlitColor(
|
||||||
VulkanRenderer gd,
|
VulkanRenderer gd,
|
||||||
CommandBufferScoped cbs,
|
CommandBufferScoped cbs,
|
||||||
TextureView src,
|
TextureView src,
|
||||||
Auto<DisposableImageView> dst,
|
Auto<DisposableImageView> dst,
|
||||||
int dstWidth,
|
int dstWidth,
|
||||||
int dstHeight,
|
int dstHeight,
|
||||||
|
int dstSamples,
|
||||||
VkFormat dstFormat,
|
VkFormat dstFormat,
|
||||||
|
bool dstIsDepthOrStencil,
|
||||||
Extents2D srcRegion,
|
Extents2D srcRegion,
|
||||||
Extents2D dstRegion,
|
Extents2D dstRegion,
|
||||||
bool linearFilter,
|
bool linearFilter,
|
||||||
@@ -237,8 +408,25 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
scissors[0] = new Rectangle<int>(0, 0, dstWidth, dstHeight);
|
scissors[0] = new Rectangle<int>(0, 0, dstWidth, dstHeight);
|
||||||
|
|
||||||
_pipeline.SetProgram(clearAlpha ? _programColorBlitClearAlpha : _programColorBlit);
|
if (dstIsDepthOrStencil)
|
||||||
_pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false, dstFormat);
|
{
|
||||||
|
_pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit);
|
||||||
|
_pipeline.SetDepthTest(new DepthTestDescriptor(true, true, GAL.CompareOp.Always));
|
||||||
|
}
|
||||||
|
else if (src.Info.Target.IsMultisample())
|
||||||
|
{
|
||||||
|
_pipeline.SetProgram(_programColorBlitMs);
|
||||||
|
}
|
||||||
|
else if (clearAlpha)
|
||||||
|
{
|
||||||
|
_pipeline.SetProgram(_programColorBlitClearAlpha);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_pipeline.SetProgram(_programColorBlit);
|
||||||
|
}
|
||||||
|
|
||||||
|
_pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, (uint)dstSamples, dstIsDepthOrStencil, dstFormat);
|
||||||
_pipeline.SetRenderTargetColorMasks(new uint[] { 0xf });
|
_pipeline.SetRenderTargetColorMasks(new uint[] { 0xf });
|
||||||
_pipeline.SetScissors(scissors);
|
_pipeline.SetScissors(scissors);
|
||||||
|
|
||||||
@@ -250,11 +438,185 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_pipeline.SetViewports(viewports, false);
|
_pipeline.SetViewports(viewports, false);
|
||||||
_pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip);
|
_pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip);
|
||||||
_pipeline.Draw(4, 1, 0, 0);
|
_pipeline.Draw(4, 1, 0, 0);
|
||||||
|
|
||||||
|
if (dstIsDepthOrStencil)
|
||||||
|
{
|
||||||
|
_pipeline.SetDepthTest(new DepthTestDescriptor(false, false, GAL.CompareOp.Always));
|
||||||
|
}
|
||||||
|
|
||||||
_pipeline.Finish(gd, cbs);
|
_pipeline.Finish(gd, cbs);
|
||||||
|
|
||||||
gd.BufferManager.Delete(bufferHandle);
|
gd.BufferManager.Delete(bufferHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void BlitDepthStencil(
|
||||||
|
VulkanRenderer gd,
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
TextureView src,
|
||||||
|
Auto<DisposableImageView> dst,
|
||||||
|
int dstWidth,
|
||||||
|
int dstHeight,
|
||||||
|
int dstSamples,
|
||||||
|
VkFormat dstFormat,
|
||||||
|
Extents2D srcRegion,
|
||||||
|
Extents2D dstRegion)
|
||||||
|
{
|
||||||
|
_pipeline.SetCommandBuffer(cbs);
|
||||||
|
|
||||||
|
const int RegionBufferSize = 16;
|
||||||
|
|
||||||
|
Span<float> region = stackalloc float[RegionBufferSize / sizeof(float)];
|
||||||
|
|
||||||
|
region[0] = (float)srcRegion.X1 / src.Width;
|
||||||
|
region[1] = (float)srcRegion.X2 / src.Width;
|
||||||
|
region[2] = (float)srcRegion.Y1 / src.Height;
|
||||||
|
region[3] = (float)srcRegion.Y2 / src.Height;
|
||||||
|
|
||||||
|
if (dstRegion.X1 > dstRegion.X2)
|
||||||
|
{
|
||||||
|
(region[0], region[1]) = (region[1], region[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dstRegion.Y1 > dstRegion.Y2)
|
||||||
|
{
|
||||||
|
(region[2], region[3]) = (region[3], region[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var bufferHandle = gd.BufferManager.CreateWithHandle(gd, RegionBufferSize, false);
|
||||||
|
|
||||||
|
gd.BufferManager.SetData<float>(bufferHandle, 0, region);
|
||||||
|
|
||||||
|
_pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, RegionBufferSize)) });
|
||||||
|
|
||||||
|
Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1];
|
||||||
|
|
||||||
|
var rect = new Rectangle<float>(
|
||||||
|
MathF.Min(dstRegion.X1, dstRegion.X2),
|
||||||
|
MathF.Min(dstRegion.Y1, dstRegion.Y2),
|
||||||
|
MathF.Abs(dstRegion.X2 - dstRegion.X1),
|
||||||
|
MathF.Abs(dstRegion.Y2 - dstRegion.Y1));
|
||||||
|
|
||||||
|
viewports[0] = new GAL.Viewport(
|
||||||
|
rect,
|
||||||
|
ViewportSwizzle.PositiveX,
|
||||||
|
ViewportSwizzle.PositiveY,
|
||||||
|
ViewportSwizzle.PositiveZ,
|
||||||
|
ViewportSwizzle.PositiveW,
|
||||||
|
0f,
|
||||||
|
1f);
|
||||||
|
|
||||||
|
Span<Rectangle<int>> scissors = stackalloc Rectangle<int>[1];
|
||||||
|
|
||||||
|
scissors[0] = new Rectangle<int>(0, 0, dstWidth, dstHeight);
|
||||||
|
|
||||||
|
_pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, (uint)dstSamples, true, dstFormat);
|
||||||
|
_pipeline.SetScissors(scissors);
|
||||||
|
_pipeline.SetViewports(viewports, false);
|
||||||
|
_pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip);
|
||||||
|
|
||||||
|
var aspectFlags = src.Info.Format.ConvertAspectFlags();
|
||||||
|
|
||||||
|
if (aspectFlags.HasFlag(ImageAspectFlags.DepthBit))
|
||||||
|
{
|
||||||
|
var depthTexture = CreateDepthOrStencilView(src, DepthStencilMode.Depth);
|
||||||
|
|
||||||
|
BlitDepthStencilDraw(depthTexture, isDepth: true);
|
||||||
|
|
||||||
|
if (depthTexture != src)
|
||||||
|
{
|
||||||
|
depthTexture.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aspectFlags.HasFlag(ImageAspectFlags.StencilBit) && _programStencilBlit != null)
|
||||||
|
{
|
||||||
|
var stencilTexture = CreateDepthOrStencilView(src, DepthStencilMode.Stencil);
|
||||||
|
|
||||||
|
BlitDepthStencilDraw(stencilTexture, isDepth: false);
|
||||||
|
|
||||||
|
if (stencilTexture != src)
|
||||||
|
{
|
||||||
|
stencilTexture.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_pipeline.Finish(gd, cbs);
|
||||||
|
|
||||||
|
gd.BufferManager.Delete(bufferHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TextureView CreateDepthOrStencilView(TextureView depthStencilTexture, DepthStencilMode depthStencilMode)
|
||||||
|
{
|
||||||
|
if (depthStencilTexture.Info.DepthStencilMode == depthStencilMode)
|
||||||
|
{
|
||||||
|
return depthStencilTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (TextureView)depthStencilTexture.CreateView(new TextureCreateInfo(
|
||||||
|
depthStencilTexture.Info.Width,
|
||||||
|
depthStencilTexture.Info.Height,
|
||||||
|
depthStencilTexture.Info.Depth,
|
||||||
|
depthStencilTexture.Info.Levels,
|
||||||
|
depthStencilTexture.Info.Samples,
|
||||||
|
depthStencilTexture.Info.BlockWidth,
|
||||||
|
depthStencilTexture.Info.BlockHeight,
|
||||||
|
depthStencilTexture.Info.BytesPerPixel,
|
||||||
|
depthStencilTexture.Info.Format,
|
||||||
|
depthStencilMode,
|
||||||
|
depthStencilTexture.Info.Target,
|
||||||
|
SwizzleComponent.Red,
|
||||||
|
SwizzleComponent.Green,
|
||||||
|
SwizzleComponent.Blue,
|
||||||
|
SwizzleComponent.Alpha), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BlitDepthStencilDraw(TextureView src, bool isDepth)
|
||||||
|
{
|
||||||
|
_pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, _samplerNearest);
|
||||||
|
|
||||||
|
if (isDepth)
|
||||||
|
{
|
||||||
|
_pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit);
|
||||||
|
_pipeline.SetDepthTest(new DepthTestDescriptor(true, true, GAL.CompareOp.Always));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programStencilBlitMs : _programStencilBlit);
|
||||||
|
_pipeline.SetStencilTest(CreateStencilTestDescriptor(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
_pipeline.Draw(4, 1, 0, 0);
|
||||||
|
|
||||||
|
if (isDepth)
|
||||||
|
{
|
||||||
|
_pipeline.SetDepthTest(new DepthTestDescriptor(false, false, GAL.CompareOp.Always));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_pipeline.SetStencilTest(CreateStencilTestDescriptor(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StencilTestDescriptor CreateStencilTestDescriptor(bool enabled)
|
||||||
|
{
|
||||||
|
return new StencilTestDescriptor(
|
||||||
|
enabled,
|
||||||
|
GAL.CompareOp.Always,
|
||||||
|
GAL.StencilOp.Replace,
|
||||||
|
GAL.StencilOp.Replace,
|
||||||
|
GAL.StencilOp.Replace,
|
||||||
|
0,
|
||||||
|
0xff,
|
||||||
|
0xff,
|
||||||
|
GAL.CompareOp.Always,
|
||||||
|
GAL.StencilOp.Replace,
|
||||||
|
GAL.StencilOp.Replace,
|
||||||
|
GAL.StencilOp.Replace,
|
||||||
|
0,
|
||||||
|
0xff,
|
||||||
|
0xff);
|
||||||
|
}
|
||||||
|
|
||||||
public void Clear(
|
public void Clear(
|
||||||
VulkanRenderer gd,
|
VulkanRenderer gd,
|
||||||
Auto<DisposableImageView> dst,
|
Auto<DisposableImageView> dst,
|
||||||
@@ -603,33 +965,25 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
_pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) });
|
_pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) });
|
||||||
|
|
||||||
if (src.Info.Target == Target.Texture2DMultisampleArray ||
|
for (int z = 0; z < depth; z++)
|
||||||
dst.Info.Target == Target.Texture2DMultisampleArray)
|
|
||||||
{
|
{
|
||||||
for (int z = 0; z < depth; z++)
|
var srcView = Create2DLayerView(src, srcLayer + z, 0, format);
|
||||||
{
|
var dstView = Create2DLayerView(dst, dstLayer + z, 0);
|
||||||
var srcView = Create2DLayerView(src, srcLayer + z, format);
|
|
||||||
var dstView = Create2DLayerView(dst, dstLayer + z);
|
|
||||||
|
|
||||||
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null);
|
|
||||||
_pipeline.SetImage(0, dstView, format);
|
|
||||||
|
|
||||||
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
|
|
||||||
|
|
||||||
srcView.Release();
|
|
||||||
dstView.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var srcView = Create2DLayerView(src, srcLayer, format);
|
|
||||||
|
|
||||||
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null);
|
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null);
|
||||||
_pipeline.SetImage(0, dst, format);
|
_pipeline.SetImage(0, dstView, format);
|
||||||
|
|
||||||
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
|
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
|
||||||
|
|
||||||
srcView.Release();
|
if (srcView != src)
|
||||||
|
{
|
||||||
|
srcView.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dstView != dst)
|
||||||
|
{
|
||||||
|
dstView.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gd.BufferManager.Delete(bufferHandle);
|
gd.BufferManager.Delete(bufferHandle);
|
||||||
@@ -714,36 +1068,14 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
var format = GetFormat(src.Info.BytesPerPixel);
|
var format = GetFormat(src.Info.BytesPerPixel);
|
||||||
var vkFormat = FormatTable.GetFormat(format);
|
var vkFormat = FormatTable.GetFormat(format);
|
||||||
|
|
||||||
if (src.Info.Target == Target.Texture2DMultisampleArray ||
|
for (int z = 0; z < depth; z++)
|
||||||
dst.Info.Target == Target.Texture2DMultisampleArray)
|
|
||||||
{
|
{
|
||||||
for (int z = 0; z < depth; z++)
|
var srcView = Create2DLayerView(src, srcLayer + z, 0, format);
|
||||||
{
|
var dstView = Create2DLayerView(dst, dstLayer + z, 0);
|
||||||
var srcView = Create2DLayerView(src, srcLayer + z, format);
|
|
||||||
var dstView = Create2DLayerView(dst, dstLayer + z);
|
|
||||||
|
|
||||||
_pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, srcView, null);
|
|
||||||
_pipeline.SetRenderTarget(
|
|
||||||
((TextureView)dstView).GetView(format).GetImageViewForAttachment(),
|
|
||||||
(uint)dst.Width,
|
|
||||||
(uint)dst.Height,
|
|
||||||
(uint)samples,
|
|
||||||
false,
|
|
||||||
vkFormat);
|
|
||||||
|
|
||||||
_pipeline.Draw(4, 1, 0, 0);
|
|
||||||
|
|
||||||
srcView.Release();
|
|
||||||
dstView.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var srcView = Create2DLayerView(src, srcLayer, format);
|
|
||||||
|
|
||||||
_pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, srcView, null);
|
_pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, srcView, null);
|
||||||
_pipeline.SetRenderTarget(
|
_pipeline.SetRenderTarget(
|
||||||
dst.GetView(format).GetImageViewForAttachment(),
|
((TextureView)dstView).GetView(format).GetImageViewForAttachment(),
|
||||||
(uint)dst.Width,
|
(uint)dst.Width,
|
||||||
(uint)dst.Height,
|
(uint)dst.Height,
|
||||||
(uint)samples,
|
(uint)samples,
|
||||||
@@ -752,7 +1084,15 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
_pipeline.Draw(4, 1, 0, 0);
|
_pipeline.Draw(4, 1, 0, 0);
|
||||||
|
|
||||||
srcView.Release();
|
if (srcView != src)
|
||||||
|
{
|
||||||
|
srcView.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dstView != dst)
|
||||||
|
{
|
||||||
|
dstView.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gd.BufferManager.Delete(bufferHandle);
|
gd.BufferManager.Delete(bufferHandle);
|
||||||
@@ -809,14 +1149,18 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return (samplesInXLog2, samplesInYLog2);
|
return (samplesInXLog2, samplesInYLog2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ITexture Create2DLayerView(TextureView from, int layer, GAL.Format? format = null)
|
private static TextureView Create2DLayerView(TextureView from, int layer, int level, GAL.Format? format = null)
|
||||||
{
|
{
|
||||||
|
if (from.Info.Target == Target.Texture2D && level == 0 && (format == null || format.Value == from.Info.Format))
|
||||||
|
{
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
|
||||||
var target = from.Info.Target switch
|
var target = from.Info.Target switch
|
||||||
{
|
{
|
||||||
Target.Texture1DArray => Target.Texture1D,
|
Target.Texture1DArray => Target.Texture1D,
|
||||||
Target.Texture2DArray => Target.Texture2D,
|
|
||||||
Target.Texture2DMultisampleArray => Target.Texture2DMultisample,
|
Target.Texture2DMultisampleArray => Target.Texture2DMultisample,
|
||||||
_ => from.Info.Target
|
_ => Target.Texture2D
|
||||||
};
|
};
|
||||||
|
|
||||||
var info = new TextureCreateInfo(
|
var info = new TextureCreateInfo(
|
||||||
@@ -836,7 +1180,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
from.Info.SwizzleB,
|
from.Info.SwizzleB,
|
||||||
from.Info.SwizzleA);
|
from.Info.SwizzleA);
|
||||||
|
|
||||||
return from.CreateView(info, layer, 0);
|
return from.CreateViewImpl(info, layer, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GAL.Format GetFormat(int bytesPerPixel)
|
private static GAL.Format GetFormat(int bytesPerPixel)
|
||||||
@@ -985,6 +1329,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
_programColorBlitClearAlpha.Dispose();
|
_programColorBlitClearAlpha.Dispose();
|
||||||
_programColorBlit.Dispose();
|
_programColorBlit.Dispose();
|
||||||
|
_programColorBlitMs.Dispose();
|
||||||
_programColorClearF.Dispose();
|
_programColorClearF.Dispose();
|
||||||
_programColorClearSI.Dispose();
|
_programColorClearSI.Dispose();
|
||||||
_programColorClearUI.Dispose();
|
_programColorClearUI.Dispose();
|
||||||
@@ -993,6 +1338,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_programConvertIndirectData.Dispose();
|
_programConvertIndirectData.Dispose();
|
||||||
_programColorCopyToNonMs.Dispose();
|
_programColorCopyToNonMs.Dispose();
|
||||||
_programColorDrawToMs.Dispose();
|
_programColorDrawToMs.Dispose();
|
||||||
|
_programDepthBlit.Dispose();
|
||||||
|
_programDepthBlitMs.Dispose();
|
||||||
|
_programStencilBlit?.Dispose();
|
||||||
|
_programStencilBlitMs?.Dispose();
|
||||||
_samplerNearest.Dispose();
|
_samplerNearest.Dispose();
|
||||||
_samplerLinear.Dispose();
|
_samplerLinear.Dispose();
|
||||||
_pipeline.Dispose();
|
_pipeline.Dispose();
|
||||||
|
@@ -27,6 +27,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
int attachmentCount = 0;
|
int attachmentCount = 0;
|
||||||
int colorCount = 0;
|
int colorCount = 0;
|
||||||
|
int maxColorAttachmentIndex = -1;
|
||||||
|
|
||||||
for (int i = 0; i < state.AttachmentEnable.Length; i++)
|
for (int i = 0; i < state.AttachmentEnable.Length; i++)
|
||||||
{
|
{
|
||||||
@@ -36,6 +37,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
attachmentIndices[attachmentCount++] = i;
|
attachmentIndices[attachmentCount++] = i;
|
||||||
colorCount++;
|
colorCount++;
|
||||||
|
maxColorAttachmentIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,12 +75,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (colorAttachmentsCount != 0)
|
if (colorAttachmentsCount != 0)
|
||||||
{
|
{
|
||||||
int maxAttachmentIndex = Constants.MaxRenderTargets - 1;
|
subpass.ColorAttachmentCount = (uint)maxColorAttachmentIndex + 1;
|
||||||
subpass.ColorAttachmentCount = (uint)maxAttachmentIndex + 1;
|
|
||||||
subpass.PColorAttachments = &attachmentReferences[0];
|
subpass.PColorAttachments = &attachmentReferences[0];
|
||||||
|
|
||||||
// Fill with VK_ATTACHMENT_UNUSED to cover any gaps.
|
// Fill with VK_ATTACHMENT_UNUSED to cover any gaps.
|
||||||
for (int i = 0; i <= maxAttachmentIndex; i++)
|
for (int i = 0; i <= maxColorAttachmentIndex; i++)
|
||||||
{
|
{
|
||||||
subpass.PColorAttachments[i] = new AttachmentReference(Vk.AttachmentUnused, ImageLayout.Undefined);
|
subpass.PColorAttachments[i] = new AttachmentReference(Vk.AttachmentUnused, ImageLayout.Undefined);
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
private const ulong MinByteWeightForFlush = 256 * 1024 * 1024; // MiB
|
private const ulong MinByteWeightForFlush = 256 * 1024 * 1024; // MiB
|
||||||
|
|
||||||
private readonly List<QueryPool> _activeQueries;
|
private readonly List<(QueryPool, bool)> _activeQueries;
|
||||||
private CounterQueueEvent _activeConditionalRender;
|
private CounterQueueEvent _activeConditionalRender;
|
||||||
|
|
||||||
private readonly List<BufferedQuery> _pendingQueryCopies;
|
private readonly List<BufferedQuery> _pendingQueryCopies;
|
||||||
@@ -19,7 +19,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public PipelineFull(VulkanRenderer gd, Device device) : base(gd, device)
|
public PipelineFull(VulkanRenderer gd, Device device) : base(gd, device)
|
||||||
{
|
{
|
||||||
_activeQueries = new List<QueryPool>();
|
_activeQueries = new List<(QueryPool, bool)>();
|
||||||
_pendingQueryCopies = new();
|
_pendingQueryCopies = new();
|
||||||
|
|
||||||
CommandBuffer = (Cbs = gd.CommandBufferPool.Rent()).CommandBuffer;
|
CommandBuffer = (Cbs = gd.CommandBufferPool.Rent()).CommandBuffer;
|
||||||
@@ -202,7 +202,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
AutoFlush.RegisterFlush(DrawCount);
|
AutoFlush.RegisterFlush(DrawCount);
|
||||||
EndRenderPass();
|
EndRenderPass();
|
||||||
|
|
||||||
foreach (var queryPool in _activeQueries)
|
foreach ((var queryPool, _) in _activeQueries)
|
||||||
{
|
{
|
||||||
Gd.Api.CmdEndQuery(CommandBuffer, queryPool, 0);
|
Gd.Api.CmdEndQuery(CommandBuffer, queryPool, 0);
|
||||||
}
|
}
|
||||||
@@ -220,10 +220,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
// Restore per-command buffer state.
|
// Restore per-command buffer state.
|
||||||
|
|
||||||
foreach (var queryPool in _activeQueries)
|
foreach ((var queryPool, var isOcclusion) in _activeQueries)
|
||||||
{
|
{
|
||||||
|
bool isPrecise = Gd.Capabilities.SupportsPreciseOcclusionQueries && isOcclusion;
|
||||||
|
|
||||||
Gd.Api.CmdResetQueryPool(CommandBuffer, queryPool, 0, 1);
|
Gd.Api.CmdResetQueryPool(CommandBuffer, queryPool, 0, 1);
|
||||||
Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, Gd.Capabilities.SupportsPreciseOcclusionQueries ? QueryControlFlags.PreciseBit : 0);
|
Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, isPrecise ? QueryControlFlags.PreciseBit : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gd.ResetCounterPool();
|
Gd.ResetCounterPool();
|
||||||
@@ -231,7 +233,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Restore();
|
Restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginQuery(BufferedQuery query, QueryPool pool, bool needsReset, bool fromSamplePool)
|
public void BeginQuery(BufferedQuery query, QueryPool pool, bool needsReset, bool isOcclusion, bool fromSamplePool)
|
||||||
{
|
{
|
||||||
if (needsReset)
|
if (needsReset)
|
||||||
{
|
{
|
||||||
@@ -247,16 +249,24 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Gd.Api.CmdBeginQuery(CommandBuffer, pool, 0, Gd.Capabilities.SupportsPreciseOcclusionQueries ? QueryControlFlags.PreciseBit : 0);
|
bool isPrecise = Gd.Capabilities.SupportsPreciseOcclusionQueries && isOcclusion;
|
||||||
|
Gd.Api.CmdBeginQuery(CommandBuffer, pool, 0, isPrecise ? QueryControlFlags.PreciseBit : 0);
|
||||||
|
|
||||||
_activeQueries.Add(pool);
|
_activeQueries.Add((pool, isOcclusion));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EndQuery(QueryPool pool)
|
public void EndQuery(QueryPool pool)
|
||||||
{
|
{
|
||||||
Gd.Api.CmdEndQuery(CommandBuffer, pool, 0);
|
Gd.Api.CmdEndQuery(CommandBuffer, pool, 0);
|
||||||
|
|
||||||
_activeQueries.Remove(pool);
|
for (int i = 0; i < _activeQueries.Count; i++)
|
||||||
|
{
|
||||||
|
if (_activeQueries[i].Item1.Handle == pool.Handle)
|
||||||
|
{
|
||||||
|
_activeQueries.RemoveAt(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyQueryResults(BufferedQuery query)
|
public void CopyQueryResults(BufferedQuery query)
|
||||||
|
@@ -100,7 +100,8 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
|||||||
if (_isSupported)
|
if (_isSupported)
|
||||||
{
|
{
|
||||||
bool needsReset = resetSequence == null || _resetSequence == null || resetSequence.Value != _resetSequence.Value;
|
bool needsReset = resetSequence == null || _resetSequence == null || resetSequence.Value != _resetSequence.Value;
|
||||||
_pipeline.BeginQuery(this, _queryPool, needsReset, _type == CounterType.SamplesPassed && resetSequence != null);
|
bool isOcclusion = _type == CounterType.SamplesPassed;
|
||||||
|
_pipeline.BeginQuery(this, _queryPool, needsReset, isOcclusion, isOcclusion && resetSequence != null);
|
||||||
}
|
}
|
||||||
_resetSequence = null;
|
_resetSequence = null;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,11 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout (binding = 0, set = 2) uniform sampler2DMS tex;
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 tex_coord;
|
||||||
|
layout (location = 0) out vec4 colour;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
colour = texelFetch(tex, ivec2(tex_coord * vec2(textureSize(tex).xy)), gl_SampleID);
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout (binding = 0, set = 2) uniform sampler2D texDepth;
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 tex_coord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragDepth = texture(texDepth, tex_coord).r;
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout (binding = 0, set = 2) uniform sampler2DMS texDepth;
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 tex_coord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragDepth = texelFetch(texDepth, ivec2(tex_coord * vec2(textureSize(texDepth).xy)), gl_SampleID).r;
|
||||||
|
}
|
@@ -329,6 +329,61 @@ namespace Ryujinx.Graphics.Vulkan.Shaders
|
|||||||
0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static readonly byte[] ColorBlitMsFragmentShaderSource = new byte[]
|
||||||
|
{
|
||||||
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x08, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||||
|
0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x63, 0x6F, 0x6C, 0x6F, 0x75, 0x72, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||||
|
0x74, 0x65, 0x78, 0x00, 0x05, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x5F,
|
||||||
|
0x63, 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||||
|
0x67, 0x6C, 0x5F, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x49, 0x44, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
|
||||||
|
0x1C, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00,
|
||||||
|
0x1C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00,
|
||||||
|
0x05, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x0E, 0x00, 0x00, 0x00, 0x68, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||||
|
0x12, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||||
|
0x1A, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||||
|
0x1D, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x1E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0x1F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||||
|
0x1D, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00,
|
||||||
|
0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
public static readonly byte[] ColorBlitVertexShaderSource = new byte[]
|
public static readonly byte[] ColorBlitVertexShaderSource = new byte[]
|
||||||
{
|
{
|
||||||
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x3F, 0x00, 0x00, 0x00,
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x3F, 0x00, 0x00, 0x00,
|
||||||
@@ -1459,5 +1514,216 @@ namespace Ryujinx.Graphics.Vulkan.Shaders
|
|||||||
0x3B, 0x01, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xE3, 0x00, 0x00, 0x00,
|
0x3B, 0x01, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xE3, 0x00, 0x00, 0x00,
|
||||||
0xF8, 0x00, 0x02, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
0xF8, 0x00, 0x02, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static readonly byte[] DepthBlitFragmentShaderSource = new byte[]
|
||||||
|
{
|
||||||
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x08, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x0C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x44,
|
||||||
|
0x65, 0x70, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x74, 0x65, 0x78, 0x44, 0x65, 0x70, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
|
||||||
|
0x10, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x5F, 0x63, 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x3B, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x19, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x3B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||||
|
0x3B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x0A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x0E, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00,
|
||||||
|
0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||||
|
0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly byte[] DepthBlitMsFragmentShaderSource = new byte[]
|
||||||
|
{
|
||||||
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x08, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00,
|
||||||
|
0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0xC2, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46,
|
||||||
|
0x72, 0x61, 0x67, 0x44, 0x65, 0x70, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
|
||||||
|
0x0C, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x44, 0x65, 0x70, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x5F, 0x63, 0x6F, 0x6F, 0x72,
|
||||||
|
0x64, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x53,
|
||||||
|
0x61, 0x6D, 0x70, 0x6C, 0x65, 0x49, 0x44, 0x00, 0x47, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1B, 0x00, 0x00, 0x00,
|
||||||
|
0x0E, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||||
|
0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0A, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x0E, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x64, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||||
|
0x68, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
|
||||||
|
0x6F, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||||
|
0x85, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||||
|
0x1B, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00,
|
||||||
|
0x1D, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||||
|
0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||||
|
0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly byte[] StencilBlitFragmentShaderSource = new byte[]
|
||||||
|
{
|
||||||
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x08, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||||
|
0x95, 0x13, 0x00, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x53, 0x50, 0x56, 0x5F, 0x45, 0x58, 0x54, 0x5F,
|
||||||
|
0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5F, 0x73, 0x74, 0x65, 0x6E, 0x63, 0x69, 0x6C, 0x5F, 0x65,
|
||||||
|
0x78, 0x70, 0x6F, 0x72, 0x74, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0xA3, 0x13, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00,
|
||||||
|
0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5F, 0x73, 0x74,
|
||||||
|
0x65, 0x6E, 0x63, 0x69, 0x6C, 0x5F, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x53,
|
||||||
|
0x74, 0x65, 0x6E, 0x63, 0x69, 0x6C, 0x52, 0x65, 0x66, 0x41, 0x52, 0x42, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x53, 0x74, 0x65, 0x6E, 0x63,
|
||||||
|
0x69, 0x6C, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x5F,
|
||||||
|
0x63, 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x96, 0x13, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x1B, 0x00, 0x03, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
|
||||||
|
0x0E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x0E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00,
|
||||||
|
0x05, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||||
|
0x0C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00,
|
||||||
|
0x08, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly byte[] StencilBlitMsFragmentShaderSource = new byte[]
|
||||||
|
{
|
||||||
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x08, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x32, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||||
|
0x95, 0x13, 0x00, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x53, 0x50, 0x56, 0x5F, 0x45, 0x58, 0x54, 0x5F,
|
||||||
|
0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5F, 0x73, 0x74, 0x65, 0x6E, 0x63, 0x69, 0x6C, 0x5F, 0x65,
|
||||||
|
0x78, 0x70, 0x6F, 0x72, 0x74, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x08, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0xA3, 0x13, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x09, 0x00, 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x73, 0x68, 0x61, 0x64, 0x65,
|
||||||
|
0x72, 0x5F, 0x73, 0x74, 0x65, 0x6E, 0x63, 0x69, 0x6C, 0x5F, 0x65, 0x78, 0x70, 0x6F, 0x72, 0x74,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46,
|
||||||
|
0x72, 0x61, 0x67, 0x53, 0x74, 0x65, 0x6E, 0x63, 0x69, 0x6C, 0x52, 0x65, 0x66, 0x41, 0x52, 0x42,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x53,
|
||||||
|
0x74, 0x65, 0x6E, 0x63, 0x69, 0x6C, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x74, 0x65, 0x78, 0x5F, 0x63, 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
|
||||||
|
0x1B, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x49, 0x44, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x96, 0x13, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x03, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x1B, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x3B, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x19, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x3B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x16, 0x00, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x1A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x1A, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
|
||||||
|
0x1E, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x68, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||||
|
0x16, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00,
|
||||||
|
0x1E, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x22, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00,
|
||||||
|
0x08, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,12 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
#extension GL_ARB_shader_stencil_export : require
|
||||||
|
|
||||||
|
layout (binding = 0, set = 2) uniform isampler2D texStencil;
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 tex_coord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragStencilRefARB = texture(texStencil, tex_coord).r;
|
||||||
|
}
|
@@ -0,0 +1,12 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
#extension GL_ARB_shader_stencil_export : require
|
||||||
|
|
||||||
|
layout (binding = 0, set = 2) uniform isampler2DMS texStencil;
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 tex_coord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragStencilRefARB = texelFetch(texStencil, ivec2(tex_coord * vec2(textureSize(texStencil).xy)), gl_SampleID).r;
|
||||||
|
}
|
@@ -90,7 +90,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
var componentMapping = new ComponentMapping(swizzleR, swizzleG, swizzleB, swizzleA);
|
var componentMapping = new ComponentMapping(swizzleR, swizzleG, swizzleB, swizzleA);
|
||||||
|
|
||||||
var aspectFlags = info.Format.ConvertAspectFlags(info.DepthStencilMode);
|
var aspectFlags = info.Format.ConvertAspectFlags(info.DepthStencilMode);
|
||||||
var aspectFlagsDepth = info.Format.ConvertAspectFlags(DepthStencilMode.Depth);
|
var aspectFlagsDepth = info.Format.ConvertAspectFlags();
|
||||||
|
|
||||||
var subresourceRange = new ImageSubresourceRange(aspectFlags, (uint)firstLevel, levels, (uint)firstLayer, layers);
|
var subresourceRange = new ImageSubresourceRange(aspectFlags, (uint)firstLevel, levels, (uint)firstLayer, layers);
|
||||||
var subresourceRangeDepth = new ImageSubresourceRange(aspectFlagsDepth, (uint)firstLevel, levels, (uint)firstLayer, layers);
|
var subresourceRangeDepth = new ImageSubresourceRange(aspectFlagsDepth, (uint)firstLevel, levels, (uint)firstLayer, layers);
|
||||||
@@ -362,31 +362,23 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
levels,
|
levels,
|
||||||
linearFilter);
|
linearFilter);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (srcFormat == GAL.Format.D32FloatS8Uint && srcFormat == dstFormat && SupportsBlitFromD32FS8ToD32FAndS8())
|
|
||||||
{
|
|
||||||
BlitDepthStencilWithBuffer(_gd, cbs, src, dst, srcRegion, dstRegion);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VulkanConfiguration.UseSlowSafeBlitOnAmd &&
|
bool isDepthOrStencil = dst.Info.Format.IsDepthOrStencil();
|
||||||
(_gd.Vendor == Vendor.Amd || _gd.IsMoltenVk) &&
|
|
||||||
src.Info.Target == Target.Texture2D &&
|
if (VulkanConfiguration.UseSlowSafeBlitOnAmd && (_gd.Vendor == Vendor.Amd || _gd.IsMoltenVk))
|
||||||
dst.Info.Target == Target.Texture2D &&
|
|
||||||
!dst.Info.Format.IsDepthOrStencil())
|
|
||||||
{
|
{
|
||||||
_gd.HelperShader.Blit(
|
_gd.HelperShader.Blit(
|
||||||
_gd,
|
_gd,
|
||||||
src,
|
src,
|
||||||
dst.GetIdentityImageView(),
|
dst,
|
||||||
dst.Width,
|
|
||||||
dst.Height,
|
|
||||||
dst.VkFormat,
|
|
||||||
srcRegion,
|
srcRegion,
|
||||||
dstRegion,
|
dstRegion,
|
||||||
|
layers,
|
||||||
|
levels,
|
||||||
|
isDepthOrStencil,
|
||||||
linearFilter);
|
linearFilter);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -395,7 +387,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Auto<DisposableImage> srcImage;
|
Auto<DisposableImage> srcImage;
|
||||||
Auto<DisposableImage> dstImage;
|
Auto<DisposableImage> dstImage;
|
||||||
|
|
||||||
if (dst.Info.Format.IsDepthOrStencil())
|
if (isDepthOrStencil)
|
||||||
{
|
{
|
||||||
srcImage = src.Storage.CreateAliasedColorForDepthStorageUnsafe(srcFormat).GetImage();
|
srcImage = src.Storage.CreateAliasedColorForDepthStorageUnsafe(srcFormat).GetImage();
|
||||||
dstImage = dst.Storage.CreateAliasedColorForDepthStorageUnsafe(dstFormat).GetImage();
|
dstImage = dst.Storage.CreateAliasedColorForDepthStorageUnsafe(dstFormat).GetImage();
|
||||||
@@ -426,189 +418,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
ImageAspectFlags.ColorBit);
|
ImageAspectFlags.ColorBit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void BlitDepthStencilWithBuffer(
|
|
||||||
VulkanRenderer gd,
|
|
||||||
CommandBufferScoped cbs,
|
|
||||||
TextureView src,
|
|
||||||
TextureView dst,
|
|
||||||
Extents2D srcRegion,
|
|
||||||
Extents2D dstRegion)
|
|
||||||
{
|
|
||||||
int drBaseX = Math.Min(dstRegion.X1, dstRegion.X2);
|
|
||||||
int drBaseY = Math.Min(dstRegion.Y1, dstRegion.Y2);
|
|
||||||
int drWidth = Math.Abs(dstRegion.X2 - dstRegion.X1);
|
|
||||||
int drHeight = Math.Abs(dstRegion.Y2 - dstRegion.Y1);
|
|
||||||
|
|
||||||
var drOriginZero = new Extents2D(
|
|
||||||
dstRegion.X1 - drBaseX,
|
|
||||||
dstRegion.Y1 - drBaseY,
|
|
||||||
dstRegion.X2 - drBaseX,
|
|
||||||
dstRegion.Y2 - drBaseY);
|
|
||||||
|
|
||||||
var d32SrcStorageInfo = TextureStorage.NewCreateInfoWith(ref src._info, GAL.Format.D32Float, 4);
|
|
||||||
var d32DstStorageInfo = TextureStorage.NewCreateInfoWith(ref dst._info, GAL.Format.D32Float, 4, drWidth, drHeight);
|
|
||||||
var s8SrcStorageInfo = TextureStorage.NewCreateInfoWith(ref src._info, GAL.Format.S8Uint, 1);
|
|
||||||
var s8DstStorageInfo = TextureStorage.NewCreateInfoWith(ref dst._info, GAL.Format.S8Uint, 1, drWidth, drHeight);
|
|
||||||
|
|
||||||
using var d32SrcStorage = gd.CreateTextureStorage(d32SrcStorageInfo, src.Storage.ScaleFactor);
|
|
||||||
using var d32DstStorage = gd.CreateTextureStorage(d32DstStorageInfo, dst.Storage.ScaleFactor);
|
|
||||||
using var s8SrcStorage = gd.CreateTextureStorage(s8SrcStorageInfo, src.Storage.ScaleFactor);
|
|
||||||
using var s8DstStorage = gd.CreateTextureStorage(s8DstStorageInfo, dst.Storage.ScaleFactor);
|
|
||||||
|
|
||||||
void SlowBlit(TextureStorage srcTemp, TextureStorage dstTemp, ImageAspectFlags aspectFlags)
|
|
||||||
{
|
|
||||||
int levels = Math.Min(src.Info.Levels, dst.Info.Levels);
|
|
||||||
|
|
||||||
int srcSize = 0;
|
|
||||||
int dstSize = 0;
|
|
||||||
|
|
||||||
for (int l = 0; l < levels; l++)
|
|
||||||
{
|
|
||||||
srcSize += srcTemp.Info.GetMipSize2D(l);
|
|
||||||
dstSize += dstTemp.Info.GetMipSize2D(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
using var srcTempBuffer = gd.BufferManager.Create(gd, srcSize, deviceLocal: true);
|
|
||||||
using var dstTempBuffer = gd.BufferManager.Create(gd, dstSize, deviceLocal: true);
|
|
||||||
|
|
||||||
src.Storage.CopyFromOrToBuffer(
|
|
||||||
cbs.CommandBuffer,
|
|
||||||
srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value,
|
|
||||||
src.GetImage().Get(cbs).Value,
|
|
||||||
srcSize,
|
|
||||||
to: true,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
src.FirstLayer,
|
|
||||||
src.FirstLevel,
|
|
||||||
1,
|
|
||||||
levels,
|
|
||||||
true,
|
|
||||||
aspectFlags,
|
|
||||||
false);
|
|
||||||
|
|
||||||
BufferHolder.InsertBufferBarrier(
|
|
||||||
gd,
|
|
||||||
cbs.CommandBuffer,
|
|
||||||
srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value,
|
|
||||||
AccessFlags.TransferWriteBit,
|
|
||||||
AccessFlags.TransferReadBit,
|
|
||||||
PipelineStageFlags.TransferBit,
|
|
||||||
PipelineStageFlags.TransferBit,
|
|
||||||
0,
|
|
||||||
srcSize);
|
|
||||||
|
|
||||||
srcTemp.CopyFromOrToBuffer(
|
|
||||||
cbs.CommandBuffer,
|
|
||||||
srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value,
|
|
||||||
srcTemp.GetImage().Get(cbs).Value,
|
|
||||||
srcSize,
|
|
||||||
to: false,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
levels,
|
|
||||||
true,
|
|
||||||
aspectFlags,
|
|
||||||
false);
|
|
||||||
|
|
||||||
InsertImageBarrier(
|
|
||||||
gd.Api,
|
|
||||||
cbs.CommandBuffer,
|
|
||||||
srcTemp.GetImage().Get(cbs).Value,
|
|
||||||
AccessFlags.TransferWriteBit,
|
|
||||||
AccessFlags.TransferReadBit,
|
|
||||||
PipelineStageFlags.TransferBit,
|
|
||||||
PipelineStageFlags.TransferBit,
|
|
||||||
aspectFlags,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
levels);
|
|
||||||
|
|
||||||
TextureCopy.Blit(
|
|
||||||
gd.Api,
|
|
||||||
cbs.CommandBuffer,
|
|
||||||
srcTemp.GetImage().Get(cbs).Value,
|
|
||||||
dstTemp.GetImage().Get(cbs).Value,
|
|
||||||
srcTemp.Info,
|
|
||||||
dstTemp.Info,
|
|
||||||
srcRegion,
|
|
||||||
drOriginZero,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
levels,
|
|
||||||
false,
|
|
||||||
aspectFlags,
|
|
||||||
aspectFlags);
|
|
||||||
|
|
||||||
InsertImageBarrier(
|
|
||||||
gd.Api,
|
|
||||||
cbs.CommandBuffer,
|
|
||||||
dstTemp.GetImage().Get(cbs).Value,
|
|
||||||
AccessFlags.TransferWriteBit,
|
|
||||||
AccessFlags.TransferReadBit,
|
|
||||||
PipelineStageFlags.TransferBit,
|
|
||||||
PipelineStageFlags.TransferBit,
|
|
||||||
aspectFlags,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
levels);
|
|
||||||
|
|
||||||
dstTemp.CopyFromOrToBuffer(
|
|
||||||
cbs.CommandBuffer,
|
|
||||||
dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value,
|
|
||||||
dstTemp.GetImage().Get(cbs).Value,
|
|
||||||
dstSize,
|
|
||||||
to: true,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
levels,
|
|
||||||
true,
|
|
||||||
aspectFlags,
|
|
||||||
false);
|
|
||||||
|
|
||||||
BufferHolder.InsertBufferBarrier(
|
|
||||||
gd,
|
|
||||||
cbs.CommandBuffer,
|
|
||||||
dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value,
|
|
||||||
AccessFlags.TransferWriteBit,
|
|
||||||
AccessFlags.TransferReadBit,
|
|
||||||
PipelineStageFlags.TransferBit,
|
|
||||||
PipelineStageFlags.TransferBit,
|
|
||||||
0,
|
|
||||||
dstSize);
|
|
||||||
|
|
||||||
dst.Storage.CopyFromOrToBuffer(
|
|
||||||
cbs.CommandBuffer,
|
|
||||||
dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value,
|
|
||||||
dst.GetImage().Get(cbs).Value,
|
|
||||||
dstSize,
|
|
||||||
to: false,
|
|
||||||
drBaseX,
|
|
||||||
drBaseY,
|
|
||||||
dst.FirstLayer,
|
|
||||||
dst.FirstLevel,
|
|
||||||
1,
|
|
||||||
levels,
|
|
||||||
true,
|
|
||||||
aspectFlags,
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
|
|
||||||
SlowBlit(d32SrcStorage, d32DstStorage, ImageAspectFlags.DepthBit);
|
|
||||||
SlowBlit(s8SrcStorage, s8DstStorage, ImageAspectFlags.StencilBit);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static unsafe void InsertImageBarrier(
|
public static unsafe void InsertImageBarrier(
|
||||||
Vk api,
|
Vk api,
|
||||||
CommandBuffer commandBuffer,
|
CommandBuffer commandBuffer,
|
||||||
@@ -649,13 +458,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
memoryBarrier);
|
memoryBarrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool SupportsBlitFromD32FS8ToD32FAndS8()
|
|
||||||
{
|
|
||||||
var formatFeatureFlags = FormatFeatureFlags.BlitSrcBit | FormatFeatureFlags.BlitDstBit;
|
|
||||||
return _gd.FormatCapabilities.OptimalFormatSupports(formatFeatureFlags, GAL.Format.D32Float) &&
|
|
||||||
_gd.FormatCapabilities.OptimalFormatSupports(formatFeatureFlags, GAL.Format.S8Uint);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextureView GetView(GAL.Format format)
|
public TextureView GetView(GAL.Format format)
|
||||||
{
|
{
|
||||||
if (format == Info.Format)
|
if (format == Info.Format)
|
||||||
@@ -695,7 +497,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return CreateViewImpl(info, firstLayer, firstLevel);
|
return CreateViewImpl(info, firstLayer, firstLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TextureView CreateViewImpl(TextureCreateInfo info, int firstLayer, int firstLevel)
|
public TextureView CreateViewImpl(TextureCreateInfo info, int firstLayer, int firstLevel)
|
||||||
{
|
{
|
||||||
return new TextureView(_gd, _device, info, Storage, FirstLayer + firstLayer, FirstLevel + firstLevel);
|
return new TextureView(_gd, _device, info, Storage, FirstLayer + firstLayer, FirstLevel + firstLevel);
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
"VK_EXT_fragment_shader_interlock",
|
"VK_EXT_fragment_shader_interlock",
|
||||||
"VK_EXT_index_type_uint8",
|
"VK_EXT_index_type_uint8",
|
||||||
"VK_EXT_robustness2",
|
"VK_EXT_robustness2",
|
||||||
|
"VK_EXT_shader_stencil_export",
|
||||||
"VK_KHR_shader_float16_int8",
|
"VK_KHR_shader_float16_int8",
|
||||||
"VK_EXT_shader_subgroup_ballot",
|
"VK_EXT_shader_subgroup_ballot",
|
||||||
"VK_EXT_subgroup_size_control",
|
"VK_EXT_subgroup_size_control",
|
||||||
|
@@ -263,6 +263,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
supportedExtensions.Contains("VK_NV_geometry_shader_passthrough"),
|
supportedExtensions.Contains("VK_NV_geometry_shader_passthrough"),
|
||||||
supportedExtensions.Contains("VK_EXT_subgroup_size_control"),
|
supportedExtensions.Contains("VK_EXT_subgroup_size_control"),
|
||||||
featuresShaderInt8.ShaderInt8,
|
featuresShaderInt8.ShaderInt8,
|
||||||
|
supportedExtensions.Contains("VK_EXT_shader_stencil_export"),
|
||||||
supportedExtensions.Contains(ExtConditionalRendering.ExtensionName),
|
supportedExtensions.Contains(ExtConditionalRendering.ExtensionName),
|
||||||
supportedExtensions.Contains(ExtExtendedDynamicState.ExtensionName),
|
supportedExtensions.Contains(ExtExtendedDynamicState.ExtensionName),
|
||||||
features2.Features.MultiViewport,
|
features2.Features.MultiViewport,
|
||||||
|
@@ -335,14 +335,16 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
int dstY0 = crop.FlipY ? dstPaddingY : _height - dstPaddingY;
|
int dstY0 = crop.FlipY ? dstPaddingY : _height - dstPaddingY;
|
||||||
int dstY1 = crop.FlipY ? _height - dstPaddingY : dstPaddingY;
|
int dstY1 = crop.FlipY ? _height - dstPaddingY : dstPaddingY;
|
||||||
|
|
||||||
_gd.HelperShader.Blit(
|
_gd.HelperShader.BlitColor(
|
||||||
_gd,
|
_gd,
|
||||||
cbs,
|
cbs,
|
||||||
view,
|
view,
|
||||||
_swapchainImageViews[nextImage],
|
_swapchainImageViews[nextImage],
|
||||||
_width,
|
_width,
|
||||||
_height,
|
_height,
|
||||||
|
1,
|
||||||
_format,
|
_format,
|
||||||
|
false,
|
||||||
new Extents2D(srcX0, srcY0, srcX1, srcY1),
|
new Extents2D(srcX0, srcY0, srcX1, srcY1),
|
||||||
new Extents2D(dstX0, dstY1, dstX1, dstY0),
|
new Extents2D(dstX0, dstY1, dstX1, dstY0),
|
||||||
true,
|
true,
|
||||||
|
@@ -229,7 +229,7 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
string ncaId = BitConverter.ToString(cnmt.ContentEntries[0].NcaId).Replace("-", "").ToLower();
|
string ncaId = Convert.ToHexString(cnmt.ContentEntries[0].NcaId).ToLower();
|
||||||
|
|
||||||
AddAocItem(cnmt.TitleId, containerPath, $"{ncaId}.nca", true);
|
AddAocItem(cnmt.TitleId, containerPath, $"{ncaId}.nca", true);
|
||||||
}
|
}
|
||||||
|
@@ -696,8 +696,8 @@ namespace Ryujinx.HLE.HOS
|
|||||||
|
|
||||||
var buildIds = programs.Select(p => p switch
|
var buildIds = programs.Select(p => p switch
|
||||||
{
|
{
|
||||||
NsoExecutable nso => BitConverter.ToString(nso.BuildId.ItemsRo.ToArray()).Replace("-", "").TrimEnd('0'),
|
NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()).TrimEnd('0'),
|
||||||
NroExecutable nro => BitConverter.ToString(nro.Header.BuildId).Replace("-", "").TrimEnd('0'),
|
NroExecutable nro => Convert.ToHexString(nro.Header.BuildId).TrimEnd('0'),
|
||||||
_ => string.Empty
|
_ => string.Empty
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
|
@@ -51,11 +51,11 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
|
|||||||
|
|
||||||
var payload = new JwtPayload
|
var payload = new JwtPayload
|
||||||
{
|
{
|
||||||
{ "sub", BitConverter.ToString(rawUserId).Replace("-", "").ToLower() },
|
{ "sub", Convert.ToHexString(rawUserId).ToLower() },
|
||||||
{ "aud", "ed9e2f05d286f7b8" },
|
{ "aud", "ed9e2f05d286f7b8" },
|
||||||
{ "di", BitConverter.ToString(deviceId).Replace("-", "").ToLower() },
|
{ "di", Convert.ToHexString(deviceId).ToLower() },
|
||||||
{ "sn", "XAW10000000000" },
|
{ "sn", "XAW10000000000" },
|
||||||
{ "bs:did", BitConverter.ToString(deviceAccountId).Replace("-", "").ToLower() },
|
{ "bs:did", Convert.ToHexString(deviceAccountId).ToLower() },
|
||||||
{ "iss", "https://e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com" },
|
{ "iss", "https://e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com" },
|
||||||
{ "typ", "id_token" },
|
{ "typ", "id_token" },
|
||||||
{ "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
|
{ "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
|
||||||
|
@@ -101,7 +101,7 @@ namespace Ryujinx.HLE.HOS.Services.Caps
|
|||||||
};
|
};
|
||||||
|
|
||||||
// NOTE: The hex hash is a HMAC-SHA256 (first 32 bytes) using a hardcoded secret key over the titleId, we can simulate it by hashing the titleId instead.
|
// NOTE: The hex hash is a HMAC-SHA256 (first 32 bytes) using a hardcoded secret key over the titleId, we can simulate it by hashing the titleId instead.
|
||||||
string hash = BitConverter.ToString(SHA256.HashData(BitConverter.GetBytes(titleId))).Replace("-", "").Remove(0x20);
|
string hash = Convert.ToHexString(SHA256.HashData(BitConverter.GetBytes(titleId))).Remove(0x20);
|
||||||
string folderPath = Path.Combine(_sdCardPath, "Nintendo", "Album", currentDateTime.Year.ToString("00"), currentDateTime.Month.ToString("00"), currentDateTime.Day.ToString("00"));
|
string folderPath = Path.Combine(_sdCardPath, "Nintendo", "Album", currentDateTime.Year.ToString("00"), currentDateTime.Month.ToString("00"), currentDateTime.Day.ToString("00"));
|
||||||
string filePath = GenerateFilePath(folderPath, applicationAlbumEntry, currentDateTime, hash);
|
string filePath = GenerateFilePath(folderPath, applicationAlbumEntry, currentDateTime, hash);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user