Hash :
6276b922
Author :
Date :
2017-09-25T02:35:57
Vulkan: Implement basic uniform shader parsing. This is a first step at implementing uniforms with descriptor sets. It does not actually bind uniforms and upload data, but it does implement uniform shader parsing. Uniforms are gathered into a single uniform block which is bound to set 0, with binding 0 for vertex uniforms and binding 1 for fragment uniforms. Also adds a ReplaceSubstring helper to string_utils. Also removes the precision writing from OutputVulkanGLSL since this was generating warnings with glslang. BUG=angleproject:2167 Change-Id: I9ec8351ec1973e583100f99292b0080ee968067b Reviewed-on: https://chromium-review.googlesource.com/699938 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Frank Henigman <fjhenigman@chromium.org> Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
//
// 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 "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);
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";
}
mInDefaultUniform = false;
// Remove the uniform declaration from the tree so it isn't parsed again.
TIntermSequence emptyReplacement;
mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(),
node, emptyReplacement));
}
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)
{
TInfoSinkBase &sink = getInfoSink().obj;
sink << "#version 450 core\n";
// Write out default uniforms into a uniform block assigned to a specific set/binding.
if (!getUniforms().empty())
{
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