diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-03-27 12:25:43 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-03-27 12:25:43 -0400 |
| commit | c9930ea56ce0d3d9783d4d2482edb91cb765109e (patch) | |
| tree | 42bc3b4d44771d1c1bca389f20b9321793d268e1 /source | |
| parent | 047adbd4dd3dd6e3098adcb63a8ac475ae06d20d (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.slang | 32 | ||||
| -rw-r--r-- | source/slang/core.meta.slang.h | 32 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 81 |
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(")"); } |
