1 2 // 3 // Copyright 2019 The ANGLE Project Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 // 7 // ProgramMtl.h: 8 // Defines the class interface for ProgramMtl, implementing ProgramImpl. 9 // 10 11 #ifndef LIBANGLE_RENDERER_METAL_PROGRAMMTL_H_ 12 #define LIBANGLE_RENDERER_METAL_PROGRAMMTL_H_ 13 14 #import <Metal/Metal.h> 15 16 #include <array> 17 18 #include "common/Optional.h" 19 #include "common/utilities.h" 20 #include "libANGLE/renderer/ProgramImpl.h" 21 #include "libANGLE/renderer/glslang_wrapper_utils.h" 22 #include "libANGLE/renderer/metal/mtl_buffer_pool.h" 23 #include "libANGLE/renderer/metal/mtl_command_buffer.h" 24 #include "libANGLE/renderer/metal/mtl_common.h" 25 #include "libANGLE/renderer/metal/mtl_glslang_mtl_utils.h" 26 #include "libANGLE/renderer/metal/mtl_resources.h" 27 #include "libANGLE/renderer/metal/mtl_state_cache.h" 28 29 namespace rx 30 { 31 #define SHADER_ENTRY_NAME @"main0" 32 class ContextMtl; 33 34 struct ProgramArgumentBufferEncoderMtl 35 { 36 void reset(ContextMtl *contextMtl); 37 38 mtl::AutoObjCPtr<id<MTLArgumentEncoder>> metalArgBufferEncoder; 39 mtl::BufferPool bufferPool; 40 }; 41 42 // Represents a specialized shader variant. For example, a shader variant with fragment coverage 43 // mask enabled and a shader variant without. 44 struct ProgramShaderObjVariantMtl 45 { 46 void reset(ContextMtl *contextMtl); 47 48 mtl::AutoObjCPtr<id<MTLFunction>> metalShader; 49 // UBO's argument buffer encoder. Used when number of UBOs used exceeds number of allowed 50 // discrete slots, and thus needs to encode all into one argument buffer. 51 ProgramArgumentBufferEncoderMtl uboArgBufferEncoder; 52 53 // Store reference to the TranslatedShaderInfo to easy querying mapped textures/UBO/XFB 54 // bindings. 55 const mtl::TranslatedShaderInfo *translatedSrcInfo; 56 }; 57 58 class ProgramMtl : public ProgramImpl, public mtl::RenderPipelineCacheSpecializeShaderFactory 59 { 60 public: 61 ProgramMtl(const gl::ProgramState &state); 62 ~ProgramMtl() override; 63 64 void destroy(const gl::Context *context) override; 65 66 std::unique_ptr<LinkEvent> load(const gl::Context *context, 67 gl::BinaryInputStream *stream, 68 gl::InfoLog &infoLog) override; 69 void save(const gl::Context *context, gl::BinaryOutputStream *stream) override; 70 void setBinaryRetrievableHint(bool retrievable) override; 71 void setSeparable(bool separable) override; 72 73 std::unique_ptr<LinkEvent> link(const gl::Context *context, 74 const gl::ProgramLinkedResources &resources, 75 gl::InfoLog &infoLog, 76 const gl::ProgramMergedVaryings &mergedVaryings) override; 77 GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; 78 79 void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override; 80 void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override; 81 void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override; 82 void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override; 83 void setUniform1iv(GLint location, GLsizei count, const GLint *v) override; 84 void setUniform2iv(GLint location, GLsizei count, const GLint *v) override; 85 void setUniform3iv(GLint location, GLsizei count, const GLint *v) override; 86 void setUniform4iv(GLint location, GLsizei count, const GLint *v) override; 87 void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override; 88 void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override; 89 void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override; 90 void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override; 91 void setUniformMatrix2fv(GLint location, 92 GLsizei count, 93 GLboolean transpose, 94 const GLfloat *value) override; 95 void setUniformMatrix3fv(GLint location, 96 GLsizei count, 97 GLboolean transpose, 98 const GLfloat *value) override; 99 void setUniformMatrix4fv(GLint location, 100 GLsizei count, 101 GLboolean transpose, 102 const GLfloat *value) override; 103 void setUniformMatrix2x3fv(GLint location, 104 GLsizei count, 105 GLboolean transpose, 106 const GLfloat *value) override; 107 void setUniformMatrix3x2fv(GLint location, 108 GLsizei count, 109 GLboolean transpose, 110 const GLfloat *value) override; 111 void setUniformMatrix2x4fv(GLint location, 112 GLsizei count, 113 GLboolean transpose, 114 const GLfloat *value) override; 115 void setUniformMatrix4x2fv(GLint location, 116 GLsizei count, 117 GLboolean transpose, 118 const GLfloat *value) override; 119 void setUniformMatrix3x4fv(GLint location, 120 GLsizei count, 121 GLboolean transpose, 122 const GLfloat *value) override; 123 void setUniformMatrix4x3fv(GLint location, 124 GLsizei count, 125 GLboolean transpose, 126 const GLfloat *value) override; 127 128 void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override; 129 void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override; 130 void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override; 131 132 // Override mtl::RenderPipelineCacheSpecializeShaderFactory 133 angle::Result getSpecializedShader(mtl::Context *context, 134 gl::ShaderType shaderType, 135 const mtl::RenderPipelineDesc &renderPipelineDesc, 136 id<MTLFunction> *shaderOut) override; 137 bool hasSpecializedShader(gl::ShaderType shaderType, 138 const mtl::RenderPipelineDesc &renderPipelineDesc) override; 139 140 angle::Result createMslShaderLib( 141 mtl::Context *context, 142 gl::ShaderType shaderType, 143 gl::InfoLog &infoLog, 144 mtl::TranslatedShaderInfo *translatedMslInfo, 145 NSDictionary<NSString *, NSObject *> *subtitutionDictionary = @{}); 146 // Calls this before drawing, changedPipelineDesc is passed when vertex attributes desc and/or 147 // shader program changed. 148 angle::Result setupDraw(const gl::Context *glContext, 149 mtl::RenderCommandEncoder *cmdEncoder, 150 const mtl::RenderPipelineDesc &pipelineDesc, 151 bool pipelineDescChanged, 152 bool forceTexturesSetting, 153 bool uniformBuffersDirty); 154 getTranslatedShaderSource(const gl::ShaderType shaderType)155 std::string getTranslatedShaderSource(const gl::ShaderType shaderType) const 156 { 157 return mMslShaderTranslateInfo[shaderType].metalShaderSource; 158 } 159 getTranslatedShaderInfo(const gl::ShaderType shaderType)160 mtl::TranslatedShaderInfo getTranslatedShaderInfo(const gl::ShaderType shaderType) const 161 { 162 return mMslShaderTranslateInfo[shaderType]; 163 } 164 hasFlatAttribute()165 bool hasFlatAttribute() const { return mProgramHasFlatAttributes; } 166 167 private: 168 template <int cols, int rows> 169 void setUniformMatrixfv(GLint location, 170 GLsizei count, 171 GLboolean transpose, 172 const GLfloat *value); 173 template <class T> 174 void getUniformImpl(GLint location, T *v, GLenum entryPointType) const; 175 176 template <typename T> 177 void setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType); 178 179 angle::Result initDefaultUniformBlocks(const gl::Context *glContext); 180 angle::Result resizeDefaultUniformBlocksMemory(const gl::Context *glContext, 181 const gl::ShaderMap<size_t> &requiredBufferSize); 182 void saveDefaultUniformBlocksInfo(gl::BinaryOutputStream *stream); 183 angle::Result loadDefaultUniformBlocksInfo(const gl::Context *glContext, 184 gl::BinaryInputStream *stream); 185 186 angle::Result commitUniforms(ContextMtl *context, mtl::RenderCommandEncoder *cmdEncoder); 187 angle::Result updateTextures(const gl::Context *glContext, 188 mtl::RenderCommandEncoder *cmdEncoder, 189 bool forceUpdate); 190 191 angle::Result updateUniformBuffers(ContextMtl *context, 192 mtl::RenderCommandEncoder *cmdEncoder, 193 const mtl::RenderPipelineDesc &pipelineDesc); 194 angle::Result updateXfbBuffers(ContextMtl *context, 195 mtl::RenderCommandEncoder *cmdEncoder, 196 const mtl::RenderPipelineDesc &pipelineDesc); 197 angle::Result legalizeUniformBufferOffsets(ContextMtl *context, 198 const std::vector<gl::InterfaceBlock> &blocks); 199 angle::Result bindUniformBuffersToDiscreteSlots(ContextMtl *context, 200 mtl::RenderCommandEncoder *cmdEncoder, 201 const std::vector<gl::InterfaceBlock> &blocks, 202 gl::ShaderType shaderType); 203 angle::Result encodeUniformBuffersInfoArgumentBuffer( 204 ContextMtl *context, 205 mtl::RenderCommandEncoder *cmdEncoder, 206 const std::vector<gl::InterfaceBlock> &blocks, 207 gl::ShaderType shaderType); 208 209 void reset(ContextMtl *context); 210 211 void saveTranslatedShaders(gl::BinaryOutputStream *stream); 212 void loadTranslatedShaders(gl::BinaryInputStream *stream); 213 214 void saveShaderInternalInfo(gl::BinaryOutputStream *stream); 215 void loadShaderInternalInfo(gl::BinaryInputStream *stream); 216 217 void linkUpdateHasFlatAttributes(); 218 219 #if ANGLE_ENABLE_METAL_SPIRV 220 221 angle::Result linkImplSpirv(const gl::Context *glContext, 222 const gl::ProgramLinkedResources &resources, 223 gl::InfoLog &infoLog); 224 #endif 225 226 angle::Result linkImplDirect(const gl::Context *glContext, 227 const gl::ProgramLinkedResources &resources, 228 gl::InfoLog &infoLog); 229 230 void linkResources(const gl::ProgramLinkedResources &resources); 231 angle::Result linkImpl(const gl::Context *glContext, 232 const gl::ProgramLinkedResources &resources, 233 gl::InfoLog &infoLog); 234 235 angle::Result linkTranslatedShaders(const gl::Context *glContext, 236 gl::BinaryInputStream *stream, 237 gl::InfoLog &infoLog); 238 239 mtl::BufferPool *getBufferPool(ContextMtl *context); 240 241 // State for the default uniform blocks. 242 struct DefaultUniformBlock final : private angle::NonCopyable 243 { 244 DefaultUniformBlock(); 245 ~DefaultUniformBlock(); 246 247 // Shadow copies of the shader uniform data. 248 angle::MemoryBuffer uniformData; 249 250 // Since the default blocks are laid out in std140, this tells us where to write on a call 251 // to a setUniform method. They are arranged in uniform location order. 252 std::vector<sh::BlockMemberInfo> uniformLayout; 253 }; 254 255 bool mProgramHasFlatAttributes; 256 gl::ShaderBitSet mDefaultUniformBlocksDirty; 257 gl::ShaderBitSet mSamplerBindingsDirty; 258 gl::ShaderMap<DefaultUniformBlock> mDefaultUniformBlocks; 259 260 // Translated metal shaders: 261 gl::ShaderMap<mtl::TranslatedShaderInfo> mMslShaderTranslateInfo; 262 263 // Translated metal version for transform feedback only vertex shader: 264 // - Metal doesn't allow vertex shader to write to both buffers and to stage output 265 // (gl_Position). Need a special version of vertex shader that only writes to transform feedback 266 // buffers. 267 mtl::TranslatedShaderInfo mMslXfbOnlyVertexShaderInfo; 268 269 // Compiled native shader object variants: 270 // - Vertex shader: One with emulated rasterization discard, one with true rasterization 271 // discard, one without. 272 mtl::RenderPipelineRasterStateMap<ProgramShaderObjVariantMtl> mVertexShaderVariants; 273 // - Fragment shader: One with sample coverage mask enabled, one with it disabled. 274 std::array<ProgramShaderObjVariantMtl, 2> mFragmentShaderVariants; 275 276 // Cached references of current shader variants. 277 gl::ShaderMap<ProgramShaderObjVariantMtl *> mCurrentShaderVariants; 278 279 ShaderInterfaceVariableInfoMap mVariableInfoMap; 280 // Scratch data: 281 // Legalized buffers and their offsets. For example, uniform buffer's offset=1 is not a valid 282 // offset, it will be converted to legal offset and the result is stored in this array. 283 std::vector<std::pair<mtl::BufferRef, uint32_t>> mLegalizedOffsetedUniformBuffers; 284 // Stores the render stages usage of each uniform buffer. Only used if the buffers are encoded 285 // into an argument buffer. 286 std::vector<uint32_t> mArgumentBufferRenderStageUsages; 287 288 uint32_t mShadowCompareModes[mtl::kMaxShaderSamplers]; 289 290 mtl::RenderPipelineCache mMetalRenderPipelineCache; 291 mtl::BufferPool *mAuxBufferPool; 292 }; 293 294 } // namespace rx 295 296 #endif /* LIBANGLE_RENDERER_METAL_PROGRAMMTL_H_ */ 297