Skip to content

Commit

Permalink
Remove the "hack sampler" workaround (#648)
Browse files Browse the repository at this point in the history
* Update glslang version

* Fix build for new glslang

The latest glslang required a few changes to our manual build for their code (because we are *not* taking a dependency on CMake).

* Rebuild project files using premake, which picks up a few files added to glslang, but also a few diffs in Slang's own project files in cases where they were edited manually instead of using premake.

* Fix up the declaration our our device limits (which are inentionally set to *not* limit what code passes through our glslang), because the underlying structure definition in glslang has changed. This is a kludgy bit of glslang's design, but it doesn't make sense for us to invest in a more serious workaround.

* Remove the "hack sampler" workaround

When the `GL_KHR_vulkan_glsl` spec was introduced to allow GLSL to be compiled for Vulkan SPIR-V, it made an annoying mistake by leaving a few builtins as taking `sampler2D`, etc. when the equivalent SPIR-V operations only require a `texture2D`, etc. The relevant builtins are:

* `textureSize`
* `textureQueryLevels`
* `textureSamples`
* `texelFetch`
* `texelFetchOffset`

This means that shader code that wanted to use those operations needed to conspire to have a `sampler` handy so they could write, e.g.:

```glsl
vec4 val = texelFetch(sampler2D(myTexture, someRandomSampler), p, lod);
```

when what they really wanted was this:

```glsl
vec4 val = texelFetch(myTexture, p, lod);
```

That is annoying but probably something each to work around for a GLSL programmer, but when cross-compiling from HLSL, you might have an operation like:

```hlsl
float4 val = myTexure.Load(p);
```

in which case a cross-compiler needs to manufacture a sampler out of thin air. If the shader happened to use a sampler for something else you could snag that, but in the worse case you had to cross-compile to GLSL that declared a new sampler.

Slang did this by declaring a sampler called `SLANG_hack_samplerForTexelFetch` (because `texelFetch` is the operation that first surfaced the issue). For complex reasons we *always* define this sampler, even if we turn out not to need it in a particular output kernel. This choice has a bunch of annoying consequences:

* There is *always* a sampler defined in descriptor set zero, because that's where we put the hack sampler, so a user-defined parameter block always has a set number of 1 or greater (see #646).

* The hack sampler shows up in reflection output because users need to size their descriptor sets appropriately to pass along this sampler that won't actually be used if they don't want to get debug spew from the validation layers.

We filed an issue on glslang about this problem, and eventually some kind folks from the gamedev community (who also saw the same problem) defined an extension spec (`GL_EXT_samplerless_texture_functions`) to fix the underlying issue and contributed a patch to glslang to make it support that extension.

This change just backs the hack out of Slang now that we have a glslang version that supports the extension to get past the defect in the original GLSL-for-Vulkan definition. Besides yanking out the code for the hack, we also change the relevant builtins to declare that they require this new GLSL extension (so that we properly request it from glslang when the builtins are used), and fix some reflection test cases that exposed the existence of the "hack sampler."

* Fixup: syntax error in stdlib generator files

* Remove more code for hack sampler

There was logic to ensure we always have a "default" register space/set when cross-compiling, because the hack sampler would need it. This is no longer necessary once we remove the hack sampler.

* Fix expected test output.

Fixing the root cause of issue #646 means that one of our test cases that tickles that issue now produces different output (luckily it can now be used as a regression test for the issue).
  • Loading branch information
Tim Foley authored Sep 21, 2018
1 parent 738bcb8 commit 7250ed1
Show file tree
Hide file tree
Showing 22 changed files with 72 additions and 195 deletions.
2 changes: 1 addition & 1 deletion external/glslang
Submodule glslang updated 828 files
2 changes: 1 addition & 1 deletion source/core/core.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
26 changes: 13 additions & 13 deletions source/core/core.vcxproj.filters
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
Expand Down Expand Up @@ -54,6 +54,12 @@
<ClInclude Include="slang-math.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="slang-memory-arena.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="slang-random-generator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="slang-string-util.h">
<Filter>Header Files</Filter>
</ClInclude>
Expand All @@ -75,12 +81,6 @@
<ClInclude Include="type-traits.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="slang-memory-arena.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="slang-random-generator.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="platform.cpp">
Expand All @@ -92,6 +92,12 @@
<ClCompile Include="slang-io.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="slang-memory-arena.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="slang-random-generator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="slang-string-util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
Expand All @@ -107,12 +113,6 @@
<ClCompile Include="token-reader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="slang-memory-arena.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="slang-random-generator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="core.natvis">
Expand Down
3 changes: 2 additions & 1 deletion source/slang-glslang/slang-glslang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ static TBuiltInResource gResources =
UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED,
UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED,
UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED,
UNLIMITED, UNLIMITED, UNLIMITED,
UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED, UNLIMITED,
UNLIMITED, UNLIMITED,

{ true, true, true, true, true, true, true, true, true, }
};
Expand Down
3 changes: 3 additions & 0 deletions source/slang-glslang/slang-glslang.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
<ClInclude Include="..\..\external\glslang\SPIRV\Logger.h" />
<ClInclude Include="..\..\external\glslang\SPIRV\SPVRemapper.h" />
<ClInclude Include="..\..\external\glslang\SPIRV\SpvBuilder.h" />
<ClInclude Include="..\..\external\glslang\SPIRV\SpvTools.h" />
<ClInclude Include="..\..\external\glslang\SPIRV\bitutils.h" />
<ClInclude Include="..\..\external\glslang\SPIRV\disassemble.h" />
<ClInclude Include="..\..\external\glslang\SPIRV\doc.h" />
Expand Down Expand Up @@ -213,6 +214,8 @@
<ClCompile Include="..\..\external\glslang\SPIRV\Logger.cpp" />
<ClCompile Include="..\..\external\glslang\SPIRV\SPVRemapper.cpp" />
<ClCompile Include="..\..\external\glslang\SPIRV\SpvBuilder.cpp" />
<ClCompile Include="..\..\external\glslang\SPIRV\SpvPostProcess.cpp" />
<ClCompile Include="..\..\external\glslang\SPIRV\SpvTools.cpp" />
<ClCompile Include="..\..\external\glslang\SPIRV\disassemble.cpp" />
<ClCompile Include="..\..\external\glslang\SPIRV\doc.cpp" />
<ClCompile Include="..\..\external\glslang\StandAlone\ResourceLimits.cpp" />
Expand Down
9 changes: 9 additions & 0 deletions source/slang-glslang/slang-glslang.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
<ClInclude Include="..\..\external\glslang\SPIRV\SpvBuilder.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\external\glslang\SPIRV\SpvTools.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\external\glslang\SPIRV\bitutils.h">
<Filter>Header Files</Filter>
</ClInclude>
Expand Down Expand Up @@ -146,6 +149,12 @@
<ClCompile Include="..\..\external\glslang\SPIRV\SpvBuilder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\external\glslang\SPIRV\SpvPostProcess.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\external\glslang\SPIRV\SpvTools.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\external\glslang\SPIRV\disassemble.cpp">
<Filter>Source Files</Filter>
</ClCompile>
Expand Down
22 changes: 14 additions & 8 deletions source/slang/core.meta.slang
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
{
{
sb << "__glsl_version(450)\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"(";

int aa = 1;
Expand All @@ -556,7 +557,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
lodStr.append(")");
}

String opStr = " = textureSize($P" + lodStr;
String opStr = " = textureSize($0" + lodStr;
switch( access )
{
case SLANG_RESOURCE_ACCESS_READ_WRITE:
Expand Down Expand Up @@ -603,12 +604,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)

if(isMultisample)
{
sb << ", ($" << aa++ << " = textureSamples($P))";
sb << ", ($" << aa++ << " = textureSamples($0))";
}

if (includeMipInfo)
{
sb << ", ($" << aa++ << " = textureQueryLevels($P))";
sb << ", ($" << aa++ << " = textureQueryLevels($0))";
}


Expand Down Expand Up @@ -680,11 +681,13 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)

if (isMultisample)
{
sb << "__target_intrinsic(glsl, \"texelFetch($P, $1, $3)\")\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, $1, $3)\")\n";
}
else
{
sb << "__target_intrinsic(glsl, \"texelFetch($P, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
}
sb << "T Load(";
sb << "int" << loadCoordCount << " location";
Expand All @@ -696,11 +699,13 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)

if (isMultisample)
{
sb << "__target_intrinsic(glsl, \"texelFetchOffset($P, $0, $1, $2)\")\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetchOffset($0, $0, $1, $2)\")\n";
}
else
{
sb << "__target_intrinsic(glsl, \"texelFetch($P, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $2)\")\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $2)\")\n";
}
sb << "T Load(";
sb << "int" << loadCoordCount << " location";
Expand Down Expand Up @@ -741,7 +746,8 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
{
case SLANG_RESOURCE_ACCESS_NONE:
case SLANG_RESOURCE_ACCESS_READ:
sb << "__target_intrinsic(glsl, \"texelFetch($P, " << ivecN << "($1)";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, " << ivecN << "($1)";
if( !isMultisample )
{
sb << ", 0";
Expand Down
22 changes: 14 additions & 8 deletions source/slang/core.meta.slang.h
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
{
{
sb << "__glsl_version(450)\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"(";

int aa = 1;
Expand All @@ -571,7 +572,7 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
lodStr.append(")");
}

String opStr = " = textureSize($P" + lodStr;
String opStr = " = textureSize($0" + lodStr;
switch( access )
{
case SLANG_RESOURCE_ACCESS_READ_WRITE:
Expand Down Expand Up @@ -618,12 +619,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)

if(isMultisample)
{
sb << ", ($" << aa++ << " = textureSamples($P))";
sb << ", ($" << aa++ << " = textureSamples($0))";
}

if (includeMipInfo)
{
sb << ", ($" << aa++ << " = textureQueryLevels($P))";
sb << ", ($" << aa++ << " = textureQueryLevels($0))";
}


Expand Down Expand Up @@ -695,11 +696,13 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)

if (isMultisample)
{
sb << "__target_intrinsic(glsl, \"texelFetch($P, $1, $3)\")\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, $1, $3)\")\n";
}
else
{
sb << "__target_intrinsic(glsl, \"texelFetch($P, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n";
}
sb << "T Load(";
sb << "int" << loadCoordCount << " location";
Expand All @@ -711,11 +714,13 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)

if (isMultisample)
{
sb << "__target_intrinsic(glsl, \"texelFetchOffset($P, $0, $1, $2)\")\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetchOffset($0, $0, $1, $2)\")\n";
}
else
{
sb << "__target_intrinsic(glsl, \"texelFetch($P, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $2)\")\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, ($1)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($1)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $2)\")\n";
}
sb << "T Load(";
sb << "int" << loadCoordCount << " location";
Expand Down Expand Up @@ -756,7 +761,8 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
{
case SLANG_RESOURCE_ACCESS_NONE:
case SLANG_RESOURCE_ACCESS_READ:
sb << "__target_intrinsic(glsl, \"texelFetch($P, " << ivecN << "($1)";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, " << ivecN << "($1)";
if( !isMultisample )
{
sb << ", 0";
Expand Down
40 changes: 0 additions & 40 deletions source/slang/emit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,6 @@ struct SharedEmitContext

ModuleDecl* program;

bool needHackSamplerForTexelFetch = false;

ExtensionUsageTracker extensionUsageTracker;

UInt uniqueIDCounter = 1;
Expand Down Expand Up @@ -3052,36 +3050,6 @@ struct EmitVisitor
}
break;

case 'P':
{
// Okay, we need a collosal hack to deal with the fact that GLSL `texelFetch()`
// for Vulkan seems to be completely broken by design. It's signature wants
// a `sampler2D` for consistency with its peers, but the actual SPIR-V operation
// ignores the sampler paart of it, and just used the `texture2D` part.
//
// The HLSL equivalent (e.g., `Texture2D.Load()`) doesn't provide a sampler
// argument, so we seemingly need to conjure one out of thin air. :(
//
// We are going to hack this *hard* for now.

auto textureArg = args[0].get();
if (auto baseTextureType = as<IRTextureType>(textureArg->getDataType()))
{
emitGLSLTextureOrTextureSamplerType(baseTextureType, "sampler");
Emit("(");
emitIROperand(ctx, textureArg, mode);
Emit(",");
Emit("SLANG_hack_samplerForTexelFetch");
context->shared->needHackSamplerForTexelFetch = true;
Emit(")");
}
else
{
SLANG_UNEXPECTED("bad format in intrinsic definition");
}
}
break;

case 'z':
{
// If we are calling a D3D texturing operation in the form t.Foo(s, ...),
Expand Down Expand Up @@ -6204,14 +6172,6 @@ String emitEntryPoint(

finalResultBuilder << sharedContext.extensionUsageTracker.glslExtensionRequireLines.ProduceString();

if (sharedContext.needHackSamplerForTexelFetch)
{
finalResultBuilder
<< "layout(set = 0, binding = "
<< programLayout->bindingForHackSampler
<< ") uniform sampler SLANG_hack_samplerForTexelFetch;\n";
}

finalResultBuilder << code;

String finalResult = finalResultBuilder.ProduceString();
Expand Down
6 changes: 4 additions & 2 deletions source/slang/hlsl.meta.slang
Original file line number Diff line number Diff line change
Expand Up @@ -1187,14 +1187,16 @@ for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)

sb << "void GetDimensions(out uint dim);\n";

sb << "__target_intrinsic(glsl, \"texelFetch($P, $1)$z\")\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, $1)$z\")\n";
sb << "T Load(int location);\n";

sb << "T Load(int location, out uint status);\n";

sb << "__subscript(uint index) -> T {\n";

sb << "__target_intrinsic(glsl, \"texelFetch($P, int($1))$z\") get;\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, int($1))$z\") get;\n";

if (kBaseBufferAccessLevels[aa].access != SLANG_RESOURCE_ACCESS_READ)
{
Expand Down
6 changes: 4 additions & 2 deletions source/slang/hlsl.meta.slang.h
Original file line number Diff line number Diff line change
Expand Up @@ -1232,14 +1232,16 @@ for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa)

sb << "void GetDimensions(out uint dim);\n";

sb << "__target_intrinsic(glsl, \"texelFetch($P, $1)$z\")\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, $1)$z\")\n";
sb << "T Load(int location);\n";

sb << "T Load(int location, out uint status);\n";

sb << "__subscript(uint index) -> T {\n";

sb << "__target_intrinsic(glsl, \"texelFetch($P, int($1))$z\") get;\n";
sb << "__glsl_extension(GL_EXT_samplerless_texture_functions)";
sb << "__target_intrinsic(glsl, \"texelFetch($0, int($1))$z\") get;\n";

if (kBaseBufferAccessLevels[aa].access != SLANG_RESOURCE_ACCESS_READ)
{
Expand Down
Loading

0 comments on commit 7250ed1

Please sign in to comment.