Compare commits

...

8 Commits

Author SHA1 Message Date
gdkchan
3be616207d Vulkan: Fix swapchain image view leak (#6509) 2024-04-06 13:38:52 -03:00
gdkchan
791bf22109 Vulkan: Skip draws when patches topology is used without a tessellation shader (#6508) 2024-04-06 13:25:51 -03:00
dependabot[bot]
66b1d59c66 nuget: bump DynamicData from 8.3.27 to 8.4.1 (#6536)
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 8.3.27 to 8.4.1.
- [Release notes](https://github.com/reactiveui/DynamicData/releases)
- [Changelog](https://github.com/reactivemarbles/DynamicData/blob/main/ReleaseNotes.md)
- [Commits](https://github.com/reactiveui/DynamicData/compare/8.3.27...8.4.1)

---
updated-dependencies:
- dependency-name: DynamicData
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-06 14:07:06 +02:00
WilliamWsyHK
c8bb05633e Add mod enablement status in the log message (#6571) 2024-04-06 13:47:01 +02:00
czcx
fb1171a21e Update README.md (#6575) 2024-04-06 13:45:24 +02:00
Marco Carvalho
22c0aa9c90 "Task.Wait()" synchronously blocks, use "await" instead (#6598) 2024-04-06 13:36:18 +02:00
Ac_K
6d28b64312 ts: Migrate service to Horizon project (#6514)
* ts: Migrate service to Horizon project

This PR migrate the `ts` service (stored in `ptm`) to the Horizon project:
- It stubs all known IPCs.
- IpcServer consts are checked by RE.

Closes #6480

* Fix args
2024-04-05 15:45:43 -03:00
gdkchan
05c041feeb Ignore diacritics on game search (#6602) 2024-04-05 15:26:45 -03:00
20 changed files with 259 additions and 68 deletions

View File

@@ -13,7 +13,7 @@
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="Concentus" Version="1.1.7" />
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageVersion Include="DynamicData" Version="8.3.27" />
<PackageVersion Include="DynamicData" Version="8.4.1" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />

View File

@@ -33,8 +33,3 @@ Project Docs
=================
To be added. Many project files will contain basic XML docs for key functions and classes in the meantime.
Other Information
=================
- N/A

View File

@@ -981,6 +981,7 @@ namespace Ryujinx.Graphics.Vulkan
_bindingBarriersDirty = true;
_newState.PipelineLayout = internalProgram.PipelineLayout;
_newState.HasTessellationControlShader = internalProgram.HasTessellationControlShader;
_newState.StagesCount = (uint)stages.Length;
stages.CopyTo(_newState.Stages.AsSpan()[..stages.Length]);

View File

@@ -311,6 +311,7 @@ namespace Ryujinx.Graphics.Vulkan
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
}
public bool HasTessellationControlShader;
public NativeArray<PipelineShaderStageCreateInfo> Stages;
public PipelineLayout PipelineLayout;
public SpecData SpecializationData;
@@ -319,6 +320,7 @@ namespace Ryujinx.Graphics.Vulkan
public void Initialize()
{
HasTessellationControlShader = false;
Stages = new NativeArray<PipelineShaderStageCreateInfo>(Constants.MaxShaderStages);
AdvancedBlendSrcPreMultiplied = true;
@@ -419,6 +421,15 @@ namespace Ryujinx.Graphics.Vulkan
PVertexBindingDescriptions = pVertexBindingDescriptions,
};
// Using patches topology without a tessellation shader is invalid.
// If we find such a case, return null pipeline to skip the draw.
if (Topology == PrimitiveTopology.PatchList && !HasTessellationControlShader)
{
program.AddGraphicsPipeline(ref Internal, null);
return null;
}
bool primitiveRestartEnable = PrimitiveRestartEnable;
bool topologySupportsRestart;

View File

@@ -122,7 +122,6 @@ namespace Ryujinx.Graphics.Vulkan
gd.Api.CreateRenderPass(device, renderPassCreateInfo, null, out var renderPass).ThrowOnError();
_renderPass?.Dispose();
_renderPass = new Auto<DisposableRenderPass>(new DisposableRenderPass(gd.Api, device, renderPass));
}
@@ -162,7 +161,7 @@ namespace Ryujinx.Graphics.Vulkan
public void Dispose()
{
// Dispose all framebuffers
// Dispose all framebuffers.
foreach (var fb in _framebuffers.Values)
{
@@ -175,6 +174,10 @@ namespace Ryujinx.Graphics.Vulkan
{
texture.RemoveRenderPass(_key);
}
// Dispose render pass.
_renderPass.Dispose();
}
}
}

View File

@@ -21,6 +21,7 @@ namespace Ryujinx.Graphics.Vulkan
public bool HasMinimalLayout { get; }
public bool UsePushDescriptors { get; }
public bool IsCompute { get; }
public bool HasTessellationControlShader => (Stages & (1u << 3)) != 0;
public uint Stages { get; }
@@ -461,6 +462,7 @@ namespace Ryujinx.Graphics.Vulkan
stages[i] = _shaders[i].GetInfo();
}
pipeline.HasTessellationControlShader = HasTessellationControlShader;
pipeline.StagesCount = (uint)_shaders.Length;
pipeline.PipelineLayout = PipelineLayout;

View File

@@ -4,6 +4,7 @@ using Silk.NET.Vulkan;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Format = Ryujinx.Graphics.GAL.Format;
using VkBuffer = Silk.NET.Vulkan.Buffer;
using VkFormat = Silk.NET.Vulkan.Format;
@@ -36,7 +37,8 @@ namespace Ryujinx.Graphics.Vulkan
public int FirstLayer { get; }
public int FirstLevel { get; }
public VkFormat VkFormat { get; }
public bool Valid { get; private set; }
private int _isValid;
public bool Valid => Volatile.Read(ref _isValid) != 0;
public TextureView(
VulkanRenderer gd,
@@ -158,7 +160,7 @@ namespace Ryujinx.Graphics.Vulkan
}
}
Valid = true;
_isValid = 1;
}
/// <summary>
@@ -178,7 +180,7 @@ namespace Ryujinx.Graphics.Vulkan
VkFormat = format;
Valid = true;
_isValid = 1;
}
public Auto<DisposableImage> GetImage()
@@ -1017,10 +1019,11 @@ namespace Ryujinx.Graphics.Vulkan
{
if (disposing)
{
Valid = false;
if (_gd.Textures.Remove(this))
bool wasValid = Interlocked.Exchange(ref _isValid, 0) != 0;
if (wasValid)
{
_gd.Textures.Remove(this);
_imageView.Dispose();
_imageView2dArray?.Dispose();
@@ -1034,7 +1037,7 @@ namespace Ryujinx.Graphics.Vulkan
_imageViewDraw.Dispose();
}
Storage.DecrementViewsCount();
Storage?.DecrementViewsCount();
if (_renderPasses != null)
{
@@ -1045,22 +1048,22 @@ namespace Ryujinx.Graphics.Vulkan
pass.Dispose();
}
}
if (_selfManagedViews != null)
{
foreach (var view in _selfManagedViews.Values)
{
view.Dispose();
}
_selfManagedViews = null;
}
}
}
}
public void Dispose()
{
if (_selfManagedViews != null)
{
foreach (var view in _selfManagedViews.Values)
{
view.Dispose();
}
_selfManagedViews = null;
}
Dispose(true);
}

View File

@@ -218,7 +218,7 @@ namespace Ryujinx.HLE.HOS
if (types.Length > 0)
{
Logger.Info?.Print(LogClass.ModLoader, $"Found mod '{mod.Name}' [{types}]");
Logger.Info?.Print(LogClass.ModLoader, $"Found {(mod.Enabled ? "enabled" : "disabled")} mod '{mod.Name}' [{types}]");
}
}
}

View File

@@ -1,39 +0,0 @@
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Ptm.Ts.Types;
namespace Ryujinx.HLE.HOS.Services.Ptm.Ts
{
[Service("ts")]
class IMeasurementServer : IpcService
{
private const uint DefaultTemperature = 42u;
public IMeasurementServer(ServiceCtx context) { }
[CommandCmif(1)]
// GetTemperature(Location location) -> u32
public ResultCode GetTemperature(ServiceCtx context)
{
Location location = (Location)context.RequestData.ReadByte();
Logger.Stub?.PrintStub(LogClass.ServicePtm, new { location });
context.ResponseData.Write(DefaultTemperature);
return ResultCode.Success;
}
[CommandCmif(3)]
// GetTemperatureMilliC(Location location) -> u32
public ResultCode GetTemperatureMilliC(ServiceCtx context)
{
Location location = (Location)context.RequestData.ReadByte();
Logger.Stub?.PrintStub(LogClass.ServicePtm, new { location });
context.ResponseData.Write(DefaultTemperature * 1000);
return ResultCode.Success;
}
}
}

View File

@@ -0,0 +1,63 @@
using Ryujinx.Common.Logging;
using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Sdk.Sf;
using Ryujinx.Horizon.Sdk.Ts;
using Ryujinx.Horizon.Ts.Ipc;
namespace Ryujinx.Horizon.Ptm.Ipc
{
partial class MeasurementServer : IMeasurementServer
{
// NOTE: Values are randomly choosen.
public const int DefaultTemperature = 42;
public const int MinimumTemperature = 0;
public const int MaximumTemperature = 100;
[CmifCommand(0)] // 1.0.0-16.1.0
public Result GetTemperatureRange(out int minimumTemperature, out int maximumTemperature, Location location)
{
Logger.Stub?.PrintStub(LogClass.ServicePtm, new { location });
minimumTemperature = MinimumTemperature;
maximumTemperature = MaximumTemperature;
return Result.Success;
}
[CmifCommand(1)] // 1.0.0-16.1.0
public Result GetTemperature(out int temperature, Location location)
{
Logger.Stub?.PrintStub(LogClass.ServicePtm, new { location });
temperature = DefaultTemperature;
return Result.Success;
}
[CmifCommand(2)] // 1.0.0-13.2.1
public Result SetMeasurementMode(Location location, byte measurementMode)
{
Logger.Stub?.PrintStub(LogClass.ServicePtm, new { location, measurementMode });
return Result.Success;
}
[CmifCommand(3)] // 1.0.0-13.2.1
public Result GetTemperatureMilliC(out int temperatureMilliC, Location location)
{
Logger.Stub?.PrintStub(LogClass.ServicePtm, new { location });
temperatureMilliC = DefaultTemperature * 1000;
return Result.Success;
}
[CmifCommand(4)] // 8.0.0+
public Result OpenSession(out ISession session, DeviceCode deviceCode)
{
session = new Session(deviceCode);
return Result.Success;
}
}
}

View File

@@ -0,0 +1,47 @@
using Ryujinx.Common.Logging;
using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Ptm.Ipc;
using Ryujinx.Horizon.Sdk.Sf;
using Ryujinx.Horizon.Sdk.Ts;
namespace Ryujinx.Horizon.Ts.Ipc
{
partial class Session : ISession
{
private readonly DeviceCode _deviceCode;
public Session(DeviceCode deviceCode)
{
_deviceCode = deviceCode;
}
[CmifCommand(0)]
public Result GetTemperatureRange(out int minimumTemperature, out int maximumTemperature)
{
Logger.Stub?.PrintStub(LogClass.ServicePtm, new { _deviceCode });
minimumTemperature = MeasurementServer.MinimumTemperature;
maximumTemperature = MeasurementServer.MaximumTemperature;
return Result.Success;
}
[CmifCommand(2)]
public Result SetMeasurementMode(byte measurementMode)
{
Logger.Stub?.PrintStub(LogClass.ServicePtm, new { _deviceCode, measurementMode });
return Result.Success;
}
[CmifCommand(4)]
public Result GetTemperature(out int temperature)
{
Logger.Stub?.PrintStub(LogClass.ServicePtm, new { _deviceCode });
temperature = MeasurementServer.DefaultTemperature;
return Result.Success;
}
}
}

View File

@@ -0,0 +1,44 @@
using Ryujinx.Horizon.Ptm.Ipc;
using Ryujinx.Horizon.Sdk.Sf.Hipc;
using Ryujinx.Horizon.Sdk.Sm;
namespace Ryujinx.Horizon.Ptm
{
class TsIpcServer
{
private const int MaxSessionsCount = 4;
private const int PointerBufferSize = 0;
private const int MaxDomains = 0;
private const int MaxDomainObjects = 0;
private const int MaxPortsCount = 1;
private static readonly ManagerOptions _managerOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
private SmApi _sm;
private ServerManager _serverManager;
public void Initialize()
{
HeapAllocator allocator = new();
_sm = new SmApi();
_sm.Initialize().AbortOnFailure();
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _managerOptions, MaxSessionsCount);
_serverManager.RegisterObjectForServer(new MeasurementServer(), ServiceName.Encode("ts"), MaxSessionsCount);
}
public void ServiceRequests()
{
_serverManager.ServiceRequests();
}
public void Shutdown()
{
_serverManager.Dispose();
_sm.Dispose();
}
}
}

View File

@@ -0,0 +1,17 @@
namespace Ryujinx.Horizon.Ptm
{
class TsMain : IService
{
public static void Main(ServiceTable serviceTable)
{
TsIpcServer ipcServer = new();
ipcServer.Initialize();
serviceTable.SignalServiceReady();
ipcServer.ServiceRequests();
ipcServer.Shutdown();
}
}
}

View File

@@ -0,0 +1,8 @@
namespace Ryujinx.Horizon.Sdk.Ts
{
enum DeviceCode : uint
{
Internal = 0x41000001,
External = 0x41000002,
}
}

View File

@@ -0,0 +1,14 @@
using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Ts
{
interface IMeasurementServer : IServiceObject
{
Result GetTemperatureRange(out int minimumTemperature, out int maximumTemperature, Location location);
Result GetTemperature(out int temperature, Location location);
Result SetMeasurementMode(Location location, byte measurementMode);
Result GetTemperatureMilliC(out int temperatureMilliC, Location location);
Result OpenSession(out ISession session, DeviceCode deviceCode);
}
}

View File

@@ -0,0 +1,12 @@
using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Ts
{
interface ISession : IServiceObject
{
Result GetTemperatureRange(out int minimumTemperature, out int maximumTemperature);
Result GetTemperature(out int temperature);
Result SetMeasurementMode(byte measurementMode);
}
}

View File

@@ -1,4 +1,4 @@
namespace Ryujinx.HLE.HOS.Services.Ptm.Ts.Types
namespace Ryujinx.Horizon.Sdk.Ts
{
enum Location : byte
{

View File

@@ -11,6 +11,7 @@ using Ryujinx.Horizon.Ngc;
using Ryujinx.Horizon.Ovln;
using Ryujinx.Horizon.Prepo;
using Ryujinx.Horizon.Psc;
using Ryujinx.Horizon.Ptm;
using Ryujinx.Horizon.Sdk.Arp;
using Ryujinx.Horizon.Srepo;
using Ryujinx.Horizon.Usb;
@@ -54,6 +55,7 @@ namespace Ryujinx.Horizon
RegisterService<PrepoMain>();
RegisterService<PscMain>();
RegisterService<SrepoMain>();
RegisterService<TsMain>();
RegisterService<UsbMain>();
RegisterService<WlanMain>();

View File

@@ -36,6 +36,7 @@ using SixLabors.ImageSharp.PixelFormats;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -980,7 +981,14 @@ namespace Ryujinx.Ava.UI.ViewModels
{
if (arg is ApplicationData app)
{
return string.IsNullOrWhiteSpace(_searchText) || app.TitleName.ToLower().Contains(_searchText.ToLower());
if (string.IsNullOrWhiteSpace(_searchText))
{
return true;
}
CompareInfo compareInfo = CultureInfo.CurrentCulture.CompareInfo;
return compareInfo.IndexOf(app.TitleName, _searchText, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) >= 0;
}
return false;

View File

@@ -285,7 +285,7 @@ namespace Ryujinx.Ava.UI.Windows
{
_deferLoad = false;
ViewModel.LoadApplication(_launchPath, _startFullscreen).Wait();
await ViewModel.LoadApplication(_launchPath, _startFullscreen);
}
}
else