summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-03-27 12:25:43 -0400
committerGitHub <noreply@github.com>2019-03-27 12:25:43 -0400
commitc9930ea56ce0d3d9783d4d2482edb91cb765109e (patch)
tree42bc3b4d44771d1c1bca389f20b9321793d268e1 /source
parent047adbd4dd3dd6e3098adcb63a8ac475ae06d20d (diff)
GLSL half texture access (#931)
* * Added $c macro - that will do casting to target type. Used here to cast texture reads back to half. Works in tandem with $z which will close parens. * half-texture.slang test * Make binding failing if TextureView fails * Simplify logic around parens. * Improve comment around $c macro. * Test against hlsl output to avoid error on CI.
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang32
-rw-r--r--source/slang/core.meta.slang.h32
-rw-r--r--source/slang/emit.cpp81
3 files changed, 97 insertions, 48 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index e42669822..dc7d1f3fb 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -703,12 +703,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if (isMultisample)
{
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- sb << "__target_intrinsic(glsl, \"texelFetch($0, $1, $3)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctexelFetch($0, $1, $3)$z\")\n";
}
else
{
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- sb << "__target_intrinsic(glsl, \"texelFetch($0, ";
+ sb << "__target_intrinsic(glsl, \"$ctexelFetch($0, ";
if( needsMipLevel )
{
sb << "($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount];
@@ -730,12 +730,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if (isMultisample)
{
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- sb << "__target_intrinsic(glsl, \"texelFetchOffset($0, $0, $1, $2)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctexelFetchOffset($0, $0, $1, $2)$z\")\n";
}
else
{
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- sb << "__target_intrinsic(glsl, \"texelFetch($0, ";
+ sb << "__target_intrinsic(glsl, \"$ctexelFetch($0, ";
if( needsMipLevel )
{
sb << "($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount];
@@ -786,7 +786,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
case SLANG_RESOURCE_ACCESS_NONE:
case SLANG_RESOURCE_ACCESS_READ:
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- sb << "__target_intrinsic(glsl, \"texelFetch($0, " << ivecN << "($1)";
+ sb << "__target_intrinsic(glsl, \"$ctexelFetch($0, " << ivecN << "($1)";
if( !isMultisample )
{
sb << ", 0";
@@ -799,7 +799,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
break;
default:
- sb << "__target_intrinsic(glsl, \"imageLoad($0, " << ivecN << "($1)";
+ sb << "__target_intrinsic(glsl, \"$cimageLoad($0, " << ivecN << "($1)";
if( isMultisample )
{
// TODO: how to handle passing through sample index?
@@ -834,13 +834,13 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
{
// `Sample()`
- sb << "__target_intrinsic(glsl, \"texture($p, $2)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctexture($p, $2)$z\")\n";
sb << "T Sample(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n";
if( baseShape != TextureFlavor::Shape::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureOffset($p, $2, $3)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureOffset($p, $2, $3)$z\")\n";
sb << "T Sample(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "constexpr int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
@@ -864,13 +864,13 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
// `SampleBias()`
- sb << "__target_intrinsic(glsl, \"texture($p, $2, $3)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctexture($p, $2, $3)$z\")\n";
sb << "T SampleBias(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias);\n";
if( baseShape != TextureFlavor::Shape::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureOffset($p, $2, $3, $4)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureOffset($p, $2, $3, $4)$z\")\n";
sb << "T SampleBias(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias, ";
sb << "constexpr int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
@@ -898,7 +898,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if (extCoordCount < 3)
extCoordCount = 3;
- sb << "__target_intrinsic(glsl, \"textureLod($p, ";
+ sb << "__target_intrinsic(glsl, \"$ctextureLod($p, ";
sb << "vec" << extCoordCount << "($2,";
for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
@@ -916,7 +916,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if (extCoordCount < 3)
extCoordCount = 3;
- sb << "__target_intrinsic(glsl, \"textureGrad($p, ";
+ sb << "__target_intrinsic(glsl, \"$ctextureGrad($p, ";
sb << "vec" << extCoordCount << "($2,";
for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
@@ -953,7 +953,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
}
- sb << "__target_intrinsic(glsl, \"textureGrad($p, $2, $3, $4)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureGrad($p, $2, $3, $4)$z\")\n";
// sb << "__intrinsic_op(sampleGrad)\n";
sb << "T SampleGrad(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
@@ -963,7 +963,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if( baseShape != TextureFlavor::Shape::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureGradOffset($p, $2, $3, $4, $5)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureGradOffset($p, $2, $3, $4, $5)$z\")\n";
// sb << "__intrinsic_op(sampleGrad)\n";
sb << "T SampleGrad(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
@@ -974,14 +974,14 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
// `SampleLevel`
- sb << "__target_intrinsic(glsl, \"textureLod($p, $2, $3)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureLod($p, $2, $3)$z\")\n";
sb << "T SampleLevel(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "float level);\n";
if( baseShape != TextureFlavor::Shape::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureLodOffset($p, $2, $3, $4)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureLodOffset($p, $2, $3, $4)$z\")\n";
sb << "T SampleLevel(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "float level, ";
diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h
index 6dc84df43..819387074 100644
--- a/source/slang/core.meta.slang.h
+++ b/source/slang/core.meta.slang.h
@@ -721,12 +721,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if (isMultisample)
{
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- sb << "__target_intrinsic(glsl, \"texelFetch($0, $1, $3)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctexelFetch($0, $1, $3)$z\")\n";
}
else
{
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- sb << "__target_intrinsic(glsl, \"texelFetch($0, ";
+ sb << "__target_intrinsic(glsl, \"$ctexelFetch($0, ";
if( needsMipLevel )
{
sb << "($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount];
@@ -748,12 +748,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if (isMultisample)
{
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- sb << "__target_intrinsic(glsl, \"texelFetchOffset($0, $0, $1, $2)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctexelFetchOffset($0, $0, $1, $2)$z\")\n";
}
else
{
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- sb << "__target_intrinsic(glsl, \"texelFetch($0, ";
+ sb << "__target_intrinsic(glsl, \"$ctexelFetch($0, ";
if( needsMipLevel )
{
sb << "($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount];
@@ -804,7 +804,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
case SLANG_RESOURCE_ACCESS_NONE:
case SLANG_RESOURCE_ACCESS_READ:
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
- sb << "__target_intrinsic(glsl, \"texelFetch($0, " << ivecN << "($1)";
+ sb << "__target_intrinsic(glsl, \"$ctexelFetch($0, " << ivecN << "($1)";
if( !isMultisample )
{
sb << ", 0";
@@ -817,7 +817,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
break;
default:
- sb << "__target_intrinsic(glsl, \"imageLoad($0, " << ivecN << "($1)";
+ sb << "__target_intrinsic(glsl, \"$cimageLoad($0, " << ivecN << "($1)";
if( isMultisample )
{
// TODO: how to handle passing through sample index?
@@ -852,13 +852,13 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
{
// `Sample()`
- sb << "__target_intrinsic(glsl, \"texture($p, $2)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctexture($p, $2)$z\")\n";
sb << "T Sample(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n";
if( baseShape != TextureFlavor::Shape::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureOffset($p, $2, $3)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureOffset($p, $2, $3)$z\")\n";
sb << "T Sample(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "constexpr int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
@@ -882,13 +882,13 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
// `SampleBias()`
- sb << "__target_intrinsic(glsl, \"texture($p, $2, $3)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctexture($p, $2, $3)$z\")\n";
sb << "T SampleBias(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias);\n";
if( baseShape != TextureFlavor::Shape::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureOffset($p, $2, $3, $4)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureOffset($p, $2, $3, $4)$z\")\n";
sb << "T SampleBias(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias, ";
sb << "constexpr int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
@@ -916,7 +916,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if (extCoordCount < 3)
extCoordCount = 3;
- sb << "__target_intrinsic(glsl, \"textureLod($p, ";
+ sb << "__target_intrinsic(glsl, \"$ctextureLod($p, ";
sb << "vec" << extCoordCount << "($2,";
for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
@@ -934,7 +934,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if (extCoordCount < 3)
extCoordCount = 3;
- sb << "__target_intrinsic(glsl, \"textureGrad($p, ";
+ sb << "__target_intrinsic(glsl, \"$ctextureGrad($p, ";
sb << "vec" << extCoordCount << "($2,";
for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii)
@@ -971,7 +971,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
}
- sb << "__target_intrinsic(glsl, \"textureGrad($p, $2, $3, $4)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureGrad($p, $2, $3, $4)$z\")\n";
// sb << "__intrinsic_op(sampleGrad)\n";
sb << "T SampleGrad(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
@@ -981,7 +981,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if( baseShape != TextureFlavor::Shape::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureGradOffset($p, $2, $3, $4, $5)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureGradOffset($p, $2, $3, $4, $5)$z\")\n";
// sb << "__intrinsic_op(sampleGrad)\n";
sb << "T SampleGrad(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
@@ -992,14 +992,14 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
// `SampleLevel`
- sb << "__target_intrinsic(glsl, \"textureLod($p, $2, $3)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureLod($p, $2, $3)$z\")\n";
sb << "T SampleLevel(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "float level);\n";
if( baseShape != TextureFlavor::Shape::ShapeCube )
{
- sb << "__target_intrinsic(glsl, \"textureLodOffset($p, $2, $3, $4)$z\")\n";
+ sb << "__target_intrinsic(glsl, \"$ctextureLodOffset($p, $2, $3, $4)$z\")\n";
sb << "T SampleLevel(SamplerState s, ";
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
sb << "float level, ";
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 5a2a93a53..5a8a349b3 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -558,7 +558,7 @@ struct EmitVisitor
// Emit a `#line` directive to the output.
- // Doesn't udpate state of source-location tracking.
+ // Doesn't update state of source-location tracking.
void emitLineDirective(
HumaneSourceLoc const& sourceLocation)
{
@@ -807,7 +807,8 @@ struct EmitVisitor
}
void emitGLSLTypePrefix(
- IRType* type)
+ IRType* type,
+ bool promoteHalfToFloat = false)
{
switch (type->op)
{
@@ -830,17 +831,24 @@ struct EmitVisitor
case kIROp_HalfType:
{
_requireHalf();
- Emit("f16");
+ if (promoteHalfToFloat)
+ {
+ // no prefix
+ }
+ else
+ {
+ Emit("f16");
+ }
break;
}
case kIROp_DoubleType: Emit("d"); break;
case kIROp_VectorType:
- emitGLSLTypePrefix(cast<IRVectorType>(type)->getElementType());
+ emitGLSLTypePrefix(cast<IRVectorType>(type)->getElementType(), promoteHalfToFloat);
break;
case kIROp_MatrixType:
- emitGLSLTypePrefix(cast<IRMatrixType>(type)->getElementType());
+ emitGLSLTypePrefix(cast<IRMatrixType>(type)->getElementType(), promoteHalfToFloat);
break;
default:
@@ -907,7 +915,15 @@ struct EmitVisitor
IRTextureTypeBase* type,
char const* baseName)
{
- emitGLSLTypePrefix(type->getElementType());
+ if (type->getElementType()->op == kIROp_HalfType)
+ {
+ // Texture access is always as float types if half is specified
+
+ }
+ else
+ {
+ emitGLSLTypePrefix(type->getElementType(), true);
+ }
Emit(baseName);
switch (type->GetBaseShape())
@@ -3020,7 +3036,6 @@ struct EmitVisitor
auto name = String(targetIntrinsic->getDefinition());
-
if(isOrdinaryName(name))
{
// Simple case: it is just an ordinary name, so we call it like a builtin.
@@ -3041,20 +3056,19 @@ struct EmitVisitor
}
else
{
- // If it returns void -> then we don't need parenthesis
+ int openParenCount = 0;
const auto returnType = inst->getDataType();
- const bool isVoid = as<IRVoidType>(returnType) != nullptr;
-
- // We could determine here is the return type is void... if so no braces?
-
- // General case: we are going to emit some more complex text.
- if (!isVoid)
+ // If it returns void -> then we don't need parenthesis
+ if (as<IRVoidType>(returnType) == nullptr)
{
Emit("(");
+ openParenCount++;
}
+ // General case: we are going to emit some more complex text.
+
char const* cursor = name.begin();
char const* end = name.end();
while(cursor != end)
@@ -3120,6 +3134,40 @@ struct EmitVisitor
}
break;
+ case 'c':
+ {
+ // When doing texture access in glsl the result may need to be cast.
+ // In particular if the underlying texture is 'half' based, glsl only accesses (read/write)
+ // as float. So we need to cast to a half type on output.
+ // When storing into a texture it is still the case the value written must be half - but
+ // we don't need to do any casting there as half is coerced to float without a problem.
+ SLANG_RELEASE_ASSERT(argCount >= 1);
+
+ auto textureArg = args[0].get();
+ if (auto baseTextureType = as<IRTextureType>(textureArg->getDataType()))
+ {
+ auto elementType = baseTextureType->getElementType();
+ IRBasicType* underlyingType = nullptr;
+ if (auto basicType = as<IRBasicType>(elementType))
+ {
+ underlyingType = basicType;
+ }
+ else if (auto vectorType = as<IRVectorType>(elementType))
+ {
+ underlyingType = as<IRBasicType>(vectorType->getElementType());
+ }
+
+ // We only need to output a cast if the underlying type is half.
+ if (underlyingType && underlyingType->op == kIROp_HalfType)
+ {
+ emitSimpleTypeImpl(elementType);
+ emit("(");
+ openParenCount++;
+ }
+ }
+ }
+ break;
+
case 'z':
{
// If we are calling a D3D texturing operation in the form t.Foo(s, ...),
@@ -3209,7 +3257,7 @@ struct EmitVisitor
}
else
{
- // Othwerwise, we need to construct a 4-vector from the
+ // Otherwise, we need to construct a 4-vector from the
// value we have, padding it out with zero elements as
// needed.
//
@@ -3413,7 +3461,8 @@ struct EmitVisitor
}
}
- if (!isVoid)
+ // Close any remaining open parens
+ for (; openParenCount > 0; --openParenCount)
{
Emit(")");
}