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