1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // Wrapper for Khronos glslang compiler. This file is used by Vulkan and Metal backends.
7 //
8 
9 #ifndef LIBANGLE_RENDERER_GLSLANG_WRAPPER_UTILS_H_
10 #define LIBANGLE_RENDERER_GLSLANG_WRAPPER_UTILS_H_
11 
12 #include <functional>
13 
14 #include "common/spirv/spirv_types.h"
15 #include "libANGLE/renderer/ProgramImpl.h"
16 #include "libANGLE/renderer/renderer_utils.h"
17 
18 namespace rx
19 {
20 constexpr gl::ShaderMap<const char *> kDefaultUniformNames = {
21     {gl::ShaderType::Vertex, sh::vk::kDefaultUniformsNameVS},
22     {gl::ShaderType::TessControl, sh::vk::kDefaultUniformsNameTCS},
23     {gl::ShaderType::TessEvaluation, sh::vk::kDefaultUniformsNameTES},
24     {gl::ShaderType::Geometry, sh::vk::kDefaultUniformsNameGS},
25     {gl::ShaderType::Fragment, sh::vk::kDefaultUniformsNameFS},
26     {gl::ShaderType::Compute, sh::vk::kDefaultUniformsNameCS},
27 };
28 
29 struct GlslangProgramInterfaceInfo
30 {
31     // Uniforms set index:
32     uint32_t uniformsAndXfbDescriptorSetIndex;
33     uint32_t currentUniformBindingIndex;
34     // Textures set index:
35     uint32_t textureDescriptorSetIndex;
36     uint32_t currentTextureBindingIndex;
37     // Other shader resources set index:
38     uint32_t shaderResourceDescriptorSetIndex;
39     uint32_t currentShaderResourceBindingIndex;
40     // ANGLE driver uniforms set index:
41     uint32_t driverUniformsDescriptorSetIndex;
42 
43     uint32_t locationsUsedForXfbExtension;
44 };
45 
46 struct GlslangSourceOptions
47 {
48     bool supportsTransformFeedbackExtension = false;
49     bool supportsTransformFeedbackEmulation = false;
50     bool enableTransformFeedbackEmulation   = false;
51     bool emulateBresenhamLines              = false;
52 };
53 
54 struct GlslangSpirvOptions
55 {
56     gl::ShaderType shaderType                 = gl::ShaderType::InvalidEnum;
57     SurfaceRotation preRotation               = SurfaceRotation::Identity;
58     bool negativeViewportSupported            = false;
59     bool transformPositionToVulkanClipSpace   = false;
60     bool removeEarlyFragmentTestsOptimization = false;
61     bool removeDebugInfo                      = false;
62     bool isTransformFeedbackStage             = false;
63     bool isTransformFeedbackEmulated          = false;
64 };
65 
66 struct ShaderInterfaceVariableXfbInfo
67 {
68     static constexpr uint32_t kInvalid = std::numeric_limits<uint32_t>::max();
69 
70     // Used by both extension and emulation
71     uint32_t buffer = kInvalid;
72     uint32_t offset = kInvalid;
73     uint32_t stride = kInvalid;
74 
75     // Used only by emulation (array index support is missing from VK_EXT_transform_feedback)
76     uint32_t arraySize   = kInvalid;
77     uint32_t columnCount = kInvalid;
78     uint32_t rowCount    = kInvalid;
79     uint32_t arrayIndex  = kInvalid;
80     GLenum componentType = GL_FLOAT;
81     // If empty, the whole array is captured.  Otherwise only the specified members are captured.
82     std::vector<ShaderInterfaceVariableXfbInfo> arrayElements;
83 };
84 
85 // Information for each shader interface variable.  Not all fields are relevant to each shader
86 // interface variable.  For example opaque uniforms require a set and binding index, while vertex
87 // attributes require a location.
88 struct ShaderInterfaceVariableInfo
89 {
90     ShaderInterfaceVariableInfo();
91 
92     static constexpr uint32_t kInvalid = std::numeric_limits<uint32_t>::max();
93 
94     // Used for interface blocks and opaque uniforms.
95     uint32_t descriptorSet = kInvalid;
96     uint32_t binding       = kInvalid;
97     // Used for vertex attributes, fragment shader outputs and varyings.  There could be different
98     // variables that share the same name, such as a vertex attribute and a fragment output.  They
99     // will share this object since they have the same name, but will find possibly different
100     // locations in their respective slots.
101     uint32_t location  = kInvalid;
102     uint32_t component = kInvalid;
103     uint32_t index     = kInvalid;
104     // The stages this shader interface variable is active.
105     gl::ShaderBitSet activeStages;
106     // Used for transform feedback extension to decorate vertex shader output.
107     ShaderInterfaceVariableXfbInfo xfb;
108     std::vector<ShaderInterfaceVariableXfbInfo> fieldXfb;
109     // Indicates that the precision needs to be modified in the generated SPIR-V
110     // to support only transferring medium precision data when there's a precision
111     // mismatch between the shaders. For example, either the VS casts highp->mediump
112     // or the FS casts mediump->highp.
113     bool useRelaxedPrecision = false;
114     // Indicate if varying is input or output, or both (in case of for example gl_Position in a
115     // geometry shader)
116     bool varyingIsInput  = false;
117     bool varyingIsOutput = false;
118     // For vertex attributes, this is the number of components / locations.  These are used by the
119     // vertex attribute aliasing transformation only.
120     uint8_t attributeComponentCount = 0;
121     uint8_t attributeLocationCount  = 0;
122 };
123 
124 // TODO: http://anglebug.com/4524: Need a different hash key than a string, since that's slow to
125 // calculate.
126 class ShaderInterfaceVariableInfoMap final : angle::NonCopyable
127 {
128   public:
129     ShaderInterfaceVariableInfoMap();
130     ~ShaderInterfaceVariableInfoMap();
131 
132     void clear();
133     bool contains(gl::ShaderType shaderType, const std::string &variableName) const;
134     const ShaderInterfaceVariableInfo &get(gl::ShaderType shaderType,
135                                            const std::string &variableName) const;
136     ShaderInterfaceVariableInfo &get(gl::ShaderType shaderType, const std::string &variableName);
137     ShaderInterfaceVariableInfo &add(gl::ShaderType shaderType, const std::string &variableName);
138     ShaderInterfaceVariableInfo &addOrGet(gl::ShaderType shaderType,
139                                           const std::string &variableName);
variableCount(gl::ShaderType shaderType)140     size_t variableCount(gl::ShaderType shaderType) const { return mData[shaderType].size(); }
141 
142     using VariableNameToInfoMap = angle::HashMap<std::string, ShaderInterfaceVariableInfo>;
143 
144     class Iterator final
145     {
146       public:
Iterator(VariableNameToInfoMap::const_iterator beginIt,VariableNameToInfoMap::const_iterator endIt)147         Iterator(VariableNameToInfoMap::const_iterator beginIt,
148                  VariableNameToInfoMap::const_iterator endIt)
149             : mBeginIt(beginIt), mEndIt(endIt)
150         {}
begin()151         VariableNameToInfoMap::const_iterator begin() { return mBeginIt; }
end()152         VariableNameToInfoMap::const_iterator end() { return mEndIt; }
153 
154       private:
155         VariableNameToInfoMap::const_iterator mBeginIt;
156         VariableNameToInfoMap::const_iterator mEndIt;
157     };
158 
159     Iterator getIterator(gl::ShaderType shaderType) const;
160 
161   private:
162     gl::ShaderMap<VariableNameToInfoMap> mData;
163 };
164 
165 bool GetImageNameWithoutIndices(std::string *name);
166 
167 // Get the mapped sampler name.
168 std::string GlslangGetMappedSamplerName(const std::string &originalName);
169 std::string GetXfbBufferName(const uint32_t bufferIndex);
170 
171 void GlslangAssignLocations(const GlslangSourceOptions &options,
172                             const gl::ProgramState &programState,
173                             const gl::ProgramVaryingPacking &varyingPacking,
174                             const gl::ShaderType shaderType,
175                             const gl::ShaderType frontShaderType,
176                             bool isTransformFeedbackStage,
177                             GlslangProgramInterfaceInfo *programInterfaceInfo,
178                             ShaderInterfaceVariableInfoMap *variableInfoMapOut);
179 
180 void GlslangAssignTransformFeedbackLocations(gl::ShaderType shaderType,
181                                              const gl::ProgramState &programState,
182                                              bool isTransformFeedbackStage,
183                                              GlslangProgramInterfaceInfo *programInterfaceInfo,
184                                              ShaderInterfaceVariableInfoMap *variableInfoMapOut);
185 
186 // Retrieves the compiled SPIR-V code for each shader stage, and calls |GlslangAssignLocations|.
187 void GlslangGetShaderSpirvCode(const GlslangSourceOptions &options,
188                                const gl::ProgramState &programState,
189                                const gl::ProgramLinkedResources &resources,
190                                GlslangProgramInterfaceInfo *programInterfaceInfo,
191                                gl::ShaderMap<const angle::spirv::Blob *> *spirvBlobsOut,
192                                ShaderInterfaceVariableInfoMap *variableInfoMapOut);
193 
194 angle::Result GlslangTransformSpirvCode(const GlslangSpirvOptions &options,
195                                         const ShaderInterfaceVariableInfoMap &variableInfoMap,
196                                         const angle::spirv::Blob &initialSpirvBlob,
197                                         angle::spirv::Blob *spirvBlobOut);
198 
199 }  // namespace rx
200 
201 #endif  // LIBANGLE_RENDERER_GLSLANG_WRAPPER_UTILS_H_
202