Skip to content

Address issues with GLSL style global in/out vars (#6669) #6998

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

sricker-nvidia
Copy link
Collaborator

@sricker-nvidia sricker-nvidia commented May 5, 2025

Asserts and segfaults were observed trying to compile a simple vertex shader like:

in int2 inPos;

[shader("vertex")]
main(uniform int2 test1, int2 test2, out float4 pos: SV_Position) void main()
{
    // Bogus use of all input vars to prevent optimizing out.
    pos = float4(inPos.x, test1.x, test2.y, 0);
}

Further investigation found that while replacing "uniform int2 test1" with "int2 test1" allowed for successful compilation, the resulting output shader would have overlapping location qualifiers. For example, compiling the above with "int2 test1" to glsl might give:

...
layout(location = 0) in ivec2 test1_0;
layout(location = 1) in ivec2 test2_0;
layout(location = 0) in ivec2 translatedGlobalParams_inPos_0; ...

This was because Slang does not actually support mixing GLSL style global in/out vars and entry point params. However, this is never checked for or noted in documentation. Slang source also assumes input shaders do not mix these and these assumptions ultimately led to the observed asserts and seg faults when using uniform entry point params.

This change makes updates to throw an error when the compiler detects that it is trying to translate global in/out variables into entry point params when an entry point already contains parameters, allowing for compilation to fail gracefully. Change also makes minor updates to documentation to clarify allowed usage of GLSL-flavored global in/out variables.

@sricker-nvidia sricker-nvidia requested a review from a team as a code owner May 5, 2025 18:49
@sricker-nvidia sricker-nvidia requested a review from jkwak-work May 5, 2025 18:50
// detected.

if (entryPointFunc->getParamCount() != 0)
SLANG_INVALID_OPERATION("Mixing of GLSL-flavored global in/out variables with entry point parameters is not supported.");
Copy link
Contributor

Choose a reason for hiding this comment

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

It's better to use diagnostic sink here instead of SLANG_INVALID_OPERATION, you can add a new error to slang-diagnostics-defs.h

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated

@sricker-nvidia sricker-nvidia added the pr: non-breaking PRs without breaking changes label May 5, 2025
// Before we continue, check for this here and throw an error if mixing is
// detected.

if (entryPointFunc->getParamCount() != 0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this is likely too strict and will fail a lot of existing tests.

Can we just support this scenario instead of throwing an error?

Copy link
Collaborator

Choose a reason for hiding this comment

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

At very least, we should only error when there are existing parameters that are varying in/out.

Existing uniform parameters, or builtin parameters are fine.

// should be allowed:
in float3 color;
void entry(float4 p: SV_Position, RWStructuredBuffer<float> b) {}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I experimented with supporting mixing GLSL style global in/out vars and entry point params, but if we stick the global in/out vars into the entry point params, I think we need to recalculate all of the offsets for the existing entry point params and that seemed like it was getting a bit complicated. I can revisit that effort if it makes sense to spend time on it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The problem with allowing existing uniform parameters, or builtin parameters is that translateGlobalVaryingVar ends up replacing all of the entry point params before we try and collect entry point uniforms and make them global. The result is that collectEntryPointUniformParams ends up seg faulting because it gets a format for the entry point params that it doesn't expect after they have been transformed in translateGlobalVaryingVar. It might be possible to shift things around to avoid the seg fault, but it still would not solve the issue with the parameter offsets.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I can use something like:

for (auto param : entryPointFunc->getParams())
{
    if (!param->findDecoration<IRSemanticDecoration>())
        // error

to allow something like

in float3 color;
void entry(float4 p: SV_Position, out float4 pos: SV_Position)

such that at least builtin parameters are fine, but working around uniform entry point parameters is more complicated to support.

Copy link
Collaborator

Choose a reason for hiding this comment

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

OK, let’s just disallow all parameters then.

@sricker-nvidia
Copy link
Collaborator Author

Might make sense to update the label to "pr: breaking" as this does effect the tests/bugs/gh-5339.slang test without additional edits and could have an effect on existing code (although it might be surprising if that code worked as intended).

@jarcherNV
Copy link
Collaborator

Might make sense to update the label to "pr: breaking" as this does effect the tests/bugs/gh-5339.slang test without additional edits and could have an effect on existing code (although it might be surprising if that code worked as intended).

Would it be possible to fix those tests in your PR?

@sricker-nvidia
Copy link
Collaborator Author

Might make sense to update the label to "pr: breaking" as this does effect the tests/bugs/gh-5339.slang test without additional edits and could have an effect on existing code (although it might be surprising if that code worked as intended).

Would it be possible to fix those tests in your PR?

Yeah, I'm working on it now for the next patch, I just wanted to note things in case someone wiser than myself thought the non-breaking label was incorrect.

Asserts and segfaults were observed trying to compile a simple
vertex shader like:

````
in int2 inPos;

[shader("vertex")]
main(uniform int2 test1, int2 test2, out float4 pos: SV_Position)
void main()
{
    // Bogus use of all input vars to prevent optimizing out.
    pos = float4(inPos.x, test1.x, test2.y, 0);
}
````

Further investigation found that while replacing "uniform int2 test1"
with "int2 test1" allowed for successful compilation, the resulting
output shader would have overlapping location qualifiers. For example,
compiling the above with "int2 test1" to glsl might give:

````
...
layout(location = 0) in ivec2 test1_0;
layout(location = 1) in ivec2 test2_0;
layout(location = 0) in ivec2 translatedGlobalParams_inPos_0;
...
````

This was because Slang does not actually support mixing GLSL style global
in/out vars and entry point params. However, this is never checked for
or noted in documentation. Slang source also assumes input shaders do not
mix these and these assumptions ultimately led to the observed asserts
and seg faults when using uniform entry point params.

This change makes updates to throw an error when the compiler detects that
it is trying to translate global in/out variables into entry point params
when an entry point already contains parameters, allowing for compilation
to fail gracefully. Change also makes minor updates to documentation to
clarify allowed usage of GLSL-flavored global in/out variables.
@sricker-nvidia sricker-nvidia force-pushed the 6669_bugfix_official branch from 0cc94e5 to 319ed89 Compare May 5, 2025 23:50
@csyonghe
Copy link
Collaborator

csyonghe commented May 6, 2025

Yes, this will need to be labeled as breaking change.

@sricker-nvidia sricker-nvidia added pr: breaking change PRs with breaking changes and removed pr: non-breaking PRs without breaking changes labels May 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr: breaking change PRs with breaking changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants