summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-check-decl.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2020-08-18 13:42:46 -0400
committerGitHub <noreply@github.com>2020-08-18 13:42:46 -0400
commit9abcb6ea24dbc7184c3a2ad9f4458f63f8901928 (patch)
tree155ae80bbd15efae88b5852b7bb24804a70af405 /source/slang/slang-check-decl.cpp
parent697e7fbbbb5dcb448c03a9887e6ef09e328505ef (diff)
Support for float atomics on RWByteAddressBuffer (#1502)
* Fix premake5.lua so it uses the new path needed for OpenCLDebugInfo100.h * Keep including the includes directory. * Added the spirv-tools-generated files. * We don't need to include the spirv/unified1 path because the files needed are actually in the spirv-tools-generated folder. * Put the build_info.h glslang generated files in external/glslang-generated. Alter premake5.lua to pick up that header. * First pass at documenting how to build glslang and spirv-tools. * Improved glsl/spir-v tools README.md * Added revision.h * Change how gResources is calculated. Update about revision.h * Update docs a little. * Split out spirv-tools into a separate project for building glslang. This was not necessary on linux, but *is* necessary on windows, because there is a file disassemble.cpp in spirv-tools and in glslang, and this leads to VS choosing only one. With the separate library, the problem is resolved. * Fix direct-spirv-emit output. * Update to latest version of spirv headers and spirv-tools. * Upgrade submodule version of glslang in external. * Add fPIC to build options of slang-spirv-tools * WIP adding support for InterlockedAddFp32 * Upgrade slang-binaries to have new glslang. * Fix issues with Windows slang-glslang binaries, via update of slang-binaries used. * WIP - atomicAdd. This solution can't work as we can't do (float*) in glsl. * WIP on atomic float ops. * Added checking for multiple decls that takes into account __target_intrinsic and __specialized_for_target. First pass impl of atomic add on float for glsl. * Split __atomicAdd so extensions are applied appropriately. * Made Dxc/Fxc support includes. Use HLSL prelude to pass the path to nvapi Added -nv-api-path * Refactor around IncludeHandler and impl of IncludeSystem * slang-include-handler -> slang-include-system Have IncludeHandler/Impl defined in slang-preprocessor * Small comment improvements. * Document atomic float add addition in target-compatibility.md. * CUDA float atomic support on RWByteAddressBuffer. * Add atomic-float-byte-address-buffer-cross.slang * Removed inappropriate-once.slang - the test is no longer valid when a file is loaded and has a unique identity by default. A test could be made, but would require an API call to create the file (so no unique id). Improved handling of loadFile - uses uniqueId if has one. * Work around for testing target overlaps - to avoid exceptions on adding targets. Simplify PathInfo setup. Modify single-target-intrinsic.slang - it no longer failed because there were no longer multiple definitions for the same target. Co-authored-by: Tim Foley <tfoleyNV@users.noreply.github.com>
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
-rw-r--r--source/slang/slang-check-decl.cpp91
1 files changed, 79 insertions, 12 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index f965f9759..13b818b26 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -3520,6 +3520,7 @@ namespace Slang
return subst;
}
+#if 0
// For simplicity we will make having a definition of a function include having a body or a target intrinsics defined.
// It may be useful to add other modifiers to mark as having body - for example perhaps
// any target intrinsic modifier (like SPIR-V version) should be included.
@@ -3536,6 +3537,40 @@ namespace Slang
{
return decl->body || decl->hasModifier<TargetIntrinsicModifier>();
}
+#endif
+
+ typedef Dictionary<Name*, CallableDecl*> TargetDeclDictionary;
+
+ static void _addTargetModifiers(CallableDecl* decl, TargetDeclDictionary& ioDict)
+ {
+ if (auto specializedModifier = decl->findModifier<SpecializedForTargetModifier>())
+ {
+ // If it's specialized for target it should have a body...
+ if (auto funcDecl = as<FunctionDeclBase>(decl))
+ {
+ SLANG_ASSERT(funcDecl->body);
+ }
+ Name* targetName = specializedModifier->targetToken.getName();
+
+ ioDict.AddIfNotExists(targetName, decl);
+ }
+ else
+ {
+ for (auto modifier : decl->getModifiersOfType<TargetIntrinsicModifier>())
+ {
+ Name* targetName = modifier->targetToken.getName();
+ ioDict.AddIfNotExists(targetName, decl);
+ }
+
+ auto funcDecl = as<FunctionDeclBase>(decl);
+ if (funcDecl && funcDecl->body)
+ {
+ // Should only be one body if it isn't specialized for target.
+ // Use nullptr for this scenario
+ ioDict.AddIfNotExists(nullptr, decl);
+ }
+ }
+ }
Result SemanticsVisitor::checkFuncRedeclaration(
FuncDecl* newDecl,
@@ -3701,23 +3736,55 @@ namespace Slang
// with the case where the two function declarations
// might represent different target-specific versions
// of a function.
- //
- // TODO: if the two declarations are specialized for
- // different targets, then skip the body checks below.
- //
- // ???: Why isn't this problem showing up in practice?
-
+
// If both of the declarations have a body, then there
// is trouble, because we wouldn't know which one to
// use during code generation.
- if (_isDefinition(newDecl) && _isDefinition(oldDecl))
+
+ // Here to cover the 'bodies'/target_intrinsics, we find all the targets that
+ // that are previously defined, and make sure the new definition
+ // doesn't try and define what is already defined.
{
- // Redefinition
- getSink()->diagnose(newDecl, Diagnostics::functionRedefinition, newDecl->getName());
- getSink()->diagnose(oldDecl, Diagnostics::seePreviousDefinitionOf, newDecl->getName());
+ TargetDeclDictionary currentTargets;
+ {
+ CallableDecl* curDecl = newDecl->primaryDecl;
+ while (curDecl)
+ {
+ if (curDecl != newDecl)
+ {
+ _addTargetModifiers(curDecl, currentTargets);
+ }
+ curDecl = curDecl->nextDecl;
+ }
+ }
- // Don't bother emitting other errors
- return SLANG_FAIL;
+ // Add the targets for this new decl
+ TargetDeclDictionary newTargets;
+ _addTargetModifiers(newDecl, newTargets);
+
+ bool hasConflict = false;
+ for (auto& pair : newTargets)
+ {
+ Name* target = pair.Key;
+ auto found = currentTargets.TryGetValue(target);
+ if (found)
+ {
+ // Redefinition
+ if (!hasConflict)
+ {
+ getSink()->diagnose(newDecl, Diagnostics::functionRedefinition, newDecl->getName());
+ hasConflict = true;
+ }
+
+ auto prevDecl = *found;
+ getSink()->diagnose(prevDecl, Diagnostics::seePreviousDefinitionOf, prevDecl->getName());
+ }
+ }
+
+ if (hasConflict)
+ {
+ return SLANG_FAIL;
+ }
}
// At this point we've processed the redeclaration and