Commit 6276b922 by Jamie Madill Committed by Commit Bot

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: 's avatarFrank Henigman <fjhenigman@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org>
parent 10d4026b
...@@ -187,4 +187,17 @@ void ToLower(std::string *str) ...@@ -187,4 +187,17 @@ void ToLower(std::string *str)
} }
} }
bool ReplaceSubstring(std::string *str,
const std::string &substring,
const std::string &replacement)
{
size_t replacePos = str->find(substring);
if (replacePos == std::string::npos)
{
return false;
}
str->replace(replacePos, substring.size(), replacement);
return true;
}
} // namespace angle } // namespace angle
...@@ -65,6 +65,12 @@ bool EndsWith(const std::string& str, const char* suffix); ...@@ -65,6 +65,12 @@ bool EndsWith(const std::string& str, const char* suffix);
// Convert to lower-case. // Convert to lower-case.
void ToLower(std::string *str); void ToLower(std::string *str);
}
// Replaces the substring 'substring' in 'str' with 'replacement'. Returns true if successful.
bool ReplaceSubstring(std::string *str,
const std::string &substring,
const std::string &replacement);
} // namespace angle
#endif // LIBANGLE_STRING_UTILS_H_ #endif // LIBANGLE_STRING_UTILS_H_
...@@ -1104,10 +1104,7 @@ void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node) ...@@ -1104,10 +1104,7 @@ void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node)
TString TOutputGLSLBase::getTypeName(const TType &type) TString TOutputGLSLBase::getTypeName(const TType &type)
{ {
if (type.getBasicType() == EbtStruct) return GetTypeName(type, mHashFunction, &mNameMap);
return hashName(TName(type.getStruct()->name()));
else
return type.getBuiltInTypeNameString();
} }
TString TOutputGLSLBase::hashName(const TName &name) TString TOutputGLSLBase::hashName(const TName &name)
......
...@@ -58,9 +58,14 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable) ...@@ -58,9 +58,14 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
// This isn't super clean, but it gets the job done. // This isn't super clean, but it gets the job done.
// See corresponding code in GlslangWrapper.cpp. // See corresponding code in GlslangWrapper.cpp.
// TODO(jmadill): Ensure declarations are separated. // TODO(jmadill): Ensure declarations are separated.
TIntermSymbol *symbol = variable->getAsSymbolNode(); TIntermSymbol *symbol = variable->getAsSymbolNode();
ASSERT(symbol); ASSERT(symbol);
out << "location = @@ LOCATION-" << symbol->getName().getString() << " @@";
if (forceLocation)
{
out << "location = @@ LOCATION-" << symbol->getName().getString() << " @@";
}
if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified) if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
{ {
...@@ -71,14 +76,4 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable) ...@@ -71,14 +76,4 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
out << ") "; out << ") ";
} }
bool TOutputVulkanGLSL::writeVariablePrecision(TPrecision precision)
{
if (precision == EbpUndefined)
return false;
TInfoSinkBase &out = objSink();
out << getPrecisionString(precision);
return true;
}
} // namespace sh } // namespace sh
...@@ -29,7 +29,6 @@ class TOutputVulkanGLSL : public TOutputGLSL ...@@ -29,7 +29,6 @@ class TOutputVulkanGLSL : public TOutputGLSL
protected: protected:
void writeLayoutQualifier(TIntermTyped *variable) override; void writeLayoutQualifier(TIntermTyped *variable) override;
bool writeVariablePrecision(TPrecision precision) override;
}; };
} // namespace sh } // namespace sh
...@@ -13,10 +13,82 @@ ...@@ -13,10 +13,82 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/OutputVulkanGLSL.h" #include "compiler/translator/OutputVulkanGLSL.h"
#include "compiler/translator/util.h"
namespace sh 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) TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec)
: TCompiler(type, spec, SH_GLSL_450_CORE_OUTPUT) : TCompiler(type, spec, SH_GLSL_450_CORE_OUTPUT)
{ {
...@@ -28,6 +100,18 @@ void TranslatorVulkan::translate(TIntermBlock *root, ShCompileOptions compileOpt ...@@ -28,6 +100,18 @@ void TranslatorVulkan::translate(TIntermBlock *root, ShCompileOptions compileOpt
sink << "#version 450 core\n"; 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 // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
// if it's core profile shaders and they are used. // if it's core profile shaders and they are used.
if (getShaderType() == GL_FRAGMENT_SHADER) if (getShaderType() == GL_FRAGMENT_SHADER)
......
...@@ -447,6 +447,14 @@ TString ArrayString(const TType &type) ...@@ -447,6 +447,14 @@ TString ArrayString(const TType &type)
return arrayString.str(); return arrayString.str();
} }
TString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap)
{
if (type.getBasicType() == EbtStruct)
return HashName(TName(type.getStruct()->name()), hashFunction, nameMap);
else
return type.getBuiltInTypeNameString();
}
bool IsVaryingOut(TQualifier qualifier) bool IsVaryingOut(TQualifier qualifier)
{ {
switch (qualifier) switch (qualifier)
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "angle_gl.h" #include "angle_gl.h"
#include <GLSLANG/ShaderLang.h> #include <GLSLANG/ShaderLang.h>
#include "compiler/translator/HashNames.h"
#include "compiler/translator/Operator.h" #include "compiler/translator/Operator.h"
#include "compiler/translator/Types.h" #include "compiler/translator/Types.h"
...@@ -44,6 +45,8 @@ InterpolationType GetInterpolationType(TQualifier qualifier); ...@@ -44,6 +45,8 @@ InterpolationType GetInterpolationType(TQualifier qualifier);
// 3.10 section 4.1.9. // 3.10 section 4.1.9.
TString ArrayString(const TType &type); TString ArrayString(const TType &type);
TString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap);
TType GetShaderVariableBasicType(const sh::ShaderVariable &var); TType GetShaderVariableBasicType(const sh::ShaderVariable &var);
bool IsBuiltinOutputVariable(TQualifier qualifier); bool IsBuiltinOutputVariable(TQualifier qualifier);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "libANGLE/renderer/d3d/DynamicHLSL.h" #include "libANGLE/renderer/d3d/DynamicHLSL.h"
#include "common/string_utils.h"
#include "common/utilities.h" #include "common/utilities.h"
#include "compiler/translator/blocklayoutHLSL.h" #include "compiler/translator/blocklayoutHLSL.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
...@@ -272,8 +273,9 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout( ...@@ -272,8 +273,9 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(
std::string vertexHLSL(sourceShader); std::string vertexHLSL(sourceShader);
size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING); bool success =
vertexHLSL.replace(copyInsertionPos, strlen(VERTEX_ATTRIBUTE_STUB_STRING), structStream.str()); angle::ReplaceSubstring(&vertexHLSL, VERTEX_ATTRIBUTE_STUB_STRING, structStream.str());
ASSERT(success);
return vertexHLSL; return vertexHLSL;
} }
...@@ -348,9 +350,9 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature( ...@@ -348,9 +350,9 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(
std::string pixelHLSL(sourceShader); std::string pixelHLSL(sourceShader);
size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING); bool success =
pixelHLSL.replace(outputInsertionPos, strlen(PIXEL_OUTPUT_STUB_STRING), angle::ReplaceSubstring(&pixelHLSL, PIXEL_OUTPUT_STUB_STRING, declarationStream.str());
declarationStream.str()); ASSERT(success);
return pixelHLSL; return pixelHLSL;
} }
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include <array> #include <array>
#include "common/string_utils.h"
namespace rx namespace rx
{ {
...@@ -70,7 +72,7 @@ gl::LinkResult GlslangWrapper::linkProgram(const gl::Context *glContext, ...@@ -70,7 +72,7 @@ gl::LinkResult GlslangWrapper::linkProgram(const gl::Context *glContext,
{ {
std::string vertexSource = std::string vertexSource =
programState.getAttachedVertexShader()->getTranslatedSource(glContext); programState.getAttachedVertexShader()->getTranslatedSource(glContext);
const std::string &fragmentSource = std::string fragmentSource =
programState.getAttachedFragmentShader()->getTranslatedSource(glContext); programState.getAttachedFragmentShader()->getTranslatedSource(glContext);
// Parse attribute locations and replace them in the vertex shader. // Parse attribute locations and replace them in the vertex shader.
...@@ -87,11 +89,22 @@ gl::LinkResult GlslangWrapper::linkProgram(const gl::Context *glContext, ...@@ -87,11 +89,22 @@ gl::LinkResult GlslangWrapper::linkProgram(const gl::Context *glContext,
std::string locationString = Str(attribute.location); std::string locationString = Str(attribute.location);
size_t replacePos = vertexSource.find(searchString); bool success = angle::ReplaceSubstring(&vertexSource, searchString, locationString);
ASSERT(replacePos != std::string::npos); ASSERT(success);
vertexSource.replace(replacePos, searchString.size(), locationString);
} }
// Bind the default uniforms for vertex and fragment shaders.
// See corresponding code in OutputVulkanGLSL.cpp.
std::stringstream searchStringBuilder;
searchStringBuilder << "@@ DEFAULT-UNIFORMS-SET-BINDING @@";
std::string searchString = searchStringBuilder.str();
std::string vertexDefaultUniformsBinding = "set = 0, binding = 0";
std::string fragmentDefaultUniformsBinding = "set = 0, binding = 1";
angle::ReplaceSubstring(&vertexSource, searchString, vertexDefaultUniformsBinding);
angle::ReplaceSubstring(&fragmentSource, searchString, fragmentDefaultUniformsBinding);
std::array<const char *, 2> strings = {{vertexSource.c_str(), fragmentSource.c_str()}}; std::array<const char *, 2> strings = {{vertexSource.c_str(), fragmentSource.c_str()}};
std::array<int, 2> lengths = { std::array<int, 2> lengths = {
......
...@@ -531,6 +531,8 @@ void RendererVk::generateCaps(gl::Caps *outCaps, ...@@ -531,6 +531,8 @@ void RendererVk::generateCaps(gl::Caps *outCaps,
outCaps->maxCombinedTextureImageUnits = 1; outCaps->maxCombinedTextureImageUnits = 1;
outCaps->max2DTextureSize = 1024; outCaps->max2DTextureSize = 1024;
outCaps->maxElementIndex = std::numeric_limits<GLuint>::max() - 1; outCaps->maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
outCaps->maxFragmentUniformVectors = 8;
outCaps->maxVertexUniformVectors = 8;
// Enable this for simple buffer readback testing, but some functionality is missing. // Enable this for simple buffer readback testing, but some functionality is missing.
// TODO(jmadill): Support full mapBufferRange extension. // TODO(jmadill): Support full mapBufferRange extension.
......
...@@ -108,13 +108,6 @@ TEST_P(SimpleOperationTest, LinkProgram) ...@@ -108,13 +108,6 @@ TEST_P(SimpleOperationTest, LinkProgram)
TEST_P(SimpleOperationTest, LinkProgramWithUniforms) TEST_P(SimpleOperationTest, LinkProgramWithUniforms)
{ {
if (IsVulkan())
{
// TODO(jmadill): Complete Vulkan implementation.
std::cout << "Test skipped on Vulkan." << std::endl;
return;
}
const std::string vsSource = const std::string vsSource =
R"(void main() R"(void main()
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment