summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-07-10 08:34:52 -0700
committerTim Foley <tfoley@nvidia.com>2017-07-10 08:34:52 -0700
commit0e220da96b819f3a31635689f78ad20bd9a36d0b (patch)
tree7728d25df51cb8488ac681715a82b359730b796d
parent928cc86160644547decc49c72304549d9009a1af (diff)
More cross-compilation fixes
- Add GLSL mappings for more `Texture*` methods - The annoying one here is `Texture*.Load()` because it doesn't take a sampler, but the GLSL equivalent needs one (while the SPIR-V does *not*). I've hacked this pretty seriously for now. - Try to ensure that we add `uniform` to global declarations that need it in GLSL - When outputting an `in` or `out` variable that might have been created from an `inout` shader parameter, filter the layout qualifiers that we output to only cover the appropriate resource kind.
-rw-r--r--source/slang/emit.cpp125
-rw-r--r--source/slang/lower.cpp20
-rw-r--r--source/slang/modifier-defs.h1
-rw-r--r--source/slang/parameter-binding.cpp2
-rw-r--r--source/slang/slang-stdlib.cpp29
5 files changed, 172 insertions, 5 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index c135090c1..01b3e8cc2 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -48,6 +48,10 @@ struct SharedEmitContext
StructTypeLayout* globalStructLayout;
ProgramLayout* programLayout;
+
+ ProgramSyntaxNode* program;
+
+ bool needHackSamplerForTexelFetch = false;
};
struct EmitContext
@@ -1758,6 +1762,66 @@ struct EmitVisitor
}
break;
+ case 'P':
+ {
+ // Okay, we need a collosal hack to deal with the fact that GLSL `texelFetch()`
+ // for Vulkan seems to be completely broken by design. It's signature wants
+ // a `sampler2D` for consistency with its peers, but the actual SPIR-V operation
+ // ignores the sampler paart of it, and just used the `texture2D` part.
+ //
+ // The HLSL equivalent (e.g., `Texture2D.Load()`) doesn't provide a sampler
+ // argument, so we seemingly need to conjure one out of thin air. :(
+ //
+ // We are going to hack this *hard* for now.
+
+ // Try to find a suitable sampler-type shader parameter in the global scope
+ // (fingers crossed)
+ RefPtr<VarDeclBase> samplerVar;
+ for (auto d : context->shared->program->Members)
+ {
+ if (auto varDecl = d.As<VarDeclBase>())
+ {
+ if (auto samplerType = varDecl->Type.type->As<SamplerStateType>())
+ {
+ samplerVar = varDecl;
+ break;
+ }
+ }
+ }
+
+ if (auto memberExpr = callExpr->FunctionExpr.As<MemberExpressionSyntaxNode>())
+ {
+ auto base = memberExpr->BaseExpression;
+ if (auto baseTextureType = base->Type->As<TextureType>())
+ {
+ emitGLSLTextureOrTextureSamplerType(baseTextureType, "sampler");
+ Emit("(");
+ EmitExpr(memberExpr->BaseExpression);
+ Emit(",");
+ if (samplerVar)
+ {
+ EmitDeclRef(makeDeclRef(samplerVar.Ptr()));
+ }
+ else
+ {
+ Emit("SLANG_hack_samplerForTexelFetch");
+ context->shared->needHackSamplerForTexelFetch = true;
+ }
+ Emit(")");
+ }
+ else
+ {
+ assert(!"unexpected");
+ }
+
+ }
+ else
+ {
+ assert(!"unexpected");
+ }
+ }
+ break;
+
default:
assert(!"unexpected");
break;
@@ -2476,6 +2540,9 @@ struct EmitVisitor
#define CASE(TYPE, KEYWORD) \
else if(auto mod_##TYPE = mod.As<TYPE>()) Emit(#KEYWORD " ")
+ #define CASE2(TYPE, HLSL_NAME, GLSL_NAME) \
+ else if(auto mod_##TYPE = mod.As<TYPE>()) Emit((context->shared->target == CodeGenTarget::GLSL) ? GLSL_NAME : HLSL_NAME)
+
CASE(RowMajorLayoutModifier, row_major);
CASE(ColumnMajorLayoutModifier, column_major);
CASE(HLSLNoInterpolationModifier, nointerpolation);
@@ -2502,6 +2569,7 @@ struct EmitVisitor
CASE(ConstModifier, const);
#undef CASE
+ #undef CASE2
else if (auto staticModifier = mod.As<HLSLStaticModifier>())
{
@@ -2949,7 +3017,8 @@ struct EmitVisitor
}
void emitGLSLLayoutQualifiers(
- RefPtr<VarLayout> layout)
+ RefPtr<VarLayout> layout,
+ LayoutResourceKind filter = LayoutResourceKind::None)
{
if(!layout) return;
@@ -2964,6 +3033,13 @@ struct EmitVisitor
for( auto info : layout->resourceInfos )
{
+ // Skip info that doesn't match our filter
+ if (filter != LayoutResourceKind::None
+ && filter != info.kind)
+ {
+ continue;
+ }
+
emitGLSLLayoutQualifier(info);
}
}
@@ -3095,7 +3171,33 @@ struct EmitVisitor
return;
}
- emitGLSLLayoutQualifiers(layout);
+
+ if (context->shared->target == CodeGenTarget::GLSL)
+ {
+ if (decl->HasModifier<InModifier>())
+ {
+ emitGLSLLayoutQualifiers(layout, LayoutResourceKind::VertexInput);
+ }
+ else if (decl->HasModifier<OutModifier>())
+ {
+ emitGLSLLayoutQualifiers(layout, LayoutResourceKind::FragmentOutput);
+ }
+ else
+ {
+ emitGLSLLayoutQualifiers(layout);
+ }
+
+ // If we have a uniform that wasn't tagged `uniform` in GLSL, then fix that here
+ if (layout
+ && !decl->HasModifier<HLSLUniformModifier>())
+ {
+ if (layout->FindResourceInfo(LayoutResourceKind::Uniform)
+ || layout->FindResourceInfo(LayoutResourceKind::DescriptorTableSlot))
+ {
+ Emit("uniform ");
+ }
+ }
+ }
EmitVarDeclCommon(decl);
@@ -3288,6 +3390,9 @@ String emitEntryPoint(
// There may be global-scope modifiers that we should emit now
visitor.emitGLSLPreprocessorDirectives(translationUnitSyntax);
+ String prefix = sharedContext.sb.ProduceString();
+ sharedContext.sb.Clear();
+
switch(target)
{
case CodeGenTarget::GLSL:
@@ -3303,6 +3408,8 @@ String emitEntryPoint(
auto lowered = lowerEntryPoint(entryPoint, programLayout, target);
+ sharedContext.program = lowered.program;
+
visitor.EmitDeclsInContainer(lowered.program.Ptr());
#if 0
@@ -3324,7 +3431,19 @@ String emitEntryPoint(
String code = sharedContext.sb.ProduceString();
- return code;
+ StringBuilder finalResultBuilder;
+ finalResultBuilder << prefix;
+
+ if (sharedContext.needHackSamplerForTexelFetch)
+ {
+ finalResultBuilder << "layout(set = 0, binding = 0) uniform sampler SLANG_hack_samplerForTexelFetch;\n";
+ }
+
+ finalResultBuilder << code;
+
+ String finalResult = finalResultBuilder.ProduceString();
+
+ return finalResult;
}
} // namespace Slang
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index 6c54d18b6..023c63591 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -194,6 +194,8 @@ public:
struct SharedLoweringContext
{
+ CompileRequest* compileRequest;
+
ProgramLayout* programLayout;
// The target we are going to generate code for.
@@ -1372,6 +1374,23 @@ struct LoweringVisitor
return loweredDecl;
}
+ SourceLanguage getSourceLanguage(ProgramSyntaxNode* moduleDecl)
+ {
+ for (auto translationUnit : shared->compileRequest->translationUnits)
+ {
+ if (moduleDecl == translationUnit->SyntaxNode)
+ return translationUnit->sourceLanguage;
+ }
+
+ for (auto loadedModuleDecl : shared->compileRequest->loadedModulesList)
+ {
+ if (moduleDecl == loadedModuleDecl)
+ return SourceLanguage::Slang;
+ }
+
+ return SourceLanguage::Unknown;
+ }
+
RefPtr<VarDeclBase> visitVariable(
Variable* decl)
{
@@ -2022,6 +2041,7 @@ LoweredEntryPoint lowerEntryPoint(
CodeGenTarget target)
{
SharedLoweringContext sharedContext;
+ sharedContext.compileRequest = entryPoint->compileRequest;
sharedContext.programLayout = programLayout;
sharedContext.target = target;
diff --git a/source/slang/modifier-defs.h b/source/slang/modifier-defs.h
index e50288600..083da79f0 100644
--- a/source/slang/modifier-defs.h
+++ b/source/slang/modifier-defs.h
@@ -6,7 +6,6 @@
#define SIMPLE_MODIFIER(NAME) \
SIMPLE_SYNTAX_CLASS(NAME##Modifier, Modifier)
-SIMPLE_MODIFIER(Uniform);
SIMPLE_MODIFIER(In);
SIMPLE_MODIFIER(Out);
SIMPLE_MODIFIER(Const);
diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp
index 228af7d99..ec611f8b1 100644
--- a/source/slang/parameter-binding.cpp
+++ b/source/slang/parameter-binding.cpp
@@ -1045,7 +1045,7 @@ static void collectEntryPointParameters(
// We have an entry-point parameter, and need to figure out what to do with it.
// TODO: need to handle `uniform`-qualified parameters here
- if (paramDecl->HasModifier<UniformModifier>())
+ if (paramDecl->HasModifier<HLSLUniformModifier>())
continue;
state.directionMask = 0;
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index e2d5829b4..23d66201a 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -1431,6 +1431,22 @@ namespace Slang
{
int loadCoordCount = kBaseTextureTypes[tt].coordCount + isArray + (isMultisample?0:1);
+ // When translating to GLSL, we need to break apart the `location` argument.
+ //
+ // TODO: this should realy be handled by having this member actually get lowered!
+ int glslLoadCoordCount = kBaseTextureTypes[tt].coordCount + isArray;
+ static const char* kGLSLLoadCoordsSwizzle[] = { "", "", "x", "xy", "xyz", "xyzw" };
+ static const char* kGLSLLoadLODSwizzle[] = { "", "", "y", "z", "w", "error" };
+
+ if (isMultisample)
+ {
+ sb << "__intrinsic(glsl, \"texelFetch($P, $0, $1)\")\n";
+ }
+ else
+ {
+ sb << "__intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
+ }
+ sb << "__intrinsic\n";
sb << "T Load(";
sb << "int" << loadCoordCount << " location";
if(isMultisample)
@@ -1439,6 +1455,15 @@ namespace Slang
}
sb << ");\n";
+ if (isMultisample)
+ {
+ sb << "__intrinsic(glsl, \"texelFetchOffset($P, $0, $1, $2)\")\n";
+ }
+ else
+ {
+ sb << "__intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $1)\")\n";
+ }
+ sb << "__intrinsic\n";
sb << "T Load(";
sb << "int" << loadCoordCount << " location";
if(isMultisample)
@@ -1470,11 +1495,15 @@ namespace Slang
{
// `Sample()`
+ sb << "__intrinsic(glsl, \"texture($p, $1)\")\n";
+ sb << "__intrinsic\n";
sb << "T Sample(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n";
if( baseShape != TextureType::ShapeCube )
{
+ sb << "__intrinsic(glsl, \"textureOffset($p, $1)\")\n";
+ sb << "__intrinsic\n";
sb << "T Sample(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";