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