diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2018-02-18 08:08:46 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-02-18 08:08:46 -0800 |
| commit | 51cdcad24b5271ac8c0f816174c6a760e264ed9e (patch) | |
| tree | 30beaa85671168ac2c73b08f4f20d894cbca88f9 /source | |
| parent | 8c872597540b2287bc18d5723c7ae3b8832246b8 (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.slang | 65 | ||||
| -rw-r--r-- | source/slang/core.meta.slang.h | 65 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 87 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang | 31 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang.h | 32 |
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"; } |
