From 3bd357045f7581ee10d6c86ed8049bcebe35eda0 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 16 Feb 2022 19:15:39 -0300 Subject: Do not allow render targets not explicitly written by the fragment shader to be modified (#3063) * Do not allow render targets not explicitly written by the fragment shader to be modified * Shader cache version bump * Remove blank lines * Avoid redundant color mask updates * HostShaderCacheEntry can be null * Avoid more redundant glColorMask calls * nit: Mask -> Masks * Fix currentComponentMask * More efficient way to update _currentComponentMasks --- .../Cache/Definition/HostShaderCacheEntry.cs | 6 ++-- .../Cache/Definition/HostShaderCacheEntryHeader.cs | 13 +++++-- Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | 41 ++++++++++++++++++---- 3 files changed, 49 insertions(+), 11 deletions(-) (limited to 'Ryujinx.Graphics.Gpu/Shader') diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs index 68f6b3c1..819c6bcc 100644 --- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs +++ b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs @@ -77,7 +77,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition programInfo.Images.Count, programInfo.UsesInstanceId, programInfo.UsesRtLayer, - programInfo.ClipDistancesWritten); + programInfo.ClipDistancesWritten, + programInfo.FragmentOutputMap); CBuffers = programInfo.CBuffers.ToArray(); SBuffers = programInfo.SBuffers.ToArray(); Textures = programInfo.Textures.ToArray(); @@ -97,7 +98,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition Images, Header.UseFlags.HasFlag(UseFlags.InstanceId), Header.UseFlags.HasFlag(UseFlags.RtLayer), - Header.ClipDistancesWritten); + Header.ClipDistancesWritten, + Header.FragmentOutputMap); } /// diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs index 4b8b15bc..c3c0de22 100644 --- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs +++ b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs @@ -26,7 +26,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition /// /// Host shader entry header used for binding information. /// - [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x14)] + [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x18)] struct HostShaderCacheEntryHeader { /// @@ -70,6 +70,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition /// public byte Reserved; + /// + /// Mask of components written by the fragment shader stage. + /// + public int FragmentOutputMap; + /// /// Create a new host shader cache entry header. /// @@ -78,6 +83,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition /// Count of texture descriptors /// Count of image descriptors /// Set to true if the shader uses instance id + /// Mask of clip distances that are written to on the shader + /// Mask of components written by the fragment shader stage public HostShaderCacheEntryHeader( int cBuffersCount, int sBuffersCount, @@ -85,13 +92,15 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition int imagesCount, bool usesInstanceId, bool usesRtLayer, - byte clipDistancesWritten) : this() + byte clipDistancesWritten, + int fragmentOutputMap) : this() { CBuffersCount = cBuffersCount; SBuffersCount = sBuffersCount; TexturesCount = texturesCount; ImagesCount = imagesCount; ClipDistancesWritten = clipDistancesWritten; + FragmentOutputMap = fragmentOutputMap; InUse = true; UseFlags = usesInstanceId ? UseFlags.InstanceId : UseFlags.None; diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index f1e9f383..bf76d592 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// /// Version of the codegen (to be changed when codegen or guest format change). /// - private const ulong ShaderCodeGenVersion = 3106; + private const ulong ShaderCodeGenVersion = 3063; // Progress reporting helpers private volatile int _shaderCount; @@ -188,7 +188,7 @@ namespace Ryujinx.Graphics.Gpu.Shader { hostShaderEntries = HostShaderCacheEntry.Parse(hostProgramBinary, out ReadOnlySpan hostProgramBinarySpan); hostProgramBinary = hostProgramBinarySpan.ToArray(); - hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary); + hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary, false, new ShaderInfo(-1)); } ShaderCompileTask task = new ShaderCompileTask(taskDoneEvent); @@ -252,7 +252,7 @@ namespace Ryujinx.Graphics.Gpu.Shader // Compile shader and create program as the shader program binary got invalidated. shader.HostShader = _context.Renderer.CompileShader(ShaderStage.Compute, program.Code); - hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }); + hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }, new ShaderInfo(-1)); task.OnCompiled(hostProgram, (bool isNewProgramValid, ShaderCompileTask task) => { @@ -303,7 +303,18 @@ namespace Ryujinx.Graphics.Gpu.Shader { hostShaderEntries = HostShaderCacheEntry.Parse(hostProgramBinary, out ReadOnlySpan hostProgramBinarySpan); hostProgramBinary = hostProgramBinarySpan.ToArray(); - hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary); + + bool hasFragmentShader = false; + int fragmentOutputMap = -1; + int fragmentIndex = (int)ShaderStage.Fragment - 1; + + if (hostShaderEntries[fragmentIndex] != null && hostShaderEntries[fragmentIndex].Header.InUse) + { + hasFragmentShader = true; + fragmentOutputMap = hostShaderEntries[fragmentIndex].Header.FragmentOutputMap; + } + + hostProgram = _context.Renderer.LoadProgramBinary(hostProgramBinary, hasFragmentShader, new ShaderInfo(fragmentOutputMap)); } ShaderCompileTask task = new ShaderCompileTask(taskDoneEvent); @@ -426,7 +437,15 @@ namespace Ryujinx.Graphics.Gpu.Shader hostShaders.Add(hostShader); } - hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray()); + int fragmentIndex = (int)ShaderStage.Fragment - 1; + int fragmentOutputMap = -1; + + if (shaders[fragmentIndex] != null) + { + fragmentOutputMap = shaders[fragmentIndex].Info.FragmentOutputMap; + } + + hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray(), new ShaderInfo(fragmentOutputMap)); task.OnCompiled(hostProgram, (bool isNewProgramValid, ShaderCompileTask task) => { @@ -617,7 +636,7 @@ namespace Ryujinx.Graphics.Gpu.Shader shader.HostShader = _context.Renderer.CompileShader(ShaderStage.Compute, shader.Program.Code); - IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }); + IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }, new ShaderInfo(-1)); cpShader = new ShaderBundle(hostProgram, shader); @@ -755,7 +774,15 @@ namespace Ryujinx.Graphics.Gpu.Shader hostShaders.Add(hostShader); } - IProgram hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray()); + int fragmentIndex = (int)ShaderStage.Fragment - 1; + int fragmentOutputMap = -1; + + if (shaders[fragmentIndex] != null) + { + fragmentOutputMap = shaders[fragmentIndex].Info.FragmentOutputMap; + } + + IProgram hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray(), new ShaderInfo(fragmentOutputMap)); gpShaders = new ShaderBundle(hostProgram, shaders); -- cgit v1.2.3