-
Notifications
You must be signed in to change notification settings - Fork 830
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
Add ES 320 support and additional error checks for SPV_NV_mesh_shader #1507
Conversation
sparmarNV
commented
Sep 25, 2018
- 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
Adding @dgkoch @johnkslang for visibility |
Test/spv.meshShaderUserDefined.mesh
Outdated
@@ -1,4 +1,4 @@ | |||
#version 450 | |||
#version 320 es | |||
|
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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"); |
There was a problem hiding this comment.
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, ...);
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay.
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)) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) {
There was a problem hiding this comment.
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( ).
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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");
}
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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. |
…nsionStage Also continue error checking post requireStage() check
Also let me know if you want me to squash all commits into 1. |
Yes, squashing would be better; I saw that too late. Next time. |