From 0e220da96b819f3a31635689f78ad20bd9a36d0b Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Mon, 10 Jul 2017 08:34:52 -0700 Subject: More cross-compilation fixes - Add GLSL mappings for more `Texture*` methods - The annoying one here is `Texture*.Load()` because it doesn't take a sampler, but the GLSL equivalent needs one (while the SPIR-V does *not*). I've hacked this pretty seriously for now. - Try to ensure that we add `uniform` to global declarations that need it in GLSL - When outputting an `in` or `out` variable that might have been created from an `inout` shader parameter, filter the layout qualifiers that we output to only cover the appropriate resource kind. --- source/slang/emit.cpp | 125 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 3 deletions(-) (limited to 'source/slang/emit.cpp') diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index c135090c1..01b3e8cc2 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -48,6 +48,10 @@ struct SharedEmitContext StructTypeLayout* globalStructLayout; ProgramLayout* programLayout; + + ProgramSyntaxNode* program; + + bool needHackSamplerForTexelFetch = false; }; struct EmitContext @@ -1758,6 +1762,66 @@ 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. + + // Try to find a suitable sampler-type shader parameter in the global scope + // (fingers crossed) + RefPtr samplerVar; + for (auto d : context->shared->program->Members) + { + if (auto varDecl = d.As()) + { + if (auto samplerType = varDecl->Type.type->As()) + { + samplerVar = varDecl; + break; + } + } + } + + if (auto memberExpr = callExpr->FunctionExpr.As()) + { + auto base = memberExpr->BaseExpression; + if (auto baseTextureType = base->Type->As()) + { + emitGLSLTextureOrTextureSamplerType(baseTextureType, "sampler"); + Emit("("); + EmitExpr(memberExpr->BaseExpression); + Emit(","); + if (samplerVar) + { + EmitDeclRef(makeDeclRef(samplerVar.Ptr())); + } + else + { + Emit("SLANG_hack_samplerForTexelFetch"); + context->shared->needHackSamplerForTexelFetch = true; + } + Emit(")"); + } + else + { + assert(!"unexpected"); + } + + } + else + { + assert(!"unexpected"); + } + } + break; + default: assert(!"unexpected"); break; @@ -2476,6 +2540,9 @@ struct EmitVisitor #define CASE(TYPE, KEYWORD) \ else if(auto mod_##TYPE = mod.As()) Emit(#KEYWORD " ") + #define CASE2(TYPE, HLSL_NAME, GLSL_NAME) \ + else if(auto mod_##TYPE = mod.As()) Emit((context->shared->target == CodeGenTarget::GLSL) ? GLSL_NAME : HLSL_NAME) + CASE(RowMajorLayoutModifier, row_major); CASE(ColumnMajorLayoutModifier, column_major); CASE(HLSLNoInterpolationModifier, nointerpolation); @@ -2502,6 +2569,7 @@ struct EmitVisitor CASE(ConstModifier, const); #undef CASE + #undef CASE2 else if (auto staticModifier = mod.As()) { @@ -2949,7 +3017,8 @@ struct EmitVisitor } void emitGLSLLayoutQualifiers( - RefPtr layout) + RefPtr layout, + LayoutResourceKind filter = LayoutResourceKind::None) { if(!layout) return; @@ -2964,6 +3033,13 @@ struct EmitVisitor for( auto info : layout->resourceInfos ) { + // Skip info that doesn't match our filter + if (filter != LayoutResourceKind::None + && filter != info.kind) + { + continue; + } + emitGLSLLayoutQualifier(info); } } @@ -3095,7 +3171,33 @@ struct EmitVisitor return; } - emitGLSLLayoutQualifiers(layout); + + if (context->shared->target == CodeGenTarget::GLSL) + { + if (decl->HasModifier()) + { + emitGLSLLayoutQualifiers(layout, LayoutResourceKind::VertexInput); + } + else if (decl->HasModifier()) + { + emitGLSLLayoutQualifiers(layout, LayoutResourceKind::FragmentOutput); + } + else + { + emitGLSLLayoutQualifiers(layout); + } + + // If we have a uniform that wasn't tagged `uniform` in GLSL, then fix that here + if (layout + && !decl->HasModifier()) + { + if (layout->FindResourceInfo(LayoutResourceKind::Uniform) + || layout->FindResourceInfo(LayoutResourceKind::DescriptorTableSlot)) + { + Emit("uniform "); + } + } + } EmitVarDeclCommon(decl); @@ -3288,6 +3390,9 @@ String emitEntryPoint( // There may be global-scope modifiers that we should emit now visitor.emitGLSLPreprocessorDirectives(translationUnitSyntax); + String prefix = sharedContext.sb.ProduceString(); + sharedContext.sb.Clear(); + switch(target) { case CodeGenTarget::GLSL: @@ -3303,6 +3408,8 @@ String emitEntryPoint( auto lowered = lowerEntryPoint(entryPoint, programLayout, target); + sharedContext.program = lowered.program; + visitor.EmitDeclsInContainer(lowered.program.Ptr()); #if 0 @@ -3324,7 +3431,19 @@ String emitEntryPoint( String code = sharedContext.sb.ProduceString(); - return code; + StringBuilder finalResultBuilder; + finalResultBuilder << prefix; + + if (sharedContext.needHackSamplerForTexelFetch) + { + finalResultBuilder << "layout(set = 0, binding = 0) uniform sampler SLANG_hack_samplerForTexelFetch;\n"; + } + + finalResultBuilder << code; + + String finalResult = finalResultBuilder.ProduceString(); + + return finalResult; } } // namespace Slang -- cgit v1.2.3 From 7af89d178736637cfad9c195f85f7f83e2f4ba99 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Mon, 10 Jul 2017 09:04:50 -0700 Subject: Cleanups for test cases: - Allow a code-generation target of `NONE` in order to suppress ordinary output in test cases where we don't care about the actual output (just pass/fail result) - Add explicit `location` layout qualifiers to intermediate vertex-to-fragment variables in GLSL test cases for rendering, to work around apparent Intel driver bugs. --- slang.h | 1 + source/slang/compiler.cpp | 4 ++++ source/slang/compiler.h | 1 + source/slang/emit.cpp | 5 +++++ source/slang/options.cpp | 1 + tests/preprocessor/import.hlsl | 2 +- tests/render/cross-compile0.hlsl | 4 ++-- tests/render/imported-parameters.hlsl | 4 ++-- tests/render/pound-import.hlsl | 4 ++-- 9 files changed, 19 insertions(+), 7 deletions(-) (limited to 'source/slang/emit.cpp') diff --git a/slang.h b/slang.h index b6f35f255..87419bf45 100644 --- a/slang.h +++ b/slang.h @@ -66,6 +66,7 @@ extern "C" enum { SLANG_TARGET_UNKNOWN, + SLANG_TARGET_NONE, SLANG_GLSL, SLANG_GLSL_VULKAN, SLANG_GLSL_VULKAN_ONE_DESC, diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp index f9c188764..2f6204eb2 100644 --- a/source/slang/compiler.cpp +++ b/source/slang/compiler.cpp @@ -461,6 +461,10 @@ namespace Slang } break; + case CodeGenTarget::None: + // The user requested no output + break; + // Note(tfoley): We currently hit this case when compiling the stdlib case CodeGenTarget::Unknown: break; diff --git a/source/slang/compiler.h b/source/slang/compiler.h index e106973bc..cb7eb6265 100644 --- a/source/slang/compiler.h +++ b/source/slang/compiler.h @@ -36,6 +36,7 @@ namespace Slang enum class CodeGenTarget { Unknown = SLANG_TARGET_UNKNOWN, + None = SLANG_TARGET_NONE, GLSL = SLANG_GLSL, GLSL_Vulkan = SLANG_GLSL_VULKAN, GLSL_Vulkan_OneDesc = SLANG_GLSL_VULKAN_ONE_DESC, diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 01b3e8cc2..155e1e39a 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -2159,6 +2159,11 @@ struct EmitVisitor void EmitStmt(RefPtr stmt) { + // TODO(tfoley): this shouldn't occur, but sometimes + // lowering will get confused by an empty function body... + if (!stmt) + return; + // Try to ensure that debugging can find the right location advanceToSourceLocation(stmt->Position); diff --git a/source/slang/options.cpp b/source/slang/options.cpp index 53c441f6b..bb292a4dc 100644 --- a/source/slang/options.cpp +++ b/source/slang/options.cpp @@ -230,6 +230,7 @@ struct OptionsParser CASE(spirv, SPIRV); CASE(spirv-assembly, SPIRV_ASM); + CASE(none, TARGET_NONE); #undef CASE diff --git a/tests/preprocessor/import.hlsl b/tests/preprocessor/import.hlsl index 486023678..f0618a667 100644 --- a/tests/preprocessor/import.hlsl +++ b/tests/preprocessor/import.hlsl @@ -1,4 +1,4 @@ -//TEST:SIMPLE:-profile vs_5_0 +//TEST:SIMPLE:-target none -profile vs_5_0 // Confirm that `#import` interacts with preprocessor as expected diff --git a/tests/render/cross-compile0.hlsl b/tests/render/cross-compile0.hlsl index d300e2bd5..d40f3460f 100644 --- a/tests/render/cross-compile0.hlsl +++ b/tests/render/cross-compile0.hlsl @@ -97,8 +97,8 @@ uniform Uniforms #define ASSEMBLED_VERTEX(QUAL) \ /* */ -#define V2F(QUAL) \ - QUAL vec3 coarse_color; \ +#define V2F(QUAL) \ + layout(location = 0) QUAL vec3 coarse_color; \ /* */ // Vertex Shader diff --git a/tests/render/imported-parameters.hlsl b/tests/render/imported-parameters.hlsl index 605214fc9..99216728e 100644 --- a/tests/render/imported-parameters.hlsl +++ b/tests/render/imported-parameters.hlsl @@ -84,8 +84,8 @@ FragmentStageOutput fragmentMain(FragmentStageInput input) #define ASSEMBLED_VERTEX(QUAL) \ /* */ -#define V2F(QUAL) \ - QUAL vec3 coarse_color; \ +#define V2F(QUAL) \ + layout(location = 0) QUAL vec3 coarse_color; \ /* */ // Vertex Shader diff --git a/tests/render/pound-import.hlsl b/tests/render/pound-import.hlsl index a9b625fb6..07b195966 100644 --- a/tests/render/pound-import.hlsl +++ b/tests/render/pound-import.hlsl @@ -97,8 +97,8 @@ uniform Uniforms #define ASSEMBLED_VERTEX(QUAL) \ /* */ -#define V2F(QUAL) \ - QUAL vec3 coarse_color; \ +#define V2F(QUAL) \ + layout(location = 0) QUAL vec3 coarse_color; \ /* */ // Vertex Shader -- cgit v1.2.3