• 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/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