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