Hash :
62742f9e
Author :
Date :
2019-05-01T16:14:50
Vulkan: Optimize shader source macro replacement @@ LAYOUT-xx @@ and @@ QUALIFIER-xx @@ macros are generated by the compiler when emitting Vulkan GLSL. These macros are replaced at link time in the Vulkan backend. Previously, this replacement was done through calls to angle::ReplaceSubstring, reiterating over the whole source on every replacement. This CL does a prepass on the input source and chunks it up in blocks. Search is optimized as only blocks of a certain type are string-compared (skipping large chunks of shader text). Replace is optimized as the whole shader is not shifted left or right on every replacement. Additionally, this CL modifies the layout macro to the following format: @@ LAYOUT-xx(extra, args) @@ This is used in a follow up CL to have the compiler provide additional layout qualifiers. Bug: angleproject:3220 Change-Id: I6367e781c3304d5f2e0a406e4fb4e6feb4c45f1d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1592070 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Jamie Madill <jmadill@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
//
// 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.
//
// OutputVulkanGLSL:
// Code 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/OutputVulkanGLSL.h"
#include "compiler/translator/BaseTypes.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/util.h"
namespace sh
{
TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap &nameMap,
TSymbolTable *symbolTable,
sh::GLenum shaderType,
int shaderVersion,
ShShaderOutput output,
ShCompileOptions compileOptions)
: TOutputGLSL(objSink,
clampingStrategy,
hashFunction,
nameMap,
symbolTable,
shaderType,
shaderVersion,
output,
compileOptions)
{}
// TODO(jmadill): This is not complete.
void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
{
const TType &type = variable->getType();
bool needsCustomLayout =
(type.getQualifier() == EvqAttribute || type.getQualifier() == EvqFragmentOut ||
type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier()) ||
IsSampler(type.getBasicType()) || type.isInterfaceBlock());
if (!NeedsToWriteLayoutQualifier(type) && !needsCustomLayout)
{
return;
}
TInfoSinkBase &out = objSink();
const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
// This isn't super clean, but it gets the job done.
// See corresponding code in GlslangWrapper.cpp.
TIntermSymbol *symbol = variable->getAsSymbolNode();
ASSERT(symbol);
if (needsCustomLayout)
{
out << "@@ LAYOUT-" << symbol->getName() << "() @@";
}
else
{
out << "layout(";
}
if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
{
ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform);
out << getImageInternalFormatString(layoutQualifier.imageInternalFormat);
}
if (!needsCustomLayout)
{
out << ") ";
}
}
void TOutputVulkanGLSL::writeQualifier(TQualifier qualifier, const TSymbol *symbol)
{
if (qualifier != EvqUniform && qualifier != EvqAttribute && !sh::IsVarying(qualifier))
{
TOutputGLSLBase::writeQualifier(qualifier, symbol);
return;
}
if (symbol == nullptr)
{
return;
}
TInfoSinkBase &out = objSink();
out << "@@ QUALIFIER-" << symbol->name().data() << " @@ ";
}
void TOutputVulkanGLSL::writeVariableType(const TType &type, const TSymbol *symbol)
{
TType overrideType(type);
// External textures are treated as 2D textures in the vulkan back-end
if (type.getBasicType() == EbtSamplerExternalOES)
{
overrideType.setBasicType(EbtSampler2D);
}
TOutputGLSL::writeVariableType(overrideType, symbol);
}
void TOutputVulkanGLSL::writeStructType(const TStructure *structure)
{
if (!structDeclared(structure))
{
declareStruct(structure);
objSink() << ";\n";
}
}
} // namespace sh