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