Merge pull request #2177 from riperiperi/feature/parallel-shader-cache
Allow parallel shader compilation when loading a shader cache
This commit is contained in:
commit
b5c72b44de
16 changed files with 785 additions and 251 deletions
|
@ -10,6 +10,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
private static readonly Lazy<bool> _supportsPolygonOffsetClamp = new Lazy<bool>(() => HasExtension("GL_EXT_polygon_offset_clamp"));
|
||||
private static readonly Lazy<bool> _supportsViewportSwizzle = new Lazy<bool>(() => HasExtension("GL_NV_viewport_swizzle"));
|
||||
private static readonly Lazy<bool> _supportsSeamlessCubemapPerTexture = new Lazy<bool>(() => HasExtension("GL_ARB_seamless_cubemap_per_texture"));
|
||||
private static readonly Lazy<bool> _supportsParallelShaderCompile = new Lazy<bool>(() => HasExtension("GL_ARB_parallel_shader_compile"));
|
||||
|
||||
private static readonly Lazy<int> _maximumComputeSharedMemorySize = new Lazy<int>(() => GetLimit(All.MaxComputeSharedMemorySize));
|
||||
private static readonly Lazy<int> _storageBufferOffsetAlignment = new Lazy<int>(() => GetLimit(All.ShaderStorageBufferOffsetAlignment));
|
||||
|
@ -34,6 +35,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value;
|
||||
public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value;
|
||||
public static bool SupportsSeamlessCubemapPerTexture => _supportsSeamlessCubemapPerTexture.Value;
|
||||
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
|
||||
public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia;
|
||||
public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.Amd || _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix;
|
||||
public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.Amd && _gpuVendor.Value != GpuVendor.IntelWindows;
|
||||
|
|
|
@ -13,11 +13,26 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
public int Handle { get; private set; }
|
||||
|
||||
public int FragmentIsBgraUniform { get; }
|
||||
public int FragmentRenderScaleUniform { get; }
|
||||
public int ComputeRenderScaleUniform { get; }
|
||||
public int FragmentIsBgraUniform { get; private set; }
|
||||
public int FragmentRenderScaleUniform { get; private set; }
|
||||
public int ComputeRenderScaleUniform { get; private set; }
|
||||
|
||||
public bool IsLinked { get; private set; }
|
||||
public bool IsLinked
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_status == ProgramLinkStatus.Incomplete)
|
||||
{
|
||||
CheckProgramLink(true);
|
||||
}
|
||||
|
||||
return _status == ProgramLinkStatus.Success;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _initialized;
|
||||
private ProgramLinkStatus _status = ProgramLinkStatus.Incomplete;
|
||||
private IShader[] _shaders;
|
||||
|
||||
public Program(IShader[] shaders, TransformFeedbackDescriptor[] transformFeedbackDescriptors)
|
||||
{
|
||||
|
@ -82,18 +97,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
GL.LinkProgram(Handle);
|
||||
|
||||
for (int index = 0; index < shaders.Length; index++)
|
||||
{
|
||||
int shaderHandle = ((Shader)shaders[index]).Handle;
|
||||
|
||||
GL.DetachShader(Handle, shaderHandle);
|
||||
}
|
||||
|
||||
CheckProgramLink();
|
||||
|
||||
FragmentIsBgraUniform = GL.GetUniformLocation(Handle, "is_bgra");
|
||||
FragmentRenderScaleUniform = GL.GetUniformLocation(Handle, "fp_renderScale");
|
||||
ComputeRenderScaleUniform = GL.GetUniformLocation(Handle, "cp_renderScale");
|
||||
_shaders = shaders;
|
||||
}
|
||||
|
||||
public Program(ReadOnlySpan<byte> code)
|
||||
|
@ -109,32 +113,60 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
GL.ProgramBinary(Handle, binaryFormat, (IntPtr)ptr, code.Length - 4);
|
||||
}
|
||||
}
|
||||
|
||||
CheckProgramLink();
|
||||
|
||||
FragmentIsBgraUniform = GL.GetUniformLocation(Handle, "is_bgra");
|
||||
FragmentRenderScaleUniform = GL.GetUniformLocation(Handle, "fp_renderScale");
|
||||
ComputeRenderScaleUniform = GL.GetUniformLocation(Handle, "cp_renderScale");
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
FragmentIsBgraUniform = GL.GetUniformLocation(Handle, "is_bgra");
|
||||
FragmentRenderScaleUniform = GL.GetUniformLocation(Handle, "fp_renderScale");
|
||||
ComputeRenderScaleUniform = GL.GetUniformLocation(Handle, "cp_renderScale");
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
GL.UseProgram(Handle);
|
||||
}
|
||||
|
||||
private void CheckProgramLink()
|
||||
public ProgramLinkStatus CheckProgramLink(bool blocking)
|
||||
{
|
||||
if (!blocking && HwCapabilities.SupportsParallelShaderCompile)
|
||||
{
|
||||
GL.GetProgram(Handle, (GetProgramParameterName)ArbParallelShaderCompile.CompletionStatusArb, out int completed);
|
||||
|
||||
if (completed == 0)
|
||||
{
|
||||
return ProgramLinkStatus.Incomplete;
|
||||
}
|
||||
}
|
||||
|
||||
GL.GetProgram(Handle, GetProgramParameterName.LinkStatus, out int status);
|
||||
|
||||
if (_shaders != null)
|
||||
{
|
||||
for (int index = 0; index < _shaders.Length; index++)
|
||||
{
|
||||
int shaderHandle = ((Shader)_shaders[index]).Handle;
|
||||
|
||||
GL.DetachShader(Handle, shaderHandle);
|
||||
}
|
||||
|
||||
_shaders = null;
|
||||
}
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
// Use GL.GetProgramInfoLog(Handle), it may be too long to print on the log.
|
||||
_status = ProgramLinkStatus.Failure;
|
||||
Logger.Debug?.Print(LogClass.Gpu, "Shader linking failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
IsLinked = true;
|
||||
_status = ProgramLinkStatus.Success;
|
||||
}
|
||||
|
||||
return _status;
|
||||
}
|
||||
|
||||
public byte[] GetBinary()
|
||||
|
|
|
@ -131,6 +131,11 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
PrintGpuInformation();
|
||||
|
||||
if (HwCapabilities.SupportsParallelShaderCompile)
|
||||
{
|
||||
GL.Arb.MaxShaderCompilerThreads(Math.Min(Environment.ProcessorCount, 8));
|
||||
}
|
||||
|
||||
_counters.Initialize();
|
||||
}
|
||||
|
||||
|
@ -178,16 +183,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
public IProgram LoadProgramBinary(byte[] programBinary)
|
||||
{
|
||||
Program program = new Program(programBinary);
|
||||
|
||||
if (program.IsLinked)
|
||||
{
|
||||
return program;
|
||||
}
|
||||
|
||||
program.Dispose();
|
||||
|
||||
return null;
|
||||
return new Program(programBinary);
|
||||
}
|
||||
|
||||
public void CreateSync(ulong id)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue