Edit

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

Branch :

  • Show log

    Commit

  • Author : Le Quyen
    Date : 2019-10-29 22:57:55
    Hash : a5a04ac0
    Message : Metal backend pt3: shader translator Implementation of GLSL to MSL translator Bug: angleproject:2634 Change-Id: I66e2374b461548fac46163ea79790a488515e6b0 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1887251 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/compiler/translator/TranslatorMetal.cpp
  • //
    // Copyright (c) 2019 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.
    //
    // TranslatorMetal:
    //   A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl.
    //   It takes into account some considerations for Metal backend also.
    //   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
    //
    //   The SPIR-V will then be translated to Metal Shading Language later in Metal backend.
    //
    
    #include "compiler/translator/TranslatorMetal.h"
    
    #include "angle_gl.h"
    #include "common/utilities.h"
    #include "compiler/translator/OutputVulkanGLSLForMetal.h"
    #include "compiler/translator/StaticType.h"
    #include "compiler/translator/tree_util/BuiltIn.h"
    #include "compiler/translator/tree_util/RunAtTheEndOfShader.h"
    #include "compiler/translator/util.h"
    
    namespace sh
    {
    
    namespace
    {
    
    // Unlike Vulkan having auto viewport flipping extension, in Metal we have to flip gl_Position.y
    // manually.
    // This operation performs flipping the gl_Position.y using this expression:
    // gl_Position.y = gl_Position.y * negViewportScaleY
    ANGLE_NO_DISCARD bool AppendVertexShaderPositionYCorrectionToMain(TCompiler *compiler,
                                                                      TIntermBlock *root,
                                                                      TSymbolTable *symbolTable,
                                                                      TIntermBinary *negViewportYScale)
    {
        // Create a symbol reference to "gl_Position"
        const TVariable *position  = BuiltInVariable::gl_Position();
        TIntermSymbol *positionRef = new TIntermSymbol(position);
    
        // Create a swizzle to "gl_Position.y"
        TVector<int> swizzleOffsetY;
        swizzleOffsetY.push_back(1);
        TIntermSwizzle *positionY = new TIntermSwizzle(positionRef, swizzleOffsetY);
    
        // Create the expression "gl_Position.y * negViewportScaleY"
        TIntermBinary *inverseY = new TIntermBinary(EOpMul, positionY->deepCopy(), negViewportYScale);
    
        // Create the assignment "gl_Position.y = gl_Position.y * negViewportScaleY
        TIntermTyped *positionYLHS = positionY->deepCopy();
        TIntermBinary *assignment  = new TIntermBinary(TOperator::EOpAssign, positionYLHS, inverseY);
    
        // Append the assignment as a statement at the end of the shader.
        return RunAtTheEndOfShader(compiler, root, assignment, symbolTable);
    }
    
    }  // anonymous namespace
    
    TranslatorMetal::TranslatorMetal(sh::GLenum type, ShShaderSpec spec) : TranslatorVulkan(type, spec)
    {}
    
    bool TranslatorMetal::translate(TIntermBlock *root,
                                    ShCompileOptions compileOptions,
                                    PerformanceDiagnostics *perfDiagnostics)
    {
        TInfoSinkBase &sink = getInfoSink().obj;
        TOutputVulkanGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(),
                                     getNameMap(), &getSymbolTable(), getShaderType(),
                                     getShaderVersion(), getOutputType(), compileOptions);
    
        const TVariable *driverUniforms = nullptr;
        if (!TranslatorVulkan::translateImpl(root, compileOptions, perfDiagnostics, &driverUniforms,
                                             &outputGLSL))
        {
            return false;
        }
    
        if (getShaderType() == GL_VERTEX_SHADER)
        {
            auto negViewportYScale = getDriverUniformNegViewportYScaleRef(driverUniforms);
    
            // Append gl_Position.y correction to main
            if (!AppendVertexShaderPositionYCorrectionToMain(this, root, &getSymbolTable(),
                                                             negViewportYScale))
            {
                return false;
            }
        }
    
        // Write translated shader.
        root->traverse(&outputGLSL);
    
        return true;
    }
    
    }  // namespace sh