Skip to content

Conversation

@Ethereal77
Copy link
Contributor

PR Details

When compiling shaders in debug mode, ShaderCompiler now disables any optimizations made to the output bytecode. This, however, is not done if shaders are being compiled on GraphicsProfile.Level_9_3 or below, as platforms that fall into those categories / graphics APIs had pretty severe limitations in instruction slots, bytecode size, etc., and it makes the compilation fail in those cases.

Related Issue

As discussed in issue #2972

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My change requires a change to the documentation.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have built and run the editor to try this change out.

* Only for GraphicsProfile 10.0 and above
@Ethereal77
Copy link
Contributor Author

This needs a documentation change to inform about this? And if it does, where and how would be the most appropriate place?

// Add debug info if needed
if (effectParameters.Debug)
{
args += " -g"; // Generate debug information
Copy link
Member

@Kryptos-FR Kryptos-FR Nov 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String concatenation creates garbage that needs to be cleaned up by the GC. Let's try to avoid that.

It can be achieved in multiple ways: either with a StringBuilder or with string interpolation (which the compiler can optimize).

For instance (pseudo code):

bool isDebug = ...;

var str = $"{isDebug ? "-D" : ""} some literal {filename}";

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did write it with string concatenation because the function already allocates a lot (to start, two Dictionarys at the top, the ShaderBytecodeResult, the ShaderBytecode, BinarySerializationWriter, MemoryStream, and even calls Encoding.ASCII.GetBytes() several times) 😢.

Also, I tried interpolation, but I think it obfuscates the logic a bit:

string args = $"-V {                  // Generate SPIR-V binary
    (effectParameters.Debug
        ? effectParameters.Profile < GraphicsProfile.Level_10_0
            ? "-g"                    // Generate debug information
            : "-g -Od"                // Generate debug and disable optimizations (only for level 10.0+)
        : "")
    } -o {outputFileName} {inputFileName}";

This is the version with StringBuilder:

var argsBuilder = new StringBuilder();

argsBuilder.Append("-V");  // Generate SPIR-V binary

if (effectParameters.Debug)
{
    argsBuilder.Append(" -g");  // Generate debug information

    if (effectParameters.Profile >= GraphicsProfile.Level_10_0)
    {
        argsBuilder.Append(" -Od"); // Disable optimizations
    }
}
argsBuilder.Append($" -o {outputFileName} {inputFileName}");
string args = argsBuilder.ToString();

What do you think? Obviously, interpolation just allocates once (the final string), but reads worse, while StringBuilder allocates twice (hopefully, not counting internal buffers), and reads better.

@VaclavElias
Copy link
Contributor

This needs a documentation change to inform about this? And if it does, where and how would be the most appropriate place?

Somewhere here? https://doc.stride3d.net/latest/en/manual/graphics/effects-and-shaders/index.html

@Ethereal77
Copy link
Contributor Author

Thanks, Vaclav. If needed I'll add to the docs. 😀

But the question was more in the sense of: this change affects very old platforms. Platforms that we may phase out soon anyway. And it is a very specific thing affecting only people who restrict themselves to compile with those low GraphicsProfiles. Not many people, I suppose. And finally, it affects them because of limitations of very old hardware which don't apply anymore on modern hardware, even hardware that presents itself as low-profile. Even cheap mobile GPUs support shaders of arbitrary length, no limits on texture slots or ALU instructions, etc.

So... do we document it? And if yes, how do we explain this without going into too much low-level depths?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants