Skip to content
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

Add ES 320 support and additional error checks for SPV_NV_mesh_shader #1507

Merged
merged 4 commits into from
Sep 28, 2018
Merged

Add ES 320 support and additional error checks for SPV_NV_mesh_shader #1507

merged 4 commits into from
Sep 28, 2018

Conversation

sparmarNV
Copy link
Contributor

  • Add ES 320 support
  • Error out use of perprimitiveNV for non mesh/fragment shaders
  • Error out use of mesh/task shaders w/o use of NV_mesh_shader
  • Error out use of NV_mesh_shader for non task/mesh shaders
  • Error out use of perviewNV for non mesh shaders
  • Error out use of taskNV for non mesh/task shaders
  • Add test case for mesh shader with ES 320 profile

- Add ES 320 support
- Error out use of perprimitiveNV for non mesh/fragment shaders
- Error out use of mesh/task shaders w/o use of NV_mesh_shader
- Error out use of NV_mesh_shader for non task/mesh shaders
- Error out use of perviewNV for non mesh shaders
- Error out use of taskNV for non mesh/task shaders
- Add test case for mesh shader with ES 320 profile
@sparmarNV
Copy link
Contributor Author

Adding @dgkoch @johnkslang for visibility

@@ -1,4 +1,4 @@
#version 450
#version 320 es

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we have a separate test shader for ES and GL profiles?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We already have 6 other tests with GL profiles. So we should be fine.

@@ -4983,7 +4998,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
if (id.compare(0, 11, "local_size_") == 0) {
#ifdef NV_EXTENSIONS
if (language == EShLangMeshNV || language == EShLangTaskNV) {
profileRequires(loc, ~EEsProfile, 450, E_GL_NV_mesh_shader, "gl_WorkGroupSize");
requireExtensions(loc, 1, &E_GL_NV_mesh_shader, "gl_WorkGroupSize");
Copy link
Member

Choose a reason for hiding this comment

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

This looks like it dropped the 450 requirement(?).

You can call profileRequires() multiple times, once for each set of requirements:

profileRequires(loc, ~EEsProfile, ...);
profileRequires(loc, EEsProfile, ...);

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 added requireExtensions check which will ensure we have the extension.
The extension in turn has the profile GL450+/ES320+ requirement.
So I removed the redundant profileRequires() check from here.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, that means it was a bug before(?), allowing 450 to support it without an extension, at least locally. If an extension must be present, the 450 should be a 0.

I think things are slightly flexible right when a brand new stage comes in, due to an extension, because their use is 100% correlated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this was a bug before. I thought profileRequires would mandates both 450 && NV_mesh_shader. But since that is not the case, I had to change it to requireExtensions.

@@ -103,6 +103,9 @@ class TParseVersions {
virtual void requireSpv(const TSourceLoc&, const char* op);
virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior);
#ifdef NV_EXTENSIONS
Copy link
Member

Choose a reason for hiding this comment

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

I'm taking these ifdef out of this header.

"\n");
}

if (profile != EEsProfile && version >= 450) {
Copy link
Member

Choose a reason for hiding this comment

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

The interface here is changing; if the test @dgkoch pointed out could easily be duplicated, it should be, unless you are sure all these interfaces changes are tested in the other files.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I will add another es 320 test.

if ((profile == EEsProfile && version >= 320) ||
extensionTurnedOn(E_GL_NV_mesh_shader))
return;
#endif
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this case be fully self contained, and not rely on a fall through?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I forgot the break statement. Thanks for the catch.

@@ -834,6 +834,23 @@ void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBe
}
}

#ifdef NV_EXTENSIONS
// Validate if extension name is used with correct shader stage.
bool TParseVersions::validateExtensionName(const TSourceLoc& loc, const char * const extension)
Copy link
Member

Choose a reason for hiding this comment

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

I don't think I agree with adding this function; it does not know what is going on.

There is a requireStage() function, to call from the place that does know what is going on. Does that work?

Or, maybe you want to call this one with a more specific name that says what it actually does, like check mesh stages.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I will inline the error check in Pp.cpp

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 realized that we also need similar checks for other turing extensions.
So instead of inlining the error check, I am renaming the function to checkShaderStageForNVExtensions( )

@@ -103,6 +103,9 @@ class TParseVersions {
virtual void requireSpv(const TSourceLoc&, const char* op);
virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior);
#ifdef NV_EXTENSIONS
Copy link
Member

Choose a reason for hiding this comment

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

I am removing these #ifdefs from this header.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay.

@johnkslang
Copy link
Member

I think this failed from testing infrastructure problems, not glslang itself.

@sparmarNV
Copy link
Contributor Author

I think this failed from testing infrastructure problems, not glslang itself.

Is it possible to rerun the tests?

@@ -874,6 +874,11 @@ int TPpContext::CPPextension(TPpToken* ppToken)
return token;
}

#ifdef NV_EXTENSIONS
if (!parseContext.checkShaderStageForNVExtensions(ppToken->loc, extensionName))
Copy link
Member

Choose a reason for hiding this comment

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

Incorrect extension semantics are not preprocessor errors.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe you want to do something in

void TParseVersions::updateExtensionBehavior(int line, const char* extension, const char* behaviorString)

@@ -834,6 +834,25 @@ void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBe
}
}

#ifdef NV_EXTENSIONS
// Check if extension is used with correct shader stage.
bool TParseVersions::checkShaderStageForNVExtensions(const TSourceLoc& loc, const char * const extension)
Copy link
Member

Choose a reason for hiding this comment

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

Do we even need #extensions to turn on a stage that can only exist if the #extension is there? Or is this incremental functionality? The system already has to buy into the fact that the stage is present to even get this far, it seems a bit circular.

Copy link
Member

Choose a reason for hiding this comment

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

See also the stage logic recently added for these stages in ShaderLang.cpp around line 568:

    // Correct for stage type...
    switch (stage) {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is to error out the case where an extension is incorrectly used in some other shader stage.
For e.g. using GL_ARB_compute_shader extension inside a non-compute shader.
I believe glslang doesn't error out such use cases.
I agree I should move the error check in updateExtensionBehavior( ).

Copy link
Member

Choose a reason for hiding this comment

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

Okay, I understand. I keep thinking it will disappear. But, it's still here, so more issues:

  • it should be not be called an NV function
  • it should not do odd checks for error reporting; it can allow errors to continue
  • basically, it only needs to be the one if-test and call to requireStage
  • (implying this is a void, not bool)

It would be fine with me if that one statement was inlined and the rest disappeared. But, to keep the function is also okay, for all checks like this, in which case it won't be NV-specific and should only do the checking.

Copy link
Member

@johnkslang johnkslang Sep 27, 2018

Choose a reason for hiding this comment

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

Something like:

void TParseVersions::checkExtensionStage(const TSourceLoc& loc, const char * const extension)
{
    // GL_NV_mesh_shader extension is only allowed in task/mesh shaders
    if (strcmp(extension, "GL_NV_mesh_shader") == 0)
        requireStage(loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask),
                     "#extension GL_NV_mesh_shader");
}

Copy link
Member

Choose a reason for hiding this comment

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

More background: there is already a generic mechanism for stopping parsing around the first error (unless cascading errors are requested), so individual error checks do not need to worry about termination, unless the next lines of code would crash glslang.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the detailed feedback.
I have done the changes to the function as suggested above.
Only thing which I added was the #ifdef NV_EXTENSIONS in function body, because the underlying code used EShLang*NVMask which is also guarded by same #ifdef.

@johnkslang
Copy link
Member

I think the preprocessor stuff needs fixing anyway; I don't think anything here should be changing the preprocessor. GLSL proper has all the semantic helpers needed; per my recent comments.

@sparmarNV
Copy link
Contributor Author

Also let me know if you want me to squash all commits into 1.

@johnkslang johnkslang merged commit 4508a81 into KhronosGroup:master Sep 28, 2018
@johnkslang
Copy link
Member

Yes, squashing would be better; I saw that too late. Next time.

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