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