hank
2019-01-22 c5dbf55ef51d521c210a7f14aace5922de8821bf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
#pragma once
 
#ifdef __OBJC__
@class CAEAGLLayer;
@class EAGLContext;
#else
typedef struct objc_object CAEAGLLayer;
typedef struct objc_object EAGLContext;
#endif
 
#ifdef __OBJC__
@class CAMetalLayer;
@protocol CAMetalDrawable;
@protocol MTLDrawable;
@protocol MTLDevice;
@protocol MTLTexture;
@protocol MTLCommandBuffer;
@protocol MTLCommandQueue;
@protocol MTLCommandEncoder;
 
typedef id<CAMetalDrawable>     CAMetalDrawableRef;
typedef id<MTLDevice>           MTLDeviceRef;
typedef id<MTLTexture>          MTLTextureRef;
typedef id<MTLCommandBuffer>    MTLCommandBufferRef;
typedef id<MTLCommandQueue>     MTLCommandQueueRef;
typedef id<MTLCommandEncoder>   MTLCommandEncoderRef;
#else
typedef struct objc_object      CAMetalLayer;
typedef struct objc_object*     CAMetalDrawableRef;
typedef struct objc_object*     MTLDeviceRef;
typedef struct objc_object*     MTLTextureRef;
typedef struct objc_object*     MTLCommandBufferRef;
typedef struct objc_object*     MTLCommandQueueRef;
typedef struct objc_object*     MTLCommandEncoderRef;
#endif
 
// unity internal native render buffer struct (the one you acquire in C# with RenderBuffer.GetNativeRenderBufferPtr())
struct RenderSurfaceBase;
typedef struct RenderSurfaceBase* UnityRenderBufferHandle;
 
// be aware that this struct is shared with unity implementation so you should absolutely not change it
typedef struct
    UnityRenderBufferDesc
{
    unsigned    width, height, depth;
    unsigned    samples;
 
    int         backbuffer;
}
UnityRenderBufferDesc;
 
// trick to make structure inheritance work transparently between c/cpp
// for c we use "anonymous struct"
#ifdef __cplusplus
    #define START_STRUCT(T, Base)   struct T : Base {
    #define END_STRUCT(T)           };
#else
    #define START_STRUCT(T, Base)   typedef struct T { struct Base;
    #define END_STRUCT(T)           } T;
#endif
 
// we will keep objc objects in struct, so we need to explicitely mark references as strong to not confuse ARC
// please note that actual object lifetime is managed in objc++ code, so __unsafe_unretained is good enough for objc code
// DO NOT assign objects to UnityDisplaySurface* members in objc code.
// DO NOT store objects from UnityDisplaySurface* members in objc code, as this wont be caught by ARC
#ifdef __OBJC__
    #ifdef __cplusplus
        #define OBJC_OBJECT_PTR __strong
    #else
        #define OBJC_OBJECT_PTR __unsafe_unretained
    #endif
#else
    #define OBJC_OBJECT_PTR
#endif
 
// unity common rendering (display) surface
typedef struct
    UnityDisplaySurfaceBase
{
    UnityRenderBufferHandle unityColorBuffer;
    UnityRenderBufferHandle unityDepthBuffer;
 
    UnityRenderBufferHandle systemColorBuffer;
    UnityRenderBufferHandle systemDepthBuffer;
 
    void*               cvTextureCache;         // CVOpenGLESTextureCacheRef
    void*               cvTextureCacheTexture;  // CVOpenGLESTextureRef
    void*               cvPixelBuffer;          // CVPixelBufferRef
 
    unsigned            targetW, targetH;
    unsigned            systemW, systemH;
 
    int                 msaaSamples;
    int                 useCVTextureCache;      // [bool]
    int                 srgb;                   // [bool]
    int                 disableDepthAndStencil; // [bool]
    int                 allowScreenshot;        // [bool] currently we allow screenshots (from script) only on main display
 
    int                 api;                    // [UnityRenderingAPI]
}
UnityDisplaySurfaceBase;
 
 
// START_STRUCT confuse clang c compiler (though it is idiomatic c code that works)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-declarations"
 
// GLES display surface
START_STRUCT(UnityDisplaySurfaceGLES, UnityDisplaySurfaceBase)
OBJC_OBJECT_PTR CAEAGLLayer *    layer;
OBJC_OBJECT_PTR EAGLContext*    context;
 
// system FB
unsigned    systemFB;
unsigned    systemColorRB;
 
// target resolution FB/target RT to blit from
unsigned    targetFB;
unsigned    targetColorRT;
 
// MSAA FB
unsigned    msaaFB;
unsigned    msaaColorRB;
 
// when we enable AA for non-native resolution we need interim RT to resolve AA to (and then we will blit it to screen)
UnityRenderBufferHandle resolvedColorBuffer;
 
// will be "shared", only one depth buffer is needed
unsigned    depthRB;
 
// render surface gl setup: formats and AA
unsigned    colorFormat;
unsigned    depthFormat;
END_STRUCT(UnityDisplaySurfaceGLES)
 
// Metal display surface
START_STRUCT(UnityDisplaySurfaceMTL, UnityDisplaySurfaceBase)
OBJC_OBJECT_PTR CAMetalLayer *       layer;
OBJC_OBJECT_PTR MTLDeviceRef        device;
 
OBJC_OBJECT_PTR MTLCommandQueueRef  commandQueue;
OBJC_OBJECT_PTR CAMetalDrawableRef  drawable;
 
OBJC_OBJECT_PTR MTLTextureRef       systemColorRB;
OBJC_OBJECT_PTR MTLTextureRef       targetColorRT;
OBJC_OBJECT_PTR MTLTextureRef       targetAAColorRT;
 
OBJC_OBJECT_PTR MTLTextureRef       depthRB;
OBJC_OBJECT_PTR MTLTextureRef       stencilRB;
 
unsigned                            colorFormat;        // [MTLPixelFormat]
unsigned                            depthFormat;        // [MTLPixelFormat]
END_STRUCT(UnityDisplaySurfaceMTL)
 
// START_STRUCT confuse clang c compiler (though it is idiomatic c code that works)
#pragma clang diagnostic pop
 
// be aware that this enum is shared with unity implementation so you should absolutely not change it
typedef enum
    UnityRenderingAPI
{
    apiOpenGLES2    = 2,
    apiOpenGLES3    = 3,
    apiMetal        = 4,
}
UnityRenderingAPI;
 
#ifdef __cplusplus
extern "C" {
#endif
int UnitySelectedRenderingAPI();
#ifdef __cplusplus
} // extern "C"
#endif
 
// gles
#ifdef __cplusplus
extern "C" {
#endif
 
void InitRenderingGLES();
 
void CreateSystemRenderingSurfaceGLES(UnityDisplaySurfaceGLES* surface);
void DestroySystemRenderingSurfaceGLES(UnityDisplaySurfaceGLES* surface);
void CreateRenderingSurfaceGLES(UnityDisplaySurfaceGLES* surface);
void DestroyRenderingSurfaceGLES(UnityDisplaySurfaceGLES* surface);
void CreateSharedDepthbufferGLES(UnityDisplaySurfaceGLES* surface);
void DestroySharedDepthbufferGLES(UnityDisplaySurfaceGLES* surface);
void CreateUnityRenderBuffersGLES(UnityDisplaySurfaceGLES* surface);
void DestroyUnityRenderBuffersGLES(UnityDisplaySurfaceGLES* surface);
void StartFrameRenderingGLES(UnityDisplaySurfaceGLES* surface);
void EndFrameRenderingGLES(UnityDisplaySurfaceGLES* surface);
void PreparePresentGLES(UnityDisplaySurfaceGLES* surface);
void PresentGLES(UnityDisplaySurfaceGLES* surface);
 
#ifdef __cplusplus
} // extern "C"
#endif
 
// metal
#ifdef __cplusplus
extern "C" {
#endif
 
void InitRenderingMTL();
 
void CreateSystemRenderingSurfaceMTL(UnityDisplaySurfaceMTL* surface);
void DestroySystemRenderingSurfaceMTL(UnityDisplaySurfaceMTL* surface);
void CreateRenderingSurfaceMTL(UnityDisplaySurfaceMTL* surface);
void DestroyRenderingSurfaceMTL(UnityDisplaySurfaceMTL* surface);
void CreateSharedDepthbufferMTL(UnityDisplaySurfaceMTL* surface);
void DestroySharedDepthbufferMTL(UnityDisplaySurfaceMTL* surface);
void CreateUnityRenderBuffersMTL(UnityDisplaySurfaceMTL* surface);
void DestroyUnityRenderBuffersMTL(UnityDisplaySurfaceMTL* surface);
void StartFrameRenderingMTL(UnityDisplaySurfaceMTL* surface);
void EndFrameRenderingMTL(UnityDisplaySurfaceMTL* surface);
void PreparePresentMTL(UnityDisplaySurfaceMTL* surface);
void PresentMTL(UnityDisplaySurfaceMTL* surface);
 
#ifdef __cplusplus
} // extern "C"
#endif
 
#ifdef __cplusplus
extern "C" {
#endif
 
// for Create* functions if surf is null we will actuially create new one, otherwise we update the one provided
// gles: one and only one of texid/rbid should be non-zero
// metal: resolveTex should be non-nil only if tex have AA
UnityRenderBufferHandle UnityCreateExternalSurfaceGLES(UnityRenderBufferHandle surf, int isColor, unsigned texid, unsigned rbid, unsigned glesFormat, const UnityRenderBufferDesc* desc);
UnityRenderBufferHandle UnityCreateExternalSurfaceMTL(UnityRenderBufferHandle surf, int isColor, MTLTextureRef tex, const UnityRenderBufferDesc* desc);
UnityRenderBufferHandle UnityCreateExternalColorSurfaceMTL(UnityRenderBufferHandle surf, MTLTextureRef tex, MTLTextureRef resolveTex, const UnityRenderBufferDesc* desc);
UnityRenderBufferHandle UnityCreateExternalDepthSurfaceMTL(UnityRenderBufferHandle surf, MTLTextureRef tex, MTLTextureRef stencilTex, const UnityRenderBufferDesc* desc);
// creates "dummy" surface - will indicate "missing" buffer (e.g. depth-only RT will have color as dummy)
UnityRenderBufferHandle UnityCreateDummySurface(UnityRenderBufferHandle surf, int isColor, const UnityRenderBufferDesc* desc);
 
// disable rendering to render buffers (all Cameras that were rendering to one of buffers would be reset to use backbuffer)
void    UnityDisableRenderBuffers(UnityRenderBufferHandle color, UnityRenderBufferHandle depth);
// destroys render buffer
void    UnityDestroyExternalSurface(UnityRenderBufferHandle surf);
// sets current render target
void    UnitySetRenderTarget(UnityRenderBufferHandle color, UnityRenderBufferHandle depth);
// final blit to backbuffer
void    UnityBlitToBackbuffer(UnityRenderBufferHandle srcColor, UnityRenderBufferHandle dstColor, UnityRenderBufferHandle dstDepth);
// get native renderbuffer from handle
UnityRenderBufferHandle UnityNativeRenderBufferFromHandle(void *rb);
 
MTLCommandBufferRef UnityCurrentMTLCommandBuffer();
 
// sets vSync on OSX 10.13 and up
#if PLATFORM_OSX
void MetalUpdateDisplaySync();
#endif
 
#ifdef __cplusplus
} // extern "C"
#endif
 
// metal/gles unification
 
#define GLES_METAL_COMMON_IMPL_SURF(f)                                              \
inline void f(UnityDisplaySurfaceBase* surface)                                     \
{                                                                                   \
    if(surface->api == apiMetal)    f ## MTL((UnityDisplaySurfaceMTL*)surface); \
    else                            f ## GLES((UnityDisplaySurfaceGLES*)surface);\
}                                                                                   \
 
#define GLES_METAL_COMMON_IMPL(f)                               \
inline void f()                                                 \
{                                                               \
    if(UnitySelectedRenderingAPI() == apiMetal) f ## MTL();     \
    else                                        f ## GLES();\
}                                                               \
 
 
GLES_METAL_COMMON_IMPL(InitRendering);
 
GLES_METAL_COMMON_IMPL_SURF(CreateSystemRenderingSurface);
GLES_METAL_COMMON_IMPL_SURF(DestroySystemRenderingSurface);
GLES_METAL_COMMON_IMPL_SURF(CreateRenderingSurface);
GLES_METAL_COMMON_IMPL_SURF(DestroyRenderingSurface);
GLES_METAL_COMMON_IMPL_SURF(CreateSharedDepthbuffer);
GLES_METAL_COMMON_IMPL_SURF(DestroySharedDepthbuffer);
GLES_METAL_COMMON_IMPL_SURF(CreateUnityRenderBuffers);
GLES_METAL_COMMON_IMPL_SURF(DestroyUnityRenderBuffers);
GLES_METAL_COMMON_IMPL_SURF(StartFrameRendering);
GLES_METAL_COMMON_IMPL_SURF(EndFrameRendering);
GLES_METAL_COMMON_IMPL_SURF(PreparePresent);
GLES_METAL_COMMON_IMPL_SURF(Present);
 
#undef GLES_METAL_COMMON_IMPL_SURF
#undef GLES_METAL_COMMON_IMPL