Edit

kc3-lang/angle/src/compiler/translator/OutputVulkanGLSL.cpp

Branch :

  • Show log

    Commit

  • Author : Le Quyen
    Date : 2019-10-14 14:49:49
    Hash : a48f95ab
    Message : Move Vulkan GlslangWrapper code to a shared location. Metal backend will reuse Vulkan's GlslangWrapper code. The Metal backend will use this code to translate glsl to spirv then cross compile to Metal Shading Language using spirv-cross. So the source code of GlslangWrapper should be moved outside vulkan folder. Bug: angleproject:2634 Change-Id: I208062daf0d77756c9d32cfdab925b7dfdf83e05 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1858042 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/compiler/translator/OutputVulkanGLSL.cpp
  • //
    // Copyright 2016 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // OutputVulkanGLSL:
    //   Code that outputs shaders that fit GL_KHR_vulkan_glsl.
    //   The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
    //   See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
    //
    
    #include "compiler/translator/OutputVulkanGLSL.h"
    
    #include "compiler/translator/BaseTypes.h"
    #include "compiler/translator/Symbol.h"
    #include "compiler/translator/util.h"
    
    namespace sh
    {
    
    TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink,
                                         ShArrayIndexClampingStrategy clampingStrategy,
                                         ShHashFunction64 hashFunction,
                                         NameMap &nameMap,
                                         TSymbolTable *symbolTable,
                                         sh::GLenum shaderType,
                                         int shaderVersion,
                                         ShShaderOutput output,
                                         ShCompileOptions compileOptions)
        : TOutputGLSL(objSink,
                      clampingStrategy,
                      hashFunction,
                      nameMap,
                      symbolTable,
                      shaderType,
                      shaderVersion,
                      output,
                      compileOptions)
    {}
    
    // TODO(jmadill): This is not complete.
    void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
    {
        const TType &type = variable->getType();
    
        bool needsCustomLayout =
            type.getQualifier() == EvqAttribute || type.getQualifier() == EvqFragmentOut ||
            type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier()) ||
            IsSampler(type.getBasicType()) || type.isInterfaceBlock() || IsImage(type.getBasicType());
    
        if (!NeedsToWriteLayoutQualifier(type) && !needsCustomLayout)
        {
            return;
        }
    
        TInfoSinkBase &out = objSink();
    
        // This isn't super clean, but it gets the job done.
        // See corresponding code in glslang_wrapper_utils.cpp.
        TIntermSymbol *symbol = variable->getAsSymbolNode();
        ASSERT(symbol);
    
        ImmutableString name      = symbol->getName();
        const char *blockStorage  = nullptr;
        const char *matrixPacking = nullptr;
    
        // For interface blocks, use the block name instead.  When the layout qualifier is being
        // replaced in the backend, that would be the name that's available.
        if (type.isInterfaceBlock())
        {
            const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
            name                                  = interfaceBlock->name();
            TLayoutBlockStorage storage           = interfaceBlock->blockStorage();
    
            // Make sure block storage format is specified.
            if (storage != EbsStd430)
            {
                // Change interface block layout qualifiers to std140 for any layout that is not
                // explicitly set to std430.  This is to comply with GL_KHR_vulkan_glsl where shared and
                // packed are not allowed (and std140 could be used instead) and unspecified layouts can
                // assume either std140 or std430 (and we choose std140 as std430 is not yet universally
                // supported).
                storage = EbsStd140;
            }
    
            if (interfaceBlock->blockStorage() != EbsUnspecified)
            {
                blockStorage = getBlockStorageString(storage);
            }
    
            // We expect all interface blocks to have been transformed to column major, so we don't
            // specify the packing.  Any remaining interface block qualified with row_major shouldn't
            // have any matrices inside.
            ASSERT(type.getLayoutQualifier().matrixPacking != EmpRowMajor ||
                   !interfaceBlock->containsMatrices());
        }
    
        if (needsCustomLayout)
        {
            out << "@@ LAYOUT-" << name << "(";
        }
        else
        {
            out << "layout(";
        }
    
        // Output the list of qualifiers already known at this stage, i.e. everything other than
        // `location` and `set`/`binding`.
        std::string otherQualifiers = getCommonLayoutQualifiers(variable);
    
        const char *separator = "";
        if (blockStorage)
        {
            out << separator << blockStorage;
            separator = ", ";
        }
        if (matrixPacking)
        {
            out << separator << matrixPacking;
            separator = ", ";
        }
        if (!otherQualifiers.empty())
        {
            out << separator << otherQualifiers;
        }
    
        out << ") ";
        if (needsCustomLayout)
        {
            out << "@@";
        }
    }
    
    void TOutputVulkanGLSL::writeFieldLayoutQualifier(const TField *field)
    {
        // We expect all interface blocks to have been transformed to column major, as Vulkan GLSL
        // doesn't allow layout qualifiers on interface block fields.  Any remaining interface block
        // qualified with row_major shouldn't have any matrices inside, so the qualifier can be
        // dropped.
    }
    
    void TOutputVulkanGLSL::writeQualifier(TQualifier qualifier,
                                           const TType &type,
                                           const TSymbol *symbol)
    {
        if (qualifier != EvqUniform && qualifier != EvqBuffer && qualifier != EvqAttribute &&
            qualifier != EvqVertexIn && !sh::IsVarying(qualifier))
        {
            TOutputGLSLBase::writeQualifier(qualifier, type, symbol);
            return;
        }
    
        if (symbol == nullptr)
        {
            return;
        }
    
        ImmutableString name = symbol->name();
    
        // For interface blocks, use the block name instead.  When the qualifier is being replaced in
        // the backend, that would be the name that's available.
        if (type.isInterfaceBlock())
        {
            name = type.getInterfaceBlock()->name();
        }
    
        TInfoSinkBase &out = objSink();
        out << "@@ QUALIFIER-" << name.data() << "(" << getMemoryQualifiers(type) << ") @@ ";
    }
    
    void TOutputVulkanGLSL::writeVariableType(const TType &type, const TSymbol *symbol)
    {
        TType overrideType(type);
    
        // External textures are treated as 2D textures in the vulkan back-end
        if (type.getBasicType() == EbtSamplerExternalOES)
        {
            overrideType.setBasicType(EbtSampler2D);
        }
    
        TOutputGLSL::writeVariableType(overrideType, symbol);
    }
    
    void TOutputVulkanGLSL::writeStructType(const TStructure *structure)
    {
        if (!structDeclared(structure))
        {
            declareStruct(structure);
            objSink() << ";\n";
        }
    }
    
    }  // namespace sh