From ac7e9b4cc868e075f63574be2b9d683ce77f9b66 Mon Sep 17 00:00:00 2001 From: Mario Guerra Date: Tue, 18 Nov 2025 06:54:48 +0100 Subject: [PATCH] Disable optimizations in debug when compiling shaders * Only for GraphicsProfile 10.0 and above --- .../Direct3D/ShaderCompiler.cs | 13 ++++++--- .../OpenGL/ShaderCompiler.cs | 28 +++++++++++++------ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/sources/engine/Stride.Shaders.Compiler/Direct3D/ShaderCompiler.cs b/sources/engine/Stride.Shaders.Compiler/Direct3D/ShaderCompiler.cs index 4afb3e78e9..f9c74a9b92 100644 --- a/sources/engine/Stride.Shaders.Compiler/Direct3D/ShaderCompiler.cs +++ b/sources/engine/Stride.Shaders.Compiler/Direct3D/ShaderCompiler.cs @@ -8,10 +8,7 @@ using SharpDX.D3DCompiler; using Stride.Core.Diagnostics; using Stride.Core.Storage; -using Stride.Rendering; using Stride.Graphics; -using ConstantBufferType = Stride.Shaders.ConstantBufferType; -using ShaderBytecode = Stride.Shaders.ShaderBytecode; using ShaderVariableType = SharpDX.D3DCompiler.ShaderVariableType; namespace Stride.Shaders.Compiler.Direct3D @@ -23,13 +20,21 @@ public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, Shad var isDebug = effectParameters.Debug; var optimLevel = effectParameters.OptimizationLevel; var profile = effectParameters.Profile; - + var shaderModel = ShaderStageToString(stage) + "_" + ShaderProfileFromGraphicsProfile(profile); var shaderFlags = ShaderFlags.None; if (isDebug) { shaderFlags = ShaderFlags.Debug; + + // Disable optimizations when debugging, except for Graphics Profiles 9.3 and below + // where optimizations are required to have valid shaders (otherwise compilation fails + // indicating too many instruction slots used) + if (profile >= GraphicsProfile.Level_10_0) + { + shaderFlags |= ShaderFlags.SkipOptimization; + } } switch (optimLevel) { diff --git a/sources/engine/Stride.Shaders.Compiler/OpenGL/ShaderCompiler.cs b/sources/engine/Stride.Shaders.Compiler/OpenGL/ShaderCompiler.cs index 85c4aeaee1..05da4b9f6b 100644 --- a/sources/engine/Stride.Shaders.Compiler/OpenGL/ShaderCompiler.cs +++ b/sources/engine/Stride.Shaders.Compiler/OpenGL/ShaderCompiler.cs @@ -2,10 +2,8 @@ // Distributed under the MIT license. See the LICENSE.md file in the project root for more information. using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Text; using Stride.Core; using Stride.Core.Extensions; @@ -14,9 +12,7 @@ using Stride.Graphics; using Stride.Core.Shaders.Ast; using Stride.Core.Shaders.Ast.Glsl; -using Stride.Core.Shaders.Ast.Hlsl; using Stride.Core.Shaders.Convertor; -using Stride.Core.Shaders.Writer.Hlsl; using ConstantBuffer = Stride.Core.Shaders.Ast.Hlsl.ConstantBuffer; using StorageQualifier = Stride.Core.Shaders.Ast.StorageQualifier; @@ -80,7 +76,7 @@ public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, Shad return shaderBytecodeResult; if (effectParameters.Platform == GraphicsPlatform.OpenGLES) // TODO: Add check to run on android only. The current version breaks OpenGL ES on windows. - { + { //TODO: Remove this ugly hack! if (shaderSource.Contains($"Texture2D StrideInternal_TextureExt0") && shader.Contains("uniform sampler2D")) { @@ -111,6 +107,20 @@ public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, Shad var inputFileName = Path.ChangeExtension(Path.GetTempFileName(), inputFileExtension); var outputFileName = Path.ChangeExtension(inputFileName, ".spv"); + var args = $"-V"; // Generate SPIR-V binary + + // Add debug info if needed + if (effectParameters.Debug) + { + args += " -g"; // Generate debug information + + if (effectParameters.Profile >= GraphicsProfile.Level_10_0) + { + args += " -Od"; // Disable optimizations + } + } + args += $" -o {outputFileName} {inputFileName}"; + // Write shader source to disk File.WriteAllBytes(inputFileName, Encoding.ASCII.GetBytes(shader)); @@ -131,7 +141,7 @@ public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, Shad default: throw new PlatformNotSupportedException(); } - ShellHelper.RunProcessAndRedirectToLogger(filename, $"-V -o {outputFileName} {inputFileName}", null, shaderBytecodeResult); + ShellHelper.RunProcessAndRedirectToLogger(filename, args, workingDirectory: null, shaderBytecodeResult); if (!File.Exists(outputFileName)) { @@ -163,13 +173,13 @@ public ShaderBytecodeResult Compile(string shaderSource, string entryPoint, Shad // store string on OpenGL platforms rawData = Encoding.UTF8.GetBytes(shader); } - + var bytecodeId = ObjectId.FromBytes(rawData); var bytecode = new ShaderBytecode(bytecodeId, rawData); bytecode.Stage = stage; shaderBytecodeResult.Bytecode = bytecode; - + return shaderBytecodeResult; } @@ -262,7 +272,7 @@ private string Compile(string shaderSource, string entryPoint, ShaderStage stage MarkResourceBindingAsUsed(reflection, resourceBindingIndex, stage); } } - + foreach (var variable in glslShader.Declarations.OfType().Where(x => (x.Qualifiers.Contains(StorageQualifier.Uniform)))) { // Check if we have a variable that starts or ends with this name (in case of samplers)