GPU: Eliminate CB0 accesses when storage buffer accesses are resolved (#3847)

* Eliminate CB0 accesses

Still some work to do, decouple from hle?

* Forgot the important part somehow

* Fix and improve alignment test

* Address Feedback

* Remove some complexity when checking storage buffer alignment

* Update Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs

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

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
This commit is contained in:
riperiperi 2022-11-17 17:47:41 +00:00 committed by GitHub
parent 391e08dd27
commit 33a4d7d1ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 317 additions and 68 deletions

View file

@ -36,6 +36,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
/// <param name="channel">GPU channel</param>
/// <param name="poolState">Texture pool state</param>
/// <param name="computeState">Compute state</param>
/// <param name="gpuVa">GPU virtual address of the compute shader</param>
/// <param name="program">Cached host program for the given state, if found</param>
/// <param name="cachedGuestCode">Cached guest code, if any found</param>
@ -43,6 +44,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
public bool TryFind(
GpuChannel channel,
GpuChannelPoolState poolState,
GpuChannelComputeState computeState,
ulong gpuVa,
out CachedShaderProgram program,
out byte[] cachedGuestCode)
@ -50,7 +52,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
program = null;
ShaderCodeAccessor codeAccessor = new ShaderCodeAccessor(channel.MemoryManager, gpuVa);
bool hasSpecList = _cache.TryFindItem(codeAccessor, out var specList, out cachedGuestCode);
return hasSpecList && specList.TryFindForCompute(channel, poolState, out program);
return hasSpecList && specList.TryFindForCompute(channel, poolState, computeState, out program);
}
/// <summary>

View file

@ -225,6 +225,12 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
return _oldSpecState.GraphicsState.EarlyZForce;
}
/// <inheritdoc/>
public bool QueryHasUnalignedStorageBuffer()
{
return _oldSpecState.GraphicsState.HasUnalignedStorageBuffer || _oldSpecState.ComputeState.HasUnalignedStorageBuffer;
}
/// <inheritdoc/>
public bool QueryViewportTransformDisable()
{

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 = 3747;
private const uint CodeGenVersion = 3848;
private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data";

View file

@ -145,6 +145,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
return _state.GraphicsState.HasConstantBufferDrawParameters;
}
/// <inheritdoc/>
public bool QueryHasUnalignedStorageBuffer()
{
return _state.GraphicsState.HasUnalignedStorageBuffer || _state.ComputeState.HasUnalignedStorageBuffer;
}
/// <inheritdoc/>
public InputTopology QueryPrimitiveTopology()
{

View file

@ -32,6 +32,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
public readonly int SharedMemorySize;
/// <summary>
/// Indicates that any storage buffer use is unaligned.
/// </summary>
public readonly bool HasUnalignedStorageBuffer;
/// <summary>
/// Creates a new GPU compute state.
/// </summary>
@ -40,18 +45,21 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <param name="localSizeZ">Local group size Z of the compute shader</param>
/// <param name="localMemorySize">Local memory size of the compute shader</param>
/// <param name="sharedMemorySize">Shared memory size of the compute shader</param>
/// <param name="hasUnalignedStorageBuffer">Indicates that any storage buffer use is unaligned</param>
public GpuChannelComputeState(
int localSizeX,
int localSizeY,
int localSizeZ,
int localMemorySize,
int sharedMemorySize)
int sharedMemorySize,
bool hasUnalignedStorageBuffer)
{
LocalSizeX = localSizeX;
LocalSizeY = localSizeY;
LocalSizeZ = localSizeZ;
LocalMemorySize = localMemorySize;
SharedMemorySize = sharedMemorySize;
HasUnalignedStorageBuffer = hasUnalignedStorageBuffer;
}
}
}

View file

@ -82,6 +82,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
public readonly bool HasConstantBufferDrawParameters;
/// <summary>
/// Indicates that any storage buffer use is unaligned.
/// </summary>
public readonly bool HasUnalignedStorageBuffer;
/// <summary>
/// Creates a new GPU graphics state.
/// </summary>
@ -99,6 +104,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <param name="alphaTestReference">When alpha test is enabled, indicates the value to compare with the fragment output alpha</param>
/// <param name="attributeTypes">Type of the vertex attributes consumed by the shader</param>
/// <param name="hasConstantBufferDrawParameters">Indicates that the draw is writing the base vertex, base instance and draw index to Constant Buffer 0</param>
/// <param name="hasUnalignedStorageBuffer">Indicates that any storage buffer use is unaligned</param>
public GpuChannelGraphicsState(
bool earlyZForce,
PrimitiveTopology topology,
@ -113,7 +119,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
CompareOp alphaTestCompare,
float alphaTestReference,
ref Array32<AttributeType> attributeTypes,
bool hasConstantBufferDrawParameters)
bool hasConstantBufferDrawParameters,
bool hasUnalignedStorageBuffer)
{
EarlyZForce = earlyZForce;
Topology = topology;
@ -129,6 +136,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
AlphaTestReference = alphaTestReference;
AttributeTypes = attributeTypes;
HasConstantBufferDrawParameters = hasConstantBufferDrawParameters;
HasUnalignedStorageBuffer = hasUnalignedStorageBuffer;
}
}
}

View file

@ -203,12 +203,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
GpuChannelComputeState computeState,
ulong gpuVa)
{
if (_cpPrograms.TryGetValue(gpuVa, out var cpShader) && IsShaderEqual(channel, poolState, cpShader, gpuVa))
if (_cpPrograms.TryGetValue(gpuVa, out var cpShader) && IsShaderEqual(channel, poolState, computeState, cpShader, gpuVa))
{
return cpShader;
}
if (_computeShaderCache.TryFind(channel, poolState, gpuVa, out cpShader, out byte[] cachedGuestCode))
if (_computeShaderCache.TryFind(channel, poolState, computeState, gpuVa, out cpShader, out byte[] cachedGuestCode))
{
_cpPrograms[gpuVa] = cpShader;
return cpShader;
@ -473,18 +473,20 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
/// <param name="channel">GPU channel using the shader</param>
/// <param name="poolState">GPU channel state to verify shader compatibility</param>
/// <param name="computeState">GPU channel compute state to verify shader compatibility</param>
/// <param name="cpShader">Cached compute shader</param>
/// <param name="gpuVa">GPU virtual address of the shader code in memory</param>
/// <returns>True if the code is different, false otherwise</returns>
private static bool IsShaderEqual(
GpuChannel channel,
GpuChannelPoolState poolState,
GpuChannelComputeState computeState,
CachedShaderProgram cpShader,
ulong gpuVa)
{
if (IsShaderEqual(channel.MemoryManager, cpShader.Shaders[0], gpuVa))
{
return cpShader.SpecializationState.MatchesCompute(channel, poolState, true);
return cpShader.SpecializationState.MatchesCompute(channel, poolState, computeState, true);
}
return false;

View file

@ -53,13 +53,14 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
/// <param name="channel">GPU channel</param>
/// <param name="poolState">Texture pool state</param>
/// <param name="computeState">Compute state</param>
/// <param name="program">Cached program, if found</param>
/// <returns>True if a compatible program is found, false otherwise</returns>
public bool TryFindForCompute(GpuChannel channel, GpuChannelPoolState poolState, out CachedShaderProgram program)
public bool TryFindForCompute(GpuChannel channel, GpuChannelPoolState poolState, GpuChannelComputeState computeState, out CachedShaderProgram program)
{
foreach (var entry in _entries)
{
if (entry.SpecializationState.MatchesCompute(channel, poolState, true))
if (entry.SpecializationState.MatchesCompute(channel, poolState, computeState, true))
{
program = entry;
return true;

View file

@ -531,6 +531,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
return false;
}
if (graphicsState.HasUnalignedStorageBuffer != GraphicsState.HasUnalignedStorageBuffer)
{
return false;
}
return Matches(channel, poolState, checkTextures, isCompute: false);
}
@ -539,10 +544,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
/// <param name="channel">GPU channel</param>
/// <param name="poolState">Texture pool state</param>
/// <param name="computeState">Compute state</param>
/// <param name="checkTextures">Indicates whether texture descriptors should be checked</param>
/// <returns>True if the state matches, false otherwise</returns>
public bool MatchesCompute(GpuChannel channel, GpuChannelPoolState poolState, bool checkTextures)
public bool MatchesCompute(GpuChannel channel, GpuChannelPoolState poolState, GpuChannelComputeState computeState, bool checkTextures)
{
if (computeState.HasUnalignedStorageBuffer != ComputeState.HasUnalignedStorageBuffer)
{
return false;
}
return Matches(channel, poolState, checkTextures, isCompute: true);
}