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