summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/core.meta.slang32
-rw-r--r--source/slang/core.meta.slang.h32
-rw-r--r--source/slang/emit.cpp81
-rw-r--r--tests/compute/half-texture.slang41
-rw-r--r--tests/compute/half-texture.slang.1.expected51
-rw-r--r--tests/compute/half-texture.slang.expected185
-rw-r--r--tools/render-test/shader-renderer-util.cpp5
7 files changed, 379 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(")");
}
diff --git a/tests/compute/half-texture.slang b/tests/compute/half-texture.slang
new file mode 100644
index 000000000..635336c66
--- /dev/null
+++ b/tests/compute/half-texture.slang
@@ -0,0 +1,41 @@
+//TEST:SIMPLE: -target spirv -entry computeMain -profile cs_6_2
+//TEST:SIMPLE: -target hlsl -entry computeMain -profile cs_6_2
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], stride=16):dxbinding(0),glbinding(0),out
+RWStructuredBuffer<int> outputBuffer;
+
+//TEST_INPUT: Texture2D(size=4):dxbinding(1),glbinding(1)
+RWTexture2D<half> halfTexture;
+//TEST_INPUT: Texture2D(size=4):dxbinding(2),glbinding(2)
+RWTexture2D<half2> halfTexture2;
+//TEST_INPUT: Texture2D(size=4):dxbinding(3),glbinding(3)
+RWTexture2D<half4> halfTexture4;
+
+//TEST_INPUT: Sampler : dxbinding(0),glbinding(0)
+SamplerState s;
+
+[numthreads(4, 4, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int2 pos = int2(dispatchThreadID.xy);
+ float2 uv = pos * (1.0f / 3.0f);
+ int2 pos2 = int2(3 - pos.y, 3 - pos.x);
+
+#if 0
+ half h = halfTexture.Sample(s, uv);
+ half2 h2 = halfTexture2.Sample(s, uv);
+ half4 h4 = halfTexture4.Sample(s, uv);
+#else
+ half h = halfTexture[pos2];
+ half2 h2 = halfTexture2[pos2];
+ half4 h4 = halfTexture4[pos2];
+#endif
+
+ // Store a results
+ halfTexture[pos] = h2.x + h2.y;
+ halfTexture2[pos] = h4.xy;
+ halfTexture4[pos] = half4(h2, h, h);
+
+ int index = pos.x + pos.y * 4;
+ outputBuffer[index] = index;
+} \ No newline at end of file
diff --git a/tests/compute/half-texture.slang.1.expected b/tests/compute/half-texture.slang.1.expected
new file mode 100644
index 000000000..5d3f84e74
--- /dev/null
+++ b/tests/compute/half-texture.slang.1.expected
@@ -0,0 +1,51 @@
+result code = 0
+standard error = {
+}
+standard output = {
+#pragma pack_matrix(column_major)
+
+#line 18 "tests/compute/half-texture.slang"
+RWTexture2D<half > halfTexture_0 : register(u1);
+
+
+#line 30
+RWTexture2D<vector<half,2> > halfTexture2_0 : register(u2);
+
+
+#line 31
+RWTexture2D<vector<half,4> > halfTexture4_0 : register(u3);
+
+
+#line 40
+RWStructuredBuffer<int > outputBuffer_0 : register(u0);
+
+
+#line 18
+[shader("compute")][numthreads(4, 4, 1)]
+void computeMain(vector<uint,3> dispatchThreadID_0 : SV_DISPATCHTHREADID)
+{
+
+#line 20
+ vector<int,2> pos_0 = (vector<int,2>) dispatchThreadID_0.xy;
+ float _S1 = 1.00000000000000000000 / 3.00000000000000000000;
+ vector<int,2> pos2_0 = vector<int,2>(3 - pos_0.y, 3 - pos_0.x);
+
+#line 29
+ half h_0 = halfTexture_0[(vector<uint,2>) pos2_0];
+ vector<half,2> h2_0 = halfTexture2_0[(vector<uint,2>) pos2_0];
+ vector<half,4> h4_0 = halfTexture4_0[(vector<uint,2>) pos2_0];
+
+
+
+ halfTexture_0[(vector<uint,2>) pos_0] = h2_0.x + h2_0.y;
+ halfTexture2_0[(vector<uint,2>) pos_0] = h4_0.xy;
+ halfTexture4_0[(vector<uint,2>) pos_0] = vector<half,4>(h2_0, h_0, h_0);
+
+ int index_0 = pos_0.x + pos_0.y * 4;
+ outputBuffer_0[(uint) index_0] = index_0;
+
+#line 18
+ return;
+}
+
+}
diff --git a/tests/compute/half-texture.slang.expected b/tests/compute/half-texture.slang.expected
new file mode 100644
index 000000000..dc8d5dcbe
--- /dev/null
+++ b/tests/compute/half-texture.slang.expected
@@ -0,0 +1,185 @@
+result code = 0
+standard error = {
+}
+standard output = {
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 129
+
+ Capability Shader
+ Capability Float16
+ Capability StorageImageExtendedFormats
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint GLCompute 4 "main" 13
+ ExecutionMode 4 LocalSize 4 4 1
+ Source GLSL 450
+ SourceExtension "GL_EXT_shader_16bit_storage"
+ SourceExtension "GL_GOOGLE_cpp_style_line_directive"
+ SourceExtension "GL_KHX_shader_explicit_arithmetic_types"
+ Name 4 "main"
+ Name 9 "pos_0"
+ Name 13 "gl_GlobalInvocationID"
+ Name 22 "pos2_0"
+ Name 36 "h_0"
+ Name 40 "halfTexture_0"
+ Name 51 "h2_0"
+ Name 54 "halfTexture2_0"
+ Name 65 "h4_0"
+ Name 68 "halfTexture4_0"
+ Name 108 "index_0"
+ Name 117 "_S1"
+ MemberName 117(_S1) 0 "_data"
+ Name 119 "outputBuffer_0"
+ Decorate 13(gl_GlobalInvocationID) BuiltIn GlobalInvocationId
+ Decorate 40(halfTexture_0) DescriptorSet 0
+ Decorate 40(halfTexture_0) Binding 1
+ Decorate 54(halfTexture2_0) DescriptorSet 0
+ Decorate 54(halfTexture2_0) Binding 2
+ Decorate 68(halfTexture4_0) DescriptorSet 0
+ Decorate 68(halfTexture4_0) Binding 3
+ Decorate 116 ArrayStride 4
+ MemberDecorate 117(_S1) 0 Offset 0
+ Decorate 117(_S1) BufferBlock
+ Decorate 119(outputBuffer_0) DescriptorSet 0
+ Decorate 119(outputBuffer_0) Binding 0
+ Decorate 128 BuiltIn WorkgroupSize
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeInt 32 1
+ 7: TypeVector 6(int) 2
+ 8: TypePointer Function 7(ivec2)
+ 10: TypeInt 32 0
+ 11: TypeVector 10(int) 3
+ 12: TypePointer Input 11(ivec3)
+13(gl_GlobalInvocationID): 12(ptr) Variable Input
+ 19: TypeVector 10(int) 2
+ 23: 6(int) Constant 3
+ 24: 10(int) Constant 1
+ 25: TypePointer Function 6(int)
+ 29: 10(int) Constant 0
+ 34: TypeFloat 16
+ 35: TypePointer Function 34(float16_t)
+ 37: TypeFloat 32
+ 38: TypeImage 37(float) 2D nonsampled format:R16f
+ 39: TypePointer UniformConstant 38
+40(halfTexture_0): 39(ptr) Variable UniformConstant
+ 45: TypeVector 37(float) 4
+ 49: TypeVector 34(float16_t) 2
+ 50: TypePointer Function 49(f16vec2)
+ 52: TypeImage 37(float) 2D nonsampled format:Rg16f
+ 53: TypePointer UniformConstant 52
+54(halfTexture2_0): 53(ptr) Variable UniformConstant
+ 60: TypeVector 37(float) 2
+ 63: TypeVector 34(float16_t) 4
+ 64: TypePointer Function 63(f16vec4)
+ 66: TypeImage 37(float) 2D nonsampled format:Rgba16f
+ 67: TypePointer UniformConstant 66
+68(halfTexture4_0): 67(ptr) Variable UniformConstant
+ 84:34(float16_t) Constant 0
+ 113: 6(int) Constant 4
+ 116: TypeRuntimeArray 6(int)
+ 117(_S1): TypeStruct 116
+ 118: TypePointer Uniform 117(_S1)
+119(outputBuffer_0): 118(ptr) Variable Uniform
+ 120: 6(int) Constant 0
+ 124: TypePointer Uniform 6(int)
+ 127: 10(int) Constant 4
+ 128: 11(ivec3) ConstantComposite 127 127 24
+ 4(main): 2 Function None 3
+ 5: Label
+ 9(pos_0): 8(ptr) Variable Function
+ 22(pos2_0): 8(ptr) Variable Function
+ 36(h_0): 35(ptr) Variable Function
+ 51(h2_0): 50(ptr) Variable Function
+ 65(h4_0): 64(ptr) Variable Function
+ 108(index_0): 25(ptr) Variable Function
+ 14: 11(ivec3) Load 13(gl_GlobalInvocationID)
+ 15: 10(int) CompositeExtract 14 0
+ 16: 10(int) CompositeExtract 14 1
+ 17: 10(int) CompositeExtract 14 2
+ 18: 11(ivec3) CompositeConstruct 15 16 17
+ 20: 19(ivec2) VectorShuffle 18 18 0 1
+ 21: 7(ivec2) Bitcast 20
+ Store 9(pos_0) 21
+ 26: 25(ptr) AccessChain 9(pos_0) 24
+ 27: 6(int) Load 26
+ 28: 6(int) ISub 23 27
+ 30: 25(ptr) AccessChain 9(pos_0) 29
+ 31: 6(int) Load 30
+ 32: 6(int) ISub 23 31
+ 33: 7(ivec2) CompositeConstruct 28 32
+ Store 22(pos2_0) 33
+ 41: 38 Load 40(halfTexture_0)
+ 42: 7(ivec2) Load 22(pos2_0)
+ 43: 19(ivec2) Bitcast 42
+ 44: 7(ivec2) Bitcast 43
+ 46: 45(fvec4) ImageRead 41 44
+ 47: 37(float) CompositeExtract 46 0
+ 48:34(float16_t) FConvert 47
+ Store 36(h_0) 48
+ 55: 52 Load 54(halfTexture2_0)
+ 56: 7(ivec2) Load 22(pos2_0)
+ 57: 19(ivec2) Bitcast 56
+ 58: 7(ivec2) Bitcast 57
+ 59: 45(fvec4) ImageRead 55 58
+ 61: 60(fvec2) VectorShuffle 59 59 0 1
+ 62: 49(f16vec2) FConvert 61
+ Store 51(h2_0) 62
+ 69: 66 Load 68(halfTexture4_0)
+ 70: 7(ivec2) Load 22(pos2_0)
+ 71: 19(ivec2) Bitcast 70
+ 72: 7(ivec2) Bitcast 71
+ 73: 45(fvec4) ImageRead 69 72
+ 74: 63(f16vec4) FConvert 73
+ Store 65(h4_0) 74
+ 75: 38 Load 40(halfTexture_0)
+ 76: 7(ivec2) Load 9(pos_0)
+ 77: 19(ivec2) Bitcast 76
+ 78: 7(ivec2) Bitcast 77
+ 79: 35(ptr) AccessChain 51(h2_0) 29
+ 80:34(float16_t) Load 79
+ 81: 35(ptr) AccessChain 51(h2_0) 24
+ 82:34(float16_t) Load 81
+ 83:34(float16_t) FAdd 80 82
+ 85: 63(f16vec4) CompositeConstruct 83 84 84 84
+ 86: 45(fvec4) FConvert 85
+ ImageWrite 75 78 86
+ 87: 52 Load 54(halfTexture2_0)
+ 88: 7(ivec2) Load 9(pos_0)
+ 89: 19(ivec2) Bitcast 88
+ 90: 7(ivec2) Bitcast 89
+ 91: 63(f16vec4) Load 65(h4_0)
+ 92: 49(f16vec2) VectorShuffle 91 91 0 1
+ 93:34(float16_t) CompositeExtract 92 0
+ 94:34(float16_t) CompositeExtract 92 1
+ 95: 63(f16vec4) CompositeConstruct 93 94 84 84
+ 96: 45(fvec4) FConvert 95
+ ImageWrite 87 90 96
+ 97: 66 Load 68(halfTexture4_0)
+ 98: 7(ivec2) Load 9(pos_0)
+ 99: 19(ivec2) Bitcast 98
+ 100: 7(ivec2) Bitcast 99
+ 101: 49(f16vec2) Load 51(h2_0)
+ 102:34(float16_t) Load 36(h_0)
+ 103:34(float16_t) Load 36(h_0)
+ 104:34(float16_t) CompositeExtract 101 0
+ 105:34(float16_t) CompositeExtract 101 1
+ 106: 63(f16vec4) CompositeConstruct 104 105 102 103
+ 107: 45(fvec4) FConvert 106
+ ImageWrite 97 100 107
+ 109: 25(ptr) AccessChain 9(pos_0) 29
+ 110: 6(int) Load 109
+ 111: 25(ptr) AccessChain 9(pos_0) 24
+ 112: 6(int) Load 111
+ 114: 6(int) IMul 112 113
+ 115: 6(int) IAdd 110 114
+ Store 108(index_0) 115
+ 121: 6(int) Load 108(index_0)
+ 122: 10(int) Bitcast 121
+ 123: 6(int) Load 108(index_0)
+ 125: 124(ptr) AccessChain 119(outputBuffer_0) 120 122
+ Store 125 123
+ Return
+ FunctionEnd
+}
diff --git a/tools/render-test/shader-renderer-util.cpp b/tools/render-test/shader-renderer-util.cpp
index 3dc717c5b..13effdd08 100644
--- a/tools/render-test/shader-renderer-util.cpp
+++ b/tools/render-test/shader-renderer-util.cpp
@@ -392,6 +392,11 @@ static RefPtr<SamplerState> _createSamplerState(
texture,
viewDesc);
+ if (!textureView)
+ {
+ return SLANG_FAIL;
+ }
+
descriptorSet->setResource(rangeIndex, 0, textureView);
if(srcEntry.isOutput)