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