├── .gitignore ├── LICENSE ├── NativePlugin ├── CMakeLists.txt ├── glew │ ├── LICENSE.txt │ ├── include │ │ └── GL │ │ │ ├── eglew.h │ │ │ ├── glew.h │ │ │ ├── glxew.h │ │ │ └── wglew.h │ └── src │ │ ├── glew.c │ │ ├── glewinfo.c │ │ └── visualinfo.c └── src │ ├── AsyncGPUReadbackPlugin.cpp │ ├── TypeHelpers.hpp │ └── Unity │ ├── IUnityGraphics.h │ ├── IUnityGraphicsD3D11.h │ ├── IUnityGraphicsD3D12.h │ ├── IUnityGraphicsD3D9.h │ ├── IUnityGraphicsMetal.h │ ├── IUnityGraphicsVulkan.h │ └── IUnityInterface.h ├── README.md └── UnityExampleProject ├── .gitignore ├── Assets ├── OpenglAsyncReadback.meta └── OpenglAsyncReadback │ ├── ExampleScenes.meta │ ├── ExampleScenes │ ├── ComputeBufferTest.cs │ ├── ComputeBufferTest.cs.meta │ ├── Scene.unity │ ├── Scene.unity.meta │ ├── UsePlugin.cs │ └── UsePlugin.cs.meta │ ├── Plugins.meta │ ├── Plugins │ ├── Linux.meta │ ├── Linux │ │ ├── libAsyncGPUReadbackPlugin.so │ │ └── libAsyncGPUReadbackPlugin.so.meta │ ├── Windows.meta │ └── Windows │ │ ├── AsyncGPUReadbackPlugin.dll │ │ └── AsyncGPUReadbackPlugin.dll.meta │ ├── Scripts.meta │ ├── Scripts │ ├── AsyncGPUReadbackPlugin.cs │ ├── AsyncGPUReadbackPlugin.cs.meta │ ├── AsyncReadbackUpdater.cs │ └── AsyncReadbackUpdater.cs.meta │ ├── b.mat │ ├── b.mat.meta │ ├── g.mat │ ├── g.mat.meta │ ├── r.mat │ └── r.mat.meta ├── Logs └── Packages-Update.log ├── Packages └── manifest.json └── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── PresetManager.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset ├── UnityConnectSettings.asset └── VFXManager.asset /.gitignore: -------------------------------------------------------------------------------- 1 | ManagedPlugin/obj 2 | ManagedPlugin/bin 3 | UnityExampleProject/test.png 4 | NativePlugin/build -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 yangrc 4 | Copyright (c) 2018 Aurélien Labate 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /NativePlugin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | PROJECT(AsyncGPUReadbackPlugin) 3 | set (CMAKE_CXX_STANDARD 11) 4 | 5 | file(GLOB_RECURSE HPPS src/*.hpp) 6 | file(GLOB_RECURSE HEADERS src/*.h) 7 | file(GLOB_RECURSE SOURCES src/*.cpp) 8 | 9 | find_package(OpenGL REQUIRED) 10 | include_directories(${OpenGL_INCLUDE_DIR}) 11 | 12 | #GLEW 13 | file(GLOB_RECURSE GLEW_SOURCES glew/src/*.c) 14 | add_library(GLEW ${GLEW_SOURCES}) 15 | target_compile_definitions(GLEW PUBLIC -D GLEW_STATIC) 16 | set_property(TARGET GLEW PROPERTY POSITION_INDEPENDENT_CODE ON) 17 | include_directories(glew/include) 18 | 19 | source_group("Source Files" FILES ${SOURCES} ${HEADERS} ${HPPS}) 20 | include_directories("/") 21 | 22 | add_library(${PROJECT_NAME} SHARED ${HEADERS} ${HPPS} ${SOURCES} ) 23 | target_compile_definitions(${PROJECT_NAME} PUBLIC -D GLEW_STATIC) 24 | target_link_libraries(${PROJECT_NAME} ${OPENGL_LIBRARY} GLEW) 25 | set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) 26 | 27 | if(MSVC) 28 | target_compile_options(${PROJECT_NAME} PRIVATE /W4 /WX) 29 | else() 30 | target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic -Werror) 31 | endif() -------------------------------------------------------------------------------- /NativePlugin/glew/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The OpenGL Extension Wrangler Library 2 | Copyright (C) 2002-2007, Milan Ikits 3 | Copyright (C) 2002-2007, Marcelo E. Magallon 4 | Copyright (C) 2002, Lev Povalahev 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | * The name of the author may be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 | THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | Mesa 3-D graphics library 32 | Version: 7.0 33 | 34 | Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 35 | 36 | Permission is hereby granted, free of charge, to any person obtaining a 37 | copy of this software and associated documentation files (the "Software"), 38 | to deal in the Software without restriction, including without limitation 39 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 40 | and/or sell copies of the Software, and to permit persons to whom the 41 | Software is furnished to do so, subject to the following conditions: 42 | 43 | The above copyright notice and this permission notice shall be included 44 | in all copies or substantial portions of the Software. 45 | 46 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 47 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 48 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 49 | BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 50 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 51 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 52 | 53 | 54 | Copyright (c) 2007 The Khronos Group Inc. 55 | 56 | Permission is hereby granted, free of charge, to any person obtaining a 57 | copy of this software and/or associated documentation files (the 58 | "Materials"), to deal in the Materials without restriction, including 59 | without limitation the rights to use, copy, modify, merge, publish, 60 | distribute, sublicense, and/or sell copies of the Materials, and to 61 | permit persons to whom the Materials are furnished to do so, subject to 62 | the following conditions: 63 | 64 | The above copyright notice and this permission notice shall be included 65 | in all copies or substantial portions of the Materials. 66 | 67 | THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 68 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 69 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 70 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 71 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 72 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 73 | MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 74 | -------------------------------------------------------------------------------- /NativePlugin/glew/src/visualinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** visualinfo.c 3 | ** 4 | ** Copyright (C) Nate Robins, 1997 5 | ** Michael Wimmer, 1999 6 | ** Milan Ikits, 2002-2008 7 | ** Nigel Stewart, 2008-2013 8 | ** 9 | ** visualinfo is a small utility that displays all available visuals, 10 | ** aka. pixelformats, in an OpenGL system along with renderer version 11 | ** information. It shows a table of all the visuals that support OpenGL 12 | ** along with their capabilities. The format of the table is similar to 13 | ** that of glxinfo on Unix systems: 14 | ** 15 | ** visual ~= pixel format descriptor 16 | ** id = visual id (integer from 1 - max visuals) 17 | ** tp = type (wn: window, pb: pbuffer, wp: window & pbuffer, bm: bitmap) 18 | ** ac = acceleration (ge: generic, fu: full, no: none) 19 | ** fm = format (i: integer, f: float, c: color index) 20 | ** db = double buffer (y = yes) 21 | ** sw = swap method (x: exchange, c: copy, u: undefined) 22 | ** st = stereo (y = yes) 23 | ** sz = total # bits 24 | ** r = # bits of red 25 | ** g = # bits of green 26 | ** b = # bits of blue 27 | ** a = # bits of alpha 28 | ** axbf = # aux buffers 29 | ** dpth = # bits of depth 30 | ** stcl = # bits of stencil 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #if defined(GLEW_OSMESA) 38 | #define GLAPI extern 39 | #include 40 | #elif defined(GLEW_EGL) 41 | #include 42 | #elif defined(_WIN32) 43 | #include 44 | #elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) 45 | #include 46 | #include 47 | #elif !defined(__HAIKU__) 48 | #include 49 | #endif 50 | 51 | #ifdef GLEW_MX 52 | GLEWContext _glewctx; 53 | # define glewGetContext() (&_glewctx) 54 | # ifdef _WIN32 55 | WGLEWContext _wglewctx; 56 | # define wglewGetContext() (&_wglewctx) 57 | # elif !defined(__APPLE__) && !defined(__HAIKU__) || defined(GLEW_APPLE_GLX) 58 | GLXEWContext _glxewctx; 59 | # define glxewGetContext() (&_glxewctx) 60 | # endif 61 | #endif /* GLEW_MX */ 62 | 63 | typedef struct GLContextStruct 64 | { 65 | #if defined(GLEW_OSMESA) 66 | OSMesaContext ctx; 67 | #elif defined(GLEW_EGL) 68 | EGLContext ctx; 69 | #elif defined(_WIN32) 70 | HWND wnd; 71 | HDC dc; 72 | HGLRC rc; 73 | #elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) 74 | CGLContextObj ctx, octx; 75 | #elif !defined(__HAIKU__) 76 | Display* dpy; 77 | XVisualInfo* vi; 78 | GLXContext ctx; 79 | Window wnd; 80 | Colormap cmap; 81 | #endif 82 | } GLContext; 83 | 84 | void InitContext (GLContext* ctx); 85 | GLboolean CreateContext (GLContext* ctx); 86 | void DestroyContext (GLContext* ctx); 87 | void VisualInfo (GLContext* ctx); 88 | void PrintExtensions (const char* s); 89 | GLboolean ParseArgs (int argc, char** argv); 90 | 91 | int showall = 0; 92 | int displaystdout = 0; 93 | int verbose = 0; 94 | int drawableonly = 0; 95 | 96 | char* display = NULL; 97 | int visual = -1; 98 | 99 | FILE* file = 0; 100 | 101 | int 102 | main (int argc, char** argv) 103 | { 104 | GLenum err; 105 | GLContext ctx; 106 | 107 | /* ---------------------------------------------------------------------- */ 108 | /* parse arguments */ 109 | if (GL_TRUE == ParseArgs(argc-1, argv+1)) 110 | { 111 | #if defined(_WIN32) 112 | fprintf(stderr, "Usage: visualinfo [-a] [-s] [-h] [-pf ]\n"); 113 | fprintf(stderr, " -a: show all visuals\n"); 114 | fprintf(stderr, " -s: display to stdout instead of visualinfo.txt\n"); 115 | fprintf(stderr, " -pf : use given pixelformat\n"); 116 | fprintf(stderr, " -h: this screen\n"); 117 | #else 118 | fprintf(stderr, "Usage: visualinfo [-h] [-display ] [-visual ]\n"); 119 | fprintf(stderr, " -h: this screen\n"); 120 | fprintf(stderr, " -display : use given display\n"); 121 | fprintf(stderr, " -visual : use given visual\n"); 122 | #endif 123 | return 1; 124 | } 125 | 126 | /* ---------------------------------------------------------------------- */ 127 | /* create OpenGL rendering context */ 128 | InitContext(&ctx); 129 | if (GL_TRUE == CreateContext(&ctx)) 130 | { 131 | fprintf(stderr, "Error: CreateContext failed\n"); 132 | DestroyContext(&ctx); 133 | return 1; 134 | } 135 | 136 | /* ---------------------------------------------------------------------- */ 137 | /* initialize GLEW */ 138 | glewExperimental = GL_TRUE; 139 | #ifdef GLEW_MX 140 | err = glewContextInit(glewGetContext()); 141 | # ifdef _WIN32 142 | err = err || wglewContextInit(wglewGetContext()); 143 | # elif !defined(__APPLE__) && !defined(__HAIKU__) || defined(GLEW_APPLE_GLX) 144 | err = err || glxewContextInit(glxewGetContext()); 145 | # endif 146 | #else 147 | err = glewInit(); 148 | #endif 149 | if (GLEW_OK != err) 150 | { 151 | fprintf(stderr, "Error [main]: glewInit failed: %s\n", glewGetErrorString(err)); 152 | DestroyContext(&ctx); 153 | return 1; 154 | } 155 | 156 | /* ---------------------------------------------------------------------- */ 157 | /* open file */ 158 | #if defined(_WIN32) 159 | if (!displaystdout) 160 | { 161 | #if defined(_MSC_VER) && (_MSC_VER >= 1400) 162 | if (fopen_s(&file, "visualinfo.txt", "w") != 0) 163 | file = stdout; 164 | #else 165 | file = fopen("visualinfo.txt", "w"); 166 | #endif 167 | } 168 | if (file == NULL) 169 | file = stdout; 170 | #else 171 | file = stdout; 172 | #endif 173 | 174 | /* ---------------------------------------------------------------------- */ 175 | /* output header information */ 176 | /* OpenGL extensions */ 177 | fprintf(file, "OpenGL vendor string: %s\n", glGetString(GL_VENDOR)); 178 | fprintf(file, "OpenGL renderer string: %s\n", glGetString(GL_RENDERER)); 179 | fprintf(file, "OpenGL version string: %s\n", glGetString(GL_VERSION)); 180 | fprintf(file, "OpenGL extensions (GL_): \n"); 181 | PrintExtensions((const char*)glGetString(GL_EXTENSIONS)); 182 | 183 | #ifndef GLEW_NO_GLU 184 | /* GLU extensions */ 185 | fprintf(file, "GLU version string: %s\n", gluGetString(GLU_VERSION)); 186 | fprintf(file, "GLU extensions (GLU_): \n"); 187 | PrintExtensions((const char*)gluGetString(GLU_EXTENSIONS)); 188 | #endif 189 | 190 | /* ---------------------------------------------------------------------- */ 191 | /* extensions string */ 192 | #if defined(GLEW_OSMESA) 193 | #elif defined(GLEW_EGL) 194 | #elif defined(_WIN32) 195 | /* WGL extensions */ 196 | if (WGLEW_ARB_extensions_string || WGLEW_EXT_extensions_string) 197 | { 198 | fprintf(file, "WGL extensions (WGL_): \n"); 199 | PrintExtensions(wglGetExtensionsStringARB ? 200 | (const char*)wglGetExtensionsStringARB(ctx.dc) : 201 | (const char*)wglGetExtensionsStringEXT()); 202 | } 203 | #elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) 204 | 205 | #elif defined(__HAIKU__) 206 | 207 | /* TODO */ 208 | 209 | #else 210 | /* GLX extensions */ 211 | fprintf(file, "GLX extensions (GLX_): \n"); 212 | PrintExtensions(glXQueryExtensionsString(glXGetCurrentDisplay(), 213 | DefaultScreen(glXGetCurrentDisplay()))); 214 | #endif 215 | 216 | /* ---------------------------------------------------------------------- */ 217 | /* enumerate all the formats */ 218 | VisualInfo(&ctx); 219 | 220 | /* ---------------------------------------------------------------------- */ 221 | /* release resources */ 222 | DestroyContext(&ctx); 223 | if (file != stdout) 224 | fclose(file); 225 | return 0; 226 | } 227 | 228 | /* do the magic to separate all extensions with comma's, except 229 | for the last one that _may_ terminate in a space. */ 230 | void PrintExtensions (const char* s) 231 | { 232 | char t[80]; 233 | int i=0; 234 | char* p=0; 235 | 236 | t[79] = '\0'; 237 | while (*s) 238 | { 239 | t[i++] = *s; 240 | if(*s == ' ') 241 | { 242 | if (*(s+1) != '\0') { 243 | t[i-1] = ','; 244 | t[i] = ' '; 245 | p = &t[i++]; 246 | } 247 | else /* zoinks! last one terminated in a space! */ 248 | { 249 | t[i-1] = '\0'; 250 | } 251 | } 252 | if(i > 80 - 5) 253 | { 254 | *p = t[i] = '\0'; 255 | fprintf(file, " %s\n", t); 256 | p++; 257 | i = (int)strlen(p); 258 | #if defined(_MSC_VER) && (_MSC_VER >= 1400) 259 | strcpy_s(t, sizeof(t), p); 260 | #else 261 | strcpy(t, p); 262 | #endif 263 | } 264 | s++; 265 | } 266 | t[i] = '\0'; 267 | fprintf(file, " %s.\n", t); 268 | } 269 | 270 | /* ---------------------------------------------------------------------- */ 271 | 272 | #if defined(GLEW_OSMESA) || defined(GLEW_EGL) 273 | 274 | void 275 | VisualInfo (GLContext* ctx) 276 | { 277 | } 278 | 279 | #elif defined(_WIN32) 280 | 281 | void 282 | VisualInfoARB (GLContext* ctx) 283 | { 284 | int attrib[32], value[32], n_attrib, n_pbuffer=0, n_float=0; 285 | int i, pf, maxpf; 286 | unsigned int c; 287 | 288 | /* to get pbuffer capable pixel formats */ 289 | attrib[0] = WGL_DRAW_TO_PBUFFER_ARB; 290 | attrib[1] = GL_TRUE; 291 | attrib[2] = 0; 292 | wglChoosePixelFormatARB(ctx->dc, attrib, 0, 1, &pf, &c); 293 | /* query number of pixel formats */ 294 | attrib[0] = WGL_NUMBER_PIXEL_FORMATS_ARB; 295 | wglGetPixelFormatAttribivARB(ctx->dc, 0, 0, 1, attrib, value); 296 | maxpf = value[0]; 297 | for (i=0; i<32; i++) 298 | value[i] = 0; 299 | 300 | attrib[0] = WGL_SUPPORT_OPENGL_ARB; 301 | attrib[1] = WGL_DRAW_TO_WINDOW_ARB; 302 | attrib[2] = WGL_DRAW_TO_BITMAP_ARB; 303 | attrib[3] = WGL_ACCELERATION_ARB; 304 | /* WGL_NO_ACCELERATION_ARB, WGL_GENERIC_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB */ 305 | attrib[4] = WGL_SWAP_METHOD_ARB; 306 | /* WGL_SWAP_EXCHANGE_ARB, WGL_SWAP_COPY_ARB, WGL_SWAP_UNDEFINED_ARB */ 307 | attrib[5] = WGL_DOUBLE_BUFFER_ARB; 308 | attrib[6] = WGL_STEREO_ARB; 309 | attrib[7] = WGL_PIXEL_TYPE_ARB; 310 | /* WGL_TYPE_RGBA_ARB, WGL_TYPE_COLORINDEX_ARB, 311 | WGL_TYPE_RGBA_FLOAT_ATI (WGL_ATI_pixel_format_float) */ 312 | /* Color buffer information */ 313 | attrib[8] = WGL_COLOR_BITS_ARB; 314 | attrib[9] = WGL_RED_BITS_ARB; 315 | attrib[10] = WGL_GREEN_BITS_ARB; 316 | attrib[11] = WGL_BLUE_BITS_ARB; 317 | attrib[12] = WGL_ALPHA_BITS_ARB; 318 | /* Accumulation buffer information */ 319 | attrib[13] = WGL_ACCUM_BITS_ARB; 320 | attrib[14] = WGL_ACCUM_RED_BITS_ARB; 321 | attrib[15] = WGL_ACCUM_GREEN_BITS_ARB; 322 | attrib[16] = WGL_ACCUM_BLUE_BITS_ARB; 323 | attrib[17] = WGL_ACCUM_ALPHA_BITS_ARB; 324 | /* Depth, stencil, and aux buffer information */ 325 | attrib[18] = WGL_DEPTH_BITS_ARB; 326 | attrib[19] = WGL_STENCIL_BITS_ARB; 327 | attrib[20] = WGL_AUX_BUFFERS_ARB; 328 | /* Layer information */ 329 | attrib[21] = WGL_NUMBER_OVERLAYS_ARB; 330 | attrib[22] = WGL_NUMBER_UNDERLAYS_ARB; 331 | attrib[23] = WGL_SWAP_LAYER_BUFFERS_ARB; 332 | attrib[24] = WGL_SAMPLES_ARB; 333 | attrib[25] = WGL_SUPPORT_GDI_ARB; 334 | n_attrib = 26; 335 | if (WGLEW_ARB_pbuffer) 336 | { 337 | attrib[n_attrib] = WGL_DRAW_TO_PBUFFER_ARB; 338 | n_pbuffer = n_attrib; 339 | n_attrib++; 340 | } 341 | if (WGLEW_NV_float_buffer) 342 | { 343 | attrib[n_attrib] = WGL_FLOAT_COMPONENTS_NV; 344 | n_float = n_attrib; 345 | n_attrib++; 346 | } 347 | 348 | if (!verbose) 349 | { 350 | /* print table header */ 351 | fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); 352 | fprintf(file, " | | visual | color | ax dp st | accum | layer |\n"); 353 | fprintf(file, " | id | tp ac gd fm db sw st ms | sz r g b a | bf th cl | sz r g b a | ov un sw |\n"); 354 | fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); 355 | /* loop through all the pixel formats */ 356 | for(i = 1; i <= maxpf; i++) 357 | { 358 | wglGetPixelFormatAttribivARB(ctx->dc, i, 0, n_attrib, attrib, value); 359 | /* only describe this format if it supports OpenGL */ 360 | if (!value[0]) continue; 361 | /* by default show only fully accelerated window or pbuffer capable visuals */ 362 | if (!showall 363 | && ((value[2] && !value[1]) 364 | || (!WGLEW_ARB_pbuffer || !value[n_pbuffer]) 365 | || (value[3] != WGL_FULL_ACCELERATION_ARB))) continue; 366 | /* print out the information for this visual */ 367 | /* visual id */ 368 | fprintf(file, " |% 4d | ", i); 369 | /* visual type */ 370 | if (value[1]) 371 | { 372 | if (WGLEW_ARB_pbuffer && value[n_pbuffer]) fprintf(file, "wp "); 373 | else fprintf(file, "wn "); 374 | } 375 | else 376 | { 377 | if (value[2]) fprintf(file, "bm "); 378 | else if (WGLEW_ARB_pbuffer && value[n_pbuffer]) fprintf(file, "pb "); 379 | } 380 | /* acceleration */ 381 | fprintf(file, "%s ", value[3] == WGL_FULL_ACCELERATION_ARB ? "fu" : 382 | value[3] == WGL_GENERIC_ACCELERATION_ARB ? "ge" : 383 | value[3] == WGL_NO_ACCELERATION_ARB ? "no" : ". "); 384 | /* gdi support */ 385 | fprintf(file, " %c ", value[25] ? 'y' : '.'); 386 | /* format */ 387 | if (WGLEW_NV_float_buffer && value[n_float]) fprintf(file, " f "); 388 | else if (WGLEW_ATI_pixel_format_float && value[7] == WGL_TYPE_RGBA_FLOAT_ATI) fprintf(file, " f "); 389 | else if (value[7] == WGL_TYPE_RGBA_ARB) fprintf(file, " i "); 390 | else if (value[7] == WGL_TYPE_COLORINDEX_ARB) fprintf(file, " c "); 391 | else if (value[7] == WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT) fprintf(file," p "); 392 | else fprintf(file," ? "); 393 | /* double buffer */ 394 | fprintf(file, " %c ", value[5] ? 'y' : '.'); 395 | /* swap method */ 396 | if (value[4] == WGL_SWAP_EXCHANGE_ARB) fprintf(file, " x "); 397 | else if (value[4] == WGL_SWAP_COPY_ARB) fprintf(file, " c "); 398 | else if (value[4] == WGL_SWAP_UNDEFINED_ARB) fprintf(file, " . "); 399 | else fprintf(file, " . "); 400 | /* stereo */ 401 | fprintf(file, " %c ", value[6] ? 'y' : '.'); 402 | /* multisample */ 403 | if (value[24] > 0) 404 | fprintf(file, "%2d | ", value[24]); 405 | else 406 | fprintf(file, " . | "); 407 | /* color size */ 408 | if (value[8]) fprintf(file, "%3d ", value[8]); 409 | else fprintf(file, " . "); 410 | /* red */ 411 | if (value[9]) fprintf(file, "%2d ", value[9]); 412 | else fprintf(file, " . "); 413 | /* green */ 414 | if (value[10]) fprintf(file, "%2d ", value[10]); 415 | else fprintf(file, " . "); 416 | /* blue */ 417 | if (value[11]) fprintf(file, "%2d ", value[11]); 418 | else fprintf(file, " . "); 419 | /* alpha */ 420 | if (value[12]) fprintf(file, "%2d | ", value[12]); 421 | else fprintf(file, " . | "); 422 | /* aux buffers */ 423 | if (value[20]) fprintf(file, "%2d ", value[20]); 424 | else fprintf(file, " . "); 425 | /* depth */ 426 | if (value[18]) fprintf(file, "%2d ", value[18]); 427 | else fprintf(file, " . "); 428 | /* stencil */ 429 | if (value[19]) fprintf(file, "%2d | ", value[19]); 430 | else fprintf(file, " . | "); 431 | /* accum size */ 432 | if (value[13]) fprintf(file, "%3d ", value[13]); 433 | else fprintf(file, " . "); 434 | /* accum red */ 435 | if (value[14]) fprintf(file, "%2d ", value[14]); 436 | else fprintf(file, " . "); 437 | /* accum green */ 438 | if (value[15]) fprintf(file, "%2d ", value[15]); 439 | else fprintf(file, " . "); 440 | /* accum blue */ 441 | if (value[16]) fprintf(file, "%2d ", value[16]); 442 | else fprintf(file, " . "); 443 | /* accum alpha */ 444 | if (value[17]) fprintf(file, "%2d | ", value[17]); 445 | else fprintf(file, " . | "); 446 | /* overlay */ 447 | if (value[21]) fprintf(file, "%2d ", value[21]); 448 | else fprintf(file, " . "); 449 | /* underlay */ 450 | if (value[22]) fprintf(file, "%2d ", value[22]); 451 | else fprintf(file, " . "); 452 | /* layer swap */ 453 | if (value[23]) fprintf(file, "y "); 454 | else fprintf(file, " . "); 455 | fprintf(file, "|\n"); 456 | } 457 | /* print table footer */ 458 | fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); 459 | fprintf(file, " | | visual | color | ax dp st | accum | layer |\n"); 460 | fprintf(file, " | id | tp ac gd fm db sw st ms | sz r g b a | bf th cl | sz r g b a | ov un sw |\n"); 461 | fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); 462 | } 463 | else /* verbose */ 464 | { 465 | #if 0 466 | fprintf(file, "\n"); 467 | /* loop through all the pixel formats */ 468 | for(i = 1; i <= maxpf; i++) 469 | { 470 | DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); 471 | /* only describe this format if it supports OpenGL */ 472 | if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL) 473 | || (drawableonly && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))) continue; 474 | fprintf(file, "Visual ID: %2d depth=%d class=%s\n", i, pfd.cDepthBits, 475 | pfd.cColorBits <= 8 ? "PseudoColor" : "TrueColor"); 476 | fprintf(file, " bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n", pfd.cColorBits, pfd.bReserved, pfd.iPixelType == PFD_TYPE_RGBA ? "rgba" : "ci", pfd.dwFlags & PFD_DOUBLEBUFFER, pfd.dwFlags & PFD_STEREO); 477 | fprintf(file, " generic=%d generic accelerated=%d\n", (pfd.dwFlags & PFD_GENERIC_FORMAT) == PFD_GENERIC_FORMAT, (pfd.dwFlags & PFD_GENERIC_ACCELERATED) == PFD_GENERIC_ACCELERATED); 478 | fprintf(file, " rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits); 479 | fprintf(file, " auxBuffers=%d depthSize=%d stencilSize=%d\n", pfd.cAuxBuffers, pfd.cDepthBits, pfd.cStencilBits); 480 | fprintf(file, " accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cAccumRedBits, pfd.cAccumGreenBits, pfd.cAccumBlueBits, pfd.cAccumAlphaBits); 481 | fprintf(file, " multiSample=%d multisampleBuffers=%d\n", 0, 0); 482 | fprintf(file, " Opaque.\n"); 483 | } 484 | #endif 485 | } 486 | } 487 | 488 | void 489 | VisualInfoGDI (GLContext* ctx) 490 | { 491 | int i, maxpf; 492 | PIXELFORMATDESCRIPTOR pfd; 493 | 494 | /* calling DescribePixelFormat() with NULL pfd (!!!) return maximum 495 | number of pixel formats */ 496 | maxpf = DescribePixelFormat(ctx->dc, 1, 0, NULL); 497 | 498 | if (!verbose) 499 | { 500 | fprintf(file, "-----------------------------------------------------------------------------\n"); 501 | fprintf(file, " visual x bf lv rg d st ge ge r g b a ax dp st accum buffs ms \n"); 502 | fprintf(file, " id dep tp sp sz l ci b ro ne ac sz sz sz sz bf th cl sz r g b a ns b\n"); 503 | fprintf(file, "-----------------------------------------------------------------------------\n"); 504 | 505 | /* loop through all the pixel formats */ 506 | for(i = 1; i <= maxpf; i++) 507 | { 508 | DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); 509 | /* only describe this format if it supports OpenGL */ 510 | if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL) 511 | || (drawableonly && (pfd.dwFlags & PFD_DRAW_TO_BITMAP))) continue; 512 | /* other criteria could be tested here for actual pixel format 513 | choosing in an application: 514 | 515 | for (...each pixel format...) { 516 | if (pfd.dwFlags & PFD_SUPPORT_OPENGL && 517 | pfd.dwFlags & PFD_DOUBLEBUFFER && 518 | pfd.cDepthBits >= 24 && 519 | pfd.cColorBits >= 24) 520 | { 521 | goto found; 522 | } 523 | } 524 | ... not found so exit ... 525 | found: 526 | ... found so use it ... 527 | */ 528 | /* print out the information for this pixel format */ 529 | fprintf(file, "0x%02x ", i); 530 | fprintf(file, "%3d ", pfd.cColorBits); 531 | if(pfd.dwFlags & PFD_DRAW_TO_WINDOW) fprintf(file, "wn "); 532 | else if(pfd.dwFlags & PFD_DRAW_TO_BITMAP) fprintf(file, "bm "); 533 | else fprintf(file, "pb "); 534 | /* should find transparent pixel from LAYERPLANEDESCRIPTOR */ 535 | fprintf(file, " . "); 536 | fprintf(file, "%3d ", pfd.cColorBits); 537 | /* bReserved field indicates number of over/underlays */ 538 | if(pfd.bReserved) fprintf(file, " %d ", pfd.bReserved); 539 | else fprintf(file, " . "); 540 | fprintf(file, " %c ", pfd.iPixelType == PFD_TYPE_RGBA ? 'r' : 'c'); 541 | fprintf(file, "%c ", pfd.dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.'); 542 | fprintf(file, " %c ", pfd.dwFlags & PFD_STEREO ? 'y' : '.'); 543 | /* added: */ 544 | fprintf(file, " %c ", pfd.dwFlags & PFD_GENERIC_FORMAT ? 'y' : '.'); 545 | fprintf(file, " %c ", pfd.dwFlags & PFD_GENERIC_ACCELERATED ? 'y' : '.'); 546 | if(pfd.cRedBits && pfd.iPixelType == PFD_TYPE_RGBA) 547 | fprintf(file, "%2d ", pfd.cRedBits); 548 | else fprintf(file, " . "); 549 | if(pfd.cGreenBits && pfd.iPixelType == PFD_TYPE_RGBA) 550 | fprintf(file, "%2d ", pfd.cGreenBits); 551 | else fprintf(file, " . "); 552 | if(pfd.cBlueBits && pfd.iPixelType == PFD_TYPE_RGBA) 553 | fprintf(file, "%2d ", pfd.cBlueBits); 554 | else fprintf(file, " . "); 555 | if(pfd.cAlphaBits && pfd.iPixelType == PFD_TYPE_RGBA) 556 | fprintf(file, "%2d ", pfd.cAlphaBits); 557 | else fprintf(file, " . "); 558 | if(pfd.cAuxBuffers) fprintf(file, "%2d ", pfd.cAuxBuffers); 559 | else fprintf(file, " . "); 560 | if(pfd.cDepthBits) fprintf(file, "%2d ", pfd.cDepthBits); 561 | else fprintf(file, " . "); 562 | if(pfd.cStencilBits) fprintf(file, "%2d ", pfd.cStencilBits); 563 | else fprintf(file, " . "); 564 | if(pfd.cAccumBits) fprintf(file, "%3d ", pfd.cAccumBits); 565 | else fprintf(file, " . "); 566 | if(pfd.cAccumRedBits) fprintf(file, "%2d ", pfd.cAccumRedBits); 567 | else fprintf(file, " . "); 568 | if(pfd.cAccumGreenBits) fprintf(file, "%2d ", pfd.cAccumGreenBits); 569 | else fprintf(file, " . "); 570 | if(pfd.cAccumBlueBits) fprintf(file, "%2d ", pfd.cAccumBlueBits); 571 | else fprintf(file, " . "); 572 | if(pfd.cAccumAlphaBits) fprintf(file, "%2d ", pfd.cAccumAlphaBits); 573 | else fprintf(file, " . "); 574 | /* no multisample in win32 */ 575 | fprintf(file, " . .\n"); 576 | } 577 | /* print table footer */ 578 | fprintf(file, "-----------------------------------------------------------------------------\n"); 579 | fprintf(file, " visual x bf lv rg d st ge ge r g b a ax dp st accum buffs ms \n"); 580 | fprintf(file, " id dep tp sp sz l ci b ro ne ac sz sz sz sz bf th cl sz r g b a ns b\n"); 581 | fprintf(file, "-----------------------------------------------------------------------------\n"); 582 | } 583 | else /* verbose */ 584 | { 585 | fprintf(file, "\n"); 586 | /* loop through all the pixel formats */ 587 | for(i = 1; i <= maxpf; i++) 588 | { 589 | DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); 590 | /* only describe this format if it supports OpenGL */ 591 | if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL) 592 | || (drawableonly && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))) continue; 593 | fprintf(file, "Visual ID: %2d depth=%d class=%s\n", i, pfd.cDepthBits, 594 | pfd.cColorBits <= 8 ? "PseudoColor" : "TrueColor"); 595 | fprintf(file, " bufferSize=%d level=%d renderType=%s doubleBuffer=%ld stereo=%ld\n", pfd.cColorBits, pfd.bReserved, pfd.iPixelType == PFD_TYPE_RGBA ? "rgba" : "ci", pfd.dwFlags & PFD_DOUBLEBUFFER, pfd.dwFlags & PFD_STEREO); 596 | fprintf(file, " generic=%d generic accelerated=%d\n", (pfd.dwFlags & PFD_GENERIC_FORMAT) == PFD_GENERIC_FORMAT, (pfd.dwFlags & PFD_GENERIC_ACCELERATED) == PFD_GENERIC_ACCELERATED); 597 | fprintf(file, " rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits); 598 | fprintf(file, " auxBuffers=%d depthSize=%d stencilSize=%d\n", pfd.cAuxBuffers, pfd.cDepthBits, pfd.cStencilBits); 599 | fprintf(file, " accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cAccumRedBits, pfd.cAccumGreenBits, pfd.cAccumBlueBits, pfd.cAccumAlphaBits); 600 | fprintf(file, " multiSample=%d multisampleBuffers=%d\n", 0, 0); 601 | fprintf(file, " Opaque.\n"); 602 | } 603 | } 604 | } 605 | 606 | void 607 | VisualInfo (GLContext* ctx) 608 | { 609 | if (WGLEW_ARB_pixel_format) 610 | VisualInfoARB(ctx); 611 | else 612 | VisualInfoGDI(ctx); 613 | } 614 | 615 | /* ---------------------------------------------------------------------- */ 616 | 617 | #elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) 618 | 619 | void 620 | VisualInfo (__attribute__((unused)) GLContext* ctx) 621 | { 622 | /* 623 | int attrib[] = { AGL_RGBA, AGL_NONE }; 624 | AGLPixelFormat pf; 625 | GLint value; 626 | pf = aglChoosePixelFormat(NULL, 0, attrib); 627 | while (pf != NULL) 628 | { 629 | aglDescribePixelFormat(pf, GL_RGBA, &value); 630 | fprintf(stderr, "%d\n", value); 631 | pf = aglNextPixelFormat(pf); 632 | } 633 | */ 634 | } 635 | 636 | /* ---------------------------------------------------------------------- */ 637 | 638 | #elif defined(__HAIKU__) 639 | 640 | void 641 | VisualInfo (GLContext* ctx) 642 | { 643 | /* TODO */ 644 | } 645 | 646 | #else /* GLX */ 647 | 648 | void 649 | VisualInfo (GLContext* ctx) 650 | { 651 | int n_fbc; 652 | GLXFBConfig* fbc; 653 | int value, ret, i; 654 | 655 | fbc = glXGetFBConfigs(ctx->dpy, DefaultScreen(ctx->dpy), &n_fbc); 656 | 657 | if (fbc) 658 | { 659 | if (!verbose) 660 | { 661 | /* print table header */ 662 | fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); 663 | fprintf(file, " | | visual | color | ax dp st | accum | ms | cav |\n"); 664 | fprintf(file, " | id | tp xr cl fm db st lv xp | sz r g b a | bf th cl | r g b a | ns b | eat |\n"); 665 | fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); 666 | /* loop through all the fbcs */ 667 | for (i=0; idpy, fbc[i], GLX_FBCONFIG_ID, &value); 672 | if (ret != Success) 673 | { 674 | fprintf(file, "| ? |"); 675 | } 676 | else 677 | { 678 | fprintf(file, " |% 4d | ", value); 679 | } 680 | /* visual type */ 681 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DRAWABLE_TYPE, &value); 682 | if (ret != Success) 683 | { 684 | fprintf(file, " ? "); 685 | } 686 | else 687 | { 688 | if (value & GLX_WINDOW_BIT) 689 | { 690 | if (value & GLX_PBUFFER_BIT) 691 | { 692 | fprintf(file, "wp "); 693 | } 694 | else 695 | { 696 | fprintf(file, "wn "); 697 | } 698 | } 699 | else 700 | { 701 | if (value & GLX_PBUFFER_BIT) 702 | { 703 | fprintf(file, "pb "); 704 | } 705 | else if (value & GLX_PIXMAP_BIT) 706 | { 707 | fprintf(file, "pm "); 708 | } 709 | else 710 | { 711 | fprintf(file, " ? "); 712 | } 713 | } 714 | } 715 | /* x renderable */ 716 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_X_RENDERABLE, &value); 717 | if (ret != Success) 718 | { 719 | fprintf(file, " ? "); 720 | } 721 | else 722 | { 723 | fprintf(file, value ? " y " : " n "); 724 | } 725 | /* class */ 726 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_X_VISUAL_TYPE, &value); 727 | if (ret != Success) 728 | { 729 | fprintf(file, " ? "); 730 | } 731 | else 732 | { 733 | if (GLX_TRUE_COLOR == value) 734 | fprintf(file, "tc "); 735 | else if (GLX_DIRECT_COLOR == value) 736 | fprintf(file, "dc "); 737 | else if (GLX_PSEUDO_COLOR == value) 738 | fprintf(file, "pc "); 739 | else if (GLX_STATIC_COLOR == value) 740 | fprintf(file, "sc "); 741 | else if (GLX_GRAY_SCALE == value) 742 | fprintf(file, "gs "); 743 | else if (GLX_STATIC_GRAY == value) 744 | fprintf(file, "sg "); 745 | else if (GLX_X_VISUAL_TYPE == value) 746 | fprintf(file, " . "); 747 | else 748 | fprintf(file, " ? "); 749 | } 750 | /* format */ 751 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_RENDER_TYPE, &value); 752 | if (ret != Success) 753 | { 754 | fprintf(file, " ? "); 755 | } 756 | else 757 | { 758 | if (GLXEW_NV_float_buffer) 759 | { 760 | int ret2, value2; 761 | ret2 = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_FLOAT_COMPONENTS_NV, &value2); 762 | if (Success == ret2 && GL_TRUE == value2) 763 | { 764 | fprintf(file, " f "); 765 | } 766 | else if (value & GLX_RGBA_BIT) 767 | fprintf(file, " i "); 768 | else if (value & GLX_COLOR_INDEX_BIT) 769 | fprintf(file, " c "); 770 | else 771 | fprintf(file, " ? "); 772 | } 773 | else 774 | { 775 | if (value & GLX_RGBA_FLOAT_ATI_BIT) 776 | fprintf(file, " f "); 777 | else if (value & GLX_RGBA_BIT) 778 | fprintf(file, " i "); 779 | else if (value & GLX_COLOR_INDEX_BIT) 780 | fprintf(file, " c "); 781 | else 782 | fprintf(file, " ? "); 783 | } 784 | } 785 | /* double buffer */ 786 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DOUBLEBUFFER, &value); 787 | fprintf(file, " %c ", Success != ret ? '?' : (value ? 'y' : '.')); 788 | /* stereo */ 789 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_STEREO, &value); 790 | fprintf(file, " %c ", Success != ret ? '?' : (value ? 'y' : '.')); 791 | /* level */ 792 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_LEVEL, &value); 793 | if (Success != ret) 794 | { 795 | fprintf(file, " ? "); 796 | } 797 | else 798 | { 799 | fprintf(file, "%2d ", value); 800 | } 801 | /* transparency */ 802 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_TRANSPARENT_TYPE, &value); 803 | if (Success != ret) 804 | { 805 | fprintf(file, " ? | "); 806 | } 807 | else 808 | { 809 | if (GLX_TRANSPARENT_RGB == value) 810 | fprintf(file, " r | "); 811 | else if (GLX_TRANSPARENT_INDEX == value) 812 | fprintf(file, " i | "); 813 | else if (GLX_NONE == value) 814 | fprintf(file, " . | "); 815 | else 816 | fprintf(file, " ? | "); 817 | } 818 | /* color size */ 819 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_BUFFER_SIZE, &value); 820 | if (Success != ret) 821 | { 822 | fprintf(file, " ? "); 823 | } 824 | else 825 | { 826 | if (value) 827 | fprintf(file, "%3d ", value); 828 | else 829 | fprintf(file, " . "); 830 | } 831 | /* red size */ 832 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_RED_SIZE, &value); 833 | if (Success != ret) 834 | { 835 | fprintf(file, " ? "); 836 | } 837 | else 838 | { 839 | if (value) 840 | fprintf(file, "%2d ", value); 841 | else 842 | fprintf(file, " . "); 843 | } 844 | /* green size */ 845 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_GREEN_SIZE, &value); 846 | if (Success != ret) 847 | { 848 | fprintf(file, " ? "); 849 | } 850 | else 851 | { 852 | if (value) 853 | fprintf(file, "%2d ", value); 854 | else 855 | fprintf(file, " . "); 856 | } 857 | /* blue size */ 858 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_BLUE_SIZE, &value); 859 | if (Success != ret) 860 | { 861 | fprintf(file, " ? "); 862 | } 863 | else 864 | { 865 | if (value) 866 | fprintf(file, "%2d ", value); 867 | else 868 | fprintf(file, " . "); 869 | } 870 | /* alpha size */ 871 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ALPHA_SIZE, &value); 872 | if (Success != ret) 873 | { 874 | fprintf(file, " ? | "); 875 | } 876 | else 877 | { 878 | if (value) 879 | fprintf(file, "%2d | ", value); 880 | else 881 | fprintf(file, " . | "); 882 | } 883 | /* aux buffers */ 884 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_AUX_BUFFERS, &value); 885 | if (Success != ret) 886 | { 887 | fprintf(file, " ? "); 888 | } 889 | else 890 | { 891 | if (value) 892 | fprintf(file, "%2d ", value); 893 | else 894 | fprintf(file, " . "); 895 | } 896 | /* depth size */ 897 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DEPTH_SIZE, &value); 898 | if (Success != ret) 899 | { 900 | fprintf(file, " ? "); 901 | } 902 | else 903 | { 904 | if (value) 905 | fprintf(file, "%2d ", value); 906 | else 907 | fprintf(file, " . "); 908 | } 909 | /* stencil size */ 910 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_STENCIL_SIZE, &value); 911 | if (Success != ret) 912 | { 913 | fprintf(file, " ? | "); 914 | } 915 | else 916 | { 917 | if (value) 918 | fprintf(file, "%2d | ", value); 919 | else 920 | fprintf(file, " . | "); 921 | } 922 | /* accum red size */ 923 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_RED_SIZE, &value); 924 | if (Success != ret) 925 | { 926 | fprintf(file, " ? "); 927 | } 928 | else 929 | { 930 | if (value) 931 | fprintf(file, "%2d ", value); 932 | else 933 | fprintf(file, " . "); 934 | } 935 | /* accum green size */ 936 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_GREEN_SIZE, &value); 937 | if (Success != ret) 938 | { 939 | fprintf(file, " ? "); 940 | } 941 | else 942 | { 943 | if (value) 944 | fprintf(file, "%2d ", value); 945 | else 946 | fprintf(file, " . "); 947 | } 948 | /* accum blue size */ 949 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_BLUE_SIZE, &value); 950 | if (Success != ret) 951 | { 952 | fprintf(file, " ? "); 953 | } 954 | else 955 | { 956 | if (value) 957 | fprintf(file, "%2d ", value); 958 | else 959 | fprintf(file, " . "); 960 | } 961 | /* accum alpha size */ 962 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_ALPHA_SIZE, &value); 963 | if (Success != ret) 964 | { 965 | fprintf(file, " ? | "); 966 | } 967 | else 968 | { 969 | if (value) 970 | fprintf(file, "%2d | ", value); 971 | else 972 | fprintf(file, " . | "); 973 | } 974 | /* multisample */ 975 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_SAMPLES, &value); 976 | if (Success != ret) 977 | { 978 | fprintf(file, " ? "); 979 | } 980 | else 981 | { 982 | fprintf(file, "%2d ", value); 983 | } 984 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_SAMPLE_BUFFERS, &value); 985 | if (Success != ret) 986 | { 987 | fprintf(file, " ? | "); 988 | } 989 | else 990 | { 991 | fprintf(file, "%2d | ", value); 992 | } 993 | /* caveat */ 994 | ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_CONFIG_CAVEAT, &value); 995 | if (Success != ret) 996 | { 997 | fprintf(file, "???? |"); 998 | } 999 | else 1000 | { 1001 | if (GLX_NONE == value) 1002 | fprintf(file, "none |\n"); 1003 | else if (GLX_SLOW_CONFIG == value) 1004 | fprintf(file, "slow |\n"); 1005 | else if (GLX_NON_CONFORMANT_CONFIG == value) 1006 | fprintf(file, "ncft |\n"); 1007 | else 1008 | fprintf(file, "???? |\n"); 1009 | } 1010 | } 1011 | /* print table footer */ 1012 | fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); 1013 | fprintf(file, " | id | tp xr cl fm db st lv xp | sz r g b a | bf th cl | r g b a | ns b | eat |\n"); 1014 | fprintf(file, " | | visual | color | ax dp st | accum | ms | cav |\n"); 1015 | fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); 1016 | } 1017 | } 1018 | } 1019 | 1020 | #endif 1021 | 1022 | /* ------------------------------------------------------------------------ */ 1023 | 1024 | #if defined(GLEW_OSMESA) 1025 | void InitContext (GLContext* ctx) 1026 | { 1027 | ctx->ctx = NULL; 1028 | } 1029 | 1030 | static const GLint osmFormat = GL_UNSIGNED_BYTE; 1031 | static const GLint osmWidth = 640; 1032 | static const GLint osmHeight = 480; 1033 | static GLubyte *osmPixels = NULL; 1034 | 1035 | GLboolean CreateContext (GLContext* ctx) 1036 | { 1037 | if (NULL == ctx) return GL_TRUE; 1038 | ctx->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); 1039 | if (NULL == ctx->ctx) return GL_TRUE; 1040 | if (NULL == osmPixels) 1041 | { 1042 | osmPixels = (GLubyte *) calloc(osmWidth*osmHeight*4, 1); 1043 | } 1044 | if (!OSMesaMakeCurrent(ctx->ctx, osmPixels, GL_UNSIGNED_BYTE, osmWidth, osmHeight)) 1045 | { 1046 | return GL_TRUE; 1047 | } 1048 | return GL_FALSE; 1049 | } 1050 | 1051 | void DestroyContext (GLContext* ctx) 1052 | { 1053 | if (NULL == ctx) return; 1054 | if (NULL != ctx->ctx) OSMesaDestroyContext(ctx->ctx); 1055 | } 1056 | /* ------------------------------------------------------------------------ */ 1057 | 1058 | #elif defined(GLEW_EGL) 1059 | void InitContext (GLContext* ctx) 1060 | { 1061 | ctx->ctx = NULL; 1062 | } 1063 | 1064 | GLboolean CreateContext (GLContext* ctx) 1065 | { 1066 | return GL_FALSE; 1067 | } 1068 | 1069 | void DestroyContext (GLContext* ctx) 1070 | { 1071 | if (NULL == ctx) return; 1072 | return; 1073 | } 1074 | 1075 | /* ------------------------------------------------------------------------ */ 1076 | 1077 | #elif defined(_WIN32) 1078 | 1079 | void InitContext (GLContext* ctx) 1080 | { 1081 | ctx->wnd = NULL; 1082 | ctx->dc = NULL; 1083 | ctx->rc = NULL; 1084 | } 1085 | 1086 | GLboolean CreateContext (GLContext* ctx) 1087 | { 1088 | WNDCLASS wc; 1089 | PIXELFORMATDESCRIPTOR pfd; 1090 | /* check for input */ 1091 | if (NULL == ctx) return GL_TRUE; 1092 | /* register window class */ 1093 | ZeroMemory(&wc, sizeof(WNDCLASS)); 1094 | wc.hInstance = GetModuleHandle(NULL); 1095 | wc.lpfnWndProc = DefWindowProc; 1096 | wc.lpszClassName = "GLEW"; 1097 | if (0 == RegisterClass(&wc)) return GL_TRUE; 1098 | /* create window */ 1099 | ctx->wnd = CreateWindow("GLEW", "GLEW", 0, CW_USEDEFAULT, CW_USEDEFAULT, 1100 | CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, 1101 | GetModuleHandle(NULL), NULL); 1102 | if (NULL == ctx->wnd) return GL_TRUE; 1103 | /* get the device context */ 1104 | ctx->dc = GetDC(ctx->wnd); 1105 | if (NULL == ctx->dc) return GL_TRUE; 1106 | /* find pixel format */ 1107 | ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); 1108 | if (visual == -1) /* find default */ 1109 | { 1110 | pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 1111 | pfd.nVersion = 1; 1112 | pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; 1113 | visual = ChoosePixelFormat(ctx->dc, &pfd); 1114 | if (0 == visual) return GL_TRUE; 1115 | } 1116 | /* set the pixel format for the dc */ 1117 | if (FALSE == SetPixelFormat(ctx->dc, visual, &pfd)) return GL_TRUE; 1118 | /* create rendering context */ 1119 | ctx->rc = wglCreateContext(ctx->dc); 1120 | if (NULL == ctx->rc) return GL_TRUE; 1121 | if (FALSE == wglMakeCurrent(ctx->dc, ctx->rc)) return GL_TRUE; 1122 | return GL_FALSE; 1123 | } 1124 | 1125 | void DestroyContext (GLContext* ctx) 1126 | { 1127 | if (NULL == ctx) return; 1128 | if (NULL != ctx->rc) wglMakeCurrent(NULL, NULL); 1129 | if (NULL != ctx->rc) wglDeleteContext(wglGetCurrentContext()); 1130 | if (NULL != ctx->wnd && NULL != ctx->dc) ReleaseDC(ctx->wnd, ctx->dc); 1131 | if (NULL != ctx->wnd) DestroyWindow(ctx->wnd); 1132 | UnregisterClass("GLEW", GetModuleHandle(NULL)); 1133 | } 1134 | 1135 | /* ------------------------------------------------------------------------ */ 1136 | 1137 | #elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) 1138 | 1139 | void InitContext (GLContext* ctx) 1140 | { 1141 | ctx->ctx = NULL; 1142 | ctx->octx = NULL; 1143 | } 1144 | 1145 | GLboolean CreateContext (GLContext* ctx) 1146 | { 1147 | CGLPixelFormatAttribute attrib[] = { kCGLPFAAccelerated, 0 }; 1148 | CGLPixelFormatObj pf; 1149 | GLint npix; 1150 | CGLError error; 1151 | /* check input */ 1152 | if (NULL == ctx) return GL_TRUE; 1153 | error = CGLChoosePixelFormat(attrib, &pf, &npix); 1154 | if (error) return GL_TRUE; 1155 | error = CGLCreateContext(pf, NULL, &ctx->ctx); 1156 | if (error) return GL_TRUE; 1157 | CGLReleasePixelFormat(pf); 1158 | ctx->octx = CGLGetCurrentContext(); 1159 | error = CGLSetCurrentContext(ctx->ctx); 1160 | if (error) return GL_TRUE; 1161 | return GL_FALSE; 1162 | } 1163 | 1164 | void DestroyContext (GLContext* ctx) 1165 | { 1166 | if (NULL == ctx) return; 1167 | CGLSetCurrentContext(ctx->octx); 1168 | if (NULL != ctx->ctx) CGLReleaseContext(ctx->ctx); 1169 | } 1170 | 1171 | /* ------------------------------------------------------------------------ */ 1172 | 1173 | #elif defined(__HAIKU__) 1174 | 1175 | void 1176 | InitContext (GLContext* ctx) 1177 | { 1178 | /* TODO */ 1179 | } 1180 | 1181 | GLboolean 1182 | CreateContext (GLContext* ctx) 1183 | { 1184 | /* TODO */ 1185 | return GL_FALSE; 1186 | } 1187 | 1188 | void 1189 | DestroyContext (GLContext* ctx) 1190 | { 1191 | /* TODO */ 1192 | } 1193 | 1194 | /* ------------------------------------------------------------------------ */ 1195 | 1196 | #else /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */ 1197 | 1198 | void InitContext (GLContext* ctx) 1199 | { 1200 | ctx->dpy = NULL; 1201 | ctx->vi = NULL; 1202 | ctx->ctx = NULL; 1203 | ctx->wnd = 0; 1204 | ctx->cmap = 0; 1205 | } 1206 | 1207 | GLboolean CreateContext (GLContext* ctx) 1208 | { 1209 | int attrib[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None }; 1210 | int erb, evb; 1211 | XSetWindowAttributes swa; 1212 | /* check input */ 1213 | if (NULL == ctx) return GL_TRUE; 1214 | /* open display */ 1215 | ctx->dpy = XOpenDisplay(display); 1216 | if (NULL == ctx->dpy) return GL_TRUE; 1217 | /* query for glx */ 1218 | if (!glXQueryExtension(ctx->dpy, &erb, &evb)) return GL_TRUE; 1219 | /* choose visual */ 1220 | ctx->vi = glXChooseVisual(ctx->dpy, DefaultScreen(ctx->dpy), attrib); 1221 | if (NULL == ctx->vi) return GL_TRUE; 1222 | /* create context */ 1223 | ctx->ctx = glXCreateContext(ctx->dpy, ctx->vi, None, True); 1224 | if (NULL == ctx->ctx) return GL_TRUE; 1225 | /* create window */ 1226 | /*wnd = XCreateSimpleWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 1, 1, 1, 0, 0);*/ 1227 | ctx->cmap = XCreateColormap(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen), 1228 | ctx->vi->visual, AllocNone); 1229 | swa.border_pixel = 0; 1230 | swa.colormap = ctx->cmap; 1231 | ctx->wnd = XCreateWindow(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen), 1232 | 0, 0, 1, 1, 0, ctx->vi->depth, InputOutput, ctx->vi->visual, 1233 | CWBorderPixel | CWColormap, &swa); 1234 | /* make context current */ 1235 | if (!glXMakeCurrent(ctx->dpy, ctx->wnd, ctx->ctx)) return GL_TRUE; 1236 | return GL_FALSE; 1237 | } 1238 | 1239 | void DestroyContext (GLContext* ctx) 1240 | { 1241 | if (NULL != ctx->dpy && NULL != ctx->ctx) glXDestroyContext(ctx->dpy, ctx->ctx); 1242 | if (NULL != ctx->dpy && 0 != ctx->wnd) XDestroyWindow(ctx->dpy, ctx->wnd); 1243 | if (NULL != ctx->dpy && 0 != ctx->cmap) XFreeColormap(ctx->dpy, ctx->cmap); 1244 | if (NULL != ctx->vi) XFree(ctx->vi); 1245 | if (NULL != ctx->dpy) XCloseDisplay(ctx->dpy); 1246 | } 1247 | 1248 | #endif /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */ 1249 | 1250 | GLboolean ParseArgs (int argc, char** argv) 1251 | { 1252 | int p = 0; 1253 | while (p < argc) 1254 | { 1255 | #if defined(_WIN32) 1256 | if (!strcmp(argv[p], "-pf") || !strcmp(argv[p], "-pixelformat")) 1257 | { 1258 | if (++p >= argc) return GL_TRUE; 1259 | display = NULL; 1260 | visual = strtol(argv[p], NULL, 0); 1261 | } 1262 | else if (!strcmp(argv[p], "-a")) 1263 | { 1264 | showall = 1; 1265 | } 1266 | else if (!strcmp(argv[p], "-s")) 1267 | { 1268 | displaystdout = 1; 1269 | } 1270 | else if (!strcmp(argv[p], "-h")) 1271 | { 1272 | return GL_TRUE; 1273 | } 1274 | else 1275 | return GL_TRUE; 1276 | #else 1277 | if (!strcmp(argv[p], "-display")) 1278 | { 1279 | if (++p >= argc) return GL_TRUE; 1280 | display = argv[p]; 1281 | } 1282 | else if (!strcmp(argv[p], "-visual")) 1283 | { 1284 | if (++p >= argc) return GL_TRUE; 1285 | visual = (int)strtol(argv[p], NULL, 0); 1286 | } 1287 | else if (!strcmp(argv[p], "-h")) 1288 | { 1289 | return GL_TRUE; 1290 | } 1291 | else 1292 | return GL_TRUE; 1293 | #endif 1294 | p++; 1295 | } 1296 | return GL_FALSE; 1297 | } 1298 | -------------------------------------------------------------------------------- /NativePlugin/src/AsyncGPUReadbackPlugin.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "Unity/IUnityInterface.h" 8 | #include "Unity/IUnityGraphics.h" 9 | #include 10 | #include "TypeHelpers.hpp" 11 | #include 12 | #include 13 | 14 | #ifdef DEBUG 15 | #include 16 | #include 17 | #endif 18 | 19 | struct BaseTask; 20 | struct SsboTask; 21 | struct FrameTask; 22 | 23 | static IUnityGraphics* graphics = NULL; 24 | static UnityGfxRenderer renderer = kUnityGfxRendererNull; 25 | 26 | static std::map> tasks; 27 | static std::vector pending_release_tasks; 28 | static std::mutex tasks_mutex; 29 | int next_event_id = 1; 30 | static bool inited = false; 31 | 32 | extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API CheckCompatible(); 33 | static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType); 34 | 35 | // Call this on a function parameter to suppress the unused paramter warning 36 | template inline 37 | void unused(T const & result) { static_cast(result); } 38 | 39 | struct BaseTask { 40 | //These vars might be accessed from both render thread and main thread. guard them. 41 | std::atomic initialized; 42 | std::atomic error; 43 | std::atomic done; 44 | /*Called in render thread*/ 45 | virtual void StartRequest() = 0; 46 | virtual void Update() = 0; 47 | 48 | BaseTask() : 49 | initialized(false), 50 | error(false), 51 | done(false) 52 | { 53 | 54 | } 55 | 56 | virtual ~BaseTask() 57 | { 58 | if (result_data != nullptr) { 59 | delete[] result_data; 60 | } 61 | } 62 | 63 | char* GetData(size_t* length) { 64 | if (!done || error) { 65 | return nullptr; 66 | } 67 | std::lock_guard guard(mainthread_data_mutex); 68 | if (this->result_data == nullptr) { 69 | return nullptr; 70 | } 71 | *length = result_data_length; 72 | return result_data; 73 | } 74 | 75 | protected: 76 | /* 77 | * Called by subclass in Update, to commit data and mark as done. 78 | */ 79 | void FinishAndCommitData(char* dataPtr, size_t length) { 80 | std::lock_guard guard(mainthread_data_mutex); 81 | if (this->result_data != nullptr) { 82 | //WTF 83 | return; 84 | } 85 | this->result_data = dataPtr; 86 | this->result_data_length = length; 87 | done = true; 88 | } 89 | 90 | /* 91 | Called by subclass to mark as error. 92 | */ 93 | void ErrorOut() { 94 | error = true; 95 | done = true; 96 | } 97 | private: 98 | std::mutex mainthread_data_mutex; 99 | char* result_data = nullptr; 100 | size_t result_data_length = 0; 101 | }; 102 | 103 | /*Task for readback from ssbo. Which is compute buffer in Unity 104 | */ 105 | struct SsboTask : public BaseTask { 106 | GLuint ssbo; 107 | GLuint pbo; 108 | GLsync fence; 109 | GLint bufferSize; 110 | void Init(GLuint _ssbo, GLint _bufferSize) { 111 | this->ssbo = _ssbo; 112 | this->bufferSize = _bufferSize; 113 | } 114 | 115 | virtual void StartRequest() override { 116 | //bind it to GL_COPY_WRITE_BUFFER to wait for use 117 | glBindBuffer(GL_SHADER_STORAGE_BUFFER, this->ssbo); 118 | 119 | //Get our pbo ready. 120 | glGenBuffers(1, &pbo); 121 | glBindBuffer(GL_PIXEL_PACK_BUFFER, this->pbo); 122 | //Initialize pbo buffer storage. 123 | glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, 0, GL_STREAM_READ); 124 | 125 | //Copy data to pbo. 126 | glCopyBufferSubData(GL_SHADER_STORAGE_BUFFER, GL_PIXEL_PACK_BUFFER, 0, 0, bufferSize); 127 | 128 | //Unbind buffers. 129 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); 130 | glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); 131 | 132 | //Create a fence. 133 | fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 134 | } 135 | 136 | virtual void Update() override { 137 | // Check fence state 138 | GLint status = 0; 139 | GLsizei length = 0; 140 | glGetSynciv(fence, GL_SYNC_STATUS, sizeof(GLint), &length, &status); 141 | if (length <= 0) { 142 | ErrorOut(); 143 | Cleanup(); 144 | return; 145 | } 146 | 147 | // When it's done 148 | if (status == GL_SIGNALED) { 149 | 150 | // Bind back the pbo 151 | glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo); 152 | 153 | // Map the buffer and copy it to data 154 | void* ptr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, bufferSize, GL_MAP_READ_BIT); 155 | 156 | // Allocate the final data buffer !!! WARNING: free, will have to be done on script side !!!! 157 | char* data = new char[bufferSize]; 158 | std::memcpy(data, ptr, bufferSize); 159 | FinishAndCommitData(data, bufferSize); 160 | 161 | // Unmap and unbind 162 | glUnmapBuffer(GL_PIXEL_PACK_BUFFER); 163 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); 164 | Cleanup(); 165 | } 166 | } 167 | 168 | void Cleanup() 169 | { 170 | if (pbo != 0) { 171 | // Clear buffers 172 | glDeleteBuffers(1, &(pbo)); 173 | } 174 | if (fence != 0) { 175 | glDeleteSync(fence); 176 | } 177 | } 178 | }; 179 | 180 | /*Task for readback texture. 181 | */ 182 | struct FrameTask : public BaseTask { 183 | int size; 184 | GLsync fence; 185 | GLuint texture; 186 | GLuint fbo; 187 | GLuint pbo; 188 | int miplevel; 189 | int height; 190 | int width; 191 | int depth; 192 | GLint internal_format; 193 | virtual void StartRequest() override { 194 | // Get texture informations 195 | glBindTexture(GL_TEXTURE_2D, texture); 196 | glGetTexLevelParameteriv(GL_TEXTURE_2D, miplevel, GL_TEXTURE_WIDTH, &(width)); 197 | glGetTexLevelParameteriv(GL_TEXTURE_2D, miplevel, GL_TEXTURE_HEIGHT, &(height)); 198 | glGetTexLevelParameteriv(GL_TEXTURE_2D, miplevel, GL_TEXTURE_DEPTH, &(depth)); 199 | glGetTexLevelParameteriv(GL_TEXTURE_2D, miplevel, GL_TEXTURE_INTERNAL_FORMAT, &(internal_format)); 200 | int pixelBits = getPixelSizeFromInternalFormat(internal_format); 201 | size = depth * width * height * pixelBits / 8; 202 | // Check for errors 203 | if (size == 0 204 | || pixelBits % 8 != 0 //Only support textures aligned to one byte. 205 | || getFormatFromInternalFormat(internal_format) == 0 206 | || getTypeFromInternalFormat(internal_format) == 0) { 207 | ErrorOut(); 208 | return; 209 | } 210 | 211 | // Create the fbo (frame buffer object) from the given texture 212 | glGenFramebuffers(1, &(fbo)); 213 | 214 | // Bind the texture to the fbo 215 | glBindFramebuffer(GL_FRAMEBUFFER, fbo); 216 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); 217 | 218 | // Create and bind pbo (pixel buffer object) to fbo 219 | glGenBuffers(1, &(pbo)); 220 | glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo); 221 | glBufferData(GL_PIXEL_PACK_BUFFER, size, 0, GL_DYNAMIC_READ); 222 | 223 | // Start the read request 224 | glReadBuffer(GL_COLOR_ATTACHMENT0); 225 | glReadPixels(0, 0, width, height, getFormatFromInternalFormat(internal_format), getTypeFromInternalFormat(internal_format), 0); 226 | 227 | // Unbind buffers 228 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); 229 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 230 | 231 | // Fence to know when it's ready 232 | fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 233 | } 234 | 235 | virtual void Update() override { 236 | // Check fence state 237 | GLint status = 0; 238 | GLsizei length = 0; 239 | glGetSynciv(fence, GL_SYNC_STATUS, sizeof(GLint), &length, &status); 240 | if (length <= 0) { 241 | ErrorOut(); 242 | Cleanup(); 243 | return; 244 | } 245 | 246 | // When it's done 247 | if (status == GL_SIGNALED) { 248 | 249 | // Bind back the pbo 250 | glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo); 251 | 252 | // Map the buffer and copy it to data 253 | 254 | char* data = new char[size]; 255 | void* ptr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, size, GL_MAP_READ_BIT); 256 | std::memcpy(data, ptr, size); 257 | FinishAndCommitData(data, size); 258 | 259 | // Unmap and unbind 260 | glUnmapBuffer(GL_PIXEL_PACK_BUFFER); 261 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); 262 | Cleanup(); 263 | } 264 | } 265 | 266 | void Cleanup() 267 | { 268 | // Clear buffers 269 | if (fbo != 0) 270 | glDeleteFramebuffers(1, &(fbo)); 271 | if (pbo != 0) 272 | glDeleteBuffers(1, &(pbo)); 273 | if (fence != 0) 274 | glDeleteSync(fence); 275 | } 276 | }; 277 | 278 | /** 279 | * Unity plugin load event 280 | */ 281 | extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API 282 | UnityPluginLoad(IUnityInterfaces* unityInterfaces) 283 | { 284 | graphics = unityInterfaces->Get(); 285 | graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); 286 | 287 | // Run OnGraphicsDeviceEvent(initialize) manually on plugin load 288 | // to not miss the event in case the graphics device is already initialized 289 | OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize); 290 | 291 | if (CheckCompatible()) { 292 | inited = true; 293 | glewInit(); 294 | } 295 | } 296 | 297 | /** 298 | * Unity unload plugin event 299 | */ 300 | extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() 301 | { 302 | graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent); 303 | } 304 | 305 | /** 306 | * Called for every graphics device events 307 | */ 308 | static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) 309 | { 310 | // Create graphics API implementation upon initialization 311 | if (eventType == kUnityGfxDeviceEventInitialize) 312 | { 313 | renderer = graphics->GetRenderer(); 314 | } 315 | 316 | // Cleanup graphics API implementation upon shutdown 317 | if (eventType == kUnityGfxDeviceEventShutdown) 318 | { 319 | renderer = kUnityGfxRendererNull; 320 | } 321 | } 322 | 323 | 324 | /** 325 | * Check if plugin is compatible with this system 326 | * This plugin is only compatible with opengl core 327 | */ 328 | extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API CheckCompatible() { 329 | return (renderer == kUnityGfxRendererOpenGLCore); 330 | } 331 | 332 | int InsertEvent(std::shared_ptr task) { 333 | int event_id = next_event_id; 334 | next_event_id++; 335 | 336 | std::lock_guard guard(tasks_mutex); 337 | tasks[event_id] = task; 338 | 339 | return event_id; 340 | } 341 | 342 | /** 343 | * @brief Init of the make request action. 344 | * You then have to call makeRequest_renderThread 345 | * via GL.IssuePluginEvent with the returned event_id 346 | * 347 | * @param texture OpenGL texture id 348 | * @return event_id to give to other functions and to IssuePluginEvent 349 | */ 350 | extern "C" int UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API RequestTextureMainThread(GLuint texture, int miplevel) { 351 | // Create the task 352 | std::shared_ptr task = std::make_shared(); 353 | task->texture = texture; 354 | task->miplevel = miplevel; 355 | return InsertEvent(task); 356 | } 357 | 358 | extern "C" int UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API RequestComputeBufferMainThread(GLuint computeBuffer, GLint bufferSize) { 359 | // Create the task 360 | std::shared_ptr task = std::make_shared(); 361 | task->Init(computeBuffer, bufferSize); 362 | return InsertEvent(task); 363 | } 364 | 365 | /** 366 | * @brief Create a a read texture request 367 | * Has to be called by GL.IssuePluginEvent 368 | * @param event_id containing the the task index, given by makeRequest_mainThread 369 | */ 370 | extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API KickstartRequestInRenderThread(int event_id) { 371 | // Get task back 372 | std::lock_guard guard(tasks_mutex); 373 | std::shared_ptr task = tasks[event_id]; 374 | task->StartRequest(); 375 | // Done init 376 | task->initialized = true; 377 | } 378 | 379 | extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetKickstartFunctionPtr() { 380 | return KickstartRequestInRenderThread; 381 | } 382 | 383 | /** 384 | * Update all current available tasks. Should be called in render thread. 385 | */ 386 | extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UpdateRenderThread(int event_id) { 387 | unused(event_id); 388 | //Lock up. 389 | std::lock_guard guard(tasks_mutex); 390 | for (auto ite = tasks.begin(); ite != tasks.end(); ite++) { 391 | auto task = ite->second; 392 | if (task != nullptr && task->initialized && !task->done) 393 | task->Update(); 394 | } 395 | } 396 | 397 | extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetUpdateRenderThreadFunctionPtr() { 398 | return UpdateRenderThread; 399 | } 400 | 401 | /** 402 | * Update in main thread. 403 | * This will erase tasks that are marked as done in last frame. 404 | * Also save tasks that are done this frame. 405 | * By doing this, all tasks are done for one frame, then removed. 406 | */ 407 | extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UpdateMainThread() { 408 | //Lock up. 409 | std::lock_guard guard(tasks_mutex); 410 | 411 | //Remove tasks that are done in the last update. 412 | for (auto& event_id : pending_release_tasks) { 413 | auto t = tasks.find(event_id); 414 | if (t != tasks.end()) { 415 | tasks.erase(t); 416 | } 417 | } 418 | pending_release_tasks.clear(); 419 | 420 | //Push new done tasks to pending list. 421 | for (auto ite = tasks.begin(); ite != tasks.end(); ite++) { 422 | auto task = ite->second; 423 | if (task->done) { 424 | pending_release_tasks.push_back(ite->first); 425 | } 426 | } 427 | } 428 | 429 | /** 430 | * @brief Get data from the main thread. 431 | * The data owner is still native plugin, outside caller should copy the data asap to avoid any problem. 432 | * 433 | */ 434 | extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetData(int event_id, void** buffer, size_t* length) { 435 | // Get task back 436 | std::lock_guard guard(tasks_mutex); 437 | std::shared_ptr task = tasks[event_id]; 438 | 439 | // Do something only if initialized (thread safety) 440 | if (!task->done) { 441 | return; 442 | } 443 | 444 | // Return the pointer. 445 | // The memory ownership doesn't transfer. 446 | auto dataPtr = task->GetData(length); 447 | *buffer = dataPtr; 448 | } 449 | 450 | /** 451 | * @brief Check if request exists 452 | * @param event_id containing the the task index, given by makeRequest_mainThread 453 | */ 454 | extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API TaskExists(int event_id) { 455 | // Get task back 456 | std::lock_guard guard(tasks_mutex); 457 | bool result = tasks.find(event_id) != tasks.end(); 458 | 459 | return result; 460 | } 461 | 462 | /** 463 | * @brief Check if request is done 464 | * @param event_id containing the the task index, given by makeRequest_mainThread 465 | */ 466 | extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API TaskDone(int event_id) { 467 | // Get task back 468 | std::lock_guard guard(tasks_mutex); 469 | auto ite = tasks.find(event_id); 470 | if (ite != tasks.end()) 471 | return ite->second->done; 472 | return true; //If it's disposed, also assume it's done. 473 | } 474 | 475 | /** 476 | * @brief Check if request is in error 477 | * @param event_id containing the the task index, given by makeRequest_mainThread 478 | */ 479 | extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API TaskError(int event_id) { 480 | // Get task back 481 | std::lock_guard guard(tasks_mutex); 482 | auto ite = tasks.find(event_id); 483 | if (ite != tasks.end()) 484 | return ite->second->error; 485 | 486 | return true; //It's disposed, assume as error. 487 | } -------------------------------------------------------------------------------- /NativePlugin/src/TypeHelpers.hpp: -------------------------------------------------------------------------------- 1 | 2 | // Opengl includes 3 | #include 4 | 5 | /** 6 | * @brief Get the size of a pixel in bytes from the given internal format 7 | * 8 | * @param internalFormat 9 | * @return int The size of the pixel in number of bytes. 0 if not found 10 | */ 11 | inline int getPixelSizeFromInternalFormat(int internalFormat) 12 | { 13 | switch(internalFormat) { 14 | case GL_R8: return 8; 15 | case GL_R8_SNORM: return 8; 16 | case GL_R16: return 16; 17 | case GL_R16_SNORM: return 16; 18 | case GL_RG8: return 8 + 8; 19 | case GL_RG8_SNORM: return 8 + 8; 20 | case GL_RG16: return 16 + 16; 21 | case GL_RG16_SNORM: return 16 + 16; 22 | case GL_R3_G3_B2: return 3 + 3 + 2; 23 | case GL_RGB4: return 4 + 4 + 4; 24 | case GL_RGB5: return 5 + 5 + 5; 25 | case GL_RGB8: return 8 + 8 + 8; 26 | case GL_RGB8_SNORM: return 8 + 8 + 8; 27 | case GL_RGB10: return 10 + 10 + 10; 28 | case GL_RGB12: return 12 + 12 + 12; 29 | case GL_RGB16: return 16 + 16 + 16; 30 | case GL_RGB16_SNORM: return 16 + 16 + 16; 31 | case GL_RGBA2: return 2 + 2 + 2 + 2; 32 | case GL_RGBA4: return 4 + 4 + 4 + 4; 33 | case GL_RGB5_A1: return 5 + 5 + 5 + 1; 34 | case GL_RGBA8: return 8 + 8 + 8 + 8; 35 | case GL_RGBA8_SNORM: return 8 + 8 + 8 + 8; 36 | case GL_RGB10_A2: return 10 + 10 + 10 + 2; 37 | case GL_RGBA12: return 12 + 12 + 12 + 12; 38 | case GL_RGBA16: return 16 + 16 + 16 + 16; 39 | case GL_RGBA16_SNORM: return 16 + 16 + 16 + 16; 40 | case GL_SRGB8: return 8 + 8 + 8; 41 | case GL_SRGB8_ALPHA8: return 8 + 8 + 8 + 8; 42 | case GL_R16F: return 16; 43 | case GL_RG16F: return 16 + 16; 44 | case GL_RGB16F: return 16 + 16 + 16; 45 | case GL_RGBA16F: return 16 + 16 + 16 + 16; 46 | case GL_R32F: return 32; 47 | case GL_RG32F: return 32 + 32; 48 | case GL_RGB32F: return 32 + 32 + 32; 49 | case GL_RGBA32F: return 32 + 32 + 32 + 32; 50 | case GL_R11F_G11F_B10F: return 11 + 11 + 10; 51 | case GL_RGB9_E5: return 9 + 9 + 9; 52 | case GL_R8I: return 8; 53 | case GL_R8UI: return 8; 54 | case GL_R16I: return 16; 55 | case GL_R16UI: return 16; 56 | case GL_R32I: return 32; 57 | case GL_R32UI: return 32; 58 | case GL_RG8I: return 8 + 8; 59 | case GL_RG8UI: return 8 + 8; 60 | case GL_RG16I: return 16 + 16; 61 | case GL_RG16UI: return 16 + 16; 62 | case GL_RG32I: return 32 + 32; 63 | case GL_RG32UI: return 32 + 32; 64 | case GL_RGB8I: return 8 + 8 + 8; 65 | case GL_RGB8UI: return 8 + 8 + 8; 66 | case GL_RGB16I: return 16 + 16 + 16; 67 | case GL_RGB16UI: return 16 + 16 + 16; 68 | case GL_RGB32I: return 32 + 32 + 32; 69 | case GL_RGB32UI: return 32 + 32 + 32; 70 | case GL_RGBA8I: return 8 + 8 + 8 + 8; 71 | case GL_RGBA8UI: return 8 + 8 + 8 + 8; 72 | case GL_RGBA16I: return 16 + 16 + 16 + 16; 73 | case GL_RGBA16UI: return 16 + 16 + 16 + 16; 74 | case GL_RGBA32I: return 32 + 32 + 32 + 32; 75 | case GL_RGBA32UI: return 32 + 32 + 32 + 32; 76 | case GL_DEPTH_COMPONENT16: return 16; 77 | case GL_DEPTH_COMPONENT24: return 24; 78 | case GL_DEPTH_COMPONENT32: return 32; 79 | case GL_DEPTH_COMPONENT32F: return 32; 80 | case GL_DEPTH24_STENCIL8: return 24 + 8; 81 | case GL_DEPTH32F_STENCIL8: return 32 + 8; 82 | } 83 | return 0; 84 | } 85 | 86 | /** 87 | * @brief Get the format from internal format 88 | * 89 | * @param internalFormat 90 | * @return int The size of the pixel in number of bytes. 0 if not found 91 | */ 92 | inline int getFormatFromInternalFormat(int internalFormat) 93 | { 94 | switch(internalFormat) { 95 | case GL_R8: 96 | case GL_R8_SNORM: 97 | case GL_R16: 98 | case GL_R16_SNORM: 99 | case GL_R16F: 100 | case GL_R32F: 101 | return GL_RED; 102 | 103 | case GL_R8UI: 104 | case GL_R8I: 105 | case GL_R16UI: 106 | case GL_R16I: 107 | case GL_R32UI: 108 | case GL_R32I: 109 | return GL_RED_INTEGER; 110 | 111 | case GL_RG8: 112 | case GL_RG8_SNORM: 113 | case GL_RG16: 114 | case GL_RG16_SNORM: 115 | case GL_RG16F: 116 | case GL_RG32F: 117 | return GL_RG; 118 | 119 | case GL_RG8UI: 120 | case GL_RG8I: 121 | case GL_RG16UI: 122 | case GL_RG16I: 123 | case GL_RG32UI: 124 | case GL_RG32I: 125 | return GL_RG_INTEGER; 126 | 127 | case GL_RGB8: 128 | case GL_RGB8_SNORM: 129 | case GL_RGB16: 130 | case GL_RGB16_SNORM: 131 | case GL_RGB16F: 132 | case GL_RGB32F: 133 | return GL_RGB; 134 | 135 | case GL_RGB8UI: 136 | case GL_RGB8I: 137 | case GL_RGB16UI: 138 | case GL_RGB16I: 139 | case GL_RGB32UI: 140 | case GL_RGB32I: 141 | return GL_RGB_INTEGER; 142 | 143 | case GL_RGBA8: 144 | case GL_RGBA8_SNORM: 145 | case GL_RGBA16: 146 | case GL_RGBA16_SNORM: 147 | case GL_RGBA16F: 148 | case GL_RGBA32F: 149 | case GL_SRGB8_ALPHA8: 150 | return GL_RGBA; 151 | 152 | case GL_RGBA8UI: 153 | case GL_RGBA8I: 154 | case GL_RGBA16UI: 155 | case GL_RGBA16I: 156 | case GL_RGBA32UI: 157 | case GL_RGBA32I: 158 | return GL_RGBA_INTEGER; 159 | 160 | case GL_SRGB8: 161 | return GL_RGB; 162 | } 163 | return 0; 164 | } 165 | 166 | /** 167 | * @brief Get the best suitable type from internal format 168 | * 169 | * @param internalFormat 170 | * @return int The size of the pixel in number of bytes. 0 if not found 171 | */ 172 | inline int getTypeFromInternalFormat(int internalFormat) 173 | { 174 | switch(internalFormat) { 175 | case GL_R8: 176 | case GL_RG8: 177 | case GL_RGB8: 178 | case GL_RGBA8: 179 | case GL_SRGB8: 180 | case GL_SRGB8_ALPHA8: 181 | case GL_R8UI: 182 | case GL_RG8UI: 183 | case GL_RGB8UI: 184 | case GL_RGBA8UI: 185 | return GL_UNSIGNED_BYTE; 186 | 187 | case GL_R8_SNORM: 188 | case GL_RG8_SNORM: 189 | case GL_RGB8_SNORM: 190 | case GL_RGBA8_SNORM: 191 | case GL_R8I: 192 | case GL_RG8I: 193 | case GL_RGB8I: 194 | case GL_RGBA8I: 195 | return GL_BYTE; 196 | 197 | case GL_R16: 198 | case GL_RG16: 199 | case GL_RGB16: 200 | case GL_RGBA16: 201 | case GL_R16UI: 202 | case GL_RG16UI: 203 | case GL_RGB16UI: 204 | case GL_RGBA16UI: 205 | return GL_UNSIGNED_SHORT; 206 | 207 | case GL_R16_SNORM: 208 | case GL_RG16_SNORM: 209 | case GL_RGB16_SNORM: 210 | case GL_RGBA16_SNORM: 211 | case GL_R16I: 212 | case GL_RG16I: 213 | case GL_RGB16I: 214 | case GL_RGBA16I: 215 | return GL_SHORT; 216 | 217 | case GL_R16F: 218 | case GL_RG16F: 219 | case GL_RGB16F: 220 | case GL_RGBA16F: 221 | return GL_HALF_FLOAT; 222 | 223 | case GL_R32F: 224 | case GL_RG32F: 225 | case GL_RGB32F: 226 | case GL_RGBA32F: 227 | return GL_FLOAT; 228 | 229 | case GL_R32UI: 230 | case GL_RG32UI: 231 | case GL_RGB32UI: 232 | case GL_RGBA32UI: 233 | return GL_UNSIGNED_INT; 234 | 235 | case GL_R32I: 236 | case GL_RG32I: 237 | case GL_RGB32I: 238 | case GL_RGBA32I: 239 | return GL_INT; 240 | } 241 | return 0; 242 | } -------------------------------------------------------------------------------- /NativePlugin/src/Unity/IUnityGraphics.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "IUnityInterface.h" 3 | 4 | typedef enum UnityGfxRenderer 5 | { 6 | //kUnityGfxRendererOpenGL = 0, // Legacy OpenGL, removed 7 | //kUnityGfxRendererD3D9 = 1, // Direct3D 9, removed 8 | kUnityGfxRendererD3D11 = 2, // Direct3D 11 9 | kUnityGfxRendererGCM = 3, // PlayStation 3 10 | kUnityGfxRendererNull = 4, // "null" device (used in batch mode) 11 | kUnityGfxRendererOpenGLES20 = 8, // OpenGL ES 2.0 12 | kUnityGfxRendererOpenGLES30 = 11, // OpenGL ES 3.0 13 | kUnityGfxRendererGXM = 12, // PlayStation Vita 14 | kUnityGfxRendererPS4 = 13, // PlayStation 4 15 | kUnityGfxRendererXboxOne = 14, // Xbox One 16 | kUnityGfxRendererMetal = 16, // iOS Metal 17 | kUnityGfxRendererOpenGLCore = 17, // OpenGL core 18 | kUnityGfxRendererD3D12 = 18, // Direct3D 12 19 | kUnityGfxRendererVulkan = 21, // Vulkan 20 | kUnityGfxRendererNvn = 22, // Nintendo Switch NVN API 21 | kUnityGfxRendererXboxOneD3D12 = 23 // MS XboxOne Direct3D 12 22 | } UnityGfxRenderer; 23 | 24 | typedef enum UnityGfxDeviceEventType 25 | { 26 | kUnityGfxDeviceEventInitialize = 0, 27 | kUnityGfxDeviceEventShutdown = 1, 28 | kUnityGfxDeviceEventBeforeReset = 2, 29 | kUnityGfxDeviceEventAfterReset = 3, 30 | } UnityGfxDeviceEventType; 31 | 32 | typedef void (UNITY_INTERFACE_API * IUnityGraphicsDeviceEventCallback)(UnityGfxDeviceEventType eventType); 33 | 34 | // Should only be used on the rendering thread unless noted otherwise. 35 | UNITY_DECLARE_INTERFACE(IUnityGraphics) 36 | { 37 | UnityGfxRenderer(UNITY_INTERFACE_API * GetRenderer)(); // Thread safe 38 | 39 | // This callback will be called when graphics device is created, destroyed, reset, etc. 40 | // It is possible to miss the kUnityGfxDeviceEventInitialize event in case plugin is loaded at a later time, 41 | // when the graphics device is already created. 42 | void(UNITY_INTERFACE_API * RegisterDeviceEventCallback)(IUnityGraphicsDeviceEventCallback callback); 43 | void(UNITY_INTERFACE_API * UnregisterDeviceEventCallback)(IUnityGraphicsDeviceEventCallback callback); 44 | int(UNITY_INTERFACE_API * ReserveEventIDRange)(int count); // reserves 'count' event IDs. Plugins should use the result as a base index when issuing events back and forth to avoid event id clashes. 45 | }; 46 | UNITY_REGISTER_INTERFACE_GUID(0x7CBA0A9CA4DDB544ULL, 0x8C5AD4926EB17B11ULL, IUnityGraphics) 47 | 48 | 49 | // Certain Unity APIs (GL.IssuePluginEvent, CommandBuffer.IssuePluginEvent) can callback into native plugins. 50 | // Provide them with an address to a function of this signature. 51 | typedef void (UNITY_INTERFACE_API * UnityRenderingEvent)(int eventId); 52 | typedef void (UNITY_INTERFACE_API * UnityRenderingEventAndData)(int eventId, void* data); 53 | -------------------------------------------------------------------------------- /NativePlugin/src/Unity/IUnityGraphicsD3D11.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "IUnityInterface.h" 3 | 4 | 5 | // Should only be used on the rendering thread unless noted otherwise. 6 | UNITY_DECLARE_INTERFACE(IUnityGraphicsD3D11) 7 | { 8 | ID3D11Device* (UNITY_INTERFACE_API * GetDevice)(); 9 | 10 | ID3D11Resource* (UNITY_INTERFACE_API * TextureFromRenderBuffer)(UnityRenderBuffer buffer); 11 | ID3D11Resource* (UNITY_INTERFACE_API * TextureFromNativeTexture)(UnityTextureID texture); 12 | 13 | ID3D11RenderTargetView* (UNITY_INTERFACE_API * RTVFromRenderBuffer)(UnityRenderBuffer surface); 14 | ID3D11ShaderResourceView* (UNITY_INTERFACE_API * SRVFromNativeTexture)(UnityTextureID texture); 15 | }; 16 | 17 | UNITY_REGISTER_INTERFACE_GUID(0xAAB37EF87A87D748ULL, 0xBF76967F07EFB177ULL, IUnityGraphicsD3D11) 18 | -------------------------------------------------------------------------------- /NativePlugin/src/Unity/IUnityGraphicsD3D12.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "IUnityInterface.h" 3 | #ifndef __cplusplus 4 | #include 5 | #endif 6 | 7 | struct RenderSurfaceBase; 8 | typedef struct RenderSurfaceBase* UnityRenderBuffer; 9 | 10 | typedef struct UnityGraphicsD3D12ResourceState UnityGraphicsD3D12ResourceState; 11 | struct UnityGraphicsD3D12ResourceState 12 | { 13 | ID3D12Resource* resource; // Resource to barrier. 14 | D3D12_RESOURCE_STATES expected; // Expected resource state before this command list is executed. 15 | D3D12_RESOURCE_STATES current; // State this resource will be in after this command list is executed. 16 | }; 17 | 18 | typedef struct UnityGraphicsD3D12PhysicalVideoMemoryControlValues UnityGraphicsD3D12PhysicalVideoMemoryControlValues; 19 | struct UnityGraphicsD3D12PhysicalVideoMemoryControlValues // all values in bytes 20 | { 21 | UINT64 reservation; // Minimum required physical memory for an application [default = 64MB]. 22 | UINT64 systemMemoryThreshold; // If free physical video memory drops below this threshold, resources will be allocated in system memory. [default = 64MB] 23 | UINT64 residencyThreshold; // Minimum free physical video memory needed to start bringing evicted resources back after shrunken video memory budget expands again. [default = 128MB] 24 | }; 25 | 26 | // Should only be used on the rendering/submission thread. 27 | UNITY_DECLARE_INTERFACE(IUnityGraphicsD3D12v5) 28 | { 29 | ID3D12Device* (UNITY_INTERFACE_API * GetDevice)(); 30 | 31 | ID3D12Fence* (UNITY_INTERFACE_API * GetFrameFence)(); 32 | // Returns the value set on the frame fence once the current frame completes or the GPU is flushed 33 | UINT64(UNITY_INTERFACE_API * GetNextFrameFenceValue)(); 34 | 35 | // Executes a given command list on a worker thread. 36 | // [Optional] Declares expected and post-execution resource states. 37 | // Returns the fence value. 38 | UINT64(UNITY_INTERFACE_API * ExecuteCommandList)(ID3D12GraphicsCommandList * commandList, int stateCount, UnityGraphicsD3D12ResourceState * states); 39 | 40 | void(UNITY_INTERFACE_API * SetPhysicalVideoMemoryControlValues)(const UnityGraphicsD3D12PhysicalVideoMemoryControlValues * memInfo); 41 | 42 | ID3D12CommandQueue* (UNITY_INTERFACE_API * GetCommandQueue)(); 43 | 44 | ID3D12Resource* (UNITY_INTERFACE_API * TextureFromRenderBuffer)(UnityRenderBuffer * rb); 45 | }; 46 | UNITY_REGISTER_INTERFACE_GUID(0xF5C8D8A37D37BC42ULL, 0xB02DFE93B5064A27ULL, IUnityGraphicsD3D12v5) 47 | 48 | // Should only be used on the rendering/submission thread. 49 | UNITY_DECLARE_INTERFACE(IUnityGraphicsD3D12v4) 50 | { 51 | ID3D12Device* (UNITY_INTERFACE_API * GetDevice)(); 52 | 53 | ID3D12Fence* (UNITY_INTERFACE_API * GetFrameFence)(); 54 | // Returns the value set on the frame fence once the current frame completes or the GPU is flushed 55 | UINT64(UNITY_INTERFACE_API * GetNextFrameFenceValue)(); 56 | 57 | // Executes a given command list on a worker thread. 58 | // [Optional] Declares expected and post-execution resource states. 59 | // Returns the fence value. 60 | UINT64(UNITY_INTERFACE_API * ExecuteCommandList)(ID3D12GraphicsCommandList * commandList, int stateCount, UnityGraphicsD3D12ResourceState * states); 61 | 62 | void(UNITY_INTERFACE_API * SetPhysicalVideoMemoryControlValues)(const UnityGraphicsD3D12PhysicalVideoMemoryControlValues * memInfo); 63 | 64 | ID3D12CommandQueue* (UNITY_INTERFACE_API * GetCommandQueue)(); 65 | }; 66 | UNITY_REGISTER_INTERFACE_GUID(0X498FFCC13EC94006ULL, 0XB18F8B0FF67778C8ULL, IUnityGraphicsD3D12v4) 67 | 68 | // Should only be used on the rendering/submission thread. 69 | UNITY_DECLARE_INTERFACE(IUnityGraphicsD3D12v3) 70 | { 71 | ID3D12Device* (UNITY_INTERFACE_API * GetDevice)(); 72 | 73 | ID3D12Fence* (UNITY_INTERFACE_API * GetFrameFence)(); 74 | // Returns the value set on the frame fence once the current frame completes or the GPU is flushed 75 | UINT64(UNITY_INTERFACE_API * GetNextFrameFenceValue)(); 76 | 77 | // Executes a given command list on a worker thread. 78 | // [Optional] Declares expected and post-execution resource states. 79 | // Returns the fence value. 80 | UINT64(UNITY_INTERFACE_API * ExecuteCommandList)(ID3D12GraphicsCommandList * commandList, int stateCount, UnityGraphicsD3D12ResourceState * states); 81 | 82 | void(UNITY_INTERFACE_API * SetPhysicalVideoMemoryControlValues)(const UnityGraphicsD3D12PhysicalVideoMemoryControlValues * memInfo); 83 | }; 84 | UNITY_REGISTER_INTERFACE_GUID(0x57C3FAFE59E5E843ULL, 0xBF4F5998474BB600ULL, IUnityGraphicsD3D12v3) 85 | 86 | // Should only be used on the rendering/submission thread. 87 | UNITY_DECLARE_INTERFACE(IUnityGraphicsD3D12v2) 88 | { 89 | ID3D12Device* (UNITY_INTERFACE_API * GetDevice)(); 90 | 91 | ID3D12Fence* (UNITY_INTERFACE_API * GetFrameFence)(); 92 | // Returns the value set on the frame fence once the current frame completes or the GPU is flushed 93 | UINT64(UNITY_INTERFACE_API * GetNextFrameFenceValue)(); 94 | 95 | // Executes a given command list on a worker thread. 96 | // [Optional] Declares expected and post-execution resource states. 97 | // Returns the fence value. 98 | UINT64(UNITY_INTERFACE_API * ExecuteCommandList)(ID3D12GraphicsCommandList * commandList, int stateCount, UnityGraphicsD3D12ResourceState * states); 99 | }; 100 | UNITY_REGISTER_INTERFACE_GUID(0xEC39D2F18446C745ULL, 0xB1A2626641D6B11FULL, IUnityGraphicsD3D12v2) 101 | 102 | 103 | // Obsolete 104 | UNITY_DECLARE_INTERFACE(IUnityGraphicsD3D12) 105 | { 106 | ID3D12Device* (UNITY_INTERFACE_API * GetDevice)(); 107 | ID3D12CommandQueue* (UNITY_INTERFACE_API * GetCommandQueue)(); 108 | 109 | ID3D12Fence* (UNITY_INTERFACE_API * GetFrameFence)(); 110 | // Returns the value set on the frame fence once the current frame completes or the GPU is flushed 111 | UINT64(UNITY_INTERFACE_API * GetNextFrameFenceValue)(); 112 | 113 | // Returns the state a resource will be in after the last command list is executed 114 | bool(UNITY_INTERFACE_API * GetResourceState)(ID3D12Resource * resource, D3D12_RESOURCE_STATES * outState); 115 | // Specifies the state a resource will be in after a plugin command list with resource barriers is executed 116 | void(UNITY_INTERFACE_API * SetResourceState)(ID3D12Resource * resource, D3D12_RESOURCE_STATES state); 117 | }; 118 | UNITY_REGISTER_INTERFACE_GUID(0xEF4CEC88A45F4C4CULL, 0xBD295B6F2A38D9DEULL, IUnityGraphicsD3D12) 119 | -------------------------------------------------------------------------------- /NativePlugin/src/Unity/IUnityGraphicsD3D9.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "IUnityInterface.h" 3 | 4 | // Should only be used on the rendering thread unless noted otherwise. 5 | UNITY_DECLARE_INTERFACE(IUnityGraphicsD3D9) 6 | { 7 | IDirect3D9* (UNITY_INTERFACE_API * GetD3D)(); 8 | IDirect3DDevice9* (UNITY_INTERFACE_API * GetDevice)(); 9 | }; 10 | UNITY_REGISTER_INTERFACE_GUID(0xE90746A523D53C4CULL, 0xAC825B19B6F82AC3ULL, IUnityGraphicsD3D9) 11 | -------------------------------------------------------------------------------- /NativePlugin/src/Unity/IUnityGraphicsMetal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "IUnityInterface.h" 3 | 4 | #ifndef __OBJC__ 5 | #error metal plugin is objc code. 6 | #endif 7 | #ifndef __clang__ 8 | #error only clang compiler is supported. 9 | #endif 10 | 11 | @class NSBundle; 12 | @protocol MTLDevice; 13 | @protocol MTLCommandBuffer; 14 | @protocol MTLCommandEncoder; 15 | @protocol MTLTexture; 16 | @class MTLRenderPassDescriptor; 17 | 18 | // Should only be used on the rendering thread unless noted otherwise. 19 | UNITY_DECLARE_INTERFACE(IUnityGraphicsMetal) 20 | { 21 | NSBundle* (UNITY_INTERFACE_API * MetalBundle)(); 22 | id(UNITY_INTERFACE_API * MetalDevice)(); 23 | 24 | id(UNITY_INTERFACE_API * CurrentCommandBuffer)(); 25 | 26 | // for custom rendering support there are two scenarios: 27 | // you want to use current in-flight MTLCommandEncoder (NB: it might be nil) 28 | id(UNITY_INTERFACE_API * CurrentCommandEncoder)(); 29 | // or you might want to create your own encoder. 30 | // In that case you should end unity's encoder before creating your own and end yours before returning control to unity 31 | void(UNITY_INTERFACE_API * EndCurrentCommandEncoder)(); 32 | 33 | // returns MTLRenderPassDescriptor used to create current MTLCommandEncoder 34 | MTLRenderPassDescriptor* (UNITY_INTERFACE_API * CurrentRenderPassDescriptor)(); 35 | 36 | // converting trampoline UnityRenderBufferHandle into native RenderBuffer 37 | UnityRenderBuffer(UNITY_INTERFACE_API * RenderBufferFromHandle)(void* bufferHandle); 38 | 39 | // access to RenderBuffer's texure 40 | // NB: you pass here *native* RenderBuffer, acquired by calling (C#) RenderBuffer.GetNativeRenderBufferPtr 41 | // AAResolvedTextureFromRenderBuffer will return nil in case of non-AA RenderBuffer or if called for depth RenderBuffer 42 | // StencilTextureFromRenderBuffer will return nil in case of no-stencil RenderBuffer or if called for color RenderBuffer 43 | id(UNITY_INTERFACE_API * TextureFromRenderBuffer)(UnityRenderBuffer buffer); 44 | id(UNITY_INTERFACE_API * AAResolvedTextureFromRenderBuffer)(UnityRenderBuffer buffer); 45 | id(UNITY_INTERFACE_API * StencilTextureFromRenderBuffer)(UnityRenderBuffer buffer); 46 | }; 47 | UNITY_REGISTER_INTERFACE_GUID(0x992C8EAEA95811E5ULL, 0x9A62C4B5B9876117ULL, IUnityGraphicsMetal) 48 | -------------------------------------------------------------------------------- /NativePlugin/src/Unity/IUnityGraphicsVulkan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "IUnityInterface.h" 3 | 4 | #ifndef UNITY_VULKAN_HEADER 5 | #define UNITY_VULKAN_HEADER 6 | #endif 7 | 8 | #include UNITY_VULKAN_HEADER 9 | 10 | struct UnityVulkanInstance 11 | { 12 | VkPipelineCache pipelineCache; // Unity's pipeline cache is serialized to disk 13 | VkInstance instance; 14 | VkPhysicalDevice physicalDevice; 15 | VkDevice device; 16 | VkQueue graphicsQueue; 17 | PFN_vkGetInstanceProcAddr getInstanceProcAddr; // vkGetInstanceProcAddr of the Vulkan loader, same as the one passed to UnityVulkanInitCallback 18 | unsigned int queueFamilyIndex; 19 | 20 | void* reserved[8]; 21 | }; 22 | 23 | struct UnityVulkanMemory 24 | { 25 | VkDeviceMemory memory; // Vulkan memory handle 26 | VkDeviceSize offset; // offset within memory 27 | VkDeviceSize size; // size in bytes, may be less than the total size of memory; 28 | void* mapped; // pointer to mapped memory block, NULL if not mappable, offset is already applied, remaining block still has at least the given size. 29 | VkMemoryPropertyFlags flags; // Vulkan memory properties 30 | unsigned int memoryTypeIndex; // index into VkPhysicalDeviceMemoryProperties::memoryTypes 31 | 32 | void* reserved[4]; 33 | }; 34 | 35 | enum UnityVulkanResourceAccessMode 36 | { 37 | // Does not imply any pipeline barriers, should only be used to query resource attributes 38 | kUnityVulkanResourceAccess_ObserveOnly, 39 | 40 | // Handles layout transition and barriers 41 | kUnityVulkanResourceAccess_PipelineBarrier, 42 | 43 | // Recreates the backing resource (VkBuffer/VkImage) but keeps the previous one alive if it's in use 44 | kUnityVulkanResourceAccess_Recreate, 45 | }; 46 | 47 | struct UnityVulkanImage 48 | { 49 | UnityVulkanMemory memory; // memory that backs the image 50 | VkImage image; // Vulkan image handle 51 | VkImageLayout layout; // current layout, may change resource access 52 | VkImageAspectFlags aspect; 53 | VkImageUsageFlags usage; 54 | VkFormat format; 55 | VkExtent3D extent; 56 | VkImageTiling tiling; 57 | VkImageType type; 58 | VkSampleCountFlagBits samples; 59 | int layers; 60 | int mipCount; 61 | 62 | void* reserved[4]; 63 | }; 64 | 65 | struct UnityVulkanBuffer 66 | { 67 | UnityVulkanMemory memory; // memory that backs the buffer 68 | VkBuffer buffer; // Vulkan buffer handle 69 | size_t sizeInBytes; // size of the buffer in bytes, may be less than memory size 70 | VkBufferUsageFlags usage; 71 | 72 | void* reserved[4]; 73 | }; 74 | 75 | struct UnityVulkanRecordingState 76 | { 77 | VkCommandBuffer commandBuffer; // Vulkan command buffer that is currently recorded by Unity 78 | VkCommandBufferLevel commandBufferLevel; 79 | VkRenderPass renderPass; // Current render pass, a compatible one or VK_NULL_HANDLE 80 | VkFramebuffer framebuffer; // Current framebuffer or VK_NULL_HANDLE 81 | int subPassIndex; // index of the current sub pass, -1 if not inside a render pass 82 | 83 | // Resource life-time tracking counters, only relevant for resources allocated by the plugin 84 | unsigned long long currentFrameNumber; // can be used to track lifetime of own resources 85 | unsigned long long safeFrameNumber; // all resources that were used in this frame (or before) are safe to be released 86 | 87 | void* reserved[4]; 88 | }; 89 | 90 | enum UnityVulkanEventRenderPassPreCondition 91 | { 92 | // Don't care about the state on Unity's current command buffer 93 | // This is the default precondition 94 | kUnityVulkanRenderPass_DontCare, 95 | 96 | // Make sure that there is currently no RenderPass in progress. 97 | // This allows e.g. resource uploads. 98 | // There are no guarantees about the currently bound descriptor sets, vertex buffers, index buffers and pipeline objects 99 | // Unity does however set dynamic pipeline set VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR based on the current settings 100 | // If used in combination with the SRP RenderPass API the resuls is undefined 101 | kUnityVulkanRenderPass_EnsureInside, 102 | 103 | // Make sure that there is currently no RenderPass in progress. 104 | // Ends the current render pass (and resumes it afterwards if needed) 105 | // If used in combination with the SRP RenderPass API the resuls is undefined. 106 | kUnityVulkanRenderPass_EnsureOutside 107 | }; 108 | 109 | enum UnityVulkanGraphicsQueueAccess 110 | { 111 | // No queue acccess, no work must be submitted to UnityVulkanInstance::graphicsQueue from the plugin event callback 112 | kUnityVulkanGraphicsQueueAccess_DontCare, 113 | 114 | // Make sure that Unity worker threads don't access the Vulkan graphics queue 115 | // This disables access to the current Unity command buffer 116 | kUnityVulkanGraphicsQueueAccess_Allow, 117 | }; 118 | 119 | enum UnityVulkanEventConfigFlagBits 120 | { 121 | kUnityVulkanEventConfigFlag_EnsurePreviousFrameSubmission = (1 << 0), // default: set 122 | kUnityVulkanEventConfigFlag_FlushCommandBuffers = (1 << 1), // submit existing command buffers, default: not set 123 | kUnityVulkanEventConfigFlag_SyncWorkerThreads = (1 << 2), // wait for worker threads to finish, default: not set 124 | kUnityVulkanEventConfigFlag_ModifiesCommandBuffersState = (1 << 3), // should be set when descriptor set bindings, vertex buffer bindings, etc are changed (default: set) 125 | }; 126 | 127 | struct UnityVulkanPluginEventConfig 128 | { 129 | UnityVulkanEventRenderPassPreCondition renderPassPrecondition; 130 | UnityVulkanGraphicsQueueAccess graphicsQueueAccess; 131 | uint32_t flags; 132 | }; 133 | 134 | // Constant that can be used to reference the whole image 135 | const VkImageSubresource* const UnityVulkanWholeImage = NULL; 136 | 137 | // callback function, see InterceptInitialization 138 | typedef PFN_vkGetInstanceProcAddr(UNITY_INTERFACE_API * UnityVulkanInitCallback)(PFN_vkGetInstanceProcAddr getInstanceProcAddr, void* userdata); 139 | 140 | enum UnityVulkanSwapchainMode 141 | { 142 | kUnityVulkanSwapchainMode_Default, 143 | kUnityVulkanSwapchainMode_Offscreen 144 | }; 145 | 146 | struct UnityVulkanSwapchainConfiguration 147 | { 148 | UnityVulkanSwapchainMode mode; 149 | }; 150 | 151 | UNITY_DECLARE_INTERFACE(IUnityGraphicsVulkan) 152 | { 153 | // Vulkan API hooks 154 | // 155 | // Must be called before kUnityGfxDeviceEventInitialize (preload plugin) 156 | // Unity will call 'func' when initializing the Vulkan API 157 | // The 'getInstanceProcAddr' passed to the callback is the function pointer from the Vulkan Loader 158 | // The function pointer returned from UnityVulkanInitCallback may be a different implementation 159 | // This allows intercepting all Vulkan API calls 160 | // 161 | // Most rules/restrictions for implementing a Vulkan layer apply 162 | // Returns true on success, false on failure (typically because it is used too late) 163 | bool(UNITY_INTERFACE_API * InterceptInitialization)(UnityVulkanInitCallback func, void* userdata); 164 | 165 | // Intercept Vulkan API function of the given name with the given function 166 | // In contrast to InterceptInitialization this interface can be used at any time 167 | // The user must handle all synchronization 168 | // Generally this cannot be used to wrap Vulkan object because there might because there may already be non-wrapped instances 169 | // returns the previous function pointer 170 | PFN_vkVoidFunction(UNITY_INTERFACE_API * InterceptVulkanAPI)(const char* name, PFN_vkVoidFunction func); 171 | 172 | // Change the precondition for a specific user-defined event 173 | // Should be called during initialization 174 | void(UNITY_INTERFACE_API * ConfigureEvent)(int eventID, const UnityVulkanPluginEventConfig * pluginEventConfig); 175 | 176 | // Access the Vulkan instance and render queue created by Unity 177 | // UnityVulkanInstance does not change between kUnityGfxDeviceEventInitialize and kUnityGfxDeviceEventShutdown 178 | UnityVulkanInstance(UNITY_INTERFACE_API * Instance)(); 179 | 180 | // Access the current command buffer 181 | // 182 | // outCommandRecordingState is invalidated by any resource access calls. 183 | // queueAccess must be kUnityVulkanGraphicsQueueAccess_Allow when called from from a AccessQueue callback or from a event that is configured for queue access. 184 | // Otherwise queueAccess must be kUnityVulkanGraphicsQueueAccess_DontCare. 185 | bool(UNITY_INTERFACE_API * CommandRecordingState)(UnityVulkanRecordingState * outCommandRecordingState, UnityVulkanGraphicsQueueAccess queueAccess); 186 | 187 | // Resource access 188 | // 189 | // Using the following resource query APIs will mark the resources as used for the current frame. 190 | // Pipeline barriers will be inserted when needed. 191 | // 192 | // Resource access APIs may record commands, so the current UnityVulkanRecordingState is invalidated 193 | // Must not be called from event callbacks configured for queue access (UnityVulkanGraphicsQueueAccess_Allow) 194 | // or from a AccessQueue callback of an event 195 | bool(UNITY_INTERFACE_API * AccessTexture)(void* nativeTexture, const VkImageSubresource * subResource, VkImageLayout layout, 196 | VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanImage * outImage); 197 | 198 | bool(UNITY_INTERFACE_API * AccessRenderBufferTexture)(UnityRenderBuffer nativeRenderBuffer, const VkImageSubresource * subResource, VkImageLayout layout, 199 | VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanImage * outImage); 200 | 201 | bool(UNITY_INTERFACE_API * AccessRenderBufferResolveTexture)(UnityRenderBuffer nativeRenderBuffer, const VkImageSubresource * subResource, VkImageLayout layout, 202 | VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanImage * outImage); 203 | 204 | bool(UNITY_INTERFACE_API * AccessBuffer)(void* nativeBuffer, VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanBuffer * outBuffer); 205 | 206 | // Control current state of render pass 207 | // 208 | // Must not be called from event callbacks configured for queue access (UnityVulkanGraphicsQueueAccess_Allow, UnityVulkanGraphicsQueueAccess_FlushAndAllow) 209 | // or from a AccessQueue callback of an event 210 | // See kUnityVulkanRenderPass_EnsureInside, kUnityVulkanRenderPass_EnsureOutside 211 | void(UNITY_INTERFACE_API * EnsureOutsideRenderPass)(); 212 | void(UNITY_INTERFACE_API * EnsureInsideRenderPass)(); 213 | 214 | // Allow command buffer submission to the the Vulkan graphics queue from the given UnityRenderingEventAndData callback. 215 | // This is an alternative to using ConfigureEvent with kUnityVulkanGraphicsQueueAccess_Allow. 216 | // 217 | // eventId and userdata are passed to the callback 218 | // This may or may not be called synchronously or from the submission thread. 219 | // If flush is true then all Unity command buffers of this frame are submitted before UnityQueueAccessCallback 220 | void(UNITY_INTERFACE_API * AccessQueue)(UnityRenderingEventAndData, int eventId, void* userData, bool flush); 221 | 222 | // Configure swapchains that are created by Unity. 223 | // Must be called before kUnityGfxDeviceEventInitialize (preload plugin) 224 | bool(UNITY_INTERFACE_API * ConfigureSwapchain)(const UnityVulkanSwapchainConfiguration * swapChainConfig); 225 | }; 226 | UNITY_REGISTER_INTERFACE_GUID(0x95355348d4ef4e11ULL, 0x9789313dfcffcc87ULL, IUnityGraphicsVulkan) 227 | -------------------------------------------------------------------------------- /NativePlugin/src/Unity/IUnityInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Unity native plugin API 4 | // Compatible with C99 5 | 6 | #if defined(__CYGWIN32__) 7 | #define UNITY_INTERFACE_API __stdcall 8 | #define UNITY_INTERFACE_EXPORT __declspec(dllexport) 9 | #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(WINAPI_FAMILY) 10 | #define UNITY_INTERFACE_API __stdcall 11 | #define UNITY_INTERFACE_EXPORT __declspec(dllexport) 12 | #elif defined(__MACH__) || defined(__ANDROID__) || defined(__linux__) 13 | #define UNITY_INTERFACE_API 14 | #define UNITY_INTERFACE_EXPORT 15 | #else 16 | #define UNITY_INTERFACE_API 17 | #define UNITY_INTERFACE_EXPORT 18 | #endif 19 | 20 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 | // IUnityInterface is a registry of interfaces we choose to expose to plugins. 22 | // 23 | // USAGE: 24 | // --------- 25 | // To retrieve an interface a user can do the following from a plugin, assuming they have the header file for the interface: 26 | // 27 | // IMyInterface * ptr = registry->Get(); 28 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | 30 | // Unity Interface GUID 31 | // Ensures global uniqueness. 32 | // 33 | // Template specialization is used to produce a means of looking up a GUID from its interface type at compile time. 34 | // The net result should compile down to passing around the GUID. 35 | // 36 | // UNITY_REGISTER_INTERFACE_GUID should be placed in the header file of any interface definition outside of all namespaces. 37 | // The interface structure and the registration GUID are all that is required to expose the interface to other systems. 38 | struct UnityInterfaceGUID 39 | { 40 | #ifdef __cplusplus 41 | UnityInterfaceGUID(unsigned long long high, unsigned long long low) 42 | : m_GUIDHigh(high) 43 | , m_GUIDLow(low) 44 | { 45 | } 46 | 47 | UnityInterfaceGUID(const UnityInterfaceGUID& other) 48 | { 49 | m_GUIDHigh = other.m_GUIDHigh; 50 | m_GUIDLow = other.m_GUIDLow; 51 | } 52 | 53 | UnityInterfaceGUID& operator=(const UnityInterfaceGUID& other) 54 | { 55 | m_GUIDHigh = other.m_GUIDHigh; 56 | m_GUIDLow = other.m_GUIDLow; 57 | return *this; 58 | } 59 | 60 | bool Equals(const UnityInterfaceGUID& other) const { return m_GUIDHigh == other.m_GUIDHigh && m_GUIDLow == other.m_GUIDLow; } 61 | bool LessThan(const UnityInterfaceGUID& other) const { return m_GUIDHigh < other.m_GUIDHigh || (m_GUIDHigh == other.m_GUIDHigh && m_GUIDLow < other.m_GUIDLow); } 62 | #endif 63 | unsigned long long m_GUIDHigh; 64 | unsigned long long m_GUIDLow; 65 | }; 66 | #ifdef __cplusplus 67 | inline bool operator==(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return left.Equals(right); } 68 | inline bool operator!=(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return !left.Equals(right); } 69 | inline bool operator<(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return left.LessThan(right); } 70 | inline bool operator>(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return right.LessThan(left); } 71 | inline bool operator>=(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return !operator<(left, right); } 72 | inline bool operator<=(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return !operator>(left, right); } 73 | #else 74 | typedef struct UnityInterfaceGUID UnityInterfaceGUID; 75 | #endif 76 | 77 | 78 | #ifdef __cplusplus 79 | #define UNITY_DECLARE_INTERFACE(NAME) \ 80 | struct NAME : IUnityInterface 81 | 82 | // Generic version of GetUnityInterfaceGUID to allow us to specialize it 83 | // per interface below. The generic version has no actual implementation 84 | // on purpose. 85 | // 86 | // If you get errors about return values related to this method then 87 | // you have forgotten to include UNITY_REGISTER_INTERFACE_GUID with 88 | // your interface, or it is not visible at some point when you are 89 | // trying to retrieve or add an interface. 90 | template 91 | inline const UnityInterfaceGUID GetUnityInterfaceGUID(); 92 | 93 | // This is the macro you provide in your public interface header 94 | // outside of a namespace to allow us to map between type and GUID 95 | // without the user having to worry about it when attempting to 96 | // add or retrieve and interface from the registry. 97 | #define UNITY_REGISTER_INTERFACE_GUID(HASHH, HASHL, TYPE) \ 98 | template<> \ 99 | inline const UnityInterfaceGUID GetUnityInterfaceGUID() \ 100 | { \ 101 | return UnityInterfaceGUID(HASHH,HASHL); \ 102 | } 103 | 104 | // Same as UNITY_REGISTER_INTERFACE_GUID but allows the interface to live in 105 | // a particular namespace. As long as the namespace is visible at the time you call 106 | // GetUnityInterfaceGUID< INTERFACETYPE >() or you explicitly qualify it in the template 107 | // calls this will work fine, only the macro here needs to have the additional parameter 108 | #define UNITY_REGISTER_INTERFACE_GUID_IN_NAMESPACE(HASHH, HASHL, TYPE, NAMESPACE) \ 109 | const UnityInterfaceGUID TYPE##_GUID(HASHH, HASHL); \ 110 | template<> \ 111 | inline const UnityInterfaceGUID GetUnityInterfaceGUID< NAMESPACE :: TYPE >() \ 112 | { \ 113 | return UnityInterfaceGUID(HASHH,HASHL); \ 114 | } 115 | 116 | // These macros allow for C compatibility in user code. 117 | #define UNITY_GET_INTERFACE_GUID(TYPE) GetUnityInterfaceGUID< TYPE >() 118 | 119 | 120 | #else 121 | #define UNITY_DECLARE_INTERFACE(NAME) \ 122 | typedef struct NAME NAME; \ 123 | struct NAME 124 | 125 | // NOTE: This has the downside that one some compilers it will not get stripped from all compilation units that 126 | // can see a header containing this constant. However, it's only for C compatibility and thus should have 127 | // minimal impact. 128 | #define UNITY_REGISTER_INTERFACE_GUID(HASHH, HASHL, TYPE) \ 129 | const UnityInterfaceGUID TYPE##_GUID = {HASHH, HASHL}; 130 | 131 | // In general namespaces are going to be a problem for C code any interfaces we expose in a namespace are 132 | // not going to be usable from C. 133 | #define UNITY_REGISTER_INTERFACE_GUID_IN_NAMESPACE(HASHH, HASHL, TYPE, NAMESPACE) 134 | 135 | // These macros allow for C compatibility in user code. 136 | #define UNITY_GET_INTERFACE_GUID(TYPE) TYPE##_GUID 137 | #endif 138 | 139 | // Using this in user code rather than INTERFACES->Get() will be C compatible for those places in plugins where 140 | // this may be needed. Unity code itself does not need this. 141 | #define UNITY_GET_INTERFACE(INTERFACES, TYPE) (TYPE*)INTERFACES->GetInterfaceSplit (UNITY_GET_INTERFACE_GUID(TYPE).m_GUIDHigh, UNITY_GET_INTERFACE_GUID(TYPE).m_GUIDLow); 142 | 143 | 144 | #ifdef __cplusplus 145 | struct IUnityInterface 146 | { 147 | }; 148 | #else 149 | typedef void IUnityInterface; 150 | #endif 151 | 152 | 153 | typedef struct IUnityInterfaces 154 | { 155 | // Returns an interface matching the guid. 156 | // Returns nullptr if the given interface is unavailable in the active Unity runtime. 157 | IUnityInterface* (UNITY_INTERFACE_API * GetInterface)(UnityInterfaceGUID guid); 158 | 159 | // Registers a new interface. 160 | void(UNITY_INTERFACE_API * RegisterInterface)(UnityInterfaceGUID guid, IUnityInterface * ptr); 161 | 162 | // Split APIs for C 163 | IUnityInterface* (UNITY_INTERFACE_API * GetInterfaceSplit)(unsigned long long guidHigh, unsigned long long guidLow); 164 | void(UNITY_INTERFACE_API * RegisterInterfaceSplit)(unsigned long long guidHigh, unsigned long long guidLow, IUnityInterface * ptr); 165 | 166 | #ifdef __cplusplus 167 | // Helper for GetInterface. 168 | template 169 | INTERFACE* Get() 170 | { 171 | return static_cast(GetInterface(GetUnityInterfaceGUID())); 172 | } 173 | 174 | // Helper for RegisterInterface. 175 | template 176 | void Register(IUnityInterface* ptr) 177 | { 178 | RegisterInterface(GetUnityInterfaceGUID(), ptr); 179 | } 180 | 181 | #endif 182 | } IUnityInterfaces; 183 | 184 | 185 | #ifdef __cplusplus 186 | extern "C" { 187 | #endif 188 | 189 | // If exported by a plugin, this function will be called when the plugin is loaded. 190 | void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces); 191 | // If exported by a plugin, this function will be called when the plugin is about to be unloaded. 192 | void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload(); 193 | 194 | #ifdef __cplusplus 195 | } 196 | #endif 197 | 198 | struct RenderSurfaceBase; 199 | typedef struct RenderSurfaceBase* UnityRenderBuffer; 200 | typedef unsigned int UnityTextureID; 201 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # AsyncGPUReadbackPlugin 3 | This repo is heavily based on [Alabate's great work](https://github.com/Alabate/AsyncGPUReadbackPlugin), also added function to read compute buffer. The api is sligtly changed from original repo, to make it easier to use. The native code has been refactored to be more safe. Since I can't reach to Alabate, so I create this new repo to add more functionality. 4 | 5 | On Unity 2018.2 was introduced a really neat feature: being able get a frame from the gpu to the cpu without blocking the rendering. This feature is really useful for screenshot or network stream of a game camera because we need the frame on the cpu, but we don't care if there is a little delay. 6 | 7 | However this feature is only available on platform supporting DirectX (Windows) and Metal (Apple), but not OpenGL and it's not planned. (source: https://forum.unity.com/threads/graphics-asynchronous-gpu-readback-api.529901/#post-3487735). 8 | 9 | This plugin aims to provide this feature for OpenGL platform. It tries to match the official AsyncGPUReadback as closes as possible to let you easily switch between the plugin or the official API. Under the hood, it use the official API if available on the current platform. 10 | 11 | The native code has been tested to compile on g++ 5.4.0 and vs2015. 12 | 13 | ## Use it 14 | ### Install 15 | Copy plugin folder at `UnityExampleProject\Assets\Plugins` to your project. It contains both Windows and Linux native libraries for use. 16 | 17 | Copy `UnityExampleProject\Assets\OpenglAsyncReadback` to anywhere in your project. It contains C# code as interface of native code. 18 | 19 | ### The API 20 | All C# apis are inside namespace Yangrc.OpenGLAsyncReadback. 21 | 22 | To start a readback, use `UniversalAsyncGPUReadbackRequest UniversalAsyncGPUReadbackRequest.Request(Texture tex)`. This function returns "universal" object, which means it could be a Unity's standard readback request, or a OpenGL request if under opengl environment. After that, it will automatically update during every frame(You don't have to manually call Update(), there's a global dontdestroyonload gameobject doing this). 23 | 24 | Once the request is started, you should check if it's done by `request.done` in update every frame. If it returns true, call `request.hasError` to check if any error exists. If no error, call `request.GetData` to get result data in `NativeArray`. 25 | 26 | The done status will only be valid for one frame, then everything is automatically disposed. So once it's done, copy the data to your own storage ASAP. 27 | 28 | ### Example 29 | To see a working example you can open `UnityExampleProject` with the Unity editor. It saves screenshot of the camera every 60 frames. The script taking screenshot is in `UnityExampleProject/Assets/OpenglAsyncReadback/Scripts/UsePlugin.cs` 30 | 31 | ## Build Native Plugin 32 | To build native plugin, you need to have cmake installed. If you have it, just go to NativePlugin/ folder and use cmake to build it. There's no other dependencies except OpenGL library(The glew library is staticlly linked using source code), which should always be available. 33 | 34 | ## Troubleshoots 35 | 36 | ### The type or namespace name 'AsyncGPUReadbackPluginNs' could not be found. Are you missing an assembly reference? 37 | If you click on `AsyncGPUReadbackPlugin.dll` under Unity Editor, you will see 38 | 39 | ``` 40 | Plugin targets .NET 4.x and is marked as compatible with Editor, Editor can only use assemblies targeting .NET 3.5 or lower, please unselect Editor as compatible platform 41 | ``` 42 | 43 | In this case a solution is to change you runtime version in: 44 | 45 | ``` 46 | Editor > Project Settings > Player > Other Settings > Scripting Runtime Version : Set it to '.NET 4.x Equivalent'. 47 | ``` 48 | 49 | ### Other 50 | There's lots of buffer/texture format/type in Unity, and I can't have them all tested. If you encounter any problem, feel free to create an new issue. 51 | 52 | ## Thanks 53 | Again, thanks to [Alabate's great work](https://github.com/Alabate/AsyncGPUReadbackPlugin). It's his/her work that I learnt it's possible to do async readback under opengl. 54 | 55 | # Changelog 56 | 2020-03-01 Remove ReadbackStarter class, it's not needed anymore. -------------------------------------------------------------------------------- /UnityExampleProject/.gitignore: -------------------------------------------------------------------------------- 1 | [Ll]ibrary/ 2 | [Tt]emp/ 3 | [Oo]bj/ 4 | [Bb]uild/ 5 | [Bb]uilds/ 6 | Assets/AssetStoreTools* 7 | 8 | # Visual Studio cache directory 9 | .vs/ 10 | 11 | # Autogenerated VS/MD/Consulo solution and project files 12 | ExportedObj/ 13 | .consulo/ 14 | *.csproj 15 | *.unityproj 16 | *.sln 17 | *.suo 18 | *.tmp 19 | *.user 20 | *.userprefs 21 | *.pidb 22 | *.booproj 23 | *.svd 24 | *.pdb 25 | *.opendb 26 | *.VC.db 27 | 28 | # Unity3D generated meta files 29 | *.pidb.meta 30 | *.pdb.meta 31 | 32 | # Unity3D Generated File On Crash Reports 33 | sysinfo.txt 34 | 35 | # Builds 36 | *.apk 37 | *.unitypackage 38 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: acf68c5db65e0b145b45870c251e039e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/ExampleScenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4f704ae4b4f98ae41a0bce26658850c1 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/ExampleScenes/ComputeBufferTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using Unity.Collections; 5 | 6 | namespace Yangrc.OpenGLAsyncReadback { 7 | public class ComputeBufferTest : MonoBehaviour { 8 | NativeArray test; 9 | ComputeBuffer t; 10 | UniversalAsyncGPUReadbackRequest request; 11 | // Start is called before the first frame update 12 | 13 | IEnumerator Start() { 14 | t = new ComputeBuffer(100, 4, ComputeBufferType.Default); 15 | var tempList = new List(); 16 | for (int i = 0; i < 100; i++) { 17 | tempList.Add(i); 18 | } 19 | t.SetData(tempList); 20 | yield return null; 21 | request = UniversalAsyncGPUReadbackRequest.Request(t); 22 | t.Dispose(); 23 | } 24 | 25 | private void Update() { 26 | if (request.valid) { 27 | if (request.done) { 28 | test = request.GetData(); 29 | foreach (var item in test) { 30 | Debug.Log(item); 31 | } 32 | } 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/ExampleScenes/ComputeBufferTest.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c923305fc710d054487d9332fae54667 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/ExampleScenes/Scene.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 9 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 0} 41 | m_IndirectSpecularColor: {r: 0.45019424, g: 0.50023425, b: 0.57540494, a: 1} 42 | m_UseRadianceAmbientProbe: 0 43 | --- !u!157 &3 44 | LightmapSettings: 45 | m_ObjectHideFlags: 0 46 | serializedVersion: 11 47 | m_GIWorkflowMode: 0 48 | m_GISettings: 49 | serializedVersion: 2 50 | m_BounceScale: 1 51 | m_IndirectOutputScale: 1 52 | m_AlbedoBoost: 1 53 | m_EnvironmentLightingMode: 0 54 | m_EnableBakedLightmaps: 1 55 | m_EnableRealtimeLightmaps: 0 56 | m_LightmapEditorSettings: 57 | serializedVersion: 10 58 | m_Resolution: 2 59 | m_BakeResolution: 10 60 | m_AtlasSize: 512 61 | m_AO: 0 62 | m_AOMaxDistance: 1 63 | m_CompAOExponent: 1 64 | m_CompAOExponentDirect: 0 65 | m_Padding: 2 66 | m_LightmapParameters: {fileID: 0} 67 | m_LightmapsBakeMode: 1 68 | m_TextureCompression: 1 69 | m_FinalGather: 0 70 | m_FinalGatherFiltering: 1 71 | m_FinalGatherRayCount: 256 72 | m_ReflectionCompression: 2 73 | m_MixedBakeMode: 2 74 | m_BakeBackend: 1 75 | m_PVRSampling: 1 76 | m_PVRDirectSampleCount: 32 77 | m_PVRSampleCount: 256 78 | m_PVRBounces: 2 79 | m_PVRFilterTypeDirect: 0 80 | m_PVRFilterTypeIndirect: 0 81 | m_PVRFilterTypeAO: 0 82 | m_PVRFilteringMode: 1 83 | m_PVRCulling: 1 84 | m_PVRFilteringGaussRadiusDirect: 1 85 | m_PVRFilteringGaussRadiusIndirect: 5 86 | m_PVRFilteringGaussRadiusAO: 2 87 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 88 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 89 | m_PVRFilteringAtrousPositionSigmaAO: 1 90 | m_ShowResolutionOverlay: 1 91 | m_LightingDataAsset: {fileID: 0} 92 | m_UseShadowmask: 1 93 | --- !u!196 &4 94 | NavMeshSettings: 95 | serializedVersion: 2 96 | m_ObjectHideFlags: 0 97 | m_BuildSettings: 98 | serializedVersion: 2 99 | agentTypeID: 0 100 | agentRadius: 0.5 101 | agentHeight: 2 102 | agentSlope: 45 103 | agentClimb: 0.4 104 | ledgeDropHeight: 0 105 | maxJumpAcrossDistance: 0 106 | minRegionArea: 2 107 | manualCellSize: 0 108 | cellSize: 0.16666667 109 | manualTileSize: 0 110 | tileSize: 256 111 | accuratePlacement: 0 112 | debug: 113 | m_Flags: 0 114 | m_NavMeshData: {fileID: 0} 115 | --- !u!1 &20561885 116 | GameObject: 117 | m_ObjectHideFlags: 0 118 | m_CorrespondingSourceObject: {fileID: 0} 119 | m_PrefabInstance: {fileID: 0} 120 | m_PrefabAsset: {fileID: 0} 121 | serializedVersion: 6 122 | m_Component: 123 | - component: {fileID: 20561886} 124 | - component: {fileID: 20561889} 125 | - component: {fileID: 20561888} 126 | - component: {fileID: 20561887} 127 | m_Layer: 0 128 | m_Name: Cube R 129 | m_TagString: Untagged 130 | m_Icon: {fileID: 0} 131 | m_NavMeshLayer: 0 132 | m_StaticEditorFlags: 0 133 | m_IsActive: 1 134 | --- !u!4 &20561886 135 | Transform: 136 | m_ObjectHideFlags: 0 137 | m_CorrespondingSourceObject: {fileID: 0} 138 | m_PrefabInstance: {fileID: 0} 139 | m_PrefabAsset: {fileID: 0} 140 | m_GameObject: {fileID: 20561885} 141 | m_LocalRotation: {x: -0.083019085, y: 0.7004615, z: 0.11833734, w: 0.69889754} 142 | m_LocalPosition: {x: 5.062609, y: 4.564308, z: -1.4620893} 143 | m_LocalScale: {x: 1, y: 1, z: 1} 144 | m_Children: [] 145 | m_Father: {fileID: 0} 146 | m_RootOrder: 2 147 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 148 | --- !u!65 &20561887 149 | BoxCollider: 150 | m_ObjectHideFlags: 0 151 | m_CorrespondingSourceObject: {fileID: 0} 152 | m_PrefabInstance: {fileID: 0} 153 | m_PrefabAsset: {fileID: 0} 154 | m_GameObject: {fileID: 20561885} 155 | m_Material: {fileID: 0} 156 | m_IsTrigger: 0 157 | m_Enabled: 1 158 | serializedVersion: 2 159 | m_Size: {x: 1, y: 1, z: 1} 160 | m_Center: {x: 0, y: 0, z: 0} 161 | --- !u!23 &20561888 162 | MeshRenderer: 163 | m_ObjectHideFlags: 0 164 | m_CorrespondingSourceObject: {fileID: 0} 165 | m_PrefabInstance: {fileID: 0} 166 | m_PrefabAsset: {fileID: 0} 167 | m_GameObject: {fileID: 20561885} 168 | m_Enabled: 1 169 | m_CastShadows: 1 170 | m_ReceiveShadows: 1 171 | m_DynamicOccludee: 1 172 | m_MotionVectors: 1 173 | m_LightProbeUsage: 1 174 | m_ReflectionProbeUsage: 1 175 | m_RenderingLayerMask: 4294967295 176 | m_RendererPriority: 0 177 | m_Materials: 178 | - {fileID: 2100000, guid: e996f5cabfdfd4f53b5edf237286723f, type: 2} 179 | m_StaticBatchInfo: 180 | firstSubMesh: 0 181 | subMeshCount: 0 182 | m_StaticBatchRoot: {fileID: 0} 183 | m_ProbeAnchor: {fileID: 0} 184 | m_LightProbeVolumeOverride: {fileID: 0} 185 | m_ScaleInLightmap: 1 186 | m_PreserveUVs: 0 187 | m_IgnoreNormalsForChartDetection: 0 188 | m_ImportantGI: 0 189 | m_StitchLightmapSeams: 0 190 | m_SelectedEditorRenderState: 3 191 | m_MinimumChartSize: 4 192 | m_AutoUVMaxDistance: 0.5 193 | m_AutoUVMaxAngle: 89 194 | m_LightmapParameters: {fileID: 0} 195 | m_SortingLayerID: 0 196 | m_SortingLayer: 0 197 | m_SortingOrder: 0 198 | --- !u!33 &20561889 199 | MeshFilter: 200 | m_ObjectHideFlags: 0 201 | m_CorrespondingSourceObject: {fileID: 0} 202 | m_PrefabInstance: {fileID: 0} 203 | m_PrefabAsset: {fileID: 0} 204 | m_GameObject: {fileID: 20561885} 205 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 206 | --- !u!1 &170076733 207 | GameObject: 208 | m_ObjectHideFlags: 0 209 | m_CorrespondingSourceObject: {fileID: 0} 210 | m_PrefabInstance: {fileID: 0} 211 | m_PrefabAsset: {fileID: 0} 212 | serializedVersion: 6 213 | m_Component: 214 | - component: {fileID: 170076735} 215 | - component: {fileID: 170076734} 216 | m_Layer: 0 217 | m_Name: Directional Light 218 | m_TagString: Untagged 219 | m_Icon: {fileID: 0} 220 | m_NavMeshLayer: 0 221 | m_StaticEditorFlags: 0 222 | m_IsActive: 1 223 | --- !u!108 &170076734 224 | Light: 225 | m_ObjectHideFlags: 0 226 | m_CorrespondingSourceObject: {fileID: 0} 227 | m_PrefabInstance: {fileID: 0} 228 | m_PrefabAsset: {fileID: 0} 229 | m_GameObject: {fileID: 170076733} 230 | m_Enabled: 1 231 | serializedVersion: 8 232 | m_Type: 1 233 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 234 | m_Intensity: 1 235 | m_Range: 10 236 | m_SpotAngle: 30 237 | m_CookieSize: 10 238 | m_Shadows: 239 | m_Type: 2 240 | m_Resolution: -1 241 | m_CustomResolution: -1 242 | m_Strength: 1 243 | m_Bias: 0.05 244 | m_NormalBias: 0.4 245 | m_NearPlane: 0.2 246 | m_Cookie: {fileID: 0} 247 | m_DrawHalo: 0 248 | m_Flare: {fileID: 0} 249 | m_RenderMode: 0 250 | m_CullingMask: 251 | serializedVersion: 2 252 | m_Bits: 4294967295 253 | m_Lightmapping: 1 254 | m_LightShadowCasterMode: 0 255 | m_AreaSize: {x: 1, y: 1} 256 | m_BounceIntensity: 1 257 | m_ColorTemperature: 6570 258 | m_UseColorTemperature: 0 259 | m_ShadowRadius: 0 260 | m_ShadowAngle: 0 261 | --- !u!4 &170076735 262 | Transform: 263 | m_ObjectHideFlags: 0 264 | m_CorrespondingSourceObject: {fileID: 0} 265 | m_PrefabInstance: {fileID: 0} 266 | m_PrefabAsset: {fileID: 0} 267 | m_GameObject: {fileID: 170076733} 268 | m_LocalRotation: {x: 0.42194957, y: -0.4965706, z: -0.023763597, w: 0.7581632} 269 | m_LocalPosition: {x: 10.4, y: 11.29, z: -2.03} 270 | m_LocalScale: {x: 1, y: 1, z: 1} 271 | m_Children: [] 272 | m_Father: {fileID: 0} 273 | m_RootOrder: 0 274 | m_LocalEulerAnglesHint: {x: 38.04, y: -78.965004, z: -35.298} 275 | --- !u!1 &544430954 276 | GameObject: 277 | m_ObjectHideFlags: 0 278 | m_CorrespondingSourceObject: {fileID: 0} 279 | m_PrefabInstance: {fileID: 0} 280 | m_PrefabAsset: {fileID: 0} 281 | serializedVersion: 6 282 | m_Component: 283 | - component: {fileID: 544430955} 284 | - component: {fileID: 544430957} 285 | - component: {fileID: 544430956} 286 | - component: {fileID: 544430958} 287 | m_Layer: 0 288 | m_Name: Camera 289 | m_TagString: Untagged 290 | m_Icon: {fileID: 0} 291 | m_NavMeshLayer: 0 292 | m_StaticEditorFlags: 0 293 | m_IsActive: 1 294 | --- !u!4 &544430955 295 | Transform: 296 | m_ObjectHideFlags: 0 297 | m_CorrespondingSourceObject: {fileID: 0} 298 | m_PrefabInstance: {fileID: 0} 299 | m_PrefabAsset: {fileID: 0} 300 | m_GameObject: {fileID: 544430954} 301 | m_LocalRotation: {x: -0.6435459, y: -0.35615987, z: 0.60144454, w: -0.31187057} 302 | m_LocalPosition: {x: 7.3796563, y: 7.709575, z: 0.3250594} 303 | m_LocalScale: {x: 1, y: 1, z: 1} 304 | m_Children: [] 305 | m_Father: {fileID: 0} 306 | m_RootOrder: 1 307 | m_LocalEulerAnglesHint: {x: -217.368, y: 0.10699463, z: -1.5759888} 308 | --- !u!114 &544430956 309 | MonoBehaviour: 310 | m_ObjectHideFlags: 0 311 | m_CorrespondingSourceObject: {fileID: 0} 312 | m_PrefabInstance: {fileID: 0} 313 | m_PrefabAsset: {fileID: 0} 314 | m_GameObject: {fileID: 544430954} 315 | m_Enabled: 1 316 | m_EditorHideFlags: 0 317 | m_Script: {fileID: 11500000, guid: 47db193163fd0473a9d3662fc2bbd11b, type: 3} 318 | m_Name: 319 | m_EditorClassIdentifier: 320 | --- !u!20 &544430957 321 | Camera: 322 | m_ObjectHideFlags: 0 323 | m_CorrespondingSourceObject: {fileID: 0} 324 | m_PrefabInstance: {fileID: 0} 325 | m_PrefabAsset: {fileID: 0} 326 | m_GameObject: {fileID: 544430954} 327 | m_Enabled: 1 328 | serializedVersion: 2 329 | m_ClearFlags: 1 330 | m_BackGroundColor: {r: 0.5137255, g: 0.2, b: 0.03137255, a: 0} 331 | m_projectionMatrixMode: 1 332 | m_SensorSize: {x: 36, y: 24} 333 | m_LensShift: {x: 0, y: 0} 334 | m_GateFitMode: 2 335 | m_FocalLength: 50 336 | m_NormalizedViewPortRect: 337 | serializedVersion: 2 338 | x: 0 339 | y: 0 340 | width: 1 341 | height: 1 342 | near clip plane: 0.3 343 | far clip plane: 10 344 | field of view: 31.8 345 | orthographic: 0 346 | orthographic size: 5 347 | m_Depth: 0 348 | m_CullingMask: 349 | serializedVersion: 2 350 | m_Bits: 4294967295 351 | m_RenderingPath: -1 352 | m_TargetTexture: {fileID: 0} 353 | m_TargetDisplay: 0 354 | m_TargetEye: 3 355 | m_HDR: 1 356 | m_AllowMSAA: 1 357 | m_AllowDynamicResolution: 0 358 | m_ForceIntoRT: 0 359 | m_OcclusionCulling: 1 360 | m_StereoConvergence: 10 361 | m_StereoSeparation: 0.022 362 | --- !u!114 &544430958 363 | MonoBehaviour: 364 | m_ObjectHideFlags: 0 365 | m_CorrespondingSourceObject: {fileID: 0} 366 | m_PrefabInstance: {fileID: 0} 367 | m_PrefabAsset: {fileID: 0} 368 | m_GameObject: {fileID: 544430954} 369 | m_Enabled: 0 370 | m_EditorHideFlags: 0 371 | m_Script: {fileID: 11500000, guid: c923305fc710d054487d9332fae54667, type: 3} 372 | m_Name: 373 | m_EditorClassIdentifier: 374 | --- !u!1 &1657501090 375 | GameObject: 376 | m_ObjectHideFlags: 0 377 | m_CorrespondingSourceObject: {fileID: 0} 378 | m_PrefabInstance: {fileID: 0} 379 | m_PrefabAsset: {fileID: 0} 380 | serializedVersion: 6 381 | m_Component: 382 | - component: {fileID: 1657501091} 383 | - component: {fileID: 1657501094} 384 | - component: {fileID: 1657501093} 385 | - component: {fileID: 1657501092} 386 | m_Layer: 0 387 | m_Name: Cube G 388 | m_TagString: Untagged 389 | m_Icon: {fileID: 0} 390 | m_NavMeshLayer: 0 391 | m_StaticEditorFlags: 0 392 | m_IsActive: 1 393 | --- !u!4 &1657501091 394 | Transform: 395 | m_ObjectHideFlags: 0 396 | m_CorrespondingSourceObject: {fileID: 0} 397 | m_PrefabInstance: {fileID: 0} 398 | m_PrefabAsset: {fileID: 0} 399 | m_GameObject: {fileID: 1657501090} 400 | m_LocalRotation: {x: -0.083019085, y: 0.7004615, z: 0.11833734, w: 0.69889754} 401 | m_LocalPosition: {x: 5.1004524, y: 4.498183, z: 0.026172161} 402 | m_LocalScale: {x: 1, y: 1, z: 1} 403 | m_Children: [] 404 | m_Father: {fileID: 0} 405 | m_RootOrder: 3 406 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 407 | --- !u!65 &1657501092 408 | BoxCollider: 409 | m_ObjectHideFlags: 0 410 | m_CorrespondingSourceObject: {fileID: 0} 411 | m_PrefabInstance: {fileID: 0} 412 | m_PrefabAsset: {fileID: 0} 413 | m_GameObject: {fileID: 1657501090} 414 | m_Material: {fileID: 0} 415 | m_IsTrigger: 0 416 | m_Enabled: 1 417 | serializedVersion: 2 418 | m_Size: {x: 1, y: 1, z: 1} 419 | m_Center: {x: 0, y: 0, z: 0} 420 | --- !u!23 &1657501093 421 | MeshRenderer: 422 | m_ObjectHideFlags: 0 423 | m_CorrespondingSourceObject: {fileID: 0} 424 | m_PrefabInstance: {fileID: 0} 425 | m_PrefabAsset: {fileID: 0} 426 | m_GameObject: {fileID: 1657501090} 427 | m_Enabled: 1 428 | m_CastShadows: 1 429 | m_ReceiveShadows: 1 430 | m_DynamicOccludee: 1 431 | m_MotionVectors: 1 432 | m_LightProbeUsage: 1 433 | m_ReflectionProbeUsage: 1 434 | m_RenderingLayerMask: 4294967295 435 | m_RendererPriority: 0 436 | m_Materials: 437 | - {fileID: 2100000, guid: 78036511e4c0b4f2c9c93a1edf0499f4, type: 2} 438 | m_StaticBatchInfo: 439 | firstSubMesh: 0 440 | subMeshCount: 0 441 | m_StaticBatchRoot: {fileID: 0} 442 | m_ProbeAnchor: {fileID: 0} 443 | m_LightProbeVolumeOverride: {fileID: 0} 444 | m_ScaleInLightmap: 1 445 | m_PreserveUVs: 0 446 | m_IgnoreNormalsForChartDetection: 0 447 | m_ImportantGI: 0 448 | m_StitchLightmapSeams: 0 449 | m_SelectedEditorRenderState: 3 450 | m_MinimumChartSize: 4 451 | m_AutoUVMaxDistance: 0.5 452 | m_AutoUVMaxAngle: 89 453 | m_LightmapParameters: {fileID: 0} 454 | m_SortingLayerID: 0 455 | m_SortingLayer: 0 456 | m_SortingOrder: 0 457 | --- !u!33 &1657501094 458 | MeshFilter: 459 | m_ObjectHideFlags: 0 460 | m_CorrespondingSourceObject: {fileID: 0} 461 | m_PrefabInstance: {fileID: 0} 462 | m_PrefabAsset: {fileID: 0} 463 | m_GameObject: {fileID: 1657501090} 464 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 465 | --- !u!1 &1667460925 466 | GameObject: 467 | m_ObjectHideFlags: 0 468 | m_CorrespondingSourceObject: {fileID: 0} 469 | m_PrefabInstance: {fileID: 0} 470 | m_PrefabAsset: {fileID: 0} 471 | serializedVersion: 6 472 | m_Component: 473 | - component: {fileID: 1667460926} 474 | - component: {fileID: 1667460929} 475 | - component: {fileID: 1667460928} 476 | - component: {fileID: 1667460927} 477 | m_Layer: 0 478 | m_Name: Cube B 479 | m_TagString: Untagged 480 | m_Icon: {fileID: 0} 481 | m_NavMeshLayer: 0 482 | m_StaticEditorFlags: 0 483 | m_IsActive: 1 484 | --- !u!4 &1667460926 485 | Transform: 486 | m_ObjectHideFlags: 0 487 | m_CorrespondingSourceObject: {fileID: 0} 488 | m_PrefabInstance: {fileID: 0} 489 | m_PrefabAsset: {fileID: 0} 490 | m_GameObject: {fileID: 1667460925} 491 | m_LocalRotation: {x: -0.083019085, y: 0.7004615, z: 0.11833734, w: 0.69889754} 492 | m_LocalPosition: {x: 5.112514, y: 2.56, z: 2.18} 493 | m_LocalScale: {x: 1, y: 1, z: 1} 494 | m_Children: [] 495 | m_Father: {fileID: 0} 496 | m_RootOrder: 4 497 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 498 | --- !u!65 &1667460927 499 | BoxCollider: 500 | m_ObjectHideFlags: 0 501 | m_CorrespondingSourceObject: {fileID: 0} 502 | m_PrefabInstance: {fileID: 0} 503 | m_PrefabAsset: {fileID: 0} 504 | m_GameObject: {fileID: 1667460925} 505 | m_Material: {fileID: 0} 506 | m_IsTrigger: 0 507 | m_Enabled: 1 508 | serializedVersion: 2 509 | m_Size: {x: 1, y: 1, z: 1} 510 | m_Center: {x: 0, y: 0, z: 0} 511 | --- !u!23 &1667460928 512 | MeshRenderer: 513 | m_ObjectHideFlags: 0 514 | m_CorrespondingSourceObject: {fileID: 0} 515 | m_PrefabInstance: {fileID: 0} 516 | m_PrefabAsset: {fileID: 0} 517 | m_GameObject: {fileID: 1667460925} 518 | m_Enabled: 1 519 | m_CastShadows: 1 520 | m_ReceiveShadows: 1 521 | m_DynamicOccludee: 1 522 | m_MotionVectors: 1 523 | m_LightProbeUsage: 1 524 | m_ReflectionProbeUsage: 1 525 | m_RenderingLayerMask: 4294967295 526 | m_RendererPriority: 0 527 | m_Materials: 528 | - {fileID: 2100000, guid: f83eee9781cd14c97918bf5f362beb27, type: 2} 529 | m_StaticBatchInfo: 530 | firstSubMesh: 0 531 | subMeshCount: 0 532 | m_StaticBatchRoot: {fileID: 0} 533 | m_ProbeAnchor: {fileID: 0} 534 | m_LightProbeVolumeOverride: {fileID: 0} 535 | m_ScaleInLightmap: 1 536 | m_PreserveUVs: 0 537 | m_IgnoreNormalsForChartDetection: 0 538 | m_ImportantGI: 0 539 | m_StitchLightmapSeams: 0 540 | m_SelectedEditorRenderState: 3 541 | m_MinimumChartSize: 4 542 | m_AutoUVMaxDistance: 0.5 543 | m_AutoUVMaxAngle: 89 544 | m_LightmapParameters: {fileID: 0} 545 | m_SortingLayerID: 0 546 | m_SortingLayer: 0 547 | m_SortingOrder: 0 548 | --- !u!33 &1667460929 549 | MeshFilter: 550 | m_ObjectHideFlags: 0 551 | m_CorrespondingSourceObject: {fileID: 0} 552 | m_PrefabInstance: {fileID: 0} 553 | m_PrefabAsset: {fileID: 0} 554 | m_GameObject: {fileID: 1667460925} 555 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 556 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/ExampleScenes/Scene.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bb509b92e73fe4439839f06c1aec0245 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/ExampleScenes/UsePlugin.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System; 5 | using System.Runtime.InteropServices; 6 | using Unity.Collections; 7 | using System.IO; 8 | using Yangrc.OpenGLAsyncReadback; 9 | 10 | /// 11 | /// Exemple of usage inspirated from https://github.com/keijiro/AsyncCaptureTest/blob/master/Assets/AsyncCapture.cs 12 | /// 13 | /// 14 | namespace Yangrc.OpenGLAsyncReadback { 15 | public class UsePlugin : MonoBehaviour { 16 | 17 | Queue _requests = new Queue(); 18 | 19 | private RenderTexture rt; 20 | private void Start() { 21 | var cam = GetComponent(); 22 | } 23 | 24 | void Update() { 25 | while (_requests.Count > 0) { 26 | var req = _requests.Peek(); 27 | 28 | if (req.hasError) { 29 | Debug.LogError("GPU readback error detected."); 30 | _requests.Dequeue(); 31 | } else if (req.done) { 32 | // Get data from the request when it's done 33 | var buffer = req.GetData(); 34 | 35 | // Save the image 36 | Camera cam = GetComponent(); 37 | SaveBitmap(buffer, cam.pixelWidth, cam.pixelHeight); 38 | 39 | _requests.Dequeue(); 40 | } else { 41 | break; 42 | } 43 | } 44 | } 45 | 46 | void OnRenderImage(RenderTexture source, RenderTexture destination) { 47 | Graphics.Blit(source, destination); 48 | 49 | if (Time.frameCount % 60 == 0) { 50 | if (_requests.Count < 8) 51 | _requests.Enqueue(UniversalAsyncGPUReadbackRequest.Request(source)); 52 | else 53 | Debug.LogWarning("Too many requests."); 54 | } 55 | } 56 | 57 | void SaveBitmap(NativeArray buffer, int width, int height) { 58 | Debug.Log("Write to file"); 59 | var texture = new Texture2D(width, height, TextureFormat.RGBAHalf, false); 60 | texture.LoadRawTextureData(buffer); 61 | File.WriteAllBytes("test.png", ImageConversion.EncodeToPNG(texture)); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/ExampleScenes/UsePlugin.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 47db193163fd0473a9d3662fc2bbd11b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b65640716fb1e4d8098eefc4960d2e0d 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Plugins/Linux.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 44c29691898f01b41815a2393beb6093 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Plugins/Linux/libAsyncGPUReadbackPlugin.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangrc1234/UnityOpenGLAsyncReadback/aff05c25f2c12e929d009948ebf5e84bcd1ac21d/UnityExampleProject/Assets/OpenglAsyncReadback/Plugins/Linux/libAsyncGPUReadbackPlugin.so -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Plugins/Linux/libAsyncGPUReadbackPlugin.so.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 30a799a9ac71261438d47fd52ac03d8e 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 0 11 | isExplicitlyReferenced: 0 12 | platformData: 13 | - first: 14 | '': Any 15 | second: 16 | enabled: 0 17 | settings: 18 | Exclude Editor: 0 19 | Exclude Linux: 0 20 | Exclude Linux64: 0 21 | Exclude LinuxUniversal: 0 22 | Exclude OSXUniversal: 1 23 | Exclude Win: 0 24 | Exclude Win64: 0 25 | - first: 26 | Any: 27 | second: 28 | enabled: 1 29 | settings: {} 30 | - first: 31 | Editor: Editor 32 | second: 33 | enabled: 1 34 | settings: 35 | CPU: x86_64 36 | DefaultValueInitialized: true 37 | OS: Linux 38 | - first: 39 | Facebook: Win 40 | second: 41 | enabled: 0 42 | settings: 43 | CPU: AnyCPU 44 | - first: 45 | Facebook: Win64 46 | second: 47 | enabled: 0 48 | settings: 49 | CPU: AnyCPU 50 | - first: 51 | Standalone: Linux 52 | second: 53 | enabled: 1 54 | settings: 55 | CPU: x86 56 | - first: 57 | Standalone: Linux64 58 | second: 59 | enabled: 1 60 | settings: 61 | CPU: x86_64 62 | - first: 63 | Standalone: LinuxUniversal 64 | second: 65 | enabled: 1 66 | settings: 67 | CPU: AnyCPU 68 | - first: 69 | Standalone: OSXUniversal 70 | second: 71 | enabled: 0 72 | settings: 73 | CPU: None 74 | - first: 75 | Standalone: Win 76 | second: 77 | enabled: 1 78 | settings: 79 | CPU: AnyCPU 80 | - first: 81 | Standalone: Win64 82 | second: 83 | enabled: 1 84 | settings: 85 | CPU: AnyCPU 86 | userData: 87 | assetBundleName: 88 | assetBundleVariant: 89 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Plugins/Windows.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dd4c74d5c01a748449d2d9b1099393df 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Plugins/Windows/AsyncGPUReadbackPlugin.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangrc1234/UnityOpenGLAsyncReadback/aff05c25f2c12e929d009948ebf5e84bcd1ac21d/UnityExampleProject/Assets/OpenglAsyncReadback/Plugins/Windows/AsyncGPUReadbackPlugin.dll -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Plugins/Windows/AsyncGPUReadbackPlugin.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dbb367131f703e046af0e7af725b1674 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 0 11 | isExplicitlyReferenced: 0 12 | platformData: 13 | - first: 14 | '': Any 15 | second: 16 | enabled: 0 17 | settings: 18 | Exclude Editor: 0 19 | Exclude Linux: 0 20 | Exclude Linux64: 0 21 | Exclude LinuxUniversal: 0 22 | Exclude OSXUniversal: 0 23 | Exclude Win: 0 24 | Exclude Win64: 0 25 | - first: 26 | Any: 27 | second: 28 | enabled: 1 29 | settings: {} 30 | - first: 31 | Editor: Editor 32 | second: 33 | enabled: 1 34 | settings: 35 | CPU: x86_64 36 | DefaultValueInitialized: true 37 | OS: Windows 38 | - first: 39 | Facebook: Win 40 | second: 41 | enabled: 0 42 | settings: 43 | CPU: AnyCPU 44 | - first: 45 | Facebook: Win64 46 | second: 47 | enabled: 0 48 | settings: 49 | CPU: AnyCPU 50 | - first: 51 | Standalone: Linux 52 | second: 53 | enabled: 1 54 | settings: 55 | CPU: x86 56 | - first: 57 | Standalone: Linux64 58 | second: 59 | enabled: 1 60 | settings: 61 | CPU: x86_64 62 | - first: 63 | Standalone: LinuxUniversal 64 | second: 65 | enabled: 1 66 | settings: {} 67 | - first: 68 | Standalone: OSXUniversal 69 | second: 70 | enabled: 1 71 | settings: 72 | CPU: AnyCPU 73 | - first: 74 | Standalone: Win 75 | second: 76 | enabled: 1 77 | settings: 78 | CPU: AnyCPU 79 | - first: 80 | Standalone: Win64 81 | second: 82 | enabled: 1 83 | settings: 84 | CPU: AnyCPU 85 | userData: 86 | assetBundleName: 87 | assetBundleVariant: 88 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d79f5709fc3a4490dbd7f544e1e6bf3f 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Scripts/AsyncGPUReadbackPlugin.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System; 4 | using System.Threading; 5 | using System.Runtime.InteropServices; 6 | using UnityEngine.Rendering; 7 | using Unity.Collections; 8 | using Unity.Collections.LowLevel.Unsafe; 9 | using System.Collections.Generic; 10 | 11 | namespace Yangrc.OpenGLAsyncReadback { 12 | /// 13 | /// Remember rendertexture's native pointer. 14 | /// 15 | /// It's cost to call GetNativeTexturePtr() for Unity, it will cause sync between render thread and main thread. 16 | /// 17 | internal static class RenderTextureRegistery { 18 | static Dictionary ptrs = new Dictionary(); 19 | static Dictionary cbPtrs = new Dictionary(); 20 | static public IntPtr GetFor(Texture rt) { 21 | if (ptrs.ContainsKey(rt)) { 22 | return ptrs[rt]; 23 | } else { 24 | var ptr = rt.GetNativeTexturePtr(); 25 | ptrs.Add(rt, ptr); 26 | return ptr; 27 | } 28 | } 29 | 30 | static public IntPtr GetFor(ComputeBuffer rt) { 31 | if (cbPtrs.ContainsKey(rt)) { 32 | return cbPtrs[rt]; 33 | } else { 34 | var ptr = rt.GetNativeBufferPtr(); 35 | cbPtrs.Add(rt, ptr); 36 | return ptr; 37 | } 38 | } 39 | 40 | static public void ClearDeadRefs() { //Clear disposed pointers. 41 | foreach (var item in cbPtrs) { 42 | if (item.Key == null) 43 | cbPtrs.Remove(item.Key); 44 | } 45 | 46 | foreach (var item in ptrs) { 47 | if (item.Key == null) { 48 | ptrs.Remove(item.Key); 49 | } 50 | } 51 | } 52 | } 53 | 54 | 55 | public static class RuntimeInitializer { 56 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] 57 | static void Initialize() { 58 | if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLCore && AsyncReadbackUpdater.instance == null) { 59 | var go = new GameObject("__OpenGL Async Readback Updater__"); 60 | go.hideFlags = HideFlags.HideAndDontSave; 61 | GameObject.DontDestroyOnLoad(go); 62 | var updater = go.AddComponent(); 63 | } 64 | } 65 | } 66 | 67 | /// 68 | /// Helper struct that wraps unity async readback and our opengl readback together, to hide difference 69 | /// 70 | public struct UniversalAsyncGPUReadbackRequest { 71 | 72 | /// 73 | /// Request readback of a texture. 74 | /// 75 | /// 76 | /// 77 | /// 78 | public static UniversalAsyncGPUReadbackRequest Request(Texture src, int mipmapIndex = 0) { 79 | if (SystemInfo.supportsAsyncGPUReadback) { 80 | 81 | return new UniversalAsyncGPUReadbackRequest() { 82 | isPlugin = false, 83 | uDisposd = false, 84 | uRequest = AsyncGPUReadback.Request(src, mipIndex: mipmapIndex), 85 | }; 86 | } else { 87 | return new UniversalAsyncGPUReadbackRequest() { 88 | isPlugin = true, 89 | oRequest = OpenGLAsyncReadbackRequest.CreateTextureRequest(RenderTextureRegistery.GetFor(src).ToInt32(), mipmapIndex) 90 | }; 91 | } 92 | } 93 | 94 | public static UniversalAsyncGPUReadbackRequest Request(ComputeBuffer computeBuffer) { 95 | if (SystemInfo.supportsAsyncGPUReadback) { 96 | return new UniversalAsyncGPUReadbackRequest() { 97 | isPlugin = false, 98 | uInited = true, 99 | uDisposd = false, 100 | uRequest = AsyncGPUReadback.Request(computeBuffer), 101 | }; 102 | } else { 103 | return new UniversalAsyncGPUReadbackRequest() { 104 | isPlugin = true, 105 | oRequest = OpenGLAsyncReadbackRequest.CreateComputeBufferRequest((int)computeBuffer.GetNativeBufferPtr(), computeBuffer.stride * computeBuffer.count), 106 | }; 107 | } 108 | } 109 | 110 | public static UniversalAsyncGPUReadbackRequest OpenGLRequestTexture(int texture, int mipmapIndex) { 111 | return new UniversalAsyncGPUReadbackRequest() { 112 | isPlugin = true, 113 | oRequest = OpenGLAsyncReadbackRequest.CreateTextureRequest((int)texture, mipmapIndex) 114 | }; 115 | } 116 | 117 | public static UniversalAsyncGPUReadbackRequest OpenGLRequestComputeBuffer(int computeBuffer, int size) { 118 | return new UniversalAsyncGPUReadbackRequest() { 119 | isPlugin = true, 120 | oRequest = OpenGLAsyncReadbackRequest.CreateComputeBufferRequest((int)computeBuffer, size) 121 | }; 122 | } 123 | 124 | [Obsolete] 125 | public void Update() { 126 | //if (isPlugin) { 127 | // oRequest.Update(); 128 | //} else { 129 | // uRequest.Update(); 130 | //} 131 | } 132 | 133 | public bool done { 134 | get { 135 | if (isPlugin) { 136 | return oRequest.done; 137 | } else { 138 | return uRequest.done; 139 | } 140 | } 141 | } 142 | 143 | public bool hasError { 144 | get { 145 | if (isPlugin) { 146 | return oRequest.hasError; 147 | } else { 148 | return uRequest.hasError; 149 | } 150 | } 151 | } 152 | 153 | /// 154 | /// Get data of a readback request. 155 | /// The data is allocated as temp, so it only stay alive for one frame. 156 | /// 157 | /// 158 | /// 159 | public NativeArray GetData() where T:struct{ 160 | if (isPlugin) { 161 | return oRequest.GetRawData(); 162 | } else { 163 | return uRequest.GetData(); 164 | } 165 | } 166 | 167 | public bool valid { 168 | get { 169 | return isPlugin ? oRequest.Valid() : (!uDisposd && uInited); 170 | } 171 | } 172 | 173 | public bool isPlugin { get; private set; } 174 | 175 | //fields for unity request. 176 | private bool uInited; 177 | private bool uDisposd; 178 | private AsyncGPUReadbackRequest uRequest; 179 | 180 | //fields for opengl request. 181 | private OpenGLAsyncReadbackRequest oRequest; 182 | 183 | } 184 | 185 | internal struct OpenGLAsyncReadbackRequest { 186 | public static bool IsAvailable() { 187 | return SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLCore; //Not tested on es3 yet. 188 | } 189 | /// 190 | /// Identify native task object handling the request. 191 | /// 192 | private int nativeTaskHandle; 193 | 194 | /// 195 | /// Check if the request is done 196 | /// 197 | public bool done 198 | { 199 | get { 200 | // AssertRequestValid(); 201 | return TaskDone(nativeTaskHandle); 202 | } 203 | } 204 | 205 | /// 206 | /// Check if the request has an error 207 | /// 208 | public bool hasError 209 | { 210 | get { 211 | // AssertRequestValid(); 212 | return TaskError(nativeTaskHandle); 213 | } 214 | } 215 | 216 | public static OpenGLAsyncReadbackRequest CreateTextureRequest(int textureOpenGLName, int mipmapLevel) { 217 | var result = new OpenGLAsyncReadbackRequest(); 218 | result.nativeTaskHandle = RequestTextureMainThread(textureOpenGLName, mipmapLevel); 219 | GL.IssuePluginEvent(GetKickstartFunctionPtr(), result.nativeTaskHandle); 220 | return result; 221 | } 222 | 223 | public static OpenGLAsyncReadbackRequest CreateComputeBufferRequest(int computeBufferOpenGLName, int size) { 224 | var result = new OpenGLAsyncReadbackRequest(); 225 | result.nativeTaskHandle = RequestComputeBufferMainThread(computeBufferOpenGLName, size); 226 | GL.IssuePluginEvent(GetKickstartFunctionPtr(), result.nativeTaskHandle); 227 | return result; 228 | } 229 | 230 | public bool Valid() { 231 | return TaskExists(this.nativeTaskHandle); 232 | } 233 | 234 | private void AssertRequestValid() { 235 | if (!Valid()) { 236 | throw new UnityException("The request is not valid!"); 237 | } 238 | } 239 | 240 | public unsafe NativeArray GetRawData() where T:struct 241 | { 242 | AssertRequestValid(); 243 | if (!done) { 244 | throw new InvalidOperationException("The request is not done yet!"); 245 | } 246 | // Get data from cpp plugin 247 | void* ptr = null; 248 | int length = 0; 249 | GetData(this.nativeTaskHandle, ref ptr, ref length); 250 | 251 | //Copy data from plugin native memory to unity-controlled native memory. 252 | var resultNativeArray = new NativeArray(length / UnsafeUtility.SizeOf(), Allocator.Temp); 253 | UnsafeUtility.MemMove(resultNativeArray.GetUnsafePtr(), ptr, length); 254 | //Though there exists an api named NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray. 255 | //It's only for internal use. The document on docs.unity3d.com is a lie. 256 | 257 | return resultNativeArray; 258 | } 259 | 260 | internal static void Update() 261 | { 262 | UpdateMainThread(); 263 | GL.IssuePluginEvent(GetUpdateRenderThreadFunctionPtr(), 0); 264 | } 265 | 266 | [DllImport ("AsyncGPUReadbackPlugin")] 267 | private static extern bool CheckCompatible(); 268 | [DllImport("AsyncGPUReadbackPlugin")] 269 | private static extern int RequestTextureMainThread(int texture, int miplevel); 270 | [DllImport("AsyncGPUReadbackPlugin")] 271 | private static extern int RequestComputeBufferMainThread(int bufferID, int bufferSize); 272 | [DllImport ("AsyncGPUReadbackPlugin")] 273 | private static extern IntPtr GetKickstartFunctionPtr(); 274 | [DllImport("AsyncGPUReadbackPlugin")] 275 | private static extern IntPtr UpdateMainThread(); 276 | [DllImport("AsyncGPUReadbackPlugin")] 277 | private static extern IntPtr GetUpdateRenderThreadFunctionPtr(); 278 | [DllImport ("AsyncGPUReadbackPlugin")] 279 | private static extern unsafe void GetData(int event_id, ref void* buffer, ref int length); 280 | [DllImport("AsyncGPUReadbackPlugin")] 281 | private static extern bool TaskError(int event_id); 282 | [DllImport("AsyncGPUReadbackPlugin")] 283 | private static extern bool TaskExists(int event_id); 284 | [DllImport ("AsyncGPUReadbackPlugin")] 285 | private static extern bool TaskDone(int event_id); 286 | } 287 | } -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Scripts/AsyncGPUReadbackPlugin.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 79f0f31b70e958e439f87caaa29c8b6f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Scripts/AsyncReadbackUpdater.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Yangrc.OpenGLAsyncReadback { 6 | /// 7 | /// A helper class to trigger readback update every frame. 8 | /// 9 | [AddComponentMenu("")] 10 | public class AsyncReadbackUpdater : MonoBehaviour { 11 | public static AsyncReadbackUpdater instance; 12 | private void Awake() { 13 | instance = this; 14 | } 15 | void Update() { 16 | OpenGLAsyncReadbackRequest.Update(); 17 | RenderTextureRegistery.ClearDeadRefs(); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/Scripts/AsyncReadbackUpdater.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a9b5231363473cb4a8f43b7fd4e4aedd 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/b.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: b 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 0, g: 0, b: 1, a: 1} 76 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 77 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/b.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f83eee9781cd14c97918bf5f362beb27 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/g.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: g 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 0, g: 1, b: 0, a: 1} 76 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 77 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/g.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 78036511e4c0b4f2c9c93a1edf0499f4 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/r.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: r 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 1, g: 0, b: 0, a: 1} 76 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 77 | -------------------------------------------------------------------------------- /UnityExampleProject/Assets/OpenglAsyncReadback/r.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e996f5cabfdfd4f53b5edf237286723f 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /UnityExampleProject/Logs/Packages-Update.log: -------------------------------------------------------------------------------- 1 | 2 | === Sun Jul 21 19:15:23 2019 3 | 4 | Packages were changed. 5 | Update Mode: updateDependencies 6 | 7 | The following packages were added: 8 | com.unity.collab-proxy@1.2.11 9 | The following packages were updated: 10 | com.unity.analytics from version 2.0.16 to 3.0.9 11 | com.unity.package-manager-ui from version 1.9.11 to 2.0.2 12 | com.unity.textmeshpro from version 1.2.4 to 1.3.0 13 | 14 | === Tue Jul 23 17:11:16 2019 15 | 16 | Packages were changed. 17 | Update Mode: updateDependencies 18 | 19 | The following packages were updated: 20 | com.unity.analytics from version 3.0.9 to 3.2.2 21 | com.unity.collab-proxy from version 1.2.11 to 1.2.15 22 | com.unity.package-manager-ui from version 2.0.2 to 2.0.7 23 | -------------------------------------------------------------------------------- /UnityExampleProject/Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.ads": "2.0.8", 4 | "com.unity.analytics": "3.2.2", 5 | "com.unity.collab-proxy": "1.2.15", 6 | "com.unity.package-manager-ui": "2.0.7", 7 | "com.unity.purchasing": "2.0.3", 8 | "com.unity.textmeshpro": "1.3.0", 9 | "com.unity.modules.ai": "1.0.0", 10 | "com.unity.modules.animation": "1.0.0", 11 | "com.unity.modules.assetbundle": "1.0.0", 12 | "com.unity.modules.audio": "1.0.0", 13 | "com.unity.modules.cloth": "1.0.0", 14 | "com.unity.modules.director": "1.0.0", 15 | "com.unity.modules.imageconversion": "1.0.0", 16 | "com.unity.modules.imgui": "1.0.0", 17 | "com.unity.modules.jsonserialize": "1.0.0", 18 | "com.unity.modules.particlesystem": "1.0.0", 19 | "com.unity.modules.physics": "1.0.0", 20 | "com.unity.modules.physics2d": "1.0.0", 21 | "com.unity.modules.screencapture": "1.0.0", 22 | "com.unity.modules.terrain": "1.0.0", 23 | "com.unity.modules.terrainphysics": "1.0.0", 24 | "com.unity.modules.tilemap": "1.0.0", 25 | "com.unity.modules.ui": "1.0.0", 26 | "com.unity.modules.uielements": "1.0.0", 27 | "com.unity.modules.umbra": "1.0.0", 28 | "com.unity.modules.unityanalytics": "1.0.0", 29 | "com.unity.modules.unitywebrequest": "1.0.0", 30 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 31 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 32 | "com.unity.modules.unitywebrequesttexture": "1.0.0", 33 | "com.unity.modules.unitywebrequestwww": "1.0.0", 34 | "com.unity.modules.vehicles": "1.0.0", 35 | "com.unity.modules.video": "1.0.0", 36 | "com.unity.modules.vr": "1.0.0", 37 | "com.unity.modules.wind": "1.0.0", 38 | "com.unity.modules.xr": "1.0.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | m_Volume: 1 7 | Rolloff Scale: 1 8 | Doppler Factor: 1 9 | Default Speaker Mode: 2 10 | m_SampleRate: 0 11 | m_DSPBufferSize: 1024 12 | m_VirtualVoiceCount: 512 13 | m_RealVoiceCount: 32 14 | m_SpatializerPlugin: 15 | m_AmbisonicDecoderPlugin: 16 | m_DisableAudio: 0 17 | m_VirtualizeEffects: 1 18 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_DefaultSolverIterations: 6 13 | m_DefaultSolverVelocityIterations: 1 14 | m_QueriesHitBackfaces: 0 15 | m_QueriesHitTriggers: 1 16 | m_EnableAdaptiveForce: 0 17 | m_ClothInterCollisionDistance: 0 18 | m_ClothInterCollisionStiffness: 0 19 | m_ContactsGeneration: 1 20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21 | m_AutoSimulation: 1 22 | m_AutoSyncTransforms: 1 23 | m_ClothInterCollisionSettingsToggle: 0 24 | m_ContactPairsMode: 0 25 | m_BroadphaseType: 0 26 | m_WorldBounds: 27 | m_Center: {x: 0, y: 0, z: 0} 28 | m_Extent: {x: 250, y: 250, z: 250} 29 | m_WorldSubdivisions: 8 30 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: 8 | - enabled: 0 9 | path: 10 | guid: 00000000000000000000000000000000 11 | - enabled: 1 12 | path: Assets/OpenglAsyncReadback/ExampleScenes/Scene.unity 13 | guid: bb509b92e73fe4439839f06c1aec0245 14 | m_configObjects: {} 15 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_ExternalVersionControlSupport: Visible Meta Files 8 | m_SerializationMode: 2 9 | m_LineEndingsForNewScripts: 2 10 | m_DefaultBehaviorMode: 0 11 | m_SpritePackerMode: 0 12 | m_SpritePackerPaddingPower: 1 13 | m_EtcTextureCompressorBehavior: 1 14 | m_EtcTextureFastCompressor: 1 15 | m_EtcTextureNormalCompressor: 2 16 | m_EtcTextureBestCompressor: 4 17 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd 18 | m_ProjectGenerationRootNamespace: 19 | m_UserGeneratedProjectSuffix: 20 | m_CollabEditorSettings: 21 | inProgressEnabled: 1 22 | m_EnableTextureStreamingInPlayMode: 1 23 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 12 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} 37 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 38 | - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} 39 | - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} 40 | m_PreloadedShaders: [] 41 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 42 | type: 0} 43 | m_CustomRenderPipeline: {fileID: 0} 44 | m_TransparencySortMode: 0 45 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 46 | m_DefaultRenderingPath: 1 47 | m_DefaultMobileRenderingPath: 1 48 | m_TierSettings: [] 49 | m_LightmapStripping: 0 50 | m_FogStripping: 0 51 | m_InstancingStripping: 0 52 | m_LightmapKeepPlain: 1 53 | m_LightmapKeepDirCombined: 1 54 | m_LightmapKeepDynamicPlain: 1 55 | m_LightmapKeepDynamicDirCombined: 1 56 | m_LightmapKeepShadowMask: 1 57 | m_LightmapKeepSubtractive: 1 58 | m_FogKeepLinear: 1 59 | m_FogKeepExp: 1 60 | m_FogKeepExp2: 1 61 | m_AlbedoSwatchInfos: [] 62 | m_LightsUseLinearIntensity: 0 63 | m_LightsUseColorTemperature: 0 64 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!13 &1 4 | InputManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Axes: 8 | - serializedVersion: 3 9 | m_Name: Horizontal 10 | descriptiveName: 11 | descriptiveNegativeName: 12 | negativeButton: left 13 | positiveButton: right 14 | altNegativeButton: a 15 | altPositiveButton: d 16 | gravity: 3 17 | dead: 0.001 18 | sensitivity: 3 19 | snap: 1 20 | invert: 0 21 | type: 0 22 | axis: 0 23 | joyNum: 0 24 | - serializedVersion: 3 25 | m_Name: Vertical 26 | descriptiveName: 27 | descriptiveNegativeName: 28 | negativeButton: down 29 | positiveButton: up 30 | altNegativeButton: s 31 | altPositiveButton: w 32 | gravity: 3 33 | dead: 0.001 34 | sensitivity: 3 35 | snap: 1 36 | invert: 0 37 | type: 0 38 | axis: 0 39 | joyNum: 0 40 | - serializedVersion: 3 41 | m_Name: Fire1 42 | descriptiveName: 43 | descriptiveNegativeName: 44 | negativeButton: 45 | positiveButton: left ctrl 46 | altNegativeButton: 47 | altPositiveButton: mouse 0 48 | gravity: 1000 49 | dead: 0.001 50 | sensitivity: 1000 51 | snap: 0 52 | invert: 0 53 | type: 0 54 | axis: 0 55 | joyNum: 0 56 | - serializedVersion: 3 57 | m_Name: Fire2 58 | descriptiveName: 59 | descriptiveNegativeName: 60 | negativeButton: 61 | positiveButton: left alt 62 | altNegativeButton: 63 | altPositiveButton: mouse 1 64 | gravity: 1000 65 | dead: 0.001 66 | sensitivity: 1000 67 | snap: 0 68 | invert: 0 69 | type: 0 70 | axis: 0 71 | joyNum: 0 72 | - serializedVersion: 3 73 | m_Name: Fire3 74 | descriptiveName: 75 | descriptiveNegativeName: 76 | negativeButton: 77 | positiveButton: left shift 78 | altNegativeButton: 79 | altPositiveButton: mouse 2 80 | gravity: 1000 81 | dead: 0.001 82 | sensitivity: 1000 83 | snap: 0 84 | invert: 0 85 | type: 0 86 | axis: 0 87 | joyNum: 0 88 | - serializedVersion: 3 89 | m_Name: Jump 90 | descriptiveName: 91 | descriptiveNegativeName: 92 | negativeButton: 93 | positiveButton: space 94 | altNegativeButton: 95 | altPositiveButton: 96 | gravity: 1000 97 | dead: 0.001 98 | sensitivity: 1000 99 | snap: 0 100 | invert: 0 101 | type: 0 102 | axis: 0 103 | joyNum: 0 104 | - serializedVersion: 3 105 | m_Name: Mouse X 106 | descriptiveName: 107 | descriptiveNegativeName: 108 | negativeButton: 109 | positiveButton: 110 | altNegativeButton: 111 | altPositiveButton: 112 | gravity: 0 113 | dead: 0 114 | sensitivity: 0.1 115 | snap: 0 116 | invert: 0 117 | type: 1 118 | axis: 0 119 | joyNum: 0 120 | - serializedVersion: 3 121 | m_Name: Mouse Y 122 | descriptiveName: 123 | descriptiveNegativeName: 124 | negativeButton: 125 | positiveButton: 126 | altNegativeButton: 127 | altPositiveButton: 128 | gravity: 0 129 | dead: 0 130 | sensitivity: 0.1 131 | snap: 0 132 | invert: 0 133 | type: 1 134 | axis: 1 135 | joyNum: 0 136 | - serializedVersion: 3 137 | m_Name: Mouse ScrollWheel 138 | descriptiveName: 139 | descriptiveNegativeName: 140 | negativeButton: 141 | positiveButton: 142 | altNegativeButton: 143 | altPositiveButton: 144 | gravity: 0 145 | dead: 0 146 | sensitivity: 0.1 147 | snap: 0 148 | invert: 0 149 | type: 1 150 | axis: 2 151 | joyNum: 0 152 | - serializedVersion: 3 153 | m_Name: Horizontal 154 | descriptiveName: 155 | descriptiveNegativeName: 156 | negativeButton: 157 | positiveButton: 158 | altNegativeButton: 159 | altPositiveButton: 160 | gravity: 0 161 | dead: 0.19 162 | sensitivity: 1 163 | snap: 0 164 | invert: 0 165 | type: 2 166 | axis: 0 167 | joyNum: 0 168 | - serializedVersion: 3 169 | m_Name: Vertical 170 | descriptiveName: 171 | descriptiveNegativeName: 172 | negativeButton: 173 | positiveButton: 174 | altNegativeButton: 175 | altPositiveButton: 176 | gravity: 0 177 | dead: 0.19 178 | sensitivity: 1 179 | snap: 0 180 | invert: 1 181 | type: 2 182 | axis: 1 183 | joyNum: 0 184 | - serializedVersion: 3 185 | m_Name: Fire1 186 | descriptiveName: 187 | descriptiveNegativeName: 188 | negativeButton: 189 | positiveButton: joystick button 0 190 | altNegativeButton: 191 | altPositiveButton: 192 | gravity: 1000 193 | dead: 0.001 194 | sensitivity: 1000 195 | snap: 0 196 | invert: 0 197 | type: 0 198 | axis: 0 199 | joyNum: 0 200 | - serializedVersion: 3 201 | m_Name: Fire2 202 | descriptiveName: 203 | descriptiveNegativeName: 204 | negativeButton: 205 | positiveButton: joystick button 1 206 | altNegativeButton: 207 | altPositiveButton: 208 | gravity: 1000 209 | dead: 0.001 210 | sensitivity: 1000 211 | snap: 0 212 | invert: 0 213 | type: 0 214 | axis: 0 215 | joyNum: 0 216 | - serializedVersion: 3 217 | m_Name: Fire3 218 | descriptiveName: 219 | descriptiveNegativeName: 220 | negativeButton: 221 | positiveButton: joystick button 2 222 | altNegativeButton: 223 | altPositiveButton: 224 | gravity: 1000 225 | dead: 0.001 226 | sensitivity: 1000 227 | snap: 0 228 | invert: 0 229 | type: 0 230 | axis: 0 231 | joyNum: 0 232 | - serializedVersion: 3 233 | m_Name: Jump 234 | descriptiveName: 235 | descriptiveNegativeName: 236 | negativeButton: 237 | positiveButton: joystick button 3 238 | altNegativeButton: 239 | altPositiveButton: 240 | gravity: 1000 241 | dead: 0.001 242 | sensitivity: 1000 243 | snap: 0 244 | invert: 0 245 | type: 0 246 | axis: 0 247 | joyNum: 0 248 | - serializedVersion: 3 249 | m_Name: Submit 250 | descriptiveName: 251 | descriptiveNegativeName: 252 | negativeButton: 253 | positiveButton: return 254 | altNegativeButton: 255 | altPositiveButton: joystick button 0 256 | gravity: 1000 257 | dead: 0.001 258 | sensitivity: 1000 259 | snap: 0 260 | invert: 0 261 | type: 0 262 | axis: 0 263 | joyNum: 0 264 | - serializedVersion: 3 265 | m_Name: Submit 266 | descriptiveName: 267 | descriptiveNegativeName: 268 | negativeButton: 269 | positiveButton: enter 270 | altNegativeButton: 271 | altPositiveButton: space 272 | gravity: 1000 273 | dead: 0.001 274 | sensitivity: 1000 275 | snap: 0 276 | invert: 0 277 | type: 0 278 | axis: 0 279 | joyNum: 0 280 | - serializedVersion: 3 281 | m_Name: Cancel 282 | descriptiveName: 283 | descriptiveNegativeName: 284 | negativeButton: 285 | positiveButton: escape 286 | altNegativeButton: 287 | altPositiveButton: joystick button 1 288 | gravity: 1000 289 | dead: 0.001 290 | sensitivity: 1000 291 | snap: 0 292 | invert: 0 293 | type: 0 294 | axis: 0 295 | joyNum: 0 296 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshProjectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | m_LastAgentTypeID: -887442657 73 | m_Settings: 74 | - serializedVersion: 2 75 | agentTypeID: 0 76 | agentRadius: 0.5 77 | agentHeight: 2 78 | agentSlope: 45 79 | agentClimb: 0.75 80 | ledgeDropHeight: 0 81 | maxJumpAcrossDistance: 0 82 | minRegionArea: 2 83 | manualCellSize: 0 84 | cellSize: 0.16666667 85 | manualTileSize: 0 86 | tileSize: 256 87 | accuratePlacement: 0 88 | debug: 89 | m_Flags: 0 90 | m_SettingNames: 91 | - Humanoid 92 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 3 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_BaumgarteScale: 0.2 17 | m_BaumgarteTimeOfImpactScale: 0.75 18 | m_TimeToSleep: 0.5 19 | m_LinearSleepTolerance: 0.01 20 | m_AngularSleepTolerance: 2 21 | m_DefaultContactOffset: 0.01 22 | m_AutoSimulation: 1 23 | m_QueriesHitTriggers: 1 24 | m_QueriesStartInColliders: 1 25 | m_ChangeStopsCallbacks: 0 26 | m_CallbacksOnDisable: 1 27 | m_AutoSyncTransforms: 1 28 | m_AlwaysShowColliders: 0 29 | m_ShowColliderSleep: 1 30 | m_ShowColliderContacts: 0 31 | m_ShowColliderAABB: 0 32 | m_ContactArrowScale: 0.2 33 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} 34 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} 35 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} 36 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} 37 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 38 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1386491679 &1 4 | PresetManager: 5 | m_ObjectHideFlags: 0 6 | m_DefaultList: 7 | - type: 8 | m_NativeTypeID: 108 9 | m_ManagedTypePPtr: {fileID: 0} 10 | m_ManagedTypeFallback: 11 | defaultPresets: 12 | - m_Preset: {fileID: 2655988077585873504, guid: c1cf8506f04ef2c4a88b64b6c4202eea, 13 | type: 2} 14 | - type: 15 | m_NativeTypeID: 1020 16 | m_ManagedTypePPtr: {fileID: 0} 17 | m_ManagedTypeFallback: 18 | defaultPresets: 19 | - m_Preset: {fileID: 2655988077585873504, guid: 0cd792cc87e492d43b4e95b205fc5cc6, 20 | type: 2} 21 | - type: 22 | m_NativeTypeID: 1006 23 | m_ManagedTypePPtr: {fileID: 0} 24 | m_ManagedTypeFallback: 25 | defaultPresets: 26 | - m_Preset: {fileID: 2655988077585873504, guid: 7a99f8aa944efe94cb9bd74562b7d5f9, 27 | type: 2} 28 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!129 &1 4 | PlayerSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 15 7 | productGUID: 5680f74c79b4a4d9fb9b6c2e60fb0230 8 | AndroidProfiler: 0 9 | AndroidFilterTouchesWhenObscured: 0 10 | AndroidEnableSustainedPerformanceMode: 0 11 | defaultScreenOrientation: 4 12 | targetDevice: 2 13 | useOnDemandResources: 0 14 | accelerometerFrequency: 60 15 | companyName: DefaultCompany 16 | productName: UnityExampleProject 17 | defaultCursor: {fileID: 0} 18 | cursorHotspot: {x: 0, y: 0} 19 | m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} 20 | m_ShowUnitySplashScreen: 1 21 | m_ShowUnitySplashLogo: 1 22 | m_SplashScreenOverlayOpacity: 1 23 | m_SplashScreenAnimation: 1 24 | m_SplashScreenLogoStyle: 1 25 | m_SplashScreenDrawMode: 0 26 | m_SplashScreenBackgroundAnimationZoom: 1 27 | m_SplashScreenLogoAnimationZoom: 1 28 | m_SplashScreenBackgroundLandscapeAspect: 1 29 | m_SplashScreenBackgroundPortraitAspect: 1 30 | m_SplashScreenBackgroundLandscapeUvs: 31 | serializedVersion: 2 32 | x: 0 33 | y: 0 34 | width: 1 35 | height: 1 36 | m_SplashScreenBackgroundPortraitUvs: 37 | serializedVersion: 2 38 | x: 0 39 | y: 0 40 | width: 1 41 | height: 1 42 | m_SplashScreenLogos: [] 43 | m_VirtualRealitySplashScreen: {fileID: 0} 44 | m_HolographicTrackingLossScreen: {fileID: 0} 45 | defaultScreenWidth: 1024 46 | defaultScreenHeight: 768 47 | defaultScreenWidthWeb: 960 48 | defaultScreenHeightWeb: 600 49 | m_StereoRenderingPath: 0 50 | m_ActiveColorSpace: 0 51 | m_MTRendering: 1 52 | m_StackTraceTypes: 010000000100000001000000010000000100000001000000 53 | iosShowActivityIndicatorOnLoading: -1 54 | androidShowActivityIndicatorOnLoading: -1 55 | iosAppInBackgroundBehavior: 0 56 | displayResolutionDialog: 0 57 | iosAllowHTTPDownload: 1 58 | allowedAutorotateToPortrait: 1 59 | allowedAutorotateToPortraitUpsideDown: 1 60 | allowedAutorotateToLandscapeRight: 1 61 | allowedAutorotateToLandscapeLeft: 1 62 | useOSAutorotation: 1 63 | use32BitDisplayBuffer: 1 64 | preserveFramebufferAlpha: 0 65 | disableDepthAndStencilBuffers: 0 66 | androidStartInFullscreen: 1 67 | androidRenderOutsideSafeArea: 0 68 | androidBlitType: 0 69 | defaultIsNativeResolution: 1 70 | macRetinaSupport: 1 71 | runInBackground: 1 72 | captureSingleScreen: 0 73 | muteOtherAudioSources: 0 74 | Prepare IOS For Recording: 0 75 | Force IOS Speakers When Recording: 0 76 | deferSystemGesturesMode: 0 77 | hideHomeButton: 0 78 | submitAnalytics: 1 79 | usePlayerLog: 0 80 | bakeCollisionMeshes: 0 81 | forceSingleInstance: 1 82 | resizableWindow: 1 83 | useMacAppStoreValidation: 0 84 | macAppStoreCategory: public.app-category.games 85 | gpuSkinning: 1 86 | graphicsJobs: 0 87 | xboxPIXTextureCapture: 0 88 | xboxEnableAvatar: 0 89 | xboxEnableKinect: 0 90 | xboxEnableKinectAutoTracking: 0 91 | xboxEnableFitness: 0 92 | visibleInBackground: 1 93 | allowFullscreenSwitch: 1 94 | graphicsJobMode: 0 95 | fullscreenMode: 3 96 | xboxSpeechDB: 0 97 | xboxEnableHeadOrientation: 0 98 | xboxEnableGuest: 0 99 | xboxEnablePIXSampling: 0 100 | metalFramebufferOnly: 0 101 | xboxOneResolution: 0 102 | xboxOneSResolution: 0 103 | xboxOneXResolution: 3 104 | xboxOneMonoLoggingLevel: 0 105 | xboxOneLoggingLevel: 1 106 | xboxOneDisableEsram: 0 107 | xboxOnePresentImmediateThreshold: 0 108 | switchQueueCommandMemory: 0 109 | vulkanEnableSetSRGBWrite: 0 110 | m_SupportedAspectRatios: 111 | 4:3: 1 112 | 5:4: 1 113 | 16:10: 1 114 | 16:9: 1 115 | Others: 1 116 | bundleVersion: 0.1 117 | preloadedAssets: [] 118 | metroInputSource: 0 119 | wsaTransparentSwapchain: 0 120 | m_HolographicPauseOnTrackingLoss: 1 121 | xboxOneDisableKinectGpuReservation: 0 122 | xboxOneEnable7thCore: 0 123 | isWsaHolographicRemotingEnabled: 0 124 | vrSettings: 125 | cardboard: 126 | depthFormat: 0 127 | enableTransitionView: 0 128 | daydream: 129 | depthFormat: 0 130 | useSustainedPerformanceMode: 0 131 | enableVideoLayer: 0 132 | useProtectedVideoMemory: 0 133 | minimumSupportedHeadTracking: 0 134 | maximumSupportedHeadTracking: 1 135 | hololens: 136 | depthFormat: 1 137 | depthBufferSharingEnabled: 0 138 | oculus: 139 | sharedDepthBuffer: 0 140 | dashSupport: 0 141 | enable360StereoCapture: 0 142 | protectGraphicsMemory: 0 143 | enableFrameTimingStats: 0 144 | useHDRDisplay: 0 145 | m_ColorGamuts: 00000000 146 | targetPixelDensity: 30 147 | resolutionScalingMode: 0 148 | androidSupportedAspectRatio: 1 149 | androidMaxAspectRatio: 2.1 150 | applicationIdentifier: {} 151 | buildNumber: {} 152 | AndroidBundleVersionCode: 1 153 | AndroidMinSdkVersion: 16 154 | AndroidTargetSdkVersion: 0 155 | AndroidPreferredInstallLocation: 1 156 | aotOptions: 157 | stripEngineCode: 1 158 | iPhoneStrippingLevel: 0 159 | iPhoneScriptCallOptimization: 0 160 | ForceInternetPermission: 0 161 | ForceSDCardPermission: 0 162 | CreateWallpaper: 0 163 | APKExpansionFiles: 0 164 | keepLoadedShadersAlive: 0 165 | StripUnusedMeshComponents: 1 166 | VertexChannelCompressionMask: 4054 167 | iPhoneSdkVersion: 988 168 | iOSTargetOSVersionString: 9.0 169 | tvOSSdkVersion: 0 170 | tvOSRequireExtendedGameController: 0 171 | tvOSTargetOSVersionString: 9.0 172 | uIPrerenderedIcon: 0 173 | uIRequiresPersistentWiFi: 0 174 | uIRequiresFullScreen: 1 175 | uIStatusBarHidden: 1 176 | uIExitOnSuspend: 0 177 | uIStatusBarStyle: 0 178 | iPhoneSplashScreen: {fileID: 0} 179 | iPhoneHighResSplashScreen: {fileID: 0} 180 | iPhoneTallHighResSplashScreen: {fileID: 0} 181 | iPhone47inSplashScreen: {fileID: 0} 182 | iPhone55inPortraitSplashScreen: {fileID: 0} 183 | iPhone55inLandscapeSplashScreen: {fileID: 0} 184 | iPhone58inPortraitSplashScreen: {fileID: 0} 185 | iPhone58inLandscapeSplashScreen: {fileID: 0} 186 | iPadPortraitSplashScreen: {fileID: 0} 187 | iPadHighResPortraitSplashScreen: {fileID: 0} 188 | iPadLandscapeSplashScreen: {fileID: 0} 189 | iPadHighResLandscapeSplashScreen: {fileID: 0} 190 | appleTVSplashScreen: {fileID: 0} 191 | appleTVSplashScreen2x: {fileID: 0} 192 | tvOSSmallIconLayers: [] 193 | tvOSSmallIconLayers2x: [] 194 | tvOSLargeIconLayers: [] 195 | tvOSLargeIconLayers2x: [] 196 | tvOSTopShelfImageLayers: [] 197 | tvOSTopShelfImageLayers2x: [] 198 | tvOSTopShelfImageWideLayers: [] 199 | tvOSTopShelfImageWideLayers2x: [] 200 | iOSLaunchScreenType: 0 201 | iOSLaunchScreenPortrait: {fileID: 0} 202 | iOSLaunchScreenLandscape: {fileID: 0} 203 | iOSLaunchScreenBackgroundColor: 204 | serializedVersion: 2 205 | rgba: 0 206 | iOSLaunchScreenFillPct: 100 207 | iOSLaunchScreenSize: 100 208 | iOSLaunchScreenCustomXibPath: 209 | iOSLaunchScreeniPadType: 0 210 | iOSLaunchScreeniPadImage: {fileID: 0} 211 | iOSLaunchScreeniPadBackgroundColor: 212 | serializedVersion: 2 213 | rgba: 0 214 | iOSLaunchScreeniPadFillPct: 100 215 | iOSLaunchScreeniPadSize: 100 216 | iOSLaunchScreeniPadCustomXibPath: 217 | iOSUseLaunchScreenStoryboard: 0 218 | iOSLaunchScreenCustomStoryboardPath: 219 | iOSDeviceRequirements: [] 220 | iOSURLSchemes: [] 221 | iOSBackgroundModes: 0 222 | iOSMetalForceHardShadows: 0 223 | metalEditorSupport: 1 224 | metalAPIValidation: 1 225 | iOSRenderExtraFrameOnPause: 0 226 | appleDeveloperTeamID: 227 | iOSManualSigningProvisioningProfileID: 228 | tvOSManualSigningProvisioningProfileID: 229 | iOSManualSigningProvisioningProfileType: 0 230 | tvOSManualSigningProvisioningProfileType: 0 231 | appleEnableAutomaticSigning: 0 232 | iOSRequireARKit: 0 233 | appleEnableProMotion: 0 234 | clonedFromGUID: c0afd0d1d80e3634a9dac47e8a0426ea 235 | templatePackageId: com.unity.3d@1.0.2 236 | templateDefaultScene: Assets/Scenes/SampleScene.unity 237 | AndroidTargetArchitectures: 5 238 | AndroidSplashScreenScale: 0 239 | androidSplashScreen: {fileID: 0} 240 | AndroidKeystoreName: 241 | AndroidKeyaliasName: 242 | AndroidBuildApkPerCpuArchitecture: 0 243 | AndroidTVCompatibility: 1 244 | AndroidIsGame: 1 245 | AndroidEnableTango: 0 246 | androidEnableBanner: 1 247 | androidUseLowAccuracyLocation: 0 248 | m_AndroidBanners: 249 | - width: 320 250 | height: 180 251 | banner: {fileID: 0} 252 | androidGamepadSupportLevel: 0 253 | resolutionDialogBanner: {fileID: 0} 254 | m_BuildTargetIcons: [] 255 | m_BuildTargetPlatformIcons: [] 256 | m_BuildTargetBatching: 257 | - m_BuildTarget: Standalone 258 | m_StaticBatching: 1 259 | m_DynamicBatching: 0 260 | - m_BuildTarget: tvOS 261 | m_StaticBatching: 1 262 | m_DynamicBatching: 0 263 | - m_BuildTarget: Android 264 | m_StaticBatching: 1 265 | m_DynamicBatching: 0 266 | - m_BuildTarget: iPhone 267 | m_StaticBatching: 1 268 | m_DynamicBatching: 0 269 | - m_BuildTarget: WebGL 270 | m_StaticBatching: 0 271 | m_DynamicBatching: 0 272 | m_BuildTargetGraphicsAPIs: 273 | - m_BuildTarget: AndroidPlayer 274 | m_APIs: 0b00000015000000 275 | m_Automatic: 1 276 | - m_BuildTarget: iOSSupport 277 | m_APIs: 10000000 278 | m_Automatic: 1 279 | - m_BuildTarget: AppleTVSupport 280 | m_APIs: 10000000 281 | m_Automatic: 0 282 | - m_BuildTarget: WebGLSupport 283 | m_APIs: 0b000000 284 | m_Automatic: 1 285 | - m_BuildTarget: LinuxStandaloneSupport 286 | m_APIs: 1100000015000000 287 | m_Automatic: 1 288 | - m_BuildTarget: WindowsStandaloneSupport 289 | m_APIs: 1100000002000000 290 | m_Automatic: 0 291 | m_BuildTargetVRSettings: 292 | - m_BuildTarget: Standalone 293 | m_Enabled: 0 294 | m_Devices: 295 | - Oculus 296 | - OpenVR 297 | m_BuildTargetEnableVuforiaSettings: [] 298 | openGLRequireES31: 0 299 | openGLRequireES31AEP: 0 300 | m_TemplateCustomTags: {} 301 | mobileMTRendering: 302 | Android: 1 303 | iPhone: 1 304 | tvOS: 1 305 | m_BuildTargetGroupLightmapEncodingQuality: [] 306 | m_BuildTargetGroupLightmapSettings: [] 307 | playModeTestRunnerEnabled: 0 308 | runPlayModeTestAsEditModeTest: 0 309 | actionOnDotNetUnhandledException: 1 310 | enableInternalProfiler: 0 311 | logObjCUncaughtExceptions: 1 312 | enableCrashReportAPI: 0 313 | cameraUsageDescription: 314 | locationUsageDescription: 315 | microphoneUsageDescription: 316 | switchNetLibKey: 317 | switchSocketMemoryPoolSize: 6144 318 | switchSocketAllocatorPoolSize: 128 319 | switchSocketConcurrencyLimit: 14 320 | switchScreenResolutionBehavior: 2 321 | switchUseCPUProfiler: 0 322 | switchApplicationID: 0x01004b9000490000 323 | switchNSODependencies: 324 | switchTitleNames_0: 325 | switchTitleNames_1: 326 | switchTitleNames_2: 327 | switchTitleNames_3: 328 | switchTitleNames_4: 329 | switchTitleNames_5: 330 | switchTitleNames_6: 331 | switchTitleNames_7: 332 | switchTitleNames_8: 333 | switchTitleNames_9: 334 | switchTitleNames_10: 335 | switchTitleNames_11: 336 | switchTitleNames_12: 337 | switchTitleNames_13: 338 | switchTitleNames_14: 339 | switchPublisherNames_0: 340 | switchPublisherNames_1: 341 | switchPublisherNames_2: 342 | switchPublisherNames_3: 343 | switchPublisherNames_4: 344 | switchPublisherNames_5: 345 | switchPublisherNames_6: 346 | switchPublisherNames_7: 347 | switchPublisherNames_8: 348 | switchPublisherNames_9: 349 | switchPublisherNames_10: 350 | switchPublisherNames_11: 351 | switchPublisherNames_12: 352 | switchPublisherNames_13: 353 | switchPublisherNames_14: 354 | switchIcons_0: {fileID: 0} 355 | switchIcons_1: {fileID: 0} 356 | switchIcons_2: {fileID: 0} 357 | switchIcons_3: {fileID: 0} 358 | switchIcons_4: {fileID: 0} 359 | switchIcons_5: {fileID: 0} 360 | switchIcons_6: {fileID: 0} 361 | switchIcons_7: {fileID: 0} 362 | switchIcons_8: {fileID: 0} 363 | switchIcons_9: {fileID: 0} 364 | switchIcons_10: {fileID: 0} 365 | switchIcons_11: {fileID: 0} 366 | switchIcons_12: {fileID: 0} 367 | switchIcons_13: {fileID: 0} 368 | switchIcons_14: {fileID: 0} 369 | switchSmallIcons_0: {fileID: 0} 370 | switchSmallIcons_1: {fileID: 0} 371 | switchSmallIcons_2: {fileID: 0} 372 | switchSmallIcons_3: {fileID: 0} 373 | switchSmallIcons_4: {fileID: 0} 374 | switchSmallIcons_5: {fileID: 0} 375 | switchSmallIcons_6: {fileID: 0} 376 | switchSmallIcons_7: {fileID: 0} 377 | switchSmallIcons_8: {fileID: 0} 378 | switchSmallIcons_9: {fileID: 0} 379 | switchSmallIcons_10: {fileID: 0} 380 | switchSmallIcons_11: {fileID: 0} 381 | switchSmallIcons_12: {fileID: 0} 382 | switchSmallIcons_13: {fileID: 0} 383 | switchSmallIcons_14: {fileID: 0} 384 | switchManualHTML: 385 | switchAccessibleURLs: 386 | switchLegalInformation: 387 | switchMainThreadStackSize: 1048576 388 | switchPresenceGroupId: 389 | switchLogoHandling: 0 390 | switchReleaseVersion: 0 391 | switchDisplayVersion: 1.0.0 392 | switchStartupUserAccount: 0 393 | switchTouchScreenUsage: 0 394 | switchSupportedLanguagesMask: 0 395 | switchLogoType: 0 396 | switchApplicationErrorCodeCategory: 397 | switchUserAccountSaveDataSize: 0 398 | switchUserAccountSaveDataJournalSize: 0 399 | switchApplicationAttribute: 0 400 | switchCardSpecSize: -1 401 | switchCardSpecClock: -1 402 | switchRatingsMask: 0 403 | switchRatingsInt_0: 0 404 | switchRatingsInt_1: 0 405 | switchRatingsInt_2: 0 406 | switchRatingsInt_3: 0 407 | switchRatingsInt_4: 0 408 | switchRatingsInt_5: 0 409 | switchRatingsInt_6: 0 410 | switchRatingsInt_7: 0 411 | switchRatingsInt_8: 0 412 | switchRatingsInt_9: 0 413 | switchRatingsInt_10: 0 414 | switchRatingsInt_11: 0 415 | switchLocalCommunicationIds_0: 416 | switchLocalCommunicationIds_1: 417 | switchLocalCommunicationIds_2: 418 | switchLocalCommunicationIds_3: 419 | switchLocalCommunicationIds_4: 420 | switchLocalCommunicationIds_5: 421 | switchLocalCommunicationIds_6: 422 | switchLocalCommunicationIds_7: 423 | switchParentalControl: 0 424 | switchAllowsScreenshot: 1 425 | switchAllowsVideoCapturing: 1 426 | switchAllowsRuntimeAddOnContentInstall: 0 427 | switchDataLossConfirmation: 0 428 | switchUserAccountLockEnabled: 0 429 | switchSupportedNpadStyles: 3 430 | switchNativeFsCacheSize: 32 431 | switchIsHoldTypeHorizontal: 0 432 | switchSupportedNpadCount: 8 433 | switchSocketConfigEnabled: 0 434 | switchTcpInitialSendBufferSize: 32 435 | switchTcpInitialReceiveBufferSize: 64 436 | switchTcpAutoSendBufferSizeMax: 256 437 | switchTcpAutoReceiveBufferSizeMax: 256 438 | switchUdpSendBufferSize: 9 439 | switchUdpReceiveBufferSize: 42 440 | switchSocketBufferEfficiency: 4 441 | switchSocketInitializeEnabled: 1 442 | switchNetworkInterfaceManagerInitializeEnabled: 1 443 | switchPlayerConnectionEnabled: 1 444 | ps4NPAgeRating: 12 445 | ps4NPTitleSecret: 446 | ps4NPTrophyPackPath: 447 | ps4ParentalLevel: 11 448 | ps4ContentID: ED1633-NPXX51362_00-0000000000000000 449 | ps4Category: 0 450 | ps4MasterVersion: 01.00 451 | ps4AppVersion: 01.00 452 | ps4AppType: 0 453 | ps4ParamSfxPath: 454 | ps4VideoOutPixelFormat: 0 455 | ps4VideoOutInitialWidth: 1920 456 | ps4VideoOutBaseModeInitialWidth: 1920 457 | ps4VideoOutReprojectionRate: 60 458 | ps4PronunciationXMLPath: 459 | ps4PronunciationSIGPath: 460 | ps4BackgroundImagePath: 461 | ps4StartupImagePath: 462 | ps4StartupImagesFolder: 463 | ps4IconImagesFolder: 464 | ps4SaveDataImagePath: 465 | ps4SdkOverride: 466 | ps4BGMPath: 467 | ps4ShareFilePath: 468 | ps4ShareOverlayImagePath: 469 | ps4PrivacyGuardImagePath: 470 | ps4NPtitleDatPath: 471 | ps4RemotePlayKeyAssignment: -1 472 | ps4RemotePlayKeyMappingDir: 473 | ps4PlayTogetherPlayerCount: 0 474 | ps4EnterButtonAssignment: 1 475 | ps4ApplicationParam1: 0 476 | ps4ApplicationParam2: 0 477 | ps4ApplicationParam3: 0 478 | ps4ApplicationParam4: 0 479 | ps4DownloadDataSize: 0 480 | ps4GarlicHeapSize: 2048 481 | ps4ProGarlicHeapSize: 2560 482 | ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ 483 | ps4pnSessions: 1 484 | ps4pnPresence: 1 485 | ps4pnFriends: 1 486 | ps4pnGameCustomData: 1 487 | playerPrefsSupport: 0 488 | enableApplicationExit: 0 489 | resetTempFolder: 1 490 | restrictedAudioUsageRights: 0 491 | ps4UseResolutionFallback: 0 492 | ps4ReprojectionSupport: 0 493 | ps4UseAudio3dBackend: 0 494 | ps4SocialScreenEnabled: 0 495 | ps4ScriptOptimizationLevel: 0 496 | ps4Audio3dVirtualSpeakerCount: 14 497 | ps4attribCpuUsage: 0 498 | ps4PatchPkgPath: 499 | ps4PatchLatestPkgPath: 500 | ps4PatchChangeinfoPath: 501 | ps4PatchDayOne: 0 502 | ps4attribUserManagement: 0 503 | ps4attribMoveSupport: 0 504 | ps4attrib3DSupport: 0 505 | ps4attribShareSupport: 0 506 | ps4attribExclusiveVR: 0 507 | ps4disableAutoHideSplash: 0 508 | ps4videoRecordingFeaturesUsed: 0 509 | ps4contentSearchFeaturesUsed: 0 510 | ps4attribEyeToEyeDistanceSettingVR: 0 511 | ps4IncludedModules: [] 512 | monoEnv: 513 | splashScreenBackgroundSourceLandscape: {fileID: 0} 514 | splashScreenBackgroundSourcePortrait: {fileID: 0} 515 | spritePackerPolicy: 516 | webGLMemorySize: 256 517 | webGLExceptionSupport: 1 518 | webGLNameFilesAsHashes: 0 519 | webGLDataCaching: 1 520 | webGLDebugSymbols: 0 521 | webGLEmscriptenArgs: 522 | webGLModulesDirectory: 523 | webGLTemplate: APPLICATION:Default 524 | webGLAnalyzeBuildSize: 0 525 | webGLUseEmbeddedResources: 0 526 | webGLCompressionFormat: 1 527 | webGLLinkerTarget: 1 528 | webGLThreadsSupport: 0 529 | scriptingDefineSymbols: {} 530 | platformArchitecture: {} 531 | scriptingBackend: {} 532 | il2cppCompilerConfiguration: {} 533 | managedStrippingLevel: {} 534 | incrementalIl2cppBuild: {} 535 | allowUnsafeCode: 1 536 | additionalIl2CppArgs: 537 | scriptingRuntimeVersion: 1 538 | apiCompatibilityLevelPerPlatform: {} 539 | m_RenderingPath: 1 540 | m_MobileRenderingPath: 1 541 | metroPackageName: Template_3D 542 | metroPackageVersion: 543 | metroCertificatePath: 544 | metroCertificatePassword: 545 | metroCertificateSubject: 546 | metroCertificateIssuer: 547 | metroCertificateNotAfter: 0000000000000000 548 | metroApplicationDescription: Template_3D 549 | wsaImages: {} 550 | metroTileShortName: 551 | metroTileShowName: 0 552 | metroMediumTileShowName: 0 553 | metroLargeTileShowName: 0 554 | metroWideTileShowName: 0 555 | metroSupportStreamingInstall: 0 556 | metroLastRequiredScene: 0 557 | metroDefaultTileSize: 1 558 | metroTileForegroundText: 2 559 | metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} 560 | metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, 561 | a: 1} 562 | metroSplashScreenUseBackgroundColor: 0 563 | platformCapabilities: {} 564 | metroTargetDeviceFamilies: {} 565 | metroFTAName: 566 | metroFTAFileTypes: [] 567 | metroProtocolName: 568 | metroCompilationOverrides: 1 569 | XboxOneProductId: 570 | XboxOneUpdateKey: 571 | XboxOneSandboxId: 572 | XboxOneContentId: 573 | XboxOneTitleId: 574 | XboxOneSCId: 575 | XboxOneGameOsOverridePath: 576 | XboxOnePackagingOverridePath: 577 | XboxOneAppManifestOverridePath: 578 | XboxOneVersion: 1.0.0.0 579 | XboxOnePackageEncryption: 0 580 | XboxOnePackageUpdateGranularity: 2 581 | XboxOneDescription: 582 | XboxOneLanguage: 583 | - enus 584 | XboxOneCapability: [] 585 | XboxOneGameRating: {} 586 | XboxOneIsContentPackage: 0 587 | XboxOneEnableGPUVariability: 0 588 | XboxOneSockets: {} 589 | XboxOneSplashScreen: {fileID: 0} 590 | XboxOneAllowedProductIds: [] 591 | XboxOnePersistentLocalStorageSize: 0 592 | XboxOneXTitleMemory: 8 593 | xboxOneScriptCompiler: 0 594 | XboxOneOverrideIdentityName: 595 | vrEditorSettings: 596 | daydream: 597 | daydreamIconForeground: {fileID: 0} 598 | daydreamIconBackground: {fileID: 0} 599 | cloudServicesEnabled: 600 | UNet: 1 601 | luminIcon: 602 | m_Name: 603 | m_ModelFolderPath: 604 | m_PortalFolderPath: 605 | luminCert: 606 | m_CertPath: 607 | m_PrivateKeyPath: 608 | luminIsChannelApp: 0 609 | luminVersion: 610 | m_VersionCode: 1 611 | m_VersionName: 612 | facebookSdkVersion: 7.9.4 613 | facebookAppId: 614 | facebookCookies: 1 615 | facebookLogging: 1 616 | facebookStatus: 1 617 | facebookXfbml: 0 618 | facebookFrictionlessRequests: 1 619 | apiCompatibilityLevel: 3 620 | cloudProjectId: 621 | framebufferDepthMemorylessMode: 0 622 | projectName: 623 | organizationId: 624 | cloudEnabled: 0 625 | enableNativePlatformBackendsForNewInputSystem: 0 626 | disableOldInputManagerSupport: 0 627 | legacyClampBlendShapeWeights: 1 628 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2018.3.0b7 2 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 4 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Very Low 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 3 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | shadowmaskMode: 0 21 | blendWeights: 1 22 | textureQuality: 1 23 | anisotropicTextures: 0 24 | antiAliasing: 0 25 | softParticles: 0 26 | softVegetation: 0 27 | realtimeReflectionProbes: 0 28 | billboardsFaceCameraPosition: 0 29 | vSyncCount: 0 30 | lodBias: 0.3 31 | maximumLODLevel: 0 32 | streamingMipmapsActive: 0 33 | streamingMipmapsAddAllCameras: 1 34 | streamingMipmapsMemoryBudget: 512 35 | streamingMipmapsRenderersPerFrame: 512 36 | streamingMipmapsMaxLevelReduction: 2 37 | streamingMipmapsMaxFileIORequests: 1024 38 | particleRaycastBudget: 4 39 | asyncUploadTimeSlice: 2 40 | asyncUploadBufferSize: 4 41 | asyncUploadPersistentBuffer: 1 42 | resolutionScalingFixedDPIFactor: 1 43 | excludedTargetPlatforms: [] 44 | - serializedVersion: 2 45 | name: Low 46 | pixelLightCount: 0 47 | shadows: 0 48 | shadowResolution: 0 49 | shadowProjection: 1 50 | shadowCascades: 1 51 | shadowDistance: 20 52 | shadowNearPlaneOffset: 3 53 | shadowCascade2Split: 0.33333334 54 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 55 | shadowmaskMode: 0 56 | blendWeights: 2 57 | textureQuality: 0 58 | anisotropicTextures: 0 59 | antiAliasing: 0 60 | softParticles: 0 61 | softVegetation: 0 62 | realtimeReflectionProbes: 0 63 | billboardsFaceCameraPosition: 0 64 | vSyncCount: 0 65 | lodBias: 0.4 66 | maximumLODLevel: 0 67 | streamingMipmapsActive: 0 68 | streamingMipmapsAddAllCameras: 1 69 | streamingMipmapsMemoryBudget: 512 70 | streamingMipmapsRenderersPerFrame: 512 71 | streamingMipmapsMaxLevelReduction: 2 72 | streamingMipmapsMaxFileIORequests: 1024 73 | particleRaycastBudget: 16 74 | asyncUploadTimeSlice: 2 75 | asyncUploadBufferSize: 4 76 | asyncUploadPersistentBuffer: 1 77 | resolutionScalingFixedDPIFactor: 1 78 | excludedTargetPlatforms: [] 79 | - serializedVersion: 2 80 | name: Medium 81 | pixelLightCount: 1 82 | shadows: 1 83 | shadowResolution: 0 84 | shadowProjection: 1 85 | shadowCascades: 1 86 | shadowDistance: 20 87 | shadowNearPlaneOffset: 3 88 | shadowCascade2Split: 0.33333334 89 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 90 | shadowmaskMode: 0 91 | blendWeights: 2 92 | textureQuality: 0 93 | anisotropicTextures: 1 94 | antiAliasing: 0 95 | softParticles: 0 96 | softVegetation: 0 97 | realtimeReflectionProbes: 0 98 | billboardsFaceCameraPosition: 0 99 | vSyncCount: 1 100 | lodBias: 0.7 101 | maximumLODLevel: 0 102 | streamingMipmapsActive: 0 103 | streamingMipmapsAddAllCameras: 1 104 | streamingMipmapsMemoryBudget: 512 105 | streamingMipmapsRenderersPerFrame: 512 106 | streamingMipmapsMaxLevelReduction: 2 107 | streamingMipmapsMaxFileIORequests: 1024 108 | particleRaycastBudget: 64 109 | asyncUploadTimeSlice: 2 110 | asyncUploadBufferSize: 4 111 | asyncUploadPersistentBuffer: 1 112 | resolutionScalingFixedDPIFactor: 1 113 | excludedTargetPlatforms: [] 114 | - serializedVersion: 2 115 | name: High 116 | pixelLightCount: 2 117 | shadows: 2 118 | shadowResolution: 1 119 | shadowProjection: 1 120 | shadowCascades: 2 121 | shadowDistance: 40 122 | shadowNearPlaneOffset: 3 123 | shadowCascade2Split: 0.33333334 124 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 125 | shadowmaskMode: 1 126 | blendWeights: 2 127 | textureQuality: 0 128 | anisotropicTextures: 1 129 | antiAliasing: 2 130 | softParticles: 0 131 | softVegetation: 1 132 | realtimeReflectionProbes: 1 133 | billboardsFaceCameraPosition: 1 134 | vSyncCount: 1 135 | lodBias: 1 136 | maximumLODLevel: 0 137 | streamingMipmapsActive: 0 138 | streamingMipmapsAddAllCameras: 1 139 | streamingMipmapsMemoryBudget: 512 140 | streamingMipmapsRenderersPerFrame: 512 141 | streamingMipmapsMaxLevelReduction: 2 142 | streamingMipmapsMaxFileIORequests: 1024 143 | particleRaycastBudget: 256 144 | asyncUploadTimeSlice: 2 145 | asyncUploadBufferSize: 4 146 | asyncUploadPersistentBuffer: 1 147 | resolutionScalingFixedDPIFactor: 1 148 | excludedTargetPlatforms: [] 149 | - serializedVersion: 2 150 | name: Very High 151 | pixelLightCount: 3 152 | shadows: 2 153 | shadowResolution: 2 154 | shadowProjection: 1 155 | shadowCascades: 2 156 | shadowDistance: 40 157 | shadowNearPlaneOffset: 3 158 | shadowCascade2Split: 0.33333334 159 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 160 | shadowmaskMode: 1 161 | blendWeights: 4 162 | textureQuality: 0 163 | anisotropicTextures: 1 164 | antiAliasing: 4 165 | softParticles: 1 166 | softVegetation: 1 167 | realtimeReflectionProbes: 1 168 | billboardsFaceCameraPosition: 1 169 | vSyncCount: 0 170 | lodBias: 1.5 171 | maximumLODLevel: 0 172 | streamingMipmapsActive: 0 173 | streamingMipmapsAddAllCameras: 1 174 | streamingMipmapsMemoryBudget: 512 175 | streamingMipmapsRenderersPerFrame: 512 176 | streamingMipmapsMaxLevelReduction: 2 177 | streamingMipmapsMaxFileIORequests: 1024 178 | particleRaycastBudget: 1024 179 | asyncUploadTimeSlice: 2 180 | asyncUploadBufferSize: 4 181 | asyncUploadPersistentBuffer: 1 182 | resolutionScalingFixedDPIFactor: 1 183 | excludedTargetPlatforms: [] 184 | - serializedVersion: 2 185 | name: Ultra 186 | pixelLightCount: 4 187 | shadows: 2 188 | shadowResolution: 2 189 | shadowProjection: 1 190 | shadowCascades: 4 191 | shadowDistance: 150 192 | shadowNearPlaneOffset: 3 193 | shadowCascade2Split: 0.33333334 194 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 195 | shadowmaskMode: 1 196 | blendWeights: 4 197 | textureQuality: 0 198 | anisotropicTextures: 1 199 | antiAliasing: 4 200 | softParticles: 1 201 | softVegetation: 1 202 | realtimeReflectionProbes: 1 203 | billboardsFaceCameraPosition: 1 204 | vSyncCount: 1 205 | lodBias: 2 206 | maximumLODLevel: 0 207 | streamingMipmapsActive: 0 208 | streamingMipmapsAddAllCameras: 1 209 | streamingMipmapsMemoryBudget: 512 210 | streamingMipmapsRenderersPerFrame: 512 211 | streamingMipmapsMaxLevelReduction: 2 212 | streamingMipmapsMaxFileIORequests: 1024 213 | particleRaycastBudget: 4096 214 | asyncUploadTimeSlice: 2 215 | asyncUploadBufferSize: 4 216 | asyncUploadPersistentBuffer: 1 217 | resolutionScalingFixedDPIFactor: 1 218 | excludedTargetPlatforms: [] 219 | m_PerPlatformDefaultQuality: 220 | Android: 2 221 | Nintendo 3DS: 5 222 | Nintendo Switch: 5 223 | PS4: 5 224 | PSP2: 2 225 | Standalone: 5 226 | Tizen: 2 227 | WebGL: 3 228 | WiiU: 5 229 | Windows Store Apps: 5 230 | XboxOne: 5 231 | iPhone: 2 232 | tvOS: 2 233 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 15 | - 16 | - PostProcessing 17 | - 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | - 39 | - 40 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.1 8 | m_TimeScale: 1 9 | Maximum Particle Timestep: 0.03 10 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 1 7 | m_Enabled: 1 8 | m_TestMode: 0 9 | m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events 10 | m_EventUrl: https://cdp.cloud.unity3d.com/v1/events 11 | m_ConfigUrl: https://config.uca.cloud.unity3d.com 12 | m_TestInitMode: 0 13 | CrashReportingSettings: 14 | m_EventUrl: https://perf-events.cloud.unity3d.com 15 | m_Enabled: 0 16 | m_LogBufferSize: 10 17 | m_CaptureEditorExceptions: 1 18 | UnityPurchasingSettings: 19 | m_Enabled: 0 20 | m_TestMode: 0 21 | UnityAnalyticsSettings: 22 | m_Enabled: 0 23 | m_TestMode: 0 24 | m_InitializeOnStartup: 1 25 | UnityAdsSettings: 26 | m_Enabled: 0 27 | m_InitializeOnStartup: 1 28 | m_TestMode: 0 29 | m_IosGameId: 30 | m_AndroidGameId: 31 | m_GameIds: {} 32 | m_GameId: 33 | PerformanceReportingSettings: 34 | m_Enabled: 0 35 | -------------------------------------------------------------------------------- /UnityExampleProject/ProjectSettings/VFXManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!937362698 &1 4 | VFXManager: 5 | m_ObjectHideFlags: 0 6 | m_IndirectShader: {fileID: 0} 7 | m_CopyBufferShader: {fileID: 0} 8 | m_SortShader: {fileID: 0} 9 | m_RenderPipeSettingsPath: 10 | m_FixedTimeStep: 0.016666668 11 | m_MaxDeltaTime: 0.05 12 | --------------------------------------------------------------------------------