Edit

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

Branch :

  • Show log

    Commit

  • Author : Mohan Maiya
    Date : 2021-02-24 09:49:42
    Hash : 550f2a3e
    Message : Vulkan: Shader support for EXT_shader_framebuffer_fetch_non_coherent Translator can accept gl_LastFragData and 'inout' variable to gain access to framebuffer attachment data. The Vulkan translator replaces it with the SubpassInput type variable. Note that this works only for the noncoherent version of the extension. Bug: angleproject:5454 Test: *EXTShaderFramebufferFetchNoncoherent*.* Change-Id: I392f84ee3ad3eb9fbd09d0b7ff83731a9a3f33f6 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2598060 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Mohan Maiya <m.maiya@samsung.com>

  • 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/ValidateVaryingLocations.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,
                                         bool forceHighp,
                                         bool enablePrecision,
                                         ShCompileOptions compileOptions)
        : TOutputGLSL(objSink,
                      clampingStrategy,
                      hashFunction,
                      nameMap,
                      symbolTable,
                      shaderType,
                      shaderVersion,
                      output,
                      compileOptions),
          mNextUnusedBinding(0),
          mNextUnusedInputLocation(0),
          mNextUnusedOutputLocation(0),
          mForceHighp(forceHighp),
          mEnablePrecision(enablePrecision)
    {}
    
    void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
    {
        const TType &type = variable->getType();
    
        bool needsSetBinding = IsSampler(type.getBasicType()) ||
                               (type.isInterfaceBlock() && (type.getQualifier() == EvqUniform ||
                                                            type.getQualifier() == EvqBuffer)) ||
                               IsImage(type.getBasicType()) || IsSubpassInputType(type.getBasicType());
        bool needsLocation = type.getQualifier() == EvqAttribute ||
                             type.getQualifier() == EvqVertexIn ||
                             type.getQualifier() == EvqFragmentOut || IsVarying(type.getQualifier());
        bool needsInputAttachmentIndex = IsSubpassInputType(type.getBasicType());
    
        if (!NeedsToWriteLayoutQualifier(type) && !needsSetBinding && !needsLocation &&
            !needsInputAttachmentIndex)
        {
            return;
        }
    
        TInfoSinkBase &out                      = objSink();
        const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
    
        // 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);
            }
        }
    
        // Specify matrix packing if necessary.
        if (layoutQualifier.matrixPacking != EmpUnspecified)
        {
            matrixPacking = getMatrixPackingString(layoutQualifier.matrixPacking);
        }
        const char *kCommaSeparator = ", ";
        const char *separator       = "";
        out << "layout(";
    
        // If the resource declaration is about input attachment, need to specify input_attachment_index
        if (needsInputAttachmentIndex)
        {
            out << "input_attachment_index=" << layoutQualifier.inputAttachmentIndex;
            separator = kCommaSeparator;
        }
    
        // If the resource declaration requires set & binding layout qualifiers, specify arbitrary
        // ones.
        if (needsSetBinding)
        {
            out << separator << "set=0, binding=" << nextUnusedBinding();
            separator = kCommaSeparator;
        }
    
        if (needsLocation)
        {
            const unsigned int locationCount = CalculateVaryingLocationCount(symbol, getShaderType());
            uint32_t location                = IsShaderIn(type.getQualifier())
                                    ? nextUnusedInputLocation(locationCount)
                                    : nextUnusedOutputLocation(locationCount);
    
            out << separator << "location=" << location;
            separator = kCommaSeparator;
        }
    
        // Output the list of qualifiers already known at this stage, i.e. everything other than
        // `location` and `set`/`binding`.
        std::string otherQualifiers = getCommonLayoutQualifiers(variable);
    
        if (blockStorage)
        {
            out << separator << blockStorage;
            separator = kCommaSeparator;
        }
        if (matrixPacking)
        {
            out << separator << matrixPacking;
            separator = kCommaSeparator;
        }
        if (!otherQualifiers.empty())
        {
            out << separator << otherQualifiers;
        }
    
        out << ") ";
    }
    
    void TOutputVulkanGLSL::writeVariableType(const TType &type,
                                              const TSymbol *symbol,
                                              bool isFunctionArgument)
    {
        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, isFunctionArgument);
    }
    
    void TOutputVulkanGLSL::writeStructType(const TStructure *structure)
    {
        if (!structDeclared(structure))
        {
            declareStruct(structure);
            objSink() << ";\n";
        }
    }
    
    bool TOutputVulkanGLSL::writeVariablePrecision(TPrecision precision)
    {
        if ((precision == EbpUndefined) || !mEnablePrecision)
            return false;
    
        TInfoSinkBase &out = objSink();
        if (mForceHighp)
            out << getPrecisionString(EbpHigh);
        else
            out << getPrecisionString(precision);
        return true;
    }
    
    }  // namespace sh