mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-05-19 19:55:47 +00:00
Compare commits
3 Commits
Canary-1.3
...
Canary-1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7772462f1 | ||
|
|
3473044c6e | ||
|
|
e756ad4556 |
@@ -6107,8 +6107,8 @@
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Enable Net Logs",
|
||||
"es_ES": "Habilitar registros de red.",
|
||||
"fr_FR": "",
|
||||
"es_ES": "Habilitar Registros de Red.",
|
||||
"fr_FR": "Activer les Journaux Réseau.",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
@@ -17108,7 +17108,7 @@
|
||||
"el_GR": "",
|
||||
"en_US": "Prints network log messages in the console.",
|
||||
"es_ES": "Imprimir registros de red en la consola.",
|
||||
"fr_FR": "",
|
||||
"fr_FR": "Affiche les journaux réseau dans la console.",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
||||
|
||||
namespace Ryujinx.Graphics.Vulkan
|
||||
@@ -61,29 +62,65 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
if (_count != 0)
|
||||
{
|
||||
for (int i = 0; i < _count; i++)
|
||||
{
|
||||
_buffers[i] = _bufferAutos[i].Get(cbs, _bufferOffsetsForGet[i], _bufferSizesForGet[i]).Value;
|
||||
_bufferAutos[i] = null;
|
||||
}
|
||||
|
||||
if (_gd.Capabilities.SupportsExtendedDynamicState)
|
||||
{
|
||||
_gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2(
|
||||
cbs.CommandBuffer,
|
||||
_baseBinding,
|
||||
_count,
|
||||
_buffers.Pointer,
|
||||
_offsets.Pointer,
|
||||
_sizes.Pointer,
|
||||
_strides.Pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, _baseBinding, _count, _buffers.Pointer, _offsets.Pointer);
|
||||
}
|
||||
|
||||
int count = (int)_count;
|
||||
uint baseBinding = _baseBinding;
|
||||
_count = 0;
|
||||
|
||||
Auto<DisposableBuffer>[] autos = ArrayPool<Auto<DisposableBuffer>>.Shared.Rent(count);
|
||||
Span<int> getOffsets = stackalloc int[Constants.MaxVertexBuffers];
|
||||
Span<int> getSizes = stackalloc int[Constants.MaxVertexBuffers];
|
||||
Span<ulong> offsets = stackalloc ulong[Constants.MaxVertexBuffers];
|
||||
Span<ulong> sizes = stackalloc ulong[Constants.MaxVertexBuffers];
|
||||
Span<ulong> strides = stackalloc ulong[Constants.MaxVertexBuffers];
|
||||
Span<VkBuffer> buffers = stackalloc VkBuffer[Constants.MaxVertexBuffers];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
autos[i] = _bufferAutos[i];
|
||||
_bufferAutos[i] = null;
|
||||
getOffsets[i] = _bufferOffsetsForGet[i];
|
||||
getSizes[i] = _bufferSizesForGet[i];
|
||||
offsets[i] = _offsets[i];
|
||||
sizes[i] = _sizes[i];
|
||||
strides[i] = _strides[i];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
buffers[i] = autos[i].Get(cbs, getOffsets[i], getSizes[i]).Value;
|
||||
autos[i] = null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
_buffers[i] = buffers[i];
|
||||
_offsets[i] = offsets[i];
|
||||
_sizes[i] = sizes[i];
|
||||
_strides[i] = strides[i];
|
||||
}
|
||||
|
||||
if (_gd.Capabilities.SupportsExtendedDynamicState)
|
||||
{
|
||||
_gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2(
|
||||
cbs.CommandBuffer,
|
||||
baseBinding,
|
||||
(uint)count,
|
||||
_buffers.Pointer,
|
||||
_offsets.Pointer,
|
||||
_sizes.Pointer,
|
||||
_strides.Pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, baseBinding, (uint)count, _buffers.Pointer, _offsets.Pointer);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<Auto<DisposableBuffer>>.Shared.Return(autos, clearArray: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,21 +28,61 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||
|
||||
private ulong _latestPid;
|
||||
|
||||
private readonly object _pidLock = new();
|
||||
|
||||
#nullable enable
|
||||
public ProcessResult? ActiveApplication
|
||||
{
|
||||
get
|
||||
{
|
||||
return _processesByPid.GetValueOrDefault(_latestPid);
|
||||
|
||||
// Using this if statement locks up the UI and prevents a new game from loading.
|
||||
// Haven't quite deduced why yet.
|
||||
|
||||
if (!_processesByPid.TryGetValue(_latestPid, out ProcessResult value))
|
||||
throw new RyujinxException(
|
||||
$"The HLE Process map did not have a process with ID {_latestPid}. Are you missing firmware?");
|
||||
lock (_pidLock)
|
||||
{
|
||||
// Check if _latestPid is still valid
|
||||
if (_latestPid == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return value;
|
||||
// Verify process still exists in kernel (authoritative source)
|
||||
if (!_device.System.KernelContext.Processes.TryGetValue(_latestPid, out HOS.Kernel.Process.KProcess? kernelProcess))
|
||||
{
|
||||
// Process no longer exists in kernel, clear stale state
|
||||
Logger.Warning?.Print(LogClass.Loader,
|
||||
$"ActiveApplication PID {_latestPid} no longer exists in kernel, clearing stale state");
|
||||
|
||||
_processesByPid.TryRemove(_latestPid, out _);
|
||||
_latestPid = 0;
|
||||
TitleIDs.CurrentApplication.Value = null;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Verify process still exists in ProcessLoader's dictionary
|
||||
if (_processesByPid.TryGetValue(_latestPid, out ProcessResult? processResult))
|
||||
{
|
||||
// Additional check: verify process state
|
||||
if (kernelProcess.State == HOS.Kernel.Process.ProcessState.Exited ||
|
||||
kernelProcess.State == HOS.Kernel.Process.ProcessState.Exiting)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Loader,
|
||||
$"ActiveApplication PID {_latestPid} is in state {kernelProcess.State}, clearing");
|
||||
|
||||
_processesByPid.TryRemove(_latestPid, out _);
|
||||
_latestPid = 0;
|
||||
TitleIDs.CurrentApplication.Value = null;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return processResult;
|
||||
}
|
||||
|
||||
// Fallback: clear stale PID if not in our dictionary
|
||||
Logger.Warning?.Print(LogClass.Loader,
|
||||
$"ActiveApplication PID {_latestPid} not in ProcessLoader dictionary, clearing");
|
||||
_latestPid = 0;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#nullable disable
|
||||
@@ -285,5 +325,39 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears a specific process from the ProcessLoader's tracking.
|
||||
/// This should be called when a process exits or is terminated.
|
||||
/// </summary>
|
||||
/// <param name="pid">The process ID to clear</param>
|
||||
public void ClearProcess(ulong pid)
|
||||
{
|
||||
lock (_pidLock)
|
||||
{
|
||||
if (_processesByPid.TryRemove(pid, out _))
|
||||
{
|
||||
if (_latestPid == pid)
|
||||
{
|
||||
_latestPid = 0;
|
||||
TitleIDs.CurrentApplication.Value = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all processes from the ProcessLoader's tracking.
|
||||
/// This should be called during system shutdown.
|
||||
/// </summary>
|
||||
public void ClearAllProcesses()
|
||||
{
|
||||
lock (_pidLock)
|
||||
{
|
||||
_processesByPid.Clear();
|
||||
_latestPid = 0;
|
||||
TitleIDs.CurrentApplication.Value = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +183,7 @@ namespace Ryujinx.HLE
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
Processes.ClearAllProcesses();
|
||||
System.Dispose();
|
||||
AudioDeviceDriver.Dispose();
|
||||
FileSystem.Dispose();
|
||||
|
||||
Reference in New Issue
Block a user