summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-06-26 09:07:07 -0700
committerTim Foley <tfoley@nvidia.com>2017-06-26 10:31:43 -0700
commitc16fc84a0071892ea0f4e3c5c70aa101e6400aec (patch)
tree6c5e2363cbf5c460006ea19ae4e0ac2243df291e
parentd506737b8b00bcc89adf937994ceb6df4509c98a (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.h3
-rw-r--r--source/slang/parameter-binding.cpp40
-rw-r--r--source/slang/slang.cpp9
-rw-r--r--source/slang/type-layout.cpp17
-rw-r--r--tests/reflection/reflect-imported-code.hlsl21
-rw-r--r--tests/reflection/reflect-imported-code.slang14
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;
+}