summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-02-18 08:08:46 -0800
committerGitHub <noreply@github.com>2018-02-18 08:08:46 -0800
commit51cdcad24b5271ac8c0f816174c6a760e264ed9e (patch)
tree30beaa85671168ac2c73b08f4f20d894cbca88f9 /source
parent8c872597540b2287bc18d5723c7ae3b8832246b8 (diff)
stdlib fixes for Vulkan (#414)
* stdlib fixes for Vulkan - Make sure to emit `image*` instead of `texture*` for `RWTexture*` types - Change `GetDimensions` to call `imageSize` instead of `textureSize` when we use images - Always output a `layout(rgba32f)` for variables that translate to `image` types - TODO: we should emit an appropriate format based on the type, or let the user specify one - Fix GLSL translation for `any()` function (required boolean inputs) - Add GLSL translation for `GroupMemoryBarrierWithGroupSync()` - Map HLSL `groupshared` to GLSL `shared` These together are enough to get the Falor `ComputeShader` example to work. * fixup for warning
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang65
-rw-r--r--source/slang/core.meta.slang.h65
-rw-r--r--source/slang/emit.cpp87
-rw-r--r--source/slang/hlsl.meta.slang31
-rw-r--r--source/slang/hlsl.meta.slang.h32
5 files changed, 219 insertions, 61 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index f531d0f93..b395bd08b 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -462,34 +462,47 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "__target_intrinsic(glsl, \"(";
int aa = 1;
- String lodStr = "0";
+ String lodStr = ", 0";
if (includeMipInfo)
{
int mipLevelArg = aa++;
- lodStr = "int($";
+ lodStr = ", int($";
lodStr.append(mipLevelArg);
lodStr.append(")");
}
+ String opStr = " = textureSize($$P" + lodStr;
+ switch( access )
+ {
+ case SLANG_RESOURCE_ACCESS_READ_WRITE:
+ case SLANG_RESOURCE_ACCESS_RASTER_ORDERED:
+ opStr = " = imageSize($0";
+ break;
+
+ default:
+ break;
+ }
+
+
int cc = 0;
switch(baseShape)
{
case TextureType::Shape1D:
- sb << "($" << aa++ << " = textureSize($$P, " << lodStr << "))";
+ sb << "($" << aa++ << opStr << "))";
cc = 1;
break;
case TextureType::Shape2D:
case TextureType::ShapeCube:
- sb << "($" << aa++ << " = textureSize($$P, " << lodStr << ").x)";
- sb << ", ($" << aa++ << " = textureSize($$P, " << lodStr << ").y)";
+ sb << "($" << aa++ << opStr << ").x)";
+ sb << ", ($" << aa++ << opStr << ").y)";
cc = 2;
break;
case TextureType::Shape3D:
- sb << "($" << aa++ << " = textureSize($$P, " << lodStr << ").x)";
- sb << ", ($" << aa++ << " = textureSize($$P, " << lodStr << ").y)";
- sb << ", ($" << aa++ << " = textureSize($$P, " << lodStr << ").z)";
+ sb << "($" << aa++ << opStr << ").x)";
+ sb << ", ($" << aa++ << opStr << ").y)";
+ sb << ", ($" << aa++ << opStr << ").z)";
cc = 3;
break;
@@ -500,7 +513,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if(isArray)
{
- sb << ", ($" << aa++ << " = textureSize($$P, " << lodStr << ")." << kComponentNames[cc] << ")";
+ sb << ", ($" << aa++ << opStr << ")." << kComponentNames[cc] << ")";
}
if(isMultisample)
@@ -627,13 +640,30 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if(baseShape != TextureType::ShapeCube)
{
+ int N = kBaseTextureTypes[tt].coordCount + isArray;
+
+ char const* uintNs[] = { "", "uint", "uint2", "uint3", "uint4" };
+ char const* ivecNs[] = { "", "int", "ivec2", "ivec3", "ivec4" };
+
+ auto uintN = uintNs[N];
+ auto ivecN = ivecNs[N];
+
// subscript operator
- sb << "__subscript(uint";
- if(kBaseTextureTypes[tt].coordCount + isArray > 1)
- {
- sb << kBaseTextureTypes[tt].coordCount + isArray;
- }
- sb << " location) -> T";
+ sb << "__subscript(" << uintN << " location) -> T {\n";
+
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, " << ivecN << "($1)";
+
+ if( !isMultisample )
+ {
+ sb << ", 0";
+ }
+ else
+ {
+ // TODO: how to handle this...
+ sb << ", 0";
+ }
+
+ sb << ")$$z\") get;\n";
// Depending on the access level of the texture type,
// we either have just a getter (the default), or both
@@ -642,13 +672,14 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
{
case SLANG_RESOURCE_ACCESS_NONE:
case SLANG_RESOURCE_ACCESS_READ:
- sb << ";\n";
break;
default:
- sb << " { get; set; }\n";
+ sb << "__target_intrinsic(glsl, \"imageStore($0, " << ivecN << "($1), $2)\") set;\n";
break;
}
+
+ sb << "}\n";
}
if( !isMultisample )
diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h
index 03d796301..054174d3f 100644
--- a/source/slang/core.meta.slang.h
+++ b/source/slang/core.meta.slang.h
@@ -465,34 +465,47 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << "__target_intrinsic(glsl, \"(";
int aa = 1;
- String lodStr = "0";
+ String lodStr = ", 0";
if (includeMipInfo)
{
int mipLevelArg = aa++;
- lodStr = "int($";
+ lodStr = ", int($";
lodStr.append(mipLevelArg);
lodStr.append(")");
}
+ String opStr = " = textureSize($P" + lodStr;
+ switch( access )
+ {
+ case SLANG_RESOURCE_ACCESS_READ_WRITE:
+ case SLANG_RESOURCE_ACCESS_RASTER_ORDERED:
+ opStr = " = imageSize($0";
+ break;
+
+ default:
+ break;
+ }
+
+
int cc = 0;
switch(baseShape)
{
case TextureType::Shape1D:
- sb << "($" << aa++ << " = textureSize($P, " << lodStr << "))";
+ sb << "($" << aa++ << opStr << "))";
cc = 1;
break;
case TextureType::Shape2D:
case TextureType::ShapeCube:
- sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)";
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)";
+ sb << "($" << aa++ << opStr << ").x)";
+ sb << ", ($" << aa++ << opStr << ").y)";
cc = 2;
break;
case TextureType::Shape3D:
- sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)";
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)";
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").z)";
+ sb << "($" << aa++ << opStr << ").x)";
+ sb << ", ($" << aa++ << opStr << ").y)";
+ sb << ", ($" << aa++ << opStr << ").z)";
cc = 3;
break;
@@ -503,7 +516,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if(isArray)
{
- sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ")." << kComponentNames[cc] << ")";
+ sb << ", ($" << aa++ << opStr << ")." << kComponentNames[cc] << ")";
}
if(isMultisample)
@@ -630,13 +643,30 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
if(baseShape != TextureType::ShapeCube)
{
+ int N = kBaseTextureTypes[tt].coordCount + isArray;
+
+ char const* uintNs[] = { "", "uint", "uint2", "uint3", "uint4" };
+ char const* ivecNs[] = { "", "int", "ivec2", "ivec3", "ivec4" };
+
+ auto uintN = uintNs[N];
+ auto ivecN = ivecNs[N];
+
// subscript operator
- sb << "__subscript(uint";
- if(kBaseTextureTypes[tt].coordCount + isArray > 1)
- {
- sb << kBaseTextureTypes[tt].coordCount + isArray;
- }
- sb << " location) -> T";
+ sb << "__subscript(" << uintN << " location) -> T {\n";
+
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, " << ivecN << "($1)";
+
+ if( !isMultisample )
+ {
+ sb << ", 0";
+ }
+ else
+ {
+ // TODO: how to handle this...
+ sb << ", 0";
+ }
+
+ sb << ")$z\") get;\n";
// Depending on the access level of the texture type,
// we either have just a getter (the default), or both
@@ -645,13 +675,14 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
{
case SLANG_RESOURCE_ACCESS_NONE:
case SLANG_RESOURCE_ACCESS_READ:
- sb << ";\n";
break;
default:
- sb << " { get; set; }\n";
+ sb << "__target_intrinsic(glsl, \"imageStore($0, " << ivecN << "($1), $2)\") set;\n";
break;
}
+
+ sb << "}\n";
}
if( !isMultisample )
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index e5fb6a8be..672798359 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -1015,7 +1015,17 @@ struct EmitVisitor
void emitGLSLTextureType(
RefPtr<TextureType> texType)
{
- emitGLSLTextureOrTextureSamplerType(texType, "texture");
+ switch(texType->getAccess())
+ {
+ case SLANG_RESOURCE_ACCESS_READ_WRITE:
+ case SLANG_RESOURCE_ACCESS_RASTER_ORDERED:
+ emitGLSLTextureOrTextureSamplerType(texType, "image");
+ break;
+
+ default:
+ emitGLSLTextureOrTextureSamplerType(texType, "texture");
+ break;
+ }
}
void emitGLSLTextureSamplerType(
@@ -1289,7 +1299,19 @@ struct EmitVisitor
void visitGroupSharedType(GroupSharedType* type, TypeEmitArg const& arg)
{
- Emit("groupshared ");
+ switch(getTarget(context))
+ {
+ case CodeGenTarget::HLSL:
+ Emit("groupshared ");
+ break;
+
+ case CodeGenTarget::GLSL:
+ Emit("shared ");
+ break;
+
+ default:
+ break;
+ }
emitTypeImpl(type->valueType, arg.declarator);
}
@@ -2275,7 +2297,6 @@ struct EmitVisitor
}
break;
-
default:
SLANG_UNEXPECTED("bad format in intrinsic definition");
break;
@@ -5454,6 +5475,28 @@ emitDeclImpl(decl, nullptr);
}
break;
+ case 'N':
+ {
+ // Extract the element count from a vector argument so that
+ // we can use it in the constructed expression.
+
+ SLANG_RELEASE_ASSERT(*cursor >= '0' && *cursor <= '9');
+ UInt argIndex = (*cursor++) - '0';
+ SLANG_RELEASE_ASSERT(argCount > argIndex);
+
+ auto vectorArg = args[argIndex].get();
+ if (auto vectorType = vectorArg->type->As<VectorExpressionType>())
+ {
+ auto elementCount = GetIntVal(vectorType->elementCount);
+ Emit(elementCount);
+ }
+ else
+ {
+ SLANG_UNEXPECTED("bad format in intrinsic definition");
+ }
+ }
+ break;
+
default:
SLANG_UNEXPECTED("bad format in intrinsic definition");
@@ -7090,13 +7133,43 @@ emitDeclImpl(decl, nullptr);
void emitIRVarModifiers(
EmitContext* ctx,
- VarLayout* layout)
+ VarLayout* layout,
+ Type* valueType)
{
if (!layout)
return;
emitIRMatrixLayoutModifiers(ctx, layout);
+ // As a special case, if we are emitting a GLSL declaration
+ // for an HLSL `RWTexture*` then we need to emit a `format` layout qualifier.
+ if(getTarget(context) == CodeGenTarget::GLSL)
+ {
+ if(auto resourceType = unwrapArray(valueType).As<TextureType>())
+ {
+ switch(resourceType->getAccess())
+ {
+ case SLANG_RESOURCE_ACCESS_READ_WRITE:
+ case SLANG_RESOURCE_ACCESS_RASTER_ORDERED:
+ {
+ // TODO: at this point we need to look at the element
+ // type and figure out what format we want.
+ //
+ // For now just hack it and assume a fixed format.
+ Emit("layout(rgba32f)");
+
+ // TODO: we also need a way for users to specify what
+ // the format should be explicitly, to avoid having
+ // to have us infer things...
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
if (ctx->shared->target == CodeGenTarget::GLSL)
{
// Layout-related modifiers need to come before the declaration,
@@ -7238,7 +7311,7 @@ emitDeclImpl(decl, nullptr);
if(fieldType->Equals(getSession()->getVoidType()))
continue;
- emitIRVarModifiers(ctx, fieldLayout);
+ emitIRVarModifiers(ctx, fieldLayout, fieldType);
emitIRType(ctx, fieldType, getIRName(ff));
@@ -7444,7 +7517,7 @@ emitDeclImpl(decl, nullptr);
auto layout = getVarLayout(ctx, varDecl);
- emitIRVarModifiers(ctx, layout);
+ emitIRVarModifiers(ctx, layout, varType);
#if 0
switch (addressSpace)
@@ -7597,7 +7670,7 @@ emitDeclImpl(decl, nullptr);
}
}
- emitIRVarModifiers(ctx, layout);
+ emitIRVarModifiers(ctx, layout, varType);
emitIRType(ctx, varType, getIRName(varDecl));
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index 0f1263332..f59e1b66c 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -250,9 +250,18 @@ void AllMemoryBarrier();
void AllMemoryBarrierWithGroupSync();
// Test if any components is non-zero (HLSL SM 1.0)
-__generic<T : __BuiltinType> bool any(T x);
-__generic<T : __BuiltinType, let N : int> bool any(vector<T,N> x);
-__generic<T : __BuiltinType, let N : int, let M : int> bool any(matrix<T,N,M> x);
+
+__generic<T : __BuiltinType>
+__target_intrinsic(glsl, "bool($0)")
+bool any(T x);
+
+__generic<T : __BuiltinType, let N : int>
+__target_intrinsic(glsl, "any(bvec$$N0($0))")
+bool any(vector<T,N> x);
+
+__generic<T : __BuiltinType, let N : int, let M : int>
+// TODO: need to define GLSL mapping
+bool any(matrix<T,N,M> x);
// Reinterpret bits as a double (HLSL SM 5.0)
@@ -555,7 +564,10 @@ uint GetRenderTargetSampleCount();
float2 GetRenderTargetSamplePosition(int Index);
// Group memory barrier
+__target_intrinsic(glsl, "groupMemoryBarrier")
void GroupMemoryBarrier();
+
+__target_intrinsic(glsl, "groupMemoryBarrier(); barrier")
void GroupMemoryBarrierWithGroupSync();
// Atomics
@@ -1077,18 +1089,17 @@ for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)
sb << "T Load(int location, out uint status);\n";
- sb << "__target_intrinsic(glsl, \"texelFetch($$P, int($1))$$z\")\n";
- sb << "__subscript(uint index) -> T";
+ sb << "__subscript(uint index) -> T {\n";
+
+ sb << "__target_intrinsic(glsl, \"texelFetch($$P, int($1))$$z\") get;\n";
if (kBaseBufferAccessLevels[aa].access != SLANG_RESOURCE_ACCESS_READ)
{
- sb << " { get; set; }\n";
- }
- else
- {
- sb << ";\n";
+ sb << "set;\n";
}
+ sb << "}\n";
+
sb << "};\n";
}
diff --git a/source/slang/hlsl.meta.slang.h b/source/slang/hlsl.meta.slang.h
index fd245d840..0383880e0 100644
--- a/source/slang/hlsl.meta.slang.h
+++ b/source/slang/hlsl.meta.slang.h
@@ -252,9 +252,19 @@ sb << "// Thread-group sync and barrier for writes to all memory spaces (HLSL SM
sb << "void AllMemoryBarrierWithGroupSync();\n";
sb << "\n";
sb << "// Test if any components is non-zero (HLSL SM 1.0)\n";
-sb << "__generic<T : __BuiltinType> bool any(T x);\n";
-sb << "__generic<T : __BuiltinType, let N : int> bool any(vector<T,N> x);\n";
-sb << "__generic<T : __BuiltinType, let N : int, let M : int> bool any(matrix<T,N,M> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinType>\n";
+sb << "__target_intrinsic(glsl, \"bool($0)\")\n";
+sb << "bool any(T x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinType, let N : int>\n";
+sb << "__target_intrinsic(glsl, \"any(bvec$";
+sb << "N0($0))\")\n";
+sb << "bool any(vector<T,N> x);\n";
+sb << "\n";
+sb << "__generic<T : __BuiltinType, let N : int, let M : int>\n";
+sb << "// TODO: need to define GLSL mapping\n";
+sb << "bool any(matrix<T,N,M> x);\n";
sb << "\n";
sb << "\n";
sb << "// Reinterpret bits as a double (HLSL SM 5.0)\n";
@@ -557,7 +567,10 @@ sb << "// Get position of given sample\n";
sb << "float2 GetRenderTargetSamplePosition(int Index);\n";
sb << "\n";
sb << "// Group memory barrier\n";
+sb << "__target_intrinsic(glsl, \"groupMemoryBarrier\")\n";
sb << "void GroupMemoryBarrier();\n";
+sb << "\n";
+sb << "__target_intrinsic(glsl, \"groupMemoryBarrier(); barrier\")\n";
sb << "void GroupMemoryBarrierWithGroupSync();\n";
sb << "\n";
sb << "// Atomics\n";
@@ -1080,18 +1093,17 @@ for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)
sb << "T Load(int location, out uint status);\n";
- sb << "__target_intrinsic(glsl, \"texelFetch($P, int($1))$z\")\n";
- sb << "__subscript(uint index) -> T";
+ sb << "__subscript(uint index) -> T {\n";
+
+ sb << "__target_intrinsic(glsl, \"texelFetch($P, int($1))$z\") get;\n";
if (kBaseBufferAccessLevels[aa].access != SLANG_RESOURCE_ACCESS_READ)
{
- sb << " { get; set; }\n";
- }
- else
- {
- sb << ";\n";
+ sb << "set;\n";
}
+ sb << "}\n";
+
sb << "};\n";
}