From 3bd357045f7581ee10d6c86ed8049bcebe35eda0 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
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
---
 Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | 41 +++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 7 deletions(-)

(limited to 'Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs')

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
         /// <summary>
         /// Version of the codegen (to be changed when codegen or guest format change).
         /// </summary>
-        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<byte> 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<byte> 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-70-g09d2