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