diff options
| author | Tim Foley <tfoley@nvidia.com> | 2017-07-10 08:34:52 -0700 |
|---|---|---|
| committer | Tim Foley <tfoley@nvidia.com> | 2017-07-10 08:34:52 -0700 |
| commit | 0e220da96b819f3a31635689f78ad20bd9a36d0b (patch) | |
| tree | 7728d25df51cb8488ac681715a82b359730b796d /source/slang/emit.cpp | |
| parent | 928cc86160644547decc49c72304549d9009a1af (diff) | |
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.
Diffstat (limited to 'source/slang/emit.cpp')
| -rw-r--r-- | source/slang/emit.cpp | 125 |
1 files changed, 122 insertions, 3 deletions
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<VarDeclBase> samplerVar; + for (auto d : context->shared->program->Members) + { + if (auto varDecl = d.As<VarDeclBase>()) + { + if (auto samplerType = varDecl->Type.type->As<SamplerStateType>()) + { + samplerVar = varDecl; + break; + } + } + } + + if (auto memberExpr = callExpr->FunctionExpr.As<MemberExpressionSyntaxNode>()) + { + auto base = memberExpr->BaseExpression; + if (auto baseTextureType = base->Type->As<TextureType>()) + { + 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<TYPE>()) Emit(#KEYWORD " ") + #define CASE2(TYPE, HLSL_NAME, GLSL_NAME) \ + else if(auto mod_##TYPE = mod.As<TYPE>()) 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<HLSLStaticModifier>()) { @@ -2949,7 +3017,8 @@ struct EmitVisitor } void emitGLSLLayoutQualifiers( - RefPtr<VarLayout> layout) + RefPtr<VarLayout> 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<InModifier>()) + { + emitGLSLLayoutQualifiers(layout, LayoutResourceKind::VertexInput); + } + else if (decl->HasModifier<OutModifier>()) + { + 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<HLSLUniformModifier>()) + { + 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 |
