• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Utilities to map shader interface variables to Vulkan mappings, and transform the SPIR-V
7 // accordingly.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_VULKAN_SPV_UTILS_H_
11 #define LIBANGLE_RENDERER_VULKAN_SPV_UTILS_H_
12 
13 #include <functional>
14 
15 #include "common/spirv/spirv_types.h"
16 #include "libANGLE/renderer/ProgramImpl.h"
17 #include "libANGLE/renderer/renderer_utils.h"
18 #include "platform/autogen/FeaturesVk_autogen.h"
19 
20 namespace rx
21 {
22 class ShaderInterfaceVariableInfoMap;
23 
24 struct SpvProgramInterfaceInfo
25 {
26     uint32_t currentUniformBindingIndex        = 0;
27     uint32_t currentTextureBindingIndex        = 0;
28     uint32_t currentShaderResourceBindingIndex = 0;
29 
30     uint32_t locationsUsedForXfbExtension = 0;
31 };
32 
33 struct SpvSourceOptions
34 {
35     bool supportsTransformFeedbackExtension = false;
36     bool supportsTransformFeedbackEmulation = false;
37     bool enableTransformFeedbackEmulation   = false;
38 };
39 
40 SpvSourceOptions SpvCreateSourceOptions(const angle::FeaturesVk &features);
41 
42 struct SpvTransformOptions
43 {
44     gl::ShaderType shaderType           = gl::ShaderType::InvalidEnum;
45     bool isLastPreFragmentStage         = false;
46     bool isTransformFeedbackStage       = false;
47     bool isTransformFeedbackEmulated    = false;
48     bool isMultisampledFramebufferFetch = false;
49     bool enableSampleShading            = false;
50     bool validate                       = true;
51     bool useSpirvVaryingPrecisionFixer  = false;
52 };
53 
54 struct ShaderInterfaceVariableXfbInfo
55 {
56     static constexpr uint32_t kInvalid = std::numeric_limits<uint32_t>::max();
57 
58     ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
59     struct PODStruct
60     {
61         // Used by both extension and emulation
62         uint32_t buffer = kInvalid;
63         uint32_t offset = kInvalid;
64         uint32_t stride = kInvalid;
65 
66         // Used only by emulation (array index support is missing from VK_EXT_transform_feedback)
67         uint32_t arraySize   = kInvalid;
68         uint32_t columnCount = kInvalid;
69         uint32_t rowCount    = kInvalid;
70         uint32_t arrayIndex  = kInvalid;
71         GLenum componentType = GL_FLOAT;
72     } pod;
73     ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
74     // If empty, the whole array is captured.  Otherwise only the specified members are captured.
75     std::vector<ShaderInterfaceVariableXfbInfo> arrayElements;
76 };
77 
78 // Information for each shader interface variable.  Not all fields are relevant to each shader
79 // interface variable.  For example opaque uniforms require a set and binding index, while vertex
80 // attributes require a location.
81 ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
82 struct ShaderInterfaceVariableInfo
83 {
ShaderInterfaceVariableInfoShaderInterfaceVariableInfo84     ShaderInterfaceVariableInfo()
85         : descriptorSet(kInvalid),
86           binding(kInvalid),
87           location(kInvalid),
88           component(kInvalid),
89           index(kInvalid),
90           useRelaxedPrecision(false),
91           varyingIsInput(false),
92           varyingIsOutput(false),
93           hasTransformFeedback(false),
94           isArray(false),
95           padding(0),
96           attributeComponentCount(0),
97           attributeLocationCount(0)
98     {}
99 
100     static constexpr uint32_t kInvalid = std::numeric_limits<uint32_t>::max();
101 
102     // Used for interface blocks and opaque uniforms.
103     uint32_t descriptorSet;
104     uint32_t binding;
105     // Used for vertex attributes, fragment shader outputs and varyings.  There could be different
106     // variables that share the same name, such as a vertex attribute and a fragment output.  They
107     // will share this object since they have the same name, but will find possibly different
108     // locations in their respective slots.
109     uint32_t location;
110     uint32_t component;
111     uint32_t index;
112 
113     // The stages this shader interface variable is active.
114     gl::ShaderBitSet activeStages;
115 
116     // Indicates that the precision needs to be modified in the generated SPIR-V
117     // to support only transferring medium precision data when there's a precision
118     // mismatch between the shaders. For example, either the VS casts highp->mediump
119     // or the FS casts mediump->highp.
120     uint8_t useRelaxedPrecision : 1;
121     // Indicate if varying is input or output, or both (in case of for example gl_Position in a
122     // geometry shader)
123     uint8_t varyingIsInput : 1;
124     uint8_t varyingIsOutput : 1;
125     uint8_t hasTransformFeedback : 1;
126     uint8_t isArray : 1;
127     uint8_t padding : 3;
128 
129     // For vertex attributes, this is the number of components / locations.  These are used by the
130     // vertex attribute aliasing transformation only.
131     uint8_t attributeComponentCount;
132     uint8_t attributeLocationCount;
133 };
134 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
135 
136 struct XFBInterfaceVariableInfo
137 {
138     // Used for transform feedback extension to decorate vertex shader output.
139     ShaderInterfaceVariableXfbInfo xfb;
140     std::vector<ShaderInterfaceVariableXfbInfo> fieldXfb;
141 };
142 using XFBVariableInfoPtr = std::unique_ptr<XFBInterfaceVariableInfo>;
143 
144 uint32_t SpvGetXfbBufferBlockId(const uint32_t bufferIndex);
145 
146 void SpvAssignLocations(const SpvSourceOptions &options,
147                         const gl::ProgramExecutable &programExecutable,
148                         const gl::ProgramVaryingPacking &varyingPacking,
149                         const gl::ShaderType transformFeedbackStage,
150                         SpvProgramInterfaceInfo *programInterfaceInfo,
151                         ShaderInterfaceVariableInfoMap *variableInfoMapOut);
152 
153 void SpvAssignTransformFeedbackLocations(gl::ShaderType shaderType,
154                                          const gl::ProgramExecutable &programExecutable,
155                                          bool isTransformFeedbackStage,
156                                          SpvProgramInterfaceInfo *programInterfaceInfo,
157                                          ShaderInterfaceVariableInfoMap *variableInfoMapOut);
158 
159 // Retrieves the compiled SPIR-V code for each shader stage.
160 void SpvGetShaderSpirvCode(const gl::ProgramState &programState,
161                            gl::ShaderMap<const angle::spirv::Blob *> *spirvBlobsOut);
162 
163 // Calls |SpvAssign*Locations| as necessary.
164 void SpvAssignAllLocations(const SpvSourceOptions &options,
165                            const gl::ProgramState &programState,
166                            const gl::ProgramLinkedResources &resources,
167                            ShaderInterfaceVariableInfoMap *variableInfoMapOut);
168 
169 angle::Result SpvTransformSpirvCode(const SpvTransformOptions &options,
170                                     const ShaderInterfaceVariableInfoMap &variableInfoMap,
171                                     const angle::spirv::Blob &initialSpirvBlob,
172                                     angle::spirv::Blob *spirvBlobOut);
173 
174 }  // namespace rx
175 
176 #endif  // LIBANGLE_RENDERER_VULKAN_SPV_UTILS_H_
177