• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // mtl_common.h:
7 //      Declares common constants, template classes, and mtl::Context - the MTLDevice container &
8 //      error handler base class.
9 //
10 
11 #ifndef LIBANGLE_RENDERER_METAL_MTL_COMMON_H_
12 #define LIBANGLE_RENDERER_METAL_MTL_COMMON_H_
13 
14 #import <Metal/Metal.h>
15 
16 #include <TargetConditionals.h>
17 
18 #include <string>
19 
20 #include "common/Optional.h"
21 #include "common/PackedEnums.h"
22 #include "common/angleutils.h"
23 #include "common/apple_platform_utils.h"
24 #include "libANGLE/Constants.h"
25 #include "libANGLE/Version.h"
26 #include "libANGLE/angletypes.h"
27 
28 #if TARGET_OS_IPHONE
29 #    if !defined(ANGLE_IOS_DEPLOY_TARGET)
30 #        define ANGLE_IOS_DEPLOY_TARGET __IPHONE_11_0
31 #    endif
32 #endif
33 
34 #define ANGLE_MTL_OBJC_SCOPE @autoreleasepool
35 
36 #if !__has_feature(objc_arc)
37 #    define ANGLE_MTL_AUTORELEASE autorelease
38 #else
39 #    define ANGLE_MTL_AUTORELEASE self
40 #endif
41 
42 #define ANGLE_MTL_UNUSED __attribute__((unused))
43 
44 #if defined(ANGLE_MTL_ENABLE_TRACE)
45 #    define ANGLE_MTL_LOG(...) NSLog(@__VA_ARGS__)
46 #else
47 #    define ANGLE_MTL_LOG(...) (void)0
48 #endif
49 
50 namespace egl
51 {
52 class Display;
53 class Image;
54 }  // namespace egl
55 
56 #define ANGLE_GL_OBJECTS_X(PROC) \
57     PROC(Buffer)                 \
58     PROC(Context)                \
59     PROC(Framebuffer)            \
60     PROC(MemoryObject)           \
61     PROC(Query)                  \
62     PROC(Program)                \
63     PROC(Semaphore)              \
64     PROC(Texture)                \
65     PROC(TransformFeedback)      \
66     PROC(VertexArray)
67 
68 #define ANGLE_PRE_DECLARE_OBJECT(OBJ) class OBJ;
69 
70 namespace gl
71 {
72 struct Rectangle;
73 ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_OBJECT)
74 }  // namespace gl
75 
76 #define ANGLE_PRE_DECLARE_MTL_OBJECT(OBJ) class OBJ##Mtl;
77 
78 namespace rx
79 {
80 class DisplayMtl;
81 class ContextMtl;
82 class FramebufferMtl;
83 class BufferMtl;
84 class VertexArrayMtl;
85 class TextureMtl;
86 class ProgramMtl;
87 
ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_MTL_OBJECT)88 ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_MTL_OBJECT)
89 
90 namespace mtl
91 {
92 
93 // NOTE(hqle): support variable max number of vertex attributes
94 constexpr uint32_t kMaxVertexAttribs = gl::MAX_VERTEX_ATTRIBS;
95 // NOTE(hqle): support variable max number of render targets
96 constexpr uint32_t kMaxRenderTargets = 1;
97 
98 constexpr size_t kDefaultAttributeSize = 4 * sizeof(float);
99 
100 // Metal limits
101 constexpr uint32_t kMaxShaderBuffers     = 31;
102 constexpr uint32_t kMaxShaderSamplers    = 16;
103 constexpr size_t kDefaultUniformsMaxSize = 4 * 1024;
104 constexpr uint32_t kMaxViewports         = 1;
105 
106 constexpr uint32_t kVertexAttribBufferStrideAlignment = 4;
107 // Alignment requirement for offset passed to setVertex|FragmentBuffer
108 #if TARGET_OS_OSX || TARGET_OS_MACCATALYST
109 constexpr uint32_t kUniformBufferSettingOffsetMinAlignment = 256;
110 #else
111 constexpr uint32_t kUniformBufferSettingOffsetMinAlignment = 4;
112 #endif
113 constexpr uint32_t kIndexBufferOffsetAlignment = 4;
114 
115 // Front end binding limits
116 constexpr uint32_t kMaxGLSamplerBindings = 2 * kMaxShaderSamplers;
117 
118 // Binding index start for vertex data buffers:
119 constexpr uint32_t kVboBindingIndexStart = 0;
120 
121 // Binding index for default attribute buffer:
122 constexpr uint32_t kDefaultAttribsBindingIndex = kVboBindingIndexStart + kMaxVertexAttribs;
123 // Binding index for driver uniforms:
124 constexpr uint32_t kDriverUniformsBindingIndex = kDefaultAttribsBindingIndex + 1;
125 // Binding index for default uniforms:
126 constexpr uint32_t kDefaultUniformsBindingIndex = kDefaultAttribsBindingIndex + 3;
127 
128 constexpr uint32_t kStencilMaskAll = 0xff;  // Only 8 bits stencil is supported
129 
130 constexpr float kEmulatedAlphaValue = 1.0f;
131 
132 // NOTE(hqle): Support ES 3.0.
133 constexpr gl::Version kMaxSupportedGLVersion = gl::Version(2, 0);
134 
135 template <typename T>
136 struct ImplTypeHelper;
137 
138 // clang-format off
139 #define ANGLE_IMPL_TYPE_HELPER_GL(OBJ) \
140 template<>                             \
141 struct ImplTypeHelper<gl::OBJ>         \
142 {                                      \
143     using ImplType = OBJ##Mtl;         \
144 };
145 // clang-format on
146 
147 ANGLE_GL_OBJECTS_X(ANGLE_IMPL_TYPE_HELPER_GL)
148 
149 template <>
150 struct ImplTypeHelper<egl::Display>
151 {
152     using ImplType = DisplayMtl;
153 };
154 
155 template <typename T>
156 using GetImplType = typename ImplTypeHelper<T>::ImplType;
157 
158 template <typename T>
159 GetImplType<T> *GetImpl(const T *_Nonnull glObject)
160 {
161     return GetImplAs<GetImplType<T>>(glObject);
162 }
163 
164 // This class wraps Objective-C pointer inside, it will manage the lifetime of
165 // the Objective-C pointer. Changing pointer is not supported outside subclass.
166 template <typename T>
167 class WrappedObject
168 {
169   public:
170     WrappedObject() = default;
171     ~WrappedObject() { release(); }
172 
173     bool valid() const { return (mMetalObject != nil); }
174 
175     T get() const { return mMetalObject; }
176     inline void reset() { release(); }
177 
178     operator T() const { return get(); }
179 
180   protected:
181     inline void set(T obj) { retainAssign(obj); }
182 
183     void retainAssign(T obj)
184     {
185         T retained = obj;
186 #if !__has_feature(objc_arc)
187         [retained retain];
188 #endif
189         release();
190         mMetalObject = obj;
191     }
192 
193   private:
194     void release()
195     {
196 #if !__has_feature(objc_arc)
197         [mMetalObject release];
198 #endif
199         mMetalObject = nil;
200     }
201 
202     T mMetalObject = nil;
203 };
204 
205 // This class is similar to WrappedObject, however, it allows changing the
206 // internal pointer with public methods.
207 template <typename T>
208 class AutoObjCPtr : public WrappedObject<T>
209 {
210   public:
211     using ParentType = WrappedObject<T>;
212 
213     AutoObjCPtr() {}
214 
215     AutoObjCPtr(const std::nullptr_t &theNull) {}
216 
217     AutoObjCPtr(const AutoObjCPtr &src) { this->retainAssign(src.get()); }
218 
219     AutoObjCPtr(AutoObjCPtr &&src) { this->transfer(std::forward<AutoObjCPtr>(src)); }
220 
221     // Take ownership of the pointer
222     AutoObjCPtr(T &&src)
223     {
224         this->retainAssign(src);
225         src = nil;
226     }
227 
228     AutoObjCPtr &operator=(const AutoObjCPtr &src)
229     {
230         this->retainAssign(src.get());
231         return *this;
232     }
233 
234     AutoObjCPtr &operator=(AutoObjCPtr &&src)
235     {
236         this->transfer(std::forward<AutoObjCPtr>(src));
237         return *this;
238     }
239 
240     // Take ownership of the pointer
241     AutoObjCPtr &operator=(T &&src)
242     {
243         this->retainAssign(src);
244         src = nil;
245         return *this;
246     }
247 
248     AutoObjCPtr &operator=(const std::nullptr_t &theNull)
249     {
250         this->set(nil);
251         return *this;
252     }
253 
254     bool operator==(const AutoObjCPtr &rhs) const { return (*this) == rhs.get(); }
255 
256     bool operator==(T rhs) const { return this->get() == rhs; }
257 
258     bool operator==(const std::nullptr_t &theNull) const { return this->get(); }
259 
260     inline operator bool() { return this->get(); }
261 
262     bool operator!=(const AutoObjCPtr &rhs) const { return (*this) != rhs.get(); }
263 
264     bool operator!=(T rhs) const { return this->get() != rhs; }
265 
266     using ParentType::retainAssign;
267 
268   private:
269     void transfer(AutoObjCPtr &&src)
270     {
271         this->retainAssign(std::move(src.get()));
272         src.reset();
273     }
274 };
275 
276 template <typename T>
277 using AutoObjCObj = AutoObjCPtr<T *>;
278 
279 struct ClearOptions
280 {
281     Optional<MTLClearColor> clearColor;
282     Optional<float> clearDepth;
283     Optional<uint32_t> clearStencil;
284 };
285 
286 class CommandQueue;
287 class ErrorHandler
288 {
289   public:
290     virtual ~ErrorHandler() {}
291 
292     virtual void handleError(GLenum error,
293                              const char *file,
294                              const char *function,
295                              unsigned int line) = 0;
296 
297     virtual void handleError(NSError *_Nullable error,
298                              const char *file,
299                              const char *function,
300                              unsigned int line) = 0;
301 };
302 
303 class Context : public ErrorHandler
304 {
305   public:
306     Context(DisplayMtl *displayMtl);
307     _Nullable id<MTLDevice> getMetalDevice() const;
308     mtl::CommandQueue &cmdQueue();
309 
310     DisplayMtl *getDisplay() const { return mDisplay; }
311 
312   protected:
313     DisplayMtl *mDisplay;
314 };
315 
316 #define ANGLE_MTL_CHECK(context, test, error)                                \
317     do                                                                       \
318     {                                                                        \
319         if (ANGLE_UNLIKELY(!(test)))                                         \
320         {                                                                    \
321             context->handleError(error, __FILE__, ANGLE_FUNCTION, __LINE__); \
322             return angle::Result::Stop;                                      \
323         }                                                                    \
324     } while (0)
325 
326 #define ANGLE_MTL_TRY(context, test) ANGLE_MTL_CHECK(context, test, GL_INVALID_OPERATION)
327 
328 #define ANGLE_MTL_UNREACHABLE(context) \
329     UNREACHABLE();                     \
330     ANGLE_MTL_TRY(context, false)
331 
332 }  // namespace mtl
333 }  // namespace rx
334 
335 #endif /* LIBANGLE_RENDERER_METAL_MTL_COMMON_H_ */
336