mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-31 23:19:44 +08:00
[gpu-hotfix1] Cache improvements have been made (6x performance gain) (#18)
This commit is contained in:
@@ -155,6 +155,16 @@ public static class AgcExports
|
||||
(ulong Cs, ulong State, uint LocalX, uint LocalY, uint LocalZ),
|
||||
byte[]> _computeSpirvCache = new();
|
||||
private static readonly Dictionary<ulong, ulong> _shaderHeadersByCode = new();
|
||||
private static readonly bool _traceAgc = string.Equals(
|
||||
Environment.GetEnvironmentVariable("SHARPEMU_LOG_AGC"),
|
||||
"1",
|
||||
StringComparison.Ordinal);
|
||||
private static readonly bool _traceAgcShader =
|
||||
_traceAgc ||
|
||||
string.Equals(
|
||||
Environment.GetEnvironmentVariable("SHARPEMU_LOG_AGC_SHADER"),
|
||||
"1",
|
||||
StringComparison.Ordinal);
|
||||
private static long _dcbWriteDataTraceCount;
|
||||
private static long _dcbWaitRegMemTraceCount;
|
||||
private static long _createShaderTraceCount;
|
||||
@@ -3629,6 +3639,31 @@ public static class AgcExports
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isStorage &&
|
||||
descriptor.Address != 0 &&
|
||||
VulkanVideoPresenter.IsGuestImageAvailable(
|
||||
descriptor.Address,
|
||||
descriptor.Format,
|
||||
descriptor.NumberType))
|
||||
{
|
||||
texture = new VulkanGuestDrawTexture(
|
||||
descriptor.Address,
|
||||
descriptor.Width,
|
||||
descriptor.Height,
|
||||
descriptor.Format,
|
||||
descriptor.NumberType,
|
||||
[],
|
||||
IsFallback: false,
|
||||
IsStorage: false,
|
||||
MipLevels: descriptor.MipLevels,
|
||||
MipLevel: mipLevel,
|
||||
Pitch: sourceWidth,
|
||||
TileMode: descriptor.TileMode,
|
||||
DstSelect: descriptor.DstSelect,
|
||||
Sampler: ToVulkanSampler(samplerDescriptor));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isStorage)
|
||||
{
|
||||
var initialPixels = Array.Empty<byte>();
|
||||
@@ -5405,7 +5440,7 @@ public static class AgcExports
|
||||
|
||||
private static void TraceAgc(string message)
|
||||
{
|
||||
if (!string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_AGC"), "1", StringComparison.Ordinal))
|
||||
if (!_traceAgc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -5415,8 +5450,7 @@ public static class AgcExports
|
||||
|
||||
private static void TraceAgcShader(string message)
|
||||
{
|
||||
if (!string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_AGC"), "1", StringComparison.Ordinal) &&
|
||||
!string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_AGC_SHADER"), "1", StringComparison.Ordinal))
|
||||
if (!_traceAgcShader)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using SharpEmu.HLE;
|
||||
using SharpEmu.Libs.VideoOut;
|
||||
using System.Buffers.Binary;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpEmu.Libs.Agc;
|
||||
@@ -13,6 +14,14 @@ internal static class Gen5ShaderTranslator
|
||||
private const int MaxInstructions = 4096;
|
||||
private const int MinimumUserDataDwords = 16;
|
||||
private const int MaximumUserDataDwords = 256;
|
||||
private static readonly ConditionalWeakTable<object, ShaderDecodeCache> _decodeCaches = new();
|
||||
|
||||
private sealed class ShaderDecodeCache
|
||||
{
|
||||
public object Gate { get; } = new();
|
||||
public Dictionary<ulong, Gen5ShaderProgram> Programs { get; } = new();
|
||||
public Dictionary<ulong, Gen5ShaderMetadata?> Metadata { get; } = new();
|
||||
}
|
||||
|
||||
private static readonly uint[] FullscreenBarycentricEs =
|
||||
[
|
||||
@@ -117,16 +126,51 @@ internal static class Gen5ShaderTranslator
|
||||
uint userDataScalarRegisterBase = 0)
|
||||
{
|
||||
state = default!;
|
||||
if (!TryDecodeProgram(ctx, shaderAddress, out var program, out error))
|
||||
error = string.Empty;
|
||||
var cache = _decodeCaches.GetValue(ctx.Memory, static _ => new ShaderDecodeCache());
|
||||
Gen5ShaderProgram? program;
|
||||
lock (cache.Gate)
|
||||
{
|
||||
return false;
|
||||
cache.Programs.TryGetValue(shaderAddress, out program);
|
||||
}
|
||||
|
||||
if (program is null)
|
||||
{
|
||||
if (!TryDecodeProgram(ctx, shaderAddress, out program, out error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (cache.Gate)
|
||||
{
|
||||
cache.Programs.TryAdd(shaderAddress, program);
|
||||
}
|
||||
}
|
||||
|
||||
Gen5ShaderMetadata? metadata = null;
|
||||
if (shaderHeaderAddress != 0 &&
|
||||
Gen5ShaderMetadataReader.TryRead(ctx, shaderHeaderAddress, out var decodedMetadata))
|
||||
if (shaderHeaderAddress != 0)
|
||||
{
|
||||
metadata = decodedMetadata;
|
||||
var metadataCached = false;
|
||||
lock (cache.Gate)
|
||||
{
|
||||
metadataCached = cache.Metadata.TryGetValue(shaderHeaderAddress, out metadata);
|
||||
}
|
||||
|
||||
if (!metadataCached)
|
||||
{
|
||||
if (Gen5ShaderMetadataReader.TryRead(
|
||||
ctx,
|
||||
shaderHeaderAddress,
|
||||
out var decodedMetadata))
|
||||
{
|
||||
metadata = decodedMetadata;
|
||||
}
|
||||
|
||||
lock (cache.Gate)
|
||||
{
|
||||
cache.Metadata.TryAdd(shaderHeaderAddress, metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var userData = new uint[GetUserDataDwordCount(metadata)];
|
||||
|
||||
Reference in New Issue
Block a user