summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/core.meta.slang50
-rw-r--r--source/slang/core.meta.slang.h50
-rw-r--r--source/slang/emit.cpp247
-rw-r--r--source/slang/hlsl.meta.slang4
-rw-r--r--source/slang/hlsl.meta.slang.h4
-rw-r--r--source/slang/ir-insts.h17
-rw-r--r--source/slang/ir.cpp9
-rw-r--r--source/slang/ir.h1
-rw-r--r--source/slang/lower-to-ir.cpp18
-rw-r--r--tests/bindings/glsl-parameter-blocks.slang2
-rw-r--r--tests/bindings/glsl-parameter-blocks.slang.glsl37
11 files changed, 346 insertions, 93 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 2285b16ab..13b41bce6 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -461,7 +461,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "__glsl_version(450)\n";
sb << "__target_intrinsic(glsl, \"(";
- int aa = 0;
+ int aa = 1;
String lodStr = "0";
if (includeMipInfo)
{
@@ -582,11 +582,11 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if (isMultisample)
{
- sb << "__target_intrinsic(glsl, \"texelFetch($$P, $0, $1)\")\n";
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, $1, $3)\")\n";
}
else
{
- sb << "__target_intrinsic(glsl, \"texelFetch($$P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
}
sb << "T Load(";
sb << "int" << loadCoordCount << " location";
@@ -602,7 +602,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
}
else
{
- sb << "__target_intrinsic(glsl, \"texelFetch($$P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $1)\")\n";
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $2)\")\n";
}
sb << "T Load(";
sb << "int" << loadCoordCount << " location";
@@ -643,7 +643,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
{
// `Sample()`
-// sb << "__target_intrinsic(glsl, \"texture($$p, $1)\")\n";
+ sb << "__target_intrinsic(glsl, \"texture($$p, $2)\")\n";
// TODO: only enable if IR is being used?
// sb << "__intrinsic_op(sample)\n";
@@ -651,21 +651,9 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "T Sample(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n";
- // Specialized definition for GLSL
- sb << "__specialized_for_target(glsl)\n";
- sb << "T Sample(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location) {\n";
- sb << " return texture<T>(Sampler";
- sb << kBaseTextureAccessLevels[accessLevel].name;
- sb << name;
- if (isMultisample) sb << "MS";
- if (isArray) sb << "Array";
- sb << "<T>(this, s), location);\n";
- sb << "}\n";
-
if( baseShape != TextureType::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureOffset($$p, $1, $2)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureOffset($$p, $2, $3)\")\n";
sb << "T Sample(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
@@ -689,13 +677,13 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
// `SampleBias()`
- sb << "__target_intrinsic(glsl, \"texture($$p, $1, $2)\")\n";
+ sb << "__target_intrinsic(glsl, \"texture($$p, $2, $3)\")\n";
sb << "T SampleBias(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias);\n";
if( baseShape != TextureType::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureOffset($$p, $1, $2, $3)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureOffset($$p, $2, $3, $4)\")\n";
sb << "T SampleBias(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias, ";
sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
@@ -718,12 +706,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "__target_intrinsic(glsl, \"textureLod($$p, ";
- sb << "vec" << extCoordCount << "($1,";
+ sb << "vec" << extCoordCount << "($2,";
for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
{
sb << " 0.0,";
}
- sb << "$2)";
+ sb << "$3)";
sb << ", 0.0)\")\n";
}
@@ -736,12 +724,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "__target_intrinsic(glsl, \"textureGrad($$p, ";
- sb << "vec" << extCoordCount << "($1,";
+ sb << "vec" << extCoordCount << "($2,";
for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
{
sb << " 0.0,";
}
- sb << "$2)";
+ sb << "$3)";
// Construct gradients
sb << ", vec" << baseCoordCount << "(0.0)";
@@ -774,7 +762,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
}
- sb << "__target_intrinsic(glsl, \"textureGrad($$p, $1, $2, $3)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureGrad($$p, $2, $3, $4)\")\n";
// sb << "__intrinsic_op(sampleGrad)\n";
sb << "T SampleGrad(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
@@ -784,7 +772,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if( baseShape != TextureType::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureGradOffset($$p, $1, $2, $3, $4)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureGradOffset($$p, $2, $3, $4, $5)\")\n";
// sb << "__intrinsic_op(sampleGrad)\n";
sb << "T SampleGrad(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
@@ -795,14 +783,14 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
// `SampleLevel`
- sb << "__target_intrinsic(glsl, \"textureLod($$p, $1, $2)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureLod($$p, $2, $3)\")\n";
sb << "T SampleLevel(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "float level);\n";
if( baseShape != TextureType::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureLodOffset($$p, $1, $2, $3)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureLodOffset($$p, $2, $3, $4)\")\n";
sb << "T SampleLevel(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "float level, ";
@@ -869,12 +857,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
EMIT_LINE_DIRECTIVE();
- sb << "__target_intrinsic(glsl, \"textureGather($$p, $1, " << componentIndex << ")\")\n";
+ sb << "__target_intrinsic(glsl, \"textureGather($$p, $2, " << componentIndex << ")\")\n";
sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
EMIT_LINE_DIRECTIVE();
- sb << "__target_intrinsic(glsl, \"textureGatherOffset($$p, $1, $2, " << componentIndex << ")\")\n";
+ sb << "__target_intrinsic(glsl, \"textureGatherOffset($$p, $2, $3, " << componentIndex << ")\")\n";
sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
@@ -886,7 +874,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "out uint status);\n";
EMIT_LINE_DIRECTIVE();
- sb << "__target_intrinsic(glsl, \"textureGatherOffsets($$p, $1, int" << kBaseTextureTypes[tt].coordCount << "[]($2, $3, $4, $5), " << componentIndex << ")\")\n";
+ sb << "__target_intrinsic(glsl, \"textureGatherOffsets($$p, $2, int" << kBaseTextureTypes[tt].coordCount << "[]($3, $4, $5, $6), " << componentIndex << ")\")\n";
sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, ";
diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h
index 53e1f202e..84a1abbf0 100644
--- a/source/slang/core.meta.slang.h
+++ b/source/slang/core.meta.slang.h
@@ -464,7 +464,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "__glsl_version(450)\n";
sb << "__target_intrinsic(glsl, \"(";
- int aa = 0;
+ int aa = 1;
String lodStr = "0";
if (includeMipInfo)
{
@@ -585,11 +585,11 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if (isMultisample)
{
- sb << "__target_intrinsic(glsl, \"texelFetch($P, $0, $1)\")\n";
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, $1, $3)\")\n";
}
else
{
- sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
}
sb << "T Load(";
sb << "int" << loadCoordCount << " location";
@@ -605,7 +605,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
}
else
{
- sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $1)\")\n";
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $2)\")\n";
}
sb << "T Load(";
sb << "int" << loadCoordCount << " location";
@@ -646,7 +646,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
{
// `Sample()`
-// sb << "__target_intrinsic(glsl, \"texture($p, $1)\")\n";
+ sb << "__target_intrinsic(glsl, \"texture($p, $2)\")\n";
// TODO: only enable if IR is being used?
// sb << "__intrinsic_op(sample)\n";
@@ -654,21 +654,9 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "T Sample(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n";
- // Specialized definition for GLSL
- sb << "__specialized_for_target(glsl)\n";
- sb << "T Sample(SamplerState s, ";
- sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location) {\n";
- sb << " return texture<T>(Sampler";
- sb << kBaseTextureAccessLevels[accessLevel].name;
- sb << name;
- if (isMultisample) sb << "MS";
- if (isArray) sb << "Array";
- sb << "<T>(this, s), location);\n";
- sb << "}\n";
-
if( baseShape != TextureType::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureOffset($p, $2, $3)\")\n";
sb << "T Sample(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
@@ -692,13 +680,13 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
// `SampleBias()`
- sb << "__target_intrinsic(glsl, \"texture($p, $1, $2)\")\n";
+ sb << "__target_intrinsic(glsl, \"texture($p, $2, $3)\")\n";
sb << "T SampleBias(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias);\n";
if( baseShape != TextureType::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2, $3)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureOffset($p, $2, $3, $4)\")\n";
sb << "T SampleBias(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias, ";
sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
@@ -721,12 +709,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "__target_intrinsic(glsl, \"textureLod($p, ";
- sb << "vec" << extCoordCount << "($1,";
+ sb << "vec" << extCoordCount << "($2,";
for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
{
sb << " 0.0,";
}
- sb << "$2)";
+ sb << "$3)";
sb << ", 0.0)\")\n";
}
@@ -739,12 +727,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "__target_intrinsic(glsl, \"textureGrad($p, ";
- sb << "vec" << extCoordCount << "($1,";
+ sb << "vec" << extCoordCount << "($2,";
for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
{
sb << " 0.0,";
}
- sb << "$2)";
+ sb << "$3)";
// Construct gradients
sb << ", vec" << baseCoordCount << "(0.0)";
@@ -777,7 +765,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
}
- sb << "__target_intrinsic(glsl, \"textureGrad($p, $1, $2, $3)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureGrad($p, $2, $3, $4)\")\n";
// sb << "__intrinsic_op(sampleGrad)\n";
sb << "T SampleGrad(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
@@ -787,7 +775,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if( baseShape != TextureType::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureGradOffset($p, $1, $2, $3, $4)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureGradOffset($p, $2, $3, $4, $5)\")\n";
// sb << "__intrinsic_op(sampleGrad)\n";
sb << "T SampleGrad(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
@@ -798,14 +786,14 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
// `SampleLevel`
- sb << "__target_intrinsic(glsl, \"textureLod($p, $1, $2)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureLod($p, $2, $3)\")\n";
sb << "T SampleLevel(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "float level);\n";
if( baseShape != TextureType::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureLodOffset($p, $1, $2, $3)\")\n";
+ sb << "__target_intrinsic(glsl, \"textureLodOffset($p, $2, $3, $4)\")\n";
sb << "T SampleLevel(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "float level, ";
@@ -872,12 +860,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
EMIT_LINE_DIRECTIVE();
- sb << "__target_intrinsic(glsl, \"textureGather($p, $1, " << componentIndex << ")\")\n";
+ sb << "__target_intrinsic(glsl, \"textureGather($p, $2, " << componentIndex << ")\")\n";
sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n";
EMIT_LINE_DIRECTIVE();
- sb << "__target_intrinsic(glsl, \"textureGatherOffset($p, $1, $2, " << componentIndex << ")\")\n";
+ sb << "__target_intrinsic(glsl, \"textureGatherOffset($p, $2, $3, " << componentIndex << ")\")\n";
sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
@@ -889,7 +877,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "out uint status);\n";
EMIT_LINE_DIRECTIVE();
- sb << "__target_intrinsic(glsl, \"textureGatherOffsets($p, $1, int" << kBaseTextureTypes[tt].coordCount << "[]($2, $3, $4, $5), " << componentIndex << ")\")\n";
+ sb << "__target_intrinsic(glsl, \"textureGatherOffsets($p, $2, int" << kBaseTextureTypes[tt].coordCount << "[]($3, $4, $5, $6), " << componentIndex << ")\")\n";
sb << "vector<T, 4> Gather" << componentName << "(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount << " location, ";
sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, ";
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 1ef42bdf0..f9f24fcf6 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -1559,6 +1559,20 @@ struct EmitVisitor
emitUnaryExprImpl(outerPrec, prec, preOp, postOp, expr, true);
}
+ bool isTargetIntrinsicModifierApplicable(
+ String const& targetName)
+ {
+ switch(context->shared->target)
+ {
+ default:
+ SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled code generation target");
+ return false;
+
+ case CodeGenTarget::GLSL: return targetName == "glsl";
+ case CodeGenTarget::HLSL: return targetName == "hlsl";
+ }
+ }
+
// Determine if a target intrinsic modifer is applicable to the target
// we are currently emitting code for.
bool isTargetIntrinsicModifierApplicable(
@@ -1575,17 +1589,23 @@ struct EmitVisitor
// we expect.
auto const& targetName = targetToken.Content;
- switch(context->shared->target)
- {
- default:
- SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled code generation target");
- return false;
+ return isTargetIntrinsicModifierApplicable(targetName);
+ }
- case CodeGenTarget::GLSL: return targetName == "glsl";
- case CodeGenTarget::HLSL: return targetName == "hlsl";
- }
+ bool isTargetIntrinsicModifierApplicable(
+ IRTargetIntrinsicDecoration* decoration)
+ {
+ auto targetName = decoration->targetName;
+
+ // If no target name was specified, then the modifier implicitly
+ // applies to all targets.
+ if(targetName.Length() == 0)
+ return true;
+
+ return isTargetIntrinsicModifierApplicable(targetName);
}
+
// Find an intrinsic modifier appropriate to the current compilation target.
//
// If there are multiple such modifiers, this should return the best one.
@@ -5414,6 +5434,205 @@ emitDeclImpl(decl, nullptr);
}
};
+ IRTargetIntrinsicDecoration* findTargetIntrinsicDecoration(
+ EmitContext* /* ctx */,
+ IRFunc* func)
+ {
+ for (auto dd = func->firstDecoration; dd; dd = dd->next)
+ {
+ if (dd->op != kIRDecorationOp_TargetIntrinsic)
+ continue;
+
+ auto targetIntrinsic = (IRTargetIntrinsicDecoration*)dd;
+ if (isTargetIntrinsicModifierApplicable(targetIntrinsic))
+ return targetIntrinsic;
+ }
+
+ return nullptr;
+ }
+
+ void emitTargetIntrinsicCallExpr(
+ EmitContext* ctx,
+ IRCall* inst,
+ IRFunc* /* func */,
+ IRTargetIntrinsicDecoration* targetIntrinsic)
+ {
+ IRUse* args = inst->getArgs();
+ UInt argCount = inst->getArgCount();
+
+ // First operand was the function to be called
+ args++;
+ argCount--;
+
+ auto name = targetIntrinsic->definition;
+
+
+ if(name.IndexOf('$') == -1)
+ {
+ // Simple case: it is just an ordinary name, so we call it like a builtin.
+
+ emit(name);
+ Emit("(");
+ for (UInt aa = 0; aa < argCount; ++aa)
+ {
+ if (aa != 0) Emit(", ");
+ emitIROperand(ctx, args[aa].usedValue);
+ }
+ Emit(")");
+ return;
+ }
+ else
+ {
+ // General case: we are going to emit some more complex text.
+
+ Emit("(");
+
+ char const* cursor = name.begin();
+ char const* end = name.end();
+ while(cursor != end)
+ {
+ char c = *cursor++;
+ if( c != '$' )
+ {
+ // Not an escape sequence
+ emitRawTextSpan(&c, &c+1);
+ continue;
+ }
+
+ SLANG_RELEASE_ASSERT(cursor != end);
+
+ char d = *cursor++;
+
+ switch (d)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ // Simple case: emit one of the direct arguments to the call
+ UInt argIndex = d - '0';
+ SLANG_RELEASE_ASSERT((0 <= argIndex) && (argIndex < argCount));
+ Emit("(");
+ emitIROperand(ctx, args[argIndex].usedValue);
+ Emit(")");
+ }
+ break;
+
+ case 'p':
+ {
+ // If we are calling a D3D texturing operation in the form t.Foo(s, ...),
+ // then this form will pair up the t and s arguments as needed for a GLSL
+ // texturing operation.
+ SLANG_RELEASE_ASSERT(argCount >= 2);
+
+ auto textureArg = args[0].usedValue;
+ auto samplerArg = args[1].usedValue;
+
+ if (auto baseTextureType = textureArg->type->As<TextureType>())
+ {
+ emitGLSLTextureOrTextureSamplerType(baseTextureType, "sampler");
+
+ if (auto samplerType = samplerArg->type->As<SamplerStateType>())
+ {
+ if (samplerType->flavor == SamplerStateType::Flavor::SamplerComparisonState)
+ {
+ Emit("Shadow");
+ }
+ }
+
+ Emit("(");
+ emitIROperand(ctx, textureArg);
+ Emit(",");
+ emitIROperand(ctx, samplerArg);
+ Emit(")");
+ }
+ else
+ {
+ SLANG_UNEXPECTED("bad format in intrinsic definition");
+ }
+ }
+ 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.
+
+ auto textureArg = args[0].usedValue;
+ if (auto baseTextureType = textureArg->type->As<TextureType>())
+ {
+ emitGLSLTextureOrTextureSamplerType(baseTextureType, "sampler");
+ Emit("(");
+ emitIROperand(ctx, textureArg);
+ Emit(",");
+ Emit("SLANG_hack_samplerForTexelFetch");
+ context->shared->needHackSamplerForTexelFetch = true;
+ Emit(")");
+ }
+ else
+ {
+ SLANG_UNEXPECTED("bad format in intrinsic definition");
+ }
+ }
+ break;
+
+ case 'z':
+ {
+ // If we are calling a D3D texturing operation in the form t.Foo(s, ...),
+ // where `t` is a `Texture*<T>`, then this is the step where we try to
+ // properly swizzle the output of the equivalent GLSL call into the right
+ // shape.
+ SLANG_RELEASE_ASSERT(argCount >= 1);
+
+ auto textureArg = args[0].usedValue;
+ if (auto baseTextureType = textureArg->type->As<TextureType>())
+ {
+ auto elementType = baseTextureType->elementType;
+ if (auto basicType = elementType->As<BasicExpressionType>())
+ {
+ // A scalar result is expected
+ Emit(".x");
+ }
+ else if (auto vectorType = elementType->As<VectorExpressionType>())
+ {
+ // A vector result is expected
+ auto elementCount = GetIntVal(vectorType->elementCount);
+
+ if (elementCount < 4)
+ {
+ char const* swiz[] = { "", ".x", ".xy", ".xyz", "" };
+ Emit(swiz[elementCount]);
+ }
+ }
+ else
+ {
+ // What other cases are possible?
+ }
+ }
+ else
+ {
+ SLANG_UNEXPECTED("bad format in intrinsic definition");
+ }
+ }
+ break;
+
+
+ default:
+ SLANG_UNEXPECTED("bad format in intrinsic definition");
+ break;
+ }
+ }
+
+ Emit(")");
+ }
+ }
+
void emitIntrinsicCallExpr(
EmitContext* ctx,
IRCall* inst,
@@ -5426,6 +5645,18 @@ emitDeclImpl(decl, nullptr);
UInt argCount = operandCount - 1;
UInt operandIndex = 1;
+
+ //
+ if (auto targetIntrinsicDecoration = findTargetIntrinsicDecoration(ctx, func))
+ {
+ emitTargetIntrinsicCallExpr(
+ ctx,
+ inst,
+ func,
+ targetIntrinsicDecoration);
+ return;
+ }
+
// Our current strategy for dealing with intrinsic
// calls is to "un-mangle" the mangled name, in
// order to figure out what the user was originally
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index 2027a2a0b..7c5f26ed7 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -1072,12 +1072,12 @@ for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)
sb << "void GetDimensions(out uint dim);\n";
- sb << "__target_intrinsic(glsl, \"texelFetch($$P, $0)$$z\")\n";
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, $1)$$z\")\n";
sb << "T Load(int location);\n";
sb << "T Load(int location, out uint status);\n";
- sb << "__target_intrinsic(glsl, \"texelFetch($$P, int($0))$$z\")\n";
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, int($1))$$z\")\n";
sb << "__subscript(uint index) -> T";
if (kBaseBufferAccessLevels[aa].access != SLANG_RESOURCE_ACCESS_READ)
diff --git a/source/slang/hlsl.meta.slang.h b/source/slang/hlsl.meta.slang.h
index 982f887b0..2f42e9382 100644
--- a/source/slang/hlsl.meta.slang.h
+++ b/source/slang/hlsl.meta.slang.h
@@ -1075,12 +1075,12 @@ for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)
sb << "void GetDimensions(out uint dim);\n";
- sb << "__target_intrinsic(glsl, \"texelFetch($P, $0)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, $1)$z\")\n";
sb << "T Load(int location);\n";
sb << "T Load(int location, out uint status);\n";
- sb << "__target_intrinsic(glsl, \"texelFetch($P, int($0))$z\")\n";
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, int($1))$z\")\n";
sb << "__subscript(uint index) -> T";
if (kBaseBufferAccessLevels[aa].access != SLANG_RESOURCE_ACCESS_READ)
diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h
index dedc906d0..46a804a1c 100644
--- a/source/slang/ir-insts.h
+++ b/source/slang/ir-insts.h
@@ -47,14 +47,25 @@ struct IRLoopControlDecoration : IRDecoration
IRLoopControl mode;
};
-struct IRTargetDecoration : IRDecoration
-{
- enum { kDecorationOp = kIRDecorationOp_Target };
+struct IRTargetSpecificDecoration : IRDecoration
+{
// TODO: have a more structured representation of target specifiers
String targetName;
};
+struct IRTargetDecoration : IRTargetSpecificDecoration
+{
+ enum { kDecorationOp = kIRDecorationOp_Target };
+};
+
+struct IRTargetIntrinsicDecoration : IRTargetSpecificDecoration
+{
+ enum { kDecorationOp = kIRDecorationOp_TargetIntrinsic };
+
+ String definition;
+};
+
//
// An IR node to represent a reference to an AST-level
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index b965f908c..77aac3f5a 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -3226,6 +3226,15 @@ namespace Slang
}
break;
+ case kIRDecorationOp_TargetIntrinsic:
+ {
+ auto originalDecoration = (IRTargetIntrinsicDecoration*)dd;
+ auto newDecoration = context->builder->addDecoration<IRTargetIntrinsicDecoration>(clonedValue);
+ newDecoration->targetName = originalDecoration->targetName;
+ newDecoration->definition = originalDecoration->definition;
+ }
+ break;
+
default:
// Don't clone any decorations we don't understand.
break;
diff --git a/source/slang/ir.h b/source/slang/ir.h
index fe6fab5f6..1b4529a3c 100644
--- a/source/slang/ir.h
+++ b/source/slang/ir.h
@@ -106,6 +106,7 @@ enum IRDecorationOp : uint16_t
kIRDecorationOp_Layout,
kIRDecorationOp_LoopControl,
kIRDecorationOp_Target,
+ kIRDecorationOp_TargetIntrinsic,
};
// A "decoration" that gets applied to an instruction.
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp
index 4eb762333..bde50aa89 100644
--- a/source/slang/lower-to-ir.cpp
+++ b/source/slang/lower-to-ir.cpp
@@ -3757,6 +3757,24 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
decoration->targetName = targetMod->targetToken.Content;
}
+ // If this declaration was marked as having a target-specific lowering
+ // for a particular target, then handle that here.
+ for (auto targetMod : decl->GetModifiersOfType<TargetIntrinsicModifier>())
+ {
+ auto decoration = getBuilder()->addDecoration<IRTargetIntrinsicDecoration>(irFunc);
+ decoration->targetName = targetMod->targetToken.Content;
+
+ auto definitionToken = targetMod->definitionToken;
+ if (definitionToken.type == TokenType::StringLiteral)
+ {
+ decoration->definition = getStringLiteralTokenValue(definitionToken);
+ }
+ else
+ {
+ decoration->definition = definitionToken.Content;
+ }
+ }
+
// For convenience, ensure that any additional global
// values that were emitted while outputting the function
// body appear before the function itself in the list
diff --git a/tests/bindings/glsl-parameter-blocks.slang b/tests/bindings/glsl-parameter-blocks.slang
index 64e302d90..48eacbb0f 100644
--- a/tests/bindings/glsl-parameter-blocks.slang
+++ b/tests/bindings/glsl-parameter-blocks.slang
@@ -1,5 +1,5 @@
#version 450 core
-//TEST_DISABLED:CROSS_COMPILE: -profile ps_5_0 -entry main -target spirv-assembly
+//TEST:CROSS_COMPILE: -profile ps_5_0 -entry main -target spirv-assembly
// Note: disabled because the translation of `Texture2D.Sample()`
// requires handling of local variables with resource types in the IR.
diff --git a/tests/bindings/glsl-parameter-blocks.slang.glsl b/tests/bindings/glsl-parameter-blocks.slang.glsl
index 9956800f1..e34101983 100644
--- a/tests/bindings/glsl-parameter-blocks.slang.glsl
+++ b/tests/bindings/glsl-parameter-blocks.slang.glsl
@@ -1,37 +1,44 @@
//TEST_IGNORE_FILE:
#version 450 core
-struct Test
+struct _ST04Test
{
vec4 a;
};
layout(binding = 0, set = 1)
-uniform gTest_S1
+uniform _S1
{
- Test gTest;
+ _ST04Test _SV05gTestL0;
};
layout(binding = 1, set = 1)
-uniform texture2D gTest_t;
+uniform texture2D _SV05gTestL1;
layout(binding = 2, set = 1)
-uniform sampler gTest_s;
-
-vec4 main_(vec2 uv)
-{
- return gTest.a + texture(sampler2D(gTest_t, gTest_s), uv);
-}
+uniform sampler _SV05gTestL2;
layout(location = 0)
-in vec2 SLANG_in_uv;
+in vec2 _S3;
layout(location = 0)
-out vec4 SLANG_out_main_result;
+out vec4 _S2;
void main()
{
- vec2 uv = SLANG_in_uv;
- vec4 main_result = main_(uv);
- SLANG_out_main_result = main_result;
+ vec2 _S4 = _S3;
+
+ vec2 _S5 = _S4;
+
+ vec4 _S6 = _SV05gTestL0.a;
+
+ vec2 _S7 = _S5;
+
+
+ vec4 _S8 = texture(sampler2D(_SV05gTestL1, _SV05gTestL2), _S7);
+
+ vec4 _S9 = _S6 + _S8;
+ _S2 = _S9;
+
+ return;
}