Hash :
1a5c7a16
Author :
Date :
2020-02-25T12:02:31
Reland "Vulkan:Include precision qualifier in GLSL" Currently still ignoring precision qualifiers for Vulkan shaders by default, but have added feature "enablePrecisionQualifiers" that can be enabled in order to include precision qualifiers. With this initial implementation, it's possible to get precision qualifier mis-matches in the generated GLSL 4.50. According to the spec this is allowed. From GLSLangSpec 4.50 section 4.7 "Precision and Precision Qualifiers": For the purposes of determining if an output from one shader stage matches an input of the next stage, the precision qualifier need not match. However, when converted to SPIR-V and run through the shader validation any mismatches will cause shader validation errors. Initially just ignoring those errors with this commit. Bug: angleproject:3078 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2057749 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Tobin Ehlis <tobine@google.com> Reviewed-by: Tim Van Patten <timvp@google.com> Commit-Queue: Tobin Ehlis <tobine@google.com> Change-Id: Ieecca604bb2c834c9b1c2bcab85279d1f8755dfa Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2086280
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
//
// 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(), false, true, 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;
}
// Metal needs to inverse the depth if depthRange is is reverse order, i.e. depth near > depth far
// This is achieved by multiply the depth value with scale value stored in
// driver uniform's depthRange.reserved
bool TranslatorMetal::transformDepthBeforeCorrection(TIntermBlock *root,
const TVariable *driverUniforms)
{
// Create a symbol reference to "gl_Position"
const TVariable *position = BuiltInVariable::gl_Position();
TIntermSymbol *positionRef = new TIntermSymbol(position);
// Create a swizzle to "gl_Position.z"
TVector<int> swizzleOffsetZ = {2};
TIntermSwizzle *positionZ = new TIntermSwizzle(positionRef, swizzleOffsetZ);
// Create a ref to "depthRange.reserved"
TIntermBinary *viewportZScale = getDriverUniformDepthRangeReservedFieldRef(driverUniforms);
// Create the expression "gl_Position.z * depthRange.reserved".
TIntermBinary *zScale = new TIntermBinary(EOpMul, positionZ->deepCopy(), viewportZScale);
// Create the assignment "gl_Position.z = gl_Position.z * depthRange.reserved"
TIntermTyped *positionZLHS = positionZ->deepCopy();
TIntermBinary *assignment = new TIntermBinary(TOperator::EOpAssign, positionZLHS, zScale);
// Append the assignment as a statement at the end of the shader.
return RunAtTheEndOfShader(this, root, assignment, &getSymbolTable());
}
} // namespace sh