diff options
| author | Tim Foley <tfoley@nvidia.com> | 2017-06-26 09:07:07 -0700 |
|---|---|---|
| committer | Tim Foley <tfoley@nvidia.com> | 2017-06-26 10:31:43 -0700 |
| commit | c16fc84a0071892ea0f4e3c5c70aa101e6400aec (patch) | |
| tree | 6c5e2363cbf5c460006ea19ae4e0ac2243df291e | |
| parent | d506737b8b00bcc89adf937994ceb6df4509c98a (diff) | |
Include imported code when generating reflection data
- The basic idea is simple: be sure to enumerate code in `__import`ed modules when generating reflection info
- Note that we don't currently allow an entry point to appear in an imported module, so we only consider globlal-scope parameters
- Although there isn't currently a real implementation of namespacing, I went ahead and ensured that parameters in imported modules are treated as distinct from parameters in the user's code, even if they have the same name.
| -rw-r--r-- | source/slang/compiler.h | 3 | ||||
| -rw-r--r-- | source/slang/parameter-binding.cpp | 40 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 9 | ||||
| -rw-r--r-- | source/slang/type-layout.cpp | 17 | ||||
| -rw-r--r-- | tests/reflection/reflect-imported-code.hlsl | 21 | ||||
| -rw-r--r-- | tests/reflection/reflect-imported-code.slang | 14 |
6 files changed, 91 insertions, 13 deletions
diff --git a/source/slang/compiler.h b/source/slang/compiler.h index 36fc5f42f..3f45ea5c7 100644 --- a/source/slang/compiler.h +++ b/source/slang/compiler.h @@ -211,7 +211,8 @@ namespace Slang RefPtr<ProgramLayout> layout; // Modules that have been dynamically loaded via `import` - Dictionary<String, RefPtr<ProgramSyntaxNode>> loadedModules; + Dictionary<String, RefPtr<ProgramSyntaxNode>> loadedModulesMap; + List<RefPtr<ProgramSyntaxNode> > loadedModulesList; CompileRequest(Session* session) diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp index 70cb4e7ba..939380659 100644 --- a/source/slang/parameter-binding.cpp +++ b/source/slang/parameter-binding.cpp @@ -134,9 +134,6 @@ struct SharedParameterBindingContext // All shader parameters we've discovered so far, and started to lay out... List<RefPtr<ParameterInfo>> parameters; - // A dictionary to accellerate looking up parameters by name - Dictionary<String, ParameterInfo*> mapNameToParameterInfo; - // The program layout we are trying to construct RefPtr<ProgramLayout> programLayout; @@ -158,6 +155,9 @@ struct ParameterBindingContext // The layout rules to use while computing usage... LayoutRulesFamilyImpl* layoutRules; + // A dictionary to accellerate looking up parameters by name + Dictionary<String, ParameterInfo*> mapNameToParameterInfo; + // What stage (if any) are we compiling for? Stage stage; }; @@ -448,7 +448,7 @@ static void collectGlobalScopeParameter( // of this parameter: auto parameterName = varDecl->Name.Content; ParameterInfo* parameterInfo = nullptr; - if( context->shared->mapNameToParameterInfo.TryGetValue(parameterName, parameterInfo) ) + if( context->mapNameToParameterInfo.TryGetValue(parameterName, parameterInfo) ) { // If the parameters have the same name, but don't "match" according to some reasonable rules, // then we need to bail out. @@ -463,7 +463,7 @@ static void collectGlobalScopeParameter( { parameterInfo = new ParameterInfo(); context->shared->parameters.Add(parameterInfo); - context->shared->mapNameToParameterInfo.Add(parameterName, parameterInfo); + context->mapNameToParameterInfo.Add(parameterName, parameterInfo); } else { @@ -1061,10 +1061,34 @@ inferStageForTranslationUnit( return Stage::Unknown; } +static void collectModuleParameters( + ParameterBindingContext* inContext, + ProgramSyntaxNode* module) +{ + // Each loaded module provides a separate (logical) namespace for + // parameters, so that two parameters with the same name, in + // distinct modules, should yield different bindings. + // + ParameterBindingContext contextData = *inContext; + auto context = &contextData; + + context->stage = Stage::Unknown; + + // A loaded module cannot define entry points that + // we'll expose (for now), so we just need to + // consider global-scope parameters. + collectGlobalScopeParameters(context, module); +} + static void collectParameters( ParameterBindingContext* inContext, CompileRequest* request) { + // All of the parameters in translation units directly + // referenced in the compile request are part of one + // logical namespace/"linkage" so that two parameters + // with the same name should represent the same + // parameter, and get the same binding(s) ParameterBindingContext contextData = *inContext; auto context = &contextData; @@ -1082,6 +1106,12 @@ static void collectParameters( collectEntryPointParameters(context, entryPoint.Ptr(), translationUnit->SyntaxNode.Ptr()); } } + + // Now collect parameters from loaded modules + for (auto& module : request->loadedModulesList) + { + collectModuleParameters(context, module.Ptr()); + } } void generateParameterBindings( diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 37d72cadc..fc18ea1cf 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -419,7 +419,8 @@ RefPtr<ProgramSyntaxNode> CompileRequest::loadModule( RefPtr<ProgramSyntaxNode> moduleDecl = translationUnit->SyntaxNode; - loadedModules.Add(name, moduleDecl); + loadedModulesMap.Add(name, moduleDecl); + loadedModulesList.Add(moduleDecl); return moduleDecl; @@ -434,7 +435,7 @@ String CompileRequest::autoImportModule( String name = path; // Have we already loaded a module matching this name? - if (loadedModules.TryGetValue(name)) + if (loadedModulesMap.TryGetValue(name)) return name; loadModule(name, path, source, loc); @@ -449,7 +450,7 @@ RefPtr<ProgramSyntaxNode> CompileRequest::findOrImportModule( // Have we already loaded a module matching this name? // If so, return it. RefPtr<ProgramSyntaxNode> moduleDecl; - if (loadedModules.TryGetValue(name, moduleDecl)) + if (loadedModulesMap.TryGetValue(name, moduleDecl)) return moduleDecl; // Derive a file name for the module, by taking the given @@ -488,7 +489,7 @@ RefPtr<ProgramSyntaxNode> CompileRequest::findOrImportModule( { this->mSink.diagnose(loc, Diagnostics::cannotFindFile, fileName); - loadedModules[name] = nullptr; + loadedModulesMap[name] = nullptr; return nullptr; } break; diff --git a/source/slang/type-layout.cpp b/source/slang/type-layout.cpp index 3427d6a6f..8b8a2b437 100644 --- a/source/slang/type-layout.cpp +++ b/source/slang/type-layout.cpp @@ -632,9 +632,20 @@ createParameterBlockTypeLayout( RefPtr<TypeLayout> elementTypeLayout, LayoutRulesImpl* rules) { - auto info = getParameterBlockLayoutInfo( - parameterBlockType, - rules); + SimpleLayoutInfo info; + if (parameterBlockType) + { + info = getParameterBlockLayoutInfo( + parameterBlockType, + rules); + } + else + { + // If there is no concrete type, then it seems like we are + // being asked to compute layout for the global scope + info = rules->GetObjectLayout(ShaderParameterKind::ConstantBuffer); + } + auto typeLayout = new ParameterBlockTypeLayout(); diff --git a/tests/reflection/reflect-imported-code.hlsl b/tests/reflection/reflect-imported-code.hlsl new file mode 100644 index 000000000..b95493f7e --- /dev/null +++ b/tests/reflection/reflect-imported-code.hlsl @@ -0,0 +1,21 @@ +//TEST:SIMPLE:-profile ps_4_0 -target reflection-json + +// Confirm that shader parameters in imported modules get reflected properly. + +__import reflect_imported_code; + +Texture2D t; +SamplerState s; + +cbuffer C +{ + float c; +} + +float4 main() : SV_Target +{ + return use(t,s_i) + + use(c) + + use(t_i, s) + + use(c_i); +}
\ No newline at end of file diff --git a/tests/reflection/reflect-imported-code.slang b/tests/reflection/reflect-imported-code.slang new file mode 100644 index 000000000..20beb94b8 --- /dev/null +++ b/tests/reflection/reflect-imported-code.slang @@ -0,0 +1,14 @@ +//TEST_IGNORE_FILE: + +// Imported code used by `reflect-imported-code.hlsl` + +float4 use(float4 val) { return val; }; +float4 use(Texture2D t, SamplerState s) { return t.Sample(s, 0.0); } + +Texture2D t_i; +SamplerState s_i; + +cbuffer C_i +{ + float c_i; +} |
