• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
37     // Each interface variable has an associted SPIR-V id (which is different per shader type).
38     // The following map is from a SPIR-V id to its associated info in VariableInfoArray.
39     //
40     // Note that the SPIR-V ids are mostly contiguous and start at
41     // sh::vk::spirv::kIdShaderVariablesBegin.  As such, the map key is actually
42     // |id - sh::vk::spirv::kIdShaderVariablesBegin|.
43     static constexpr size_t kIdFastMapMax = 32;
44     using IdToIndexMap                    = angle::FastMap<VariableIndex, kIdFastMapMax>;
45 
46     ShaderInterfaceVariableInfoMap();
47     ~ShaderInterfaceVariableInfoMap();
48 
49     void clear();
50     void load(VariableInfoArray &&data,
51               gl::ShaderMap<IdToIndexMap> &&idToIndexMap,
52               gl::ShaderMap<gl::PerVertexMemberBitSet> &&inputPerVertexActiveMembers,
53               gl::ShaderMap<gl::PerVertexMemberBitSet> &&outputPerVertexActiveMembers);
54 
55     ShaderInterfaceVariableInfo &add(gl::ShaderType shaderType, uint32_t id);
56     void addResource(gl::ShaderBitSet shaderTypes,
57                      const gl::ShaderMap<uint32_t> &idInShaderTypes,
58                      uint32_t descriptorSet,
59                      uint32_t binding);
60     ShaderInterfaceVariableInfo &addOrGet(gl::ShaderType shaderType, uint32_t id);
61 
62     void setInputPerVertexActiveMembers(gl::ShaderType shaderType,
63                                         gl::PerVertexMemberBitSet activeMembers);
64     void setOutputPerVertexActiveMembers(gl::ShaderType shaderType,
65                                          gl::PerVertexMemberBitSet activeMembers);
66     ShaderInterfaceVariableInfo &getMutable(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 gl::ShaderMap<gl::PerVertexMemberBitSet> &getInputPerVertexActiveMembers() const
84     {
85         return mInputPerVertexActiveMembers;
86     }
87     const gl::ShaderMap<gl::PerVertexMemberBitSet> &getOutputPerVertexActiveMembers() const
88     {
89         return mOutputPerVertexActiveMembers;
90     }
91 
92     void setHasAliasingAttributes() { mHasAliasingAttributes = true; }
93     bool hasAliasingAttributes() const { return mHasAliasingAttributes; }
94 
95   private:
96     void setVariableIndex(gl::ShaderType shaderType, uint32_t id, VariableIndex index);
97     const VariableIndex &getVariableIndex(gl::ShaderType shaderType, uint32_t id) const;
98 
99     VariableInfoArray mData;
100     gl::ShaderMap<IdToIndexMap> mIdToIndexMap;
101 
102     // Active members of `in gl_PerVertex` and `out gl_PerVertex`
103     gl::ShaderMap<gl::PerVertexMemberBitSet> mInputPerVertexActiveMembers;
104     gl::ShaderMap<gl::PerVertexMemberBitSet> mOutputPerVertexActiveMembers;
105 
106     // Whether the vertex shader has aliasing attributes.  Used by the SPIR-V transformer to tell if
107     // emulation is needed.
108     bool mHasAliasingAttributes = false;
109 };
110 
111 ANGLE_INLINE const ShaderInterfaceVariableInfo &
112 ShaderInterfaceVariableInfoMap::getDefaultUniformInfo(gl::ShaderType shaderType) const
113 {
114     return getVariableById(shaderType, sh::vk::spirv::kIdDefaultUniformsBlock);
115 }
116 
117 ANGLE_INLINE const ShaderInterfaceVariableInfo &
118 ShaderInterfaceVariableInfoMap::getAtomicCounterInfo(gl::ShaderType shaderType) const
119 {
120     return getVariableById(shaderType, sh::vk::spirv::kIdAtomicCounterBlock);
121 }
122 
123 ANGLE_INLINE const ShaderInterfaceVariableInfo &
124 ShaderInterfaceVariableInfoMap::getEmulatedXfbBufferInfo(uint32_t bufferIndex) const
125 {
126     ASSERT(bufferIndex < 4);
127     static_assert(sh::vk::spirv::kIdXfbEmulationBufferBlockOne ==
128                   sh::vk::spirv::kIdXfbEmulationBufferBlockZero + 1);
129     static_assert(sh::vk::spirv::kIdXfbEmulationBufferBlockTwo ==
130                   sh::vk::spirv::kIdXfbEmulationBufferBlockZero + 2);
131     static_assert(sh::vk::spirv::kIdXfbEmulationBufferBlockThree ==
132                   sh::vk::spirv::kIdXfbEmulationBufferBlockZero + 3);
133 
134     // Transform feedback emulation only supports vertex shaders.
135     return getVariableById(gl::ShaderType::Vertex,
136                            sh::vk::spirv::kIdXfbEmulationBufferBlockZero + bufferIndex);
137 }
138 
139 ANGLE_INLINE uint32_t
140 ShaderInterfaceVariableInfoMap::getDefaultUniformBinding(gl::ShaderType shaderType) const
141 {
142     return getDefaultUniformInfo(shaderType).binding;
143 }
144 
145 ANGLE_INLINE uint32_t
146 ShaderInterfaceVariableInfoMap::getEmulatedXfbBufferBinding(uint32_t bufferIndex) const
147 {
148     return getEmulatedXfbBufferInfo(bufferIndex).binding;
149 }
150 
151 ANGLE_INLINE uint32_t ShaderInterfaceVariableInfoMap::getAtomicCounterBufferBinding(
152     gl::ShaderType shaderType,
153     uint32_t atomicCounterBufferIndex) const
154 {
155     return getAtomicCounterInfo(shaderType).binding + atomicCounterBufferIndex;
156 }
157 
158 ANGLE_INLINE const ShaderInterfaceVariableInfo &ShaderInterfaceVariableInfoMap::getVariableById(
159     gl::ShaderType shaderType,
160     uint32_t id) const
161 {
162     return mData[getVariableIndex(shaderType, id).index];
163 }
164 }  // namespace rx
165 #endif  // LIBANGLE_RENDERER_VULKAN_SHADERINTERFACEVARIABLEINFOMAP_H_
166