xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/ShaderInterfaceVariableInfoMap.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2021 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 // ShaderInterfaceVariableInfoMap: Maps shader interface variable SPIR-V ids to their Vulkan
7 // mapping.
8 
9 #ifndef LIBANGLE_RENDERER_VULKAN_SHADERINTERFACEVARIABLEINFOMAP_H_
10 #define LIBANGLE_RENDERER_VULKAN_SHADERINTERFACEVARIABLEINFOMAP_H_
11 
12 #include "common/FastVector.h"
13 #include "libANGLE/renderer/ProgramImpl.h"
14 #include "libANGLE/renderer/renderer_utils.h"
15 #include "libANGLE/renderer/vulkan/spv_utils.h"
16 
17 #include <functional>
18 
19 #include <stdio.h>
20 
21 namespace rx
22 {
23 
24 struct VariableIndex
25 {
26     static constexpr uint32_t kInvalid = 0xFFFF'FFFF;
27     uint32_t index                     = kInvalid;
28 };
29 
30 class ShaderInterfaceVariableInfoMap final : angle::NonCopyable
31 {
32   public:
33     // For each interface variable, a ShaderInterfaceVariableInfo is created.  These are stored in a
34     // flat array.
35     using VariableInfoArray    = std::vector<ShaderInterfaceVariableInfo>;
36     using XFBVariableInfoArray = std::vector<XFBVariableInfoPtr>;
37 
38     // Each interface variable has an associted SPIR-V id (which is different per shader type).
39     // The following map is from a SPIR-V id to its associated info in VariableInfoArray.
40     //
41     // Note that the SPIR-V ids are mostly contiguous and start at
42     // sh::vk::spirv::kIdShaderVariablesBegin.  As such, the map key is actually
43     // |id - sh::vk::spirv::kIdShaderVariablesBegin|.
44     static constexpr size_t kIdFastMapMax = 32;
45     using IdToIndexMap                    = angle::FastMap<VariableIndex, kIdFastMapMax>;
46 
47     ShaderInterfaceVariableInfoMap();
48     ~ShaderInterfaceVariableInfoMap();
49 
50     void clear();
51     void load(gl::BinaryInputStream *stream);
52     void save(gl::BinaryOutputStream *stream);
53 
54     ShaderInterfaceVariableInfo &add(gl::ShaderType shaderType, uint32_t id);
55     void addResource(gl::ShaderBitSet shaderTypes,
56                      const gl::ShaderMap<uint32_t> &idInShaderTypes,
57                      uint32_t descriptorSet,
58                      uint32_t binding);
59     ShaderInterfaceVariableInfo &addOrGet(gl::ShaderType shaderType, uint32_t id);
60 
61     void setInputPerVertexActiveMembers(gl::ShaderType shaderType,
62                                         gl::PerVertexMemberBitSet activeMembers);
63     void setOutputPerVertexActiveMembers(gl::ShaderType shaderType,
64                                          gl::PerVertexMemberBitSet activeMembers);
65     ShaderInterfaceVariableInfo &getMutable(gl::ShaderType shaderType, uint32_t id);
66     XFBInterfaceVariableInfo *getXFBMutable(gl::ShaderType shaderType, uint32_t id);
67 
68     const ShaderInterfaceVariableInfo &getDefaultUniformInfo(gl::ShaderType shaderType) const;
69     const ShaderInterfaceVariableInfo &getAtomicCounterInfo(gl::ShaderType shaderType) const;
70     bool hasTransformFeedbackInfo(gl::ShaderType shaderType, uint32_t bufferIndex) const;
71     const ShaderInterfaceVariableInfo &getEmulatedXfbBufferInfo(uint32_t bufferIndex) const;
72 
73     uint32_t getDefaultUniformBinding(gl::ShaderType shaderType) const;
74     uint32_t getEmulatedXfbBufferBinding(uint32_t xfbBufferIndex) const;
75     uint32_t getAtomicCounterBufferBinding(gl::ShaderType shaderType,
76                                            uint32_t atomicCounterBufferIndex) const;
77 
78     bool hasVariable(gl::ShaderType shaderType, uint32_t id) const;
79     const ShaderInterfaceVariableInfo &getVariableById(gl::ShaderType shaderType,
80                                                        uint32_t id) const;
getData()81     const VariableInfoArray &getData() const { return mData; }
82     const gl::ShaderMap<IdToIndexMap> &getIdToIndexMap() const { return mIdToIndexMap; }
83     const XFBInterfaceVariableInfo &getXFBDataForVariableInfo(
84         const ShaderInterfaceVariableInfo *info) const
85     {
86         size_t index = info - mData.data();
87         ASSERT(index < mXFBData.size());
88         ASSERT(mXFBData[index]);
89         return *mXFBData[index];
90     }
91     const gl::ShaderMap<gl::PerVertexMemberBitSet> &getInputPerVertexActiveMembers() const
92     {
93         return mPod.inputPerVertexActiveMembers;
94     }
95     const gl::ShaderMap<gl::PerVertexMemberBitSet> &getOutputPerVertexActiveMembers() const
96     {
97         return mPod.outputPerVertexActiveMembers;
98     }
99 
100     void setHasAliasingAttributes() { mPod.hasAliasingAttributes = true; }
101     bool hasAliasingAttributes() const { return mPod.hasAliasingAttributes; }
102 
103   private:
104     void setVariableIndex(gl::ShaderType shaderType, uint32_t id, VariableIndex index);
105     const VariableIndex &getVariableIndex(gl::ShaderType shaderType, uint32_t id) const;
106 
107     VariableInfoArray mData;
108     // Transform feedback array will be empty if no XFB is used.
109     XFBVariableInfoArray mXFBData;
110     gl::ShaderMap<IdToIndexMap> mIdToIndexMap;
111 
112     ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
113     struct PodStruct
114     {
115         PodStruct() : xfbInfoCount(0), hasAliasingAttributes(false) {}
116         // Active members of `in gl_PerVertex` and `out gl_PerVertex`. 6 bytes each
117         gl::ShaderMap<gl::PerVertexMemberBitSet> inputPerVertexActiveMembers;
118         gl::ShaderMap<gl::PerVertexMemberBitSet> outputPerVertexActiveMembers;
119 
120         uint32_t xfbInfoCount : 31;
121         // Whether the vertex shader has aliasing attributes.  Used by the SPIR-V transformer to
122         // tell if emulation is needed.
123         uint32_t hasAliasingAttributes : 1;
124     } mPod;
125     ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
126 };
127 
128 ANGLE_INLINE const ShaderInterfaceVariableInfo &
129 ShaderInterfaceVariableInfoMap::getDefaultUniformInfo(gl::ShaderType shaderType) const
130 {
131     return getVariableById(shaderType, sh::vk::spirv::kIdDefaultUniformsBlock);
132 }
133 
134 ANGLE_INLINE const ShaderInterfaceVariableInfo &
135 ShaderInterfaceVariableInfoMap::getAtomicCounterInfo(gl::ShaderType shaderType) const
136 {
137     return getVariableById(shaderType, sh::vk::spirv::kIdAtomicCounterBlock);
138 }
139 
140 ANGLE_INLINE const ShaderInterfaceVariableInfo &
141 ShaderInterfaceVariableInfoMap::getEmulatedXfbBufferInfo(uint32_t bufferIndex) const
142 {
143     ASSERT(bufferIndex < 4);
144     static_assert(sh::vk::spirv::kIdXfbEmulationBufferBlockOne ==
145                   sh::vk::spirv::kIdXfbEmulationBufferBlockZero + 1);
146     static_assert(sh::vk::spirv::kIdXfbEmulationBufferBlockTwo ==
147                   sh::vk::spirv::kIdXfbEmulationBufferBlockZero + 2);
148     static_assert(sh::vk::spirv::kIdXfbEmulationBufferBlockThree ==
149                   sh::vk::spirv::kIdXfbEmulationBufferBlockZero + 3);
150 
151     // Transform feedback emulation only supports vertex shaders.
152     return getVariableById(gl::ShaderType::Vertex,
153                            sh::vk::spirv::kIdXfbEmulationBufferBlockZero + bufferIndex);
154 }
155 
156 ANGLE_INLINE uint32_t
157 ShaderInterfaceVariableInfoMap::getDefaultUniformBinding(gl::ShaderType shaderType) const
158 {
159     return getDefaultUniformInfo(shaderType).binding;
160 }
161 
162 ANGLE_INLINE uint32_t
163 ShaderInterfaceVariableInfoMap::getEmulatedXfbBufferBinding(uint32_t bufferIndex) const
164 {
165     return getEmulatedXfbBufferInfo(bufferIndex).binding;
166 }
167 
168 ANGLE_INLINE uint32_t ShaderInterfaceVariableInfoMap::getAtomicCounterBufferBinding(
169     gl::ShaderType shaderType,
170     uint32_t atomicCounterBufferIndex) const
171 {
172     return getAtomicCounterInfo(shaderType).binding + atomicCounterBufferIndex;
173 }
174 
175 ANGLE_INLINE const ShaderInterfaceVariableInfo &ShaderInterfaceVariableInfoMap::getVariableById(
176     gl::ShaderType shaderType,
177     uint32_t id) const
178 {
179     return mData[getVariableIndex(shaderType, id).index];
180 }
181 }  // namespace rx
182 #endif  // LIBANGLE_RENDERER_VULKAN_SHADERINTERFACEVARIABLEINFOMAP_H_
183