Hash :
a8a2a71b
Author :
Date :
2021-02-01T17:18:18
Vulkan: Support y-flip with no driver support. We can reuse the surface rotation matrix code to do the y-flip. This requires the SPIR-V transformation support. Because not all rotations are encoded into the table we can only support rotation with the driver support for y-flip (currently). Includes some very minimal regression testing. This work is targeted towards supporting vk-portability implementations which are not as up-to-date with Vulkan features. Bug: angleproject:5596 Change-Id: I270fa1efc03267551d28df33ddac9972e1343d60 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2665892 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Ian Elliott <ianelliott@google.com> Commit-Queue: Jamie Madill <jmadill@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 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
//
// Copyright 2019 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.
//
// Wrapper for Khronos glslang compiler. This file is used by Vulkan and Metal backends.
//
#ifndef LIBANGLE_RENDERER_GLSLANG_WRAPPER_UTILS_H_
#define LIBANGLE_RENDERER_GLSLANG_WRAPPER_UTILS_H_
#include <functional>
#include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/renderer_utils.h"
namespace rx
{
enum class GlslangError
{
InvalidShader,
InvalidSpirv,
};
constexpr gl::ShaderMap<const char *> kDefaultUniformNames = {
{gl::ShaderType::Vertex, sh::vk::kDefaultUniformsNameVS},
{gl::ShaderType::TessControl, sh::vk::kDefaultUniformsNameTCS},
{gl::ShaderType::TessEvaluation, sh::vk::kDefaultUniformsNameTES},
{gl::ShaderType::Geometry, sh::vk::kDefaultUniformsNameGS},
{gl::ShaderType::Fragment, sh::vk::kDefaultUniformsNameFS},
{gl::ShaderType::Compute, sh::vk::kDefaultUniformsNameCS},
};
struct GlslangProgramInterfaceInfo
{
// Uniforms set index:
uint32_t uniformsAndXfbDescriptorSetIndex;
uint32_t currentUniformBindingIndex;
// Textures set index:
uint32_t textureDescriptorSetIndex;
uint32_t currentTextureBindingIndex;
// Other shader resources set index:
uint32_t shaderResourceDescriptorSetIndex;
uint32_t currentShaderResourceBindingIndex;
// ANGLE driver uniforms set index:
uint32_t driverUniformsDescriptorSetIndex;
uint32_t locationsUsedForXfbExtension;
};
struct GlslangSourceOptions
{
bool supportsTransformFeedbackExtension = false;
bool supportsTransformFeedbackEmulation = false;
bool enableTransformFeedbackEmulation = false;
bool emulateBresenhamLines = false;
};
struct GlslangSpirvOptions
{
gl::ShaderType shaderType = gl::ShaderType::InvalidEnum;
SurfaceRotation preRotation = SurfaceRotation::Identity;
bool negativeViewportSupported = false;
bool transformPositionToVulkanClipSpace = false;
bool removeEarlyFragmentTestsOptimization = false;
bool removeDebugInfo = false;
bool isTransformFeedbackStage = false;
};
using SpirvBlob = std::vector<uint32_t>;
using GlslangErrorCallback = std::function<angle::Result(GlslangError)>;
struct ShaderInterfaceVariableXfbInfo
{
static constexpr uint32_t kInvalid = std::numeric_limits<uint32_t>::max();
uint32_t buffer = kInvalid;
uint32_t offset = kInvalid;
uint32_t stride = kInvalid;
};
// Information for each shader interface variable. Not all fields are relevant to each shader
// interface variable. For example opaque uniforms require a set and binding index, while vertex
// attributes require a location.
struct ShaderInterfaceVariableInfo
{
ShaderInterfaceVariableInfo();
static constexpr uint32_t kInvalid = std::numeric_limits<uint32_t>::max();
// Used for interface blocks and opaque uniforms.
uint32_t descriptorSet = kInvalid;
uint32_t binding = kInvalid;
// Used for vertex attributes, fragment shader outputs and varyings. There could be different
// variables that share the same name, such as a vertex attribute and a fragment output. They
// will share this object since they have the same name, but will find possibly different
// locations in their respective slots.
uint32_t location = kInvalid;
uint32_t component = kInvalid;
uint32_t index = kInvalid;
// The stages this shader interface variable is active.
gl::ShaderBitSet activeStages;
// Used for transform feedback extension to decorate vertex shader output.
ShaderInterfaceVariableXfbInfo xfb;
std::vector<ShaderInterfaceVariableXfbInfo> fieldXfb;
// Indicates that the precision needs to be modified in the generated SPIR-V
// to support only transferring medium precision data when there's a precision
// mismatch between the shaders. For example, either the VS casts highp->mediump
// or the FS casts mediump->highp.
bool useRelaxedPrecision = false;
// Indicate if varying is input or output, or both (in case of for example gl_Position in a
// geometry shader)
bool varyingIsInput = false;
bool varyingIsOutput = false;
// For vertex attributes, this is the number of components / locations. These are used by the
// vertex attribute aliasing transformation only.
uint8_t attributeComponentCount = 0;
uint8_t attributeLocationCount = 0;
};
// TODO: http://anglebug.com/4524: Need a different hash key than a string, since that's slow to
// calculate.
class ShaderInterfaceVariableInfoMap final : angle::NonCopyable
{
public:
ShaderInterfaceVariableInfoMap();
~ShaderInterfaceVariableInfoMap();
void clear();
bool contains(gl::ShaderType shaderType, const std::string &variableName) const;
const ShaderInterfaceVariableInfo &get(gl::ShaderType shaderType,
const std::string &variableName) const;
ShaderInterfaceVariableInfo &get(gl::ShaderType shaderType, const std::string &variableName);
ShaderInterfaceVariableInfo &add(gl::ShaderType shaderType, const std::string &variableName);
ShaderInterfaceVariableInfo &addOrGet(gl::ShaderType shaderType,
const std::string &variableName);
size_t variableCount(gl::ShaderType shaderType) const { return mData[shaderType].size(); }
using VariableNameToInfoMap = angle::HashMap<std::string, ShaderInterfaceVariableInfo>;
class Iterator final
{
public:
Iterator(VariableNameToInfoMap::const_iterator beginIt,
VariableNameToInfoMap::const_iterator endIt)
: mBeginIt(beginIt), mEndIt(endIt)
{}
VariableNameToInfoMap::const_iterator begin() { return mBeginIt; }
VariableNameToInfoMap::const_iterator end() { return mEndIt; }
private:
VariableNameToInfoMap::const_iterator mBeginIt;
VariableNameToInfoMap::const_iterator mEndIt;
};
Iterator getIterator(gl::ShaderType shaderType) const;
private:
gl::ShaderMap<VariableNameToInfoMap> mData;
};
void GlslangInitialize();
void GlslangRelease();
bool GetImageNameWithoutIndices(std::string *name);
// Get the mapped sampler name after the source is transformed by GlslangGetShaderSource()
std::string GlslangGetMappedSamplerName(const std::string &originalName);
std::string GetXfbBufferName(const uint32_t bufferIndex);
// NOTE: options.emulateTransformFeedback is ignored in this case. It is assumed to be always true.
void GlslangGenTransformFeedbackEmulationOutputs(
const GlslangSourceOptions &options,
const gl::ProgramState &programState,
GlslangProgramInterfaceInfo *programInterfaceInfo,
std::string *vertexShader,
ShaderInterfaceVariableInfoMap *variableInfoMapOut);
void GlslangAssignLocations(const GlslangSourceOptions &options,
const gl::ProgramState &programState,
const gl::ProgramVaryingPacking &varyingPacking,
const gl::ShaderType shaderType,
const gl::ShaderType frontShaderType,
bool isTransformFeedbackStage,
GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut);
// Transform the source to include actual binding points for various shader resources (textures,
// buffers, xfb, etc). For some variables, these values are instead output to the variableInfoMap
// to be set during a SPIR-V transformation. This is a transitory step towards moving all variables
// to this map, at which point GlslangGetShaderSpirvCode will also be called by this function.
void GlslangGetShaderSource(const GlslangSourceOptions &options,
const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources,
GlslangProgramInterfaceInfo *programInterfaceInfo,
gl::ShaderMap<std::string> *shaderSourcesOut,
ShaderInterfaceVariableInfoMap *variableInfoMapOut);
angle::Result GlslangTransformSpirvCode(const GlslangErrorCallback &callback,
const GlslangSpirvOptions &options,
const ShaderInterfaceVariableInfoMap &variableInfoMap,
const SpirvBlob &initialSpirvBlob,
SpirvBlob *spirvBlobOut);
angle::Result GlslangGetShaderSpirvCode(const GlslangErrorCallback &callback,
const gl::ShaderBitSet &linkedShaderStages,
const gl::Caps &glCaps,
const gl::ShaderMap<std::string> &shaderSources,
gl::ShaderMap<SpirvBlob> *spirvBlobsOut);
angle::Result GlslangCompileShaderOneOff(const GlslangErrorCallback &callback,
gl::ShaderType shaderType,
const std::string &shaderSource,
SpirvBlob *spirvBlobOut);
} // namespace rx
#endif // LIBANGLE_RENDERER_GLSLANG_WRAPPER_UTILS_H_