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