summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp173
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