Compare commits

...

8 Commits

Author SHA1 Message Date
gdkchan
7d158acc3b
Do not try to create a texture pool if shader does not use textures (#7379) 2024-09-30 11:41:07 -03:00
e2dk4r
5dbba07e33
sdl: set app name (#7370)
Ryujinx was not hinting application name, so on some platforms (e.g.
Linux) volume control shows Ryujinx as 'SDL Application'. This can cause
confusion.

This commit fixes name in volume control applets on some platforms.

see: https://wiki.libsdl.org/SDL2/SDL_HINT_APP_NAME
2024-09-28 10:44:23 +02:00
MaxLastBreath
d86249cb0a
Convert MaxTextureCacheCapacity to Dynamic MaxTextureCacheCapacity for High Resolution Mod support. (#7307)
* Add Texture Size Capacity and 8GB Dram Build

* Update AutoDeleteCache.cs

* Dynamic Texture Cache (WIP)

* Change to float Multiplier, in-case it needs fine-tuning.

* Delete src/src.sln

* Update AutoDeleteCache.cs

* Format

* Fix Formatting

* Add DefaultTextureSizeCapacity and MemoryScaleFactor

- Also remove redundant New Lines

* Fix 4GB dram crashing

* Format newline

* Refractor

- Added Initialize() function to TextureCache and AutoDeleteCache
- Removed GetMaxTextureCapacity() function and instead added _maxCacheMemoryUsage
- Added private const MaxTextureSizeCapacity to AutoDelete Cache
- Added TextureCache.Initialize() to MemoryManager in order to fetch MaxGpuMemory at the right time.
- Moved and Changed Logger.Info for Gpu Memory to Logger.Notice and Moved it to PrintGpuInformation function.
- Opted to use a ternary operator for the Initialize function, I think it looks cleaner than bunch of if statements.

* Update src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* maxMemory to CacheMemory, use Clamp instead of Ternary. Changed MinTextureCapacity 1GiB to 512 MiB

* Update src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Format comment

* comment context

* Increase TextureSize capacity for OpenGL back to 1024

- Added a new const ulong for OpenGLTextureSizeCapacity

* Fix changes from last commit.

* Adjust last OpenGL changes.

* Remove garbage VSC file

* Update src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2024-09-26 14:33:38 -03:00
riperiperi
04d68ca616
GPU: Ensure all clip distances are initialized when used (#7363)
* GPU: Ensure all clip distances are initialized when used

* Shader cache version
2024-09-26 14:19:12 -03:00
Jason Youngberg
050f22977f
Update bug_report.yml to provide better instructions for finding log file (#7333) 2024-09-24 11:10:36 +02:00
gdkchan
319507f2a1
Fix quads draws after DrawTexture on Vulkan (#7336) 2024-09-22 19:36:53 -03:00
gdkchan
d717aef2be
Shader: Assume the only remaining source is the right one when all others are undefined (#7331)
* Shader: Assume the only remaining source is the right one when all other are undefined

* Shader cache version bump

* Improve comment
2024-09-19 21:23:09 -03:00
gdkchan
24ee8c39f1
Add support for sampler sRGB disable (#7312) 2024-09-19 14:38:30 -03:00
17 changed files with 152 additions and 20 deletions

View File

@ -23,7 +23,7 @@ body:
attributes:
label: Log file
description: A log file will help our developers to better diagnose and fix the issue.
placeholder: Logs files can be found under "Logs" folder in Ryujinx program folder. You can drag and drop the log on to the text area
placeholder: Logs files can be found under "Logs" folder in Ryujinx program folder. They can also be accessed by opening Ryujinx, then going to File > Open Logs Folder. You can drag and drop the log on to the text area (do not copy paste).
validations:
required: true
- type: input
@ -83,4 +83,4 @@ body:
- Additional info about your environment:
- Any other information relevant to your issue.
validations:
required: false
required: false

View File

@ -71,6 +71,8 @@ namespace Ryujinx.Graphics.GAL
public readonly int GatherBiasPrecision;
public readonly ulong MaximumGpuMemory;
public Capabilities(
TargetApi api,
string vendorName,
@ -131,7 +133,8 @@ namespace Ryujinx.Graphics.GAL
int shaderSubgroupSize,
int storageBufferOffsetAlignment,
int textureBufferOffsetAlignment,
int gatherBiasPrecision)
int gatherBiasPrecision,
ulong maximumGpuMemory)
{
Api = api;
VendorName = vendorName;
@ -193,6 +196,7 @@ namespace Ryujinx.Graphics.GAL
StorageBufferOffsetAlignment = storageBufferOffsetAlignment;
TextureBufferOffsetAlignment = textureBufferOffsetAlignment;
GatherBiasPrecision = gatherBiasPrecision;
MaximumGpuMemory = maximumGpuMemory;
}
}
}

View File

@ -1,3 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
@ -46,7 +47,11 @@ namespace Ryujinx.Graphics.Gpu.Image
{
private const int MinCountForDeletion = 32;
private const int MaxCapacity = 2048;
private const ulong MaxTextureSizeCapacity = 1024 * 1024 * 1024; // MB;
private const ulong MinTextureSizeCapacity = 512 * 1024 * 1024;
private const ulong MaxTextureSizeCapacity = 4UL * 1024 * 1024 * 1024;
private const ulong DefaultTextureSizeCapacity = 1UL * 1024 * 1024 * 1024;
private const float MemoryScaleFactor = 0.50f;
private ulong _maxCacheMemoryUsage = 0;
private readonly LinkedList<Texture> _textures;
private ulong _totalSize;
@ -56,6 +61,25 @@ namespace Ryujinx.Graphics.Gpu.Image
private readonly Dictionary<TextureDescriptor, ShortTextureCacheEntry> _shortCacheLookup;
/// <summary>
/// Initializes the cache, setting the maximum texture capacity for the specified GPU context.
/// </summary>
/// <remarks>
/// If the backend GPU has 0 memory capacity, the cache size defaults to `DefaultTextureSizeCapacity`.
/// </remarks>
/// <param name="context">The GPU context that the cache belongs to</param>
public void Initialize(GpuContext context)
{
var cacheMemory = (ulong)(context.Capabilities.MaximumGpuMemory * MemoryScaleFactor);
_maxCacheMemoryUsage = Math.Clamp(cacheMemory, MinTextureSizeCapacity, MaxTextureSizeCapacity);
if (context.Capabilities.MaximumGpuMemory == 0)
{
_maxCacheMemoryUsage = DefaultTextureSizeCapacity;
}
}
/// <summary>
/// Creates a new instance of the automatic deletion cache.
/// </summary>
@ -85,7 +109,7 @@ namespace Ryujinx.Graphics.Gpu.Image
texture.CacheNode = _textures.AddLast(texture);
if (_textures.Count > MaxCapacity ||
(_totalSize > MaxTextureSizeCapacity && _textures.Count >= MinCountForDeletion))
(_totalSize > _maxCacheMemoryUsage && _textures.Count >= MinCountForDeletion))
{
RemoveLeastUsedTexture();
}
@ -110,7 +134,7 @@ namespace Ryujinx.Graphics.Gpu.Image
_textures.AddLast(texture.CacheNode);
}
if (_totalSize > MaxTextureSizeCapacity && _textures.Count >= MinCountForDeletion)
if (_totalSize > _maxCacheMemoryUsage && _textures.Count >= MinCountForDeletion)
{
RemoveLeastUsedTexture();
}

View File

@ -13,6 +13,11 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary>
public bool IsDisposed { get; private set; }
/// <summary>
/// True if the sampler has sRGB conversion enabled, false otherwise.
/// </summary>
public bool IsSrgb { get; }
/// <summary>
/// Host sampler object.
/// </summary>
@ -30,6 +35,8 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="descriptor">The Maxwell sampler descriptor</param>
public Sampler(GpuContext context, SamplerDescriptor descriptor)
{
IsSrgb = descriptor.UnpackSrgb();
MinFilter minFilter = descriptor.UnpackMinFilter();
MagFilter magFilter = descriptor.UnpackMagFilter();

View File

@ -113,6 +113,15 @@ namespace Ryujinx.Graphics.Gpu.Image
return (CompareOp)(((Word0 >> 10) & 7) + 1);
}
/// <summary>
/// Unpacks the sampler sRGB format flag.
/// </summary>
/// <returns>True if the has sampler is sRGB conversion enabled, false otherwise</returns>
public readonly bool UnpackSrgb()
{
return (Word0 & (1 << 13)) != 0;
}
/// <summary>
/// Unpacks and converts the maximum anisotropy value used for texture anisotropic filtering.
/// </summary>

View File

@ -187,7 +187,9 @@ namespace Ryujinx.Graphics.Gpu.Image
{
(TexturePool texturePool, SamplerPool samplerPool) = GetPools();
return (texturePool.Get(textureId), samplerPool.Get(samplerId));
Sampler sampler = samplerPool?.Get(samplerId);
return (texturePool.Get(textureId, sampler?.IsSrgb ?? true), sampler);
}
/// <summary>
@ -508,12 +510,12 @@ namespace Ryujinx.Graphics.Gpu.Image
state.TextureHandle = textureId;
state.SamplerHandle = samplerId;
ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, out Texture texture);
Sampler sampler = samplerPool?.Get(samplerId);
ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, sampler?.IsSrgb ?? true, out Texture texture);
specStateMatches &= specState.MatchesTexture(stage, index, descriptor);
Sampler sampler = samplerPool?.Get(samplerId);
ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
ISampler hostSampler = sampler?.GetHostSampler(texture);

View File

@ -68,6 +68,14 @@ namespace Ryujinx.Graphics.Gpu.Image
_cache = new AutoDeleteCache();
}
/// <summary>
/// Initializes the cache, setting the maximum texture capacity for the specified GPU context.
/// </summary>
public void Initialize()
{
_cache.Initialize(_context);
}
/// <summary>
/// Handles marking of textures written to a memory region being (partially) remapped.
/// </summary>

View File

@ -227,6 +227,17 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="id">ID of the texture. This is effectively a zero-based index</param>
/// <returns>The texture with the given ID</returns>
public override Texture Get(int id)
{
return Get(id, srgbSampler: true);
}
/// <summary>
/// Gets the texture with the given ID.
/// </summary>
/// <param name="id">ID of the texture. This is effectively a zero-based index</param>
/// <param name="srgbSampler">Whether the texture is being accessed with a sampler that has sRGB conversion enabled</param>
/// <returns>The texture with the given ID</returns>
public Texture Get(int id, bool srgbSampler)
{
if ((uint)id >= Items.Length)
{
@ -240,7 +251,7 @@ namespace Ryujinx.Graphics.Gpu.Image
SynchronizeMemory();
}
GetInternal(id, out Texture texture);
GetForBinding(id, srgbSampler, out Texture texture);
return texture;
}
@ -252,9 +263,10 @@ namespace Ryujinx.Graphics.Gpu.Image
/// This method assumes that the pool has been manually synchronized before doing binding.
/// </remarks>
/// <param name="id">ID of the texture. This is effectively a zero-based index</param>
/// <param name="srgbSampler">Whether the texture is being accessed with a sampler that has sRGB conversion enabled</param>
/// <param name="texture">The texture with the given ID</param>
/// <returns>The texture descriptor with the given ID</returns>
public ref readonly TextureDescriptor GetForBinding(int id, out Texture texture)
public ref readonly TextureDescriptor GetForBinding(int id, bool srgbSampler, out Texture texture)
{
if ((uint)id >= Items.Length)
{
@ -264,6 +276,18 @@ namespace Ryujinx.Graphics.Gpu.Image
// When getting for binding, assume the pool has already been synchronized.
if (!srgbSampler)
{
// If the sampler does not have the sRGB bit enabled, then the texture can't use a sRGB format.
ref readonly TextureDescriptor tempDescriptor = ref GetDescriptorRef(id);
if (tempDescriptor.UnpackSrgb() && FormatTable.TryGetTextureFormat(tempDescriptor.UnpackFormat(), isSrgb: false, out FormatInfo formatInfo))
{
// Get a view of the texture with the right format.
return ref GetForBinding(id, formatInfo, out texture);
}
}
return ref GetInternal(id, out texture);
}

View File

@ -1,4 +1,5 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Gpu.Image;
using Ryujinx.Memory;
using Ryujinx.Memory.Range;
using System;
@ -64,6 +65,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
MemoryUnmapped += Physical.BufferCache.MemoryUnmappedHandler;
MemoryUnmapped += VirtualRangeCache.MemoryUnmappedHandler;
MemoryUnmapped += CounterCache.MemoryUnmappedHandler;
Physical.TextureCache.Initialize();
}
/// <summary>

View File

@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
private const uint CodeGenVersion = 7320;
private const uint CodeGenVersion = 7353;
private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data";

View File

@ -743,7 +743,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
constantBufferUsePerStageMask &= ~(1 << index);
}
if (checkTextures)
if (checkTextures && _allTextures.Length > 0)
{
TexturePool pool = channel.TextureManager.GetTexturePool(poolState.TexturePoolGpuVa, poolState.TexturePoolMaximumId);

View File

@ -202,7 +202,8 @@ namespace Ryujinx.Graphics.OpenGL
shaderSubgroupSize: Constants.MaxSubgroupSize,
storageBufferOffsetAlignment: HwCapabilities.StorageBufferOffsetAlignment,
textureBufferOffsetAlignment: HwCapabilities.TextureBufferOffsetAlignment,
gatherBiasPrecision: intelWindows || amdWindows ? 8 : 0); // Precision is 8 for these vendors on Vulkan.
gatherBiasPrecision: intelWindows || amdWindows ? 8 : 0, // Precision is 8 for these vendors on Vulkan.
maximumGpuMemory: 0);
}
public void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)

View File

@ -138,6 +138,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// Ensure that conditions met for that branch are also met for the current one.
// Prefer the latest sources for the phi node.
int undefCount = 0;
for (int i = phiNode.SourcesCount - 1; i >= 0; i--)
{
BasicBlock phiBlock = phiNode.GetBlock(i);
@ -159,6 +161,26 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
return match;
}
}
else if (phiSource.Type == OperandType.Undefined)
{
undefCount++;
}
}
// If all sources but one are undefined, we can assume that the one
// that is not undefined is the right one.
if (undefCount == phiNode.SourcesCount - 1)
{
for (int i = phiNode.SourcesCount - 1; i >= 0; i--)
{
Operand phiSource = phiNode.GetSource(i);
if (phiSource.Type != OperandType.Undefined)
{
return phiSource;
}
}
}
}

View File

@ -190,7 +190,7 @@ namespace Ryujinx.Graphics.Shader.Translation
if (stage == ShaderStage.Vertex)
{
InitializePositionOutput(context);
InitializeVertexOutputs(context);
}
UInt128 usedAttributes = context.TranslatorContext.AttributeUsage.NextInputAttributesComponents;
@ -236,12 +236,20 @@ namespace Ryujinx.Graphics.Shader.Translation
}
}
private static void InitializePositionOutput(EmitterContext context)
private static void InitializeVertexOutputs(EmitterContext context)
{
for (int c = 0; c < 4; c++)
{
context.Store(StorageKind.Output, IoVariable.Position, null, Const(c), ConstF(c == 3 ? 1f : 0f));
}
if (context.Program.ClipDistancesWritten != 0)
{
for (int i = 0; i < 8; i++)
{
context.Store(StorageKind.Output, IoVariable.ClipDistance, null, Const(i), ConstF(0f));
}
}
}
private static void InitializeOutput(EmitterContext context, int location, bool perPatch)

View File

@ -636,9 +636,9 @@ namespace Ryujinx.Graphics.Vulkan
var oldStencilTestEnable = _newState.StencilTestEnable;
var oldDepthTestEnable = _newState.DepthTestEnable;
var oldDepthWriteEnable = _newState.DepthWriteEnable;
var oldTopology = _newState.Topology;
var oldViewports = DynamicState.Viewports;
var oldViewportsCount = _newState.ViewportsCount;
var oldTopology = _topology;
_newState.CullMode = CullModeFlags.None;
_newState.StencilTestEnable = false;
@ -658,7 +658,7 @@ namespace Ryujinx.Graphics.Vulkan
_newState.StencilTestEnable = oldStencilTestEnable;
_newState.DepthTestEnable = oldDepthTestEnable;
_newState.DepthWriteEnable = oldDepthWriteEnable;
_newState.Topology = oldTopology;
SetPrimitiveTopology(oldTopology);
DynamicState.SetViewports(ref oldViewports, oldViewportsCount);

View File

@ -781,7 +781,26 @@ namespace Ryujinx.Graphics.Vulkan
shaderSubgroupSize: (int)Capabilities.SubgroupSize,
storageBufferOffsetAlignment: (int)limits.MinStorageBufferOffsetAlignment,
textureBufferOffsetAlignment: (int)limits.MinTexelBufferOffsetAlignment,
gatherBiasPrecision: IsIntelWindows || IsAmdWindows ? (int)Capabilities.SubTexelPrecisionBits : 0);
gatherBiasPrecision: IsIntelWindows || IsAmdWindows ? (int)Capabilities.SubTexelPrecisionBits : 0,
maximumGpuMemory: GetTotalGPUMemory());
}
private ulong GetTotalGPUMemory()
{
ulong totalMemory = 0;
Api.GetPhysicalDeviceMemoryProperties(_physicalDevice.PhysicalDevice, out PhysicalDeviceMemoryProperties memoryProperties);
for (int i = 0; i < memoryProperties.MemoryHeapCount; i++)
{
var heap = memoryProperties.MemoryHeaps[i];
if ((heap.Flags & MemoryHeapFlags.DeviceLocalBit) == MemoryHeapFlags.DeviceLocalBit)
{
totalMemory += heap.Size;
}
}
return totalMemory;
}
public HardwareInfo GetHardwareInfo()
@ -865,6 +884,7 @@ namespace Ryujinx.Graphics.Vulkan
private void PrintGpuInformation()
{
Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB");
}
public void Initialize(GraphicsDebugLevel logLevel)

View File

@ -53,6 +53,7 @@ namespace Ryujinx.SDL2.Common
return;
}
SDL_SetHint(SDL_HINT_APP_NAME, "Ryujinx");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");