diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp new file mode 100644 index 0000000000..0fe2a21f90 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp @@ -0,0 +1,173 @@ +// +// Copyright (c) 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. +// +// TranslatorVulkan: +// A GLSL-based translator 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/TranslatorVulkan.h" + +#include "angle_gl.h" +#include "common/utilities.h" +#include "compiler/translator/OutputVulkanGLSL.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +class DeclareDefaultUniformsTraverser : public TIntermTraverser +{ + public: + DeclareDefaultUniformsTraverser(TInfoSinkBase *sink, + ShHashFunction64 hashFunction, + NameMap *nameMap) + : TIntermTraverser(true, true, true), + mSink(sink), + mHashFunction(hashFunction), + mNameMap(nameMap), + mInDefaultUniform(false) + { + } + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + const TIntermSequence &sequence = *(node->getSequence()); + + // TODO(jmadill): Compound declarations. + ASSERT(sequence.size() == 1); + + TIntermTyped *variable = sequence.front()->getAsTyped(); + const TType &type = variable->getType(); + bool isUniform = (type.getQualifier() == EvqUniform) && !IsOpaqueType(type.getBasicType()); + + if (visit == PreVisit) + { + if (isUniform) + { + (*mSink) << " " << GetTypeName(type, mHashFunction, mNameMap) << " "; + mInDefaultUniform = true; + } + } + else if (visit == InVisit) + { + mInDefaultUniform = isUniform; + } + else if (visit == PostVisit) + { + if (isUniform) + { + (*mSink) << ";\n"; + + // Remove the uniform declaration from the tree so it isn't parsed again. + TIntermSequence emptyReplacement; + mMultiReplacements.push_back(NodeReplaceWithMultipleEntry( + getParentNode()->getAsBlock(), node, emptyReplacement)); + } + + mInDefaultUniform = false; + } + return true; + } + + void visitSymbol(TIntermSymbol *symbol) override + { + if (mInDefaultUniform) + { + const TName &name = symbol->getName(); + ASSERT(name.getString().substr(0, 3) != "gl_"); + (*mSink) << HashName(name, mHashFunction, mNameMap); + } + } + + private: + TInfoSinkBase *mSink; + ShHashFunction64 mHashFunction; + NameMap *mNameMap; + bool mInDefaultUniform; +}; + +TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec) + : TCompiler(type, spec, SH_GLSL_450_CORE_OUTPUT) +{ +} + +void TranslatorVulkan::translate(TIntermBlock *root, + ShCompileOptions compileOptions, + PerformanceDiagnostics * /*perfDiagnostics*/) +{ + TInfoSinkBase &sink = getInfoSink().obj; + + sink << "#version 450 core\n"; + + // Write out default uniforms into a uniform block assigned to a specific set/binding. + int defaultUniformCount = 0; + for (const auto &uniform : getUniforms()) + { + if (!uniform.isBuiltIn() && uniform.staticUse && !gl::IsOpaqueType(uniform.type)) + { + ++defaultUniformCount; + } + } + + if (defaultUniformCount > 0) + { + sink << "\nlayout(@@ DEFAULT-UNIFORMS-SET-BINDING @@) uniform defaultUniforms\n{\n"; + + DeclareDefaultUniformsTraverser defaultTraverser(&sink, getHashFunction(), &getNameMap()); + root->traverse(&defaultTraverser); + defaultTraverser.updateTree(); + + sink << "};\n"; + } + + // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData + // if it's core profile shaders and they are used. + if (getShaderType() == GL_FRAGMENT_SHADER) + { + bool hasGLFragColor = false; + bool hasGLFragData = false; + + for (const auto &outputVar : outputVariables) + { + if (outputVar.name == "gl_FragColor") + { + ASSERT(!hasGLFragColor); + hasGLFragColor = true; + continue; + } + else if (outputVar.name == "gl_FragData") + { + ASSERT(!hasGLFragData); + hasGLFragData = true; + continue; + } + } + ASSERT(!(hasGLFragColor && hasGLFragData)); + if (hasGLFragColor) + { + sink << "layout(location = 0) out vec4 webgl_FragColor;\n"; + } + if (hasGLFragData) + { + sink << "layout(location = 0) out vec4 webgl_FragData[gl_MaxDrawBuffers];\n"; + } + } + + // Write translated shader. + TOutputVulkanGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), + getNameMap(), &getSymbolTable(), getShaderType(), + getShaderVersion(), getOutputType(), compileOptions); + root->traverse(&outputGLSL); +} + +bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll() +{ + // Not necessary. + return false; +} + +} // namespace sh |