diff options
| author | ArielG-NV <159081215+ArielG-NV@users.noreply.github.com> | 2024-03-13 15:03:16 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-13 15:03:16 -0400 |
| commit | 9fd74379c22af14f794d48fdc22e772d47f61ca3 (patch) | |
| tree | 9d15b4139d8fdaa335197617b0bc6cab14ed42a3 /source/slang/slang-parser.cpp | |
| parent | 6f7c8271710b43349d34b8f7569ceb6957400548 (diff) | |
Implement glsl atomic's [non image or memory scope] with optional extension(s); resolves #3587 for GLSL & SPIR-V targets (#3755)
The following commit implements atomic operations & types associated with OpenGL 4.6, GL_EXT_vulkan_glsl_relaxed, GLSL_EXT_shader_atomic_float, GLSL_EXT_shader_atomic_float2, for GLSL & SPIR-V targets.
Fully implements all functions, and built-in type's, resolves https://github.com/shader-slang/slang/issues/3560 for GLSL & SPRI-V targets.
[Atomic extensions for GLSL can be found here](https://github.com/KhronosGroup/GLSL/tree/main)
Notes of worth:
* atomic_uint is well defined in GLSL->OpenGL, although was removed in GLSL->VK unless a compiler extension is supported (GL_EXT_vulkan_glsl_relaxed). This support entails transforming all atomic_uint operations and references into a storage buffer. SPIR-V has AtomicCounter+AtomicStorage (atomic_uint parallel) but does not implement these capabilities for SPIR-V->VK in any scenario. Due to the case we transform atomic_uint ourselves (GLSL_Syntax->Slang_IR) to accommodate transforming atomic_uint into valid syntax.
* GLSL_EXT_shader_atomic_float2 (all float16_t & some float/double operations) support is minimal and worth watching out for if enabling the tests.
Diffstat (limited to 'source/slang/slang-parser.cpp')
| -rw-r--r-- | source/slang/slang-parser.cpp | 81 |
1 files changed, 80 insertions, 1 deletions
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index 3315c786a..cc87a3daa 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -229,6 +229,29 @@ namespace Slang lastErrorLoc = loc; } } + + public: + void setBindingOffset(int binding, int64_t byteOffset) + { + bindingToByteOffset.set(binding, byteOffset); + } + int64_t getNextBindingOffset(int binding) + { + int64_t currentOffset; + if (bindingToByteOffset.addIfNotExists(binding, 0)) + currentOffset = 0; + else + currentOffset = bindingToByteOffset.getValue(binding) + sizeof(uint32_t); + + bindingToByteOffset.set( + binding, + currentOffset + sizeof(uint32_t) + ); + return currentOffset; + } + + private: + Dictionary<int, int64_t> bindingToByteOffset; }; // Forward Declarations @@ -4365,6 +4388,42 @@ namespace Slang return attrDecl; } + static void addSpecialGLSLModifiersBasedOnType( + Parser* parser, + Decl* decl, + Modifiers* modifiers) + { + auto varDeclBase = as<VarDeclBase>(decl); + if (!varDeclBase) return; + auto declRefExpr = as<DeclRefExpr>(varDeclBase->type.exp); + if (!declRefExpr) return; + auto bindingMod = modifiers->findModifier<GLSLBindingAttribute>(); + if (!bindingMod) return; + + // here is a problem; we link types into a literal in IR stage post parse + // but, order (top down) mattter when parsing atomic_uint offset + // more over, we can have patterns like: offset = 20, no offset [+4], offset = 16. + // Therefore we must parse all in order. The issue then is we will struggle to + // subsitute atomic_uint for storage buffers... + if (auto name = declRefExpr->name) + { + if (name->text.equals("atomic_uint")) + { + if (!modifiers->findModifier<GLSLOffsetLayoutAttribute>()) + { + const int64_t nextOffset = parser->getNextBindingOffset(bindingMod->binding); + GLSLOffsetLayoutAttribute* modifier = parser->astBuilder->create<GLSLOffsetLayoutAttribute>(); + modifier->keywordName = NULL; //no keyword name given + modifier->loc = bindingMod->loc; //has no location in file, set to parent binding + modifier->offset = nextOffset; + + Modifiers newModifier; + newModifier.first = modifier; + _addModifiers(decl, newModifier); + } + } + } + } // Finish up work on a declaration that was parsed static void CompleteDecl( Parser* parser, @@ -4403,6 +4462,10 @@ namespace Slang } else { + if (parser->options.allowGLSLInput) + { + addSpecialGLSLModifiersBasedOnType(parser, declToModify, &modifiers); + } _addModifiers(declToModify, modifiers); } @@ -7787,6 +7850,7 @@ namespace Slang CASE(std140, GLSLStd140Modifier) CASE(std430, GLSLStd430Modifier) CASE(scalar, GLSLScalarModifier) + CASE(offset, GLSLOffsetLayoutAttribute) CASE(location, GLSLLocationLayoutModifier) { modifier = parser->astBuilder->create<GLSLUnparsedLayoutModifier>(); @@ -7797,12 +7861,27 @@ namespace Slang modifier->keywordName = nameAndLoc.name; modifier->loc = nameAndLoc.loc; + // Special handling for GLSLLayoutModifier if (auto glslModifier = as<GLSLLayoutModifier>(modifier)) { + // not all GLSLLayoutModifier subtypes have an OpAssign after if (AdvanceIf(parser, TokenType::OpAssign)) - { glslModifier->valToken = parser->ReadToken(TokenType::IntegerLiteral); + } + //Special handling for GLSLOffsetLayoutAttribute to add to the byte offset tracker at a binding location + else if (auto glslOffset = as<GLSLOffsetLayoutAttribute>(modifier)) + { + if (auto binding = listBuilder.find<GLSLBindingAttribute>()) + { + // all GLSLOffsetLayoutAttribute have an OpAssign with value token + parser->ReadToken(TokenType::OpAssign); + glslOffset->offset = int64_t(getIntegerLiteralValue(parser->ReadToken(TokenType::IntegerLiteral))); + parser->setBindingOffset(binding->binding, glslOffset->offset); + } + else + { + parser->diagnose(modifier->loc, Diagnostics::missingLayoutBindingModifier); } } |
