Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
#include "Headers/GLWrapper.h"

#include "GUI/Headers/GUI.h"
#include "Core/Headers/Application.h"
#include "Core/Headers/ParamHandler.h"
#include "Platform/Video/Headers/GFXDevice.h"
#include "Platform/Video/OpenGL/Buffers/Headers/glMemoryManager.h"
#include "Platform/Video/OpenGL/Buffers/ShaderBuffer/Headers/glUniformBuffer.h"
#include "Platform/Video/OpenGL/Buffers/VertexBuffer/Headers/glVertexArray.h"

#ifndef CEGUI_STATIC
#define CEGUI_STATIC
#endif //CEGUI_STATIC

#include <CEGUI/CEGUI.h>
#include <CEGUI/RendererModules/OpenGL/GL3Renderer.h>

#include <GLIM/glim.h>
#include <chrono>
#include <thread>

#define HAVE_M_PI
#include <SDL.h>

namespace Divide {
namespace {
    const U32 g_maxVAOS = 512u;

    class ContextPool {
    public:
        ContextPool()
        {
            _contexts.reserve(HARDWARE_THREAD_COUNT() * 2);
        }

        ~ContextPool() 
        {
            assert(_contexts.empty());
        }

        bool init(U32 size, const DisplayWindow& window) {
            WriteLock w_lock(_glContextLock);
            _contexts.resize(size, std::make_pair(nullptr, false));
            for (std::pair<SDL_GLContext, bool>& ctx : _contexts) {
                ctx.first = SDL_GL_CreateContext(window.getRawWindow());
            }
            return true;
        }

        bool destroy() {
            WriteLock w_lock(_glContextLock);
            for (std::pair<SDL_GLContext, bool>& ctx : _contexts) {
                SDL_GL_DeleteContext(ctx.first);
            }
            _contexts.clear();
            return true;
        }

        bool getAvailableContext(SDL_GLContext& ctx) {
            UpgradableReadLock ur_lock(_glContextLock);
            for (std::pair<SDL_GLContext, bool>& ctxIt : _contexts) {
                if (!ctxIt.second) {
                    UpgradeToWriteLock w_lock(ur_lock);
                    ctx = ctxIt.first;
                    ctxIt.second = true;
                    return true;
                }
            }

            return false;
        }

    private:
        SharedLock _glContextLock;
        vectorImpl<std::pair<SDL_GLContext, bool /*in use*/>> _contexts;
    } g_ContextPool;
};

ErrorCode GL_API::createGLContext(const DisplayWindow& window) {
    assert(_mainRenderWindow == nullptr);
    _mainRenderWindow = &window;

    g_ContextPool.init(HARDWARE_THREAD_COUNT() * 2, window);
    GLUtil::_glRenderContext = SDL_GL_CreateContext(window.getRawWindow());
    if (GLUtil::_glRenderContext == nullptr)
    {
    	Console::errorfn(Locale::get(_ID("ERROR_GFX_DEVICE")),
    					 Locale::get(_ID("ERROR_GL_OLD_VERSION")));
    	Console::printfn(Locale::get(_ID("WARN_SWITCH_D3D")));
    	Console::printfn(Locale::get(_ID("WARN_APPLICATION_CLOSE")));
   		return ErrorCode::OGL_OLD_HARDWARE;
    }

    return ErrorCode::NO_ERR;
}

ErrorCode GL_API::destroyGLContext() {
    SDL_GL_DeleteContext(GLUtil::_glRenderContext);
    g_ContextPool.destroy();

    return ErrorCode::NO_ERR;
}


/// Try and create a valid OpenGL context taking in account the specified
/// resolution and command line arguments
ErrorCode GL_API::initRenderingAPI(GLint argc, char** argv) {
    ParamHandler& par = ParamHandler::instance();

    // Fill our (abstract API <-> openGL) enum translation tables with proper
    // values
    GLUtil::fillEnumTables();

    const DisplayWindow& window = Application::instance().windowManager().getActiveWindow();
    ErrorCode errorState = createGLContext(window);
    if (errorState != ErrorCode::NO_ERR) {
        return errorState;
    }

    SDL_GL_MakeCurrent(window.getRawWindow(), GLUtil::_glRenderContext);
    glbinding::Binding::initialize();
    if (glbinding::getCurrentContext() == 0) {
        return ErrorCode::GLBINGING_INIT_ERROR;
    }

    glbinding::Binding::useCurrentContext();

    // OpenGL has a nifty error callback system, available in every build
    // configuration if required
    if (Config::ENABLE_GPU_VALIDATION) {
        // GL_DEBUG_OUTPUT_SYNCHRONOUS is essential for debugging gl commands in the IDE
        glEnable(GL_DEBUG_OUTPUT);
        glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
        // hardwire our debug callback function with OpenGL's implementation
        glDebugMessageCallback((GLDEBUGPROC)GLUtil::DebugCallback, nullptr);
        // nVidia flushes a lot of useful info about buffer allocations and shader
        // recompiles due to state and what now, but those aren't needed until that's
        // what's actually causing the bottlenecks
        /*U32 nvidiaBufferErrors[] = { 131185, 131218 };
        // Disable shader compiler errors (shader class handles that)
        glDebugMessageControl(GL_DEBUG_SOURCE_SHADER_COMPILER, GL_DEBUG_TYPE_ERROR,
            GL_DONT_CARE, 0, nullptr, GL_FALSE);
        // Disable nVidia buffer allocation info (an easy enable is to change the
        // count param to 0)
        glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_OTHER,
            GL_DONT_CARE, 2, nvidiaBufferErrors, GL_FALSE);
        // Shader will be recompiled nVidia error
        glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_PERFORMANCE,
            GL_DONT_CARE, 2, nvidiaBufferErrors, GL_FALSE);*/
    }

    // Vsync is toggled on or off via the external config file
    SDL_GL_SetSwapInterval(par.getParam<bool>(_ID("runtime.enableVSync"), false) ? 1 : 0);
        
    // If we got here, let's figure out what capabilities we have available
    // Maximum addressable texture image units in the fragment shader
    s_maxTextureUnits = GLUtil::getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS);
    s_maxAttribBindings = GLUtil::getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS);
    s_vaoBufferData.init(s_maxAttribBindings);

    assert(to_const_uint(AttribLocation::COUNT) < to_uint(s_maxAttribBindings) &&
           "GL Wrapper: insufficient number of attribute binding locations available on current hardware!");

    Console::printfn(Locale::get(_ID("GL_MAX_TEX_UNITS_FRAG")), s_maxTextureUnits);
    
    // Maximum number of colour attachments per framebuffer
    par.setParam<I32>(_ID("rendering.maxRenderTargetOutputs"),
                      GLUtil::getIntegerv(GL_MAX_COLOR_ATTACHMENTS));

    // Query GPU vendor to enable/disable vendor specific features
    GPUVendor vendor = GPUVendor::COUNT;
    const char* gpuVendorStr = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
    if (gpuVendorStr != nullptr) {
        if (strstr(gpuVendorStr, "Intel") != nullptr) {
            vendor = GPUVendor::INTEL;
        } else if (strstr(gpuVendorStr, "NVIDIA") != nullptr) {
            vendor = GPUVendor::NVIDIA;
        } else if (strstr(gpuVendorStr, "ATI") != nullptr || strstr(gpuVendorStr, "AMD") != nullptr) {
            vendor = GPUVendor::AMD;
        } else if(strstr(gpuVendorStr, "Microsoft") != nullptr) {
            vendor = GPUVendor::MICROSOFT;
        } else {
            vendor = GPUVendor::OTHER;
        }
    } else {
        gpuVendorStr = "Unknown GPU Vendor";
        vendor = GPUVendor::OTHER;
    }
    GPURenderer renderer = GPURenderer::COUNT;
    const char* gpuRendererStr = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
    if (gpuRendererStr != nullptr) {
        if (strstr(gpuRendererStr,"Tegra") || strstr(gpuRendererStr, "GeForce") || strstr(gpuRendererStr, "NV")) {
            renderer = GPURenderer::GEFORCE;
        } else if(strstr(gpuRendererStr, "PowerVR") || strstr(gpuRendererStr, "Apple")) {
            renderer = GPURenderer::POWERVR;
            vendor = GPUVendor::IMAGINATION_TECH;
        } else if(strstr(gpuRendererStr, "Mali")) {
            renderer = GPURenderer::MALI;
            vendor = GPUVendor::ARM;
        } else if (strstr(gpuRendererStr, "Adreno")) {
            renderer = GPURenderer::ADRENO;
            vendor = GPUVendor::QUALCOMM;
        } else if(strstr(gpuRendererStr, "AMD") || strstr(gpuRendererStr, "ATI")) {
            renderer = GPURenderer::RADEON;
        } else if (strstr(gpuRendererStr, "Intel")) {
            renderer = GPURenderer::INTEL;
        } else if(strstr(gpuRendererStr, "Vivante")) {
            renderer = GPURenderer::VIVANTE;
            vendor = GPUVendor::VIVANTE;
        } else if(strstr(gpuRendererStr, "VideoCore")) {
            renderer = GPURenderer::VIDEOCORE;
            vendor = GPUVendor::ALPHAMOSAIC;
        } else if(strstr(gpuRendererStr, "WebKit") || strstr(gpuRendererStr, "Mozilla") || strstr(gpuRendererStr, "ANGLE")) {
            renderer = GPURenderer::WEBGL;
            vendor = GPUVendor::WEBGL;
        } else {
            renderer = GPURenderer::UNKNOWN;
        }
    } else {
        gpuRendererStr = "Unknown GPU Renderer";
        renderer = GPURenderer::UNKNOWN;
    }

    _context.setGPURenderer(renderer);
    _context.setGPUVendor(vendor);
    // Cap max anisotropic level to what the hardware supports
    par.setParam(
        _ID("rendering.anisotropicFilteringLevel"),
        std::min(
            GLUtil::getIntegerv(gl::GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT),
            par.getParam<GLint>(_ID("rendering.anisotropicFilteringLevel"), 1)));

    Console::printfn(Locale::get(_ID("GL_MAX_VERSION")),
                     GLUtil::getIntegerv(GL_MAJOR_VERSION),
                     GLUtil::getIntegerv(GL_MINOR_VERSION));

    // Number of sample buffers associated with the framebuffer & MSAA sample
    // count
    GLint samplerBuffers = GLUtil::getIntegerv(GL_SAMPLES);
    GLint sampleCount = GLUtil::getIntegerv(GL_SAMPLE_BUFFERS);
    Console::printfn(Locale::get(_ID("GL_MULTI_SAMPLE_INFO")), sampleCount,
                     samplerBuffers);
    // If we do not support MSAA on a hardware level for whatever reason,
    // override user set MSAA levels
    I32 msaaSamples = par.getParam<I32>(_ID("rendering.MSAAsampless"), 0);
    if (samplerBuffers == 0 || sampleCount == 0) {
        msaaSamples = 0;
    }
    // Print all of the OpenGL functionality info to the console and log
    // How many uniforms can we send to fragment shaders
    Console::printfn(Locale::get(_ID("GL_MAX_UNIFORM")),
                     GLUtil::getIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS));
    // How many uniforms can we send to vertex shaders
    Console::printfn(Locale::get(_ID("GL_MAX_VERT_UNIFORM")),
                     GLUtil::getIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS));
    // How many attributes can we send to a vertex shader
    Console::printfn(Locale::get(_ID("GL_MAX_VERT_ATTRIB")),
                     GLUtil::getIntegerv(GL_MAX_VERTEX_ATTRIBS));
    // Maximum number of texture units we can address in shaders
    Console::printfn(Locale::get(_ID("GL_MAX_TEX_UNITS")),
                     GLUtil::getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS),
                     GL_API::s_maxTextureUnits);
    // Query shading language version support
    Console::printfn(Locale::get(_ID("GL_GLSL_SUPPORT")),
                     glGetString(GL_SHADING_LANGUAGE_VERSION));
    // GPU info, including vendor, gpu and driver
    Console::printfn(Locale::get(_ID("GL_VENDOR_STRING")),
                     gpuVendorStr, gpuRendererStr, glGetString(GL_VERSION));
    // In order: Maximum number of uniform buffer binding points,
    //           maximum size in basic machine units of a uniform block and
    //           minimum required alignment for uniform buffer sizes and offset
    GL_API::s_UBOffsetAlignment = GLUtil::getIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
    GL_API::s_UBMaxSize = GLUtil::getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE);
    Console::printfn(Locale::get(_ID("GL_UBO_INFO")),
                     GLUtil::getIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS),
                     GL_API::s_UBMaxSize / 1024,
                     GL_API::s_UBOffsetAlignment);

    // In order: Maximum number of shader storage buffer binding points,
    //           maximum size in basic machine units of a shader storage block,
    //           maximum total number of active shader storage blocks that may
    //           be accessed by all active shaders and
    //           minimum required alignment for shader storage buffer sizes and
    //           offset.
    GL_API::s_SSBOffsetAlignment = GLUtil::getIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
    GL_API::s_SSBMaxSize = GLUtil::getIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
    Console::printfn(
        Locale::get(_ID("GL_SSBO_INFO")),
        GLUtil::getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS),
        (GLUtil::getIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE) / 1024) / 1024,
        GLUtil::getIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS),
        GL_API::s_SSBOffsetAlignment);

    // Maximum number of subroutines and maximum number of subroutine uniform
    // locations usable in a shader
    Console::printfn(Locale::get(_ID("GL_SUBROUTINE_INFO")),
                     GLUtil::getIntegerv(GL_MAX_SUBROUTINES),
                     GLUtil::getIntegerv(GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS));

    // Seamless cubemaps are a nice feature to have enabled (core since 3.2)
    glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
    //glEnable(GL_FRAMEBUFFER_SRGB);
    // Enable multisampling if we actually support and request it
    msaaSamples  > 0 ? glEnable(GL_MULTISAMPLE) :  glDisable(GL_MULTISAMPLE);

    // Line smoothing should almost always be used
    if (Config::USE_HARDWARE_AA_LINES) {
        glEnable(GL_LINE_SMOOTH);
        glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &s_lineWidthLimit);
    } else {
        glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &s_lineWidthLimit);
    }

    // Culling is enabled by default, but RenderStateBlocks can toggle it on a
    // per-draw call basis
    glEnable(GL_CULL_FACE);

    // Prepare font rendering subsystem
    if (!createFonsContext()) {
        Console::errorfn(Locale::get(_ID("ERROR_FONT_INIT")));
        return ErrorCode::FONT_INIT_ERROR;
    }

    // Prepare immediate mode emulation rendering
    NS_GLIM::glim.SetVertexAttribLocation(to_const_uint(AttribLocation::VERTEX_POSITION));
    // Initialize our VAO pool
    GLUtil::_vaoPool.init(g_maxVAOS);
    // Initialize shader buffers
    glUniformBuffer::onGLInit();
    // We need a dummy VAO object for point rendering
    s_dummyVAO = GLUtil::_vaoPool.allocate();

    // In debug, we also have various performance counters to profile GPU rendering
    // operations
    if (Config::ENABLE_GPU_VALIDATION) {
        // We have multiple counter buffers, and each can be multi-buffered
        // (currently, only double-buffered, front and back)
        // to avoid pipeline stalls
        for (glHardwareQueryRing* queryRing : _hardwareQueries) {
            queryRing->initQueries();
        }
    }
    
    // Once OpenGL is ready for rendering, init CEGUI
    _GUIGLrenderer = &CEGUI::OpenGL3Renderer::create();
    _GUIGLrenderer->enableExtraStateSettings(par.getParam<bool>(_ID("GUI.CEGUI.ExtraStates")));
    CEGUI::System::create(*_GUIGLrenderer);

    static const vec4<F32> clearColour = DefaultColours::DIVIDE_BLUE();
    glClearColor(clearColour.r, clearColour.g, clearColour.b, clearColour.a);

    // Prepare shader headers and various shader related states
    if (initShaders()) {
        // That's it. Everything should be ready for draw calls
        Console::printfn(Locale::get(_ID("START_OGL_API_OK")));

        return ErrorCode::NO_ERR;
    }

    return ErrorCode::GLSL_INIT_ERROR;
}

/// Clear everything that was setup in initRenderingAPI()
void GL_API::closeRenderingAPI() {
    if (!deInitShaders()) {
        DIVIDE_UNEXPECTED_CALL("GLSL failed to shutdown!");
    }

    CEGUI::OpenGL3Renderer::destroy(*_GUIGLrenderer);
    _GUIGLrenderer = nullptr;
    // Destroy sampler objects
    {
        WriteLock w_lock(s_samplerMapLock);
        MemoryManager::DELETE_HASHMAP(s_samplerMap);
    }
    // Destroy the text rendering system
    deleteFonsContext();
    _fonts.clear();
    // If we have an indirect draw buffer, delete it
    if (s_indirectDrawBuffer > 0) {
        glDeleteBuffers(1, &s_indirectDrawBuffer);
        s_indirectDrawBuffer = 0;
    }
    if (s_dummyVAO > 0) {
        glDeleteVertexArrays(1, &s_dummyVAO);
        s_dummyVAO = 0;
    }
    glVertexArray::cleanup();
    GLUtil::clearVBOs();
    GLUtil::_vaoPool.destroy();

    destroyGLContext();
}

void GL_API::syncToThread(const std::thread::id& threadID) {
    ACKNOWLEDGE_UNUSED(threadID);
    if (glbinding::getCurrentContext() == 0) {
        // Double check so that we don't run into a race condition!
        UpgradableReadLock r_lock(GLUtil::_glSecondaryContextMutex);
        if (glbinding::getCurrentContext() == 0) {
            UpgradeToWriteLock w_lock(r_lock);
            // This also makes the context current
            assert(GLUtil::_glSecondaryContext == nullptr && "GL_API::syncToThread: double init context for current thread!");
            bool ctxFound = g_ContextPool.getAvailableContext(GLUtil::_glSecondaryContext);
            assert(ctxFound && "GL_API::syncToThread: context not found for current thread!");
            ACKNOWLEDGE_UNUSED(ctxFound);
            SDL_GL_MakeCurrent(_mainRenderWindow->getRawWindow(), GLUtil::_glSecondaryContext);
            glbinding::Binding::initialize(false);
            // Enable OpenGL debug callbacks for this context as well
            if (Config::ENABLE_GPU_VALIDATION) {
                glEnable(GL_DEBUG_OUTPUT);
                glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
                // Debug callback in a separate thread requires a flag to distinguish it
                // from the main thread's callbacks
                glDebugMessageCallback((GLDEBUGPROC)GLUtil::DebugCallback, GLUtil::_glSecondaryContext);
            }
        }
    }
}

};

Commits for Divide-Framework/trunk/Source Code/Platform/Video/OpenGL/SDLWindowWrapper.cpp

Diff revisions: vs.
Revision Author Commited Message
827 Diff Diff IonutCava picture IonutCava Sun 22 Jan, 2017 21:59:36 +0000

[IonutCava]
- ShaderBuffers now decide heuristically if they get persistently mapped or not (depends on size. Current limit is 512Kb for subData calls.
- Separate visible node command generation into 2 steps: onRender and getDrawPackage. onRender allows the creation of parallel tasks that should finish by the time the second call, getDrawPackage reaches the same node
- Update ParticleEmitter to take into account multiple players and increase parallelism at the cost of memory consumption and complexity.
- Add a default bounding box for Players (add extents to SceneTransform nodes)
- All buffers (ShaderBuffer, d3dConstantBuffer, glUniformBuffer, glBufferImpl, glGenericBuffer, etc) use BufferParams for creation.
— Constructor and create calls have been merged together

806 Diff Diff IonutCava picture IonutCava Sun 08 Jan, 2017 22:00:48 +0000

[IonutCava]
- Finish implementing per-fragment velocity computation using a compute shader
— Further tuning still needed
- Add VS2017 build targets

801 Diff Diff IonutCava picture IonutCava Sun 27 Nov, 2016 21:28:01 +0000

[IonutCava]
- More performance analysis guided optimizations.
- Some refactoring to allow later removal of Singletons status for: GFXDevice, SFXDevice, PXDevice, GUI and Input.
— Pass a PlatformContext around objects to access these classes.

800 Diff Diff IonutCava picture IonutCava Fri 25 Nov, 2016 17:04:02 +0000

[IonutCava]
- More profile-guided optimizations
- Added GLSL normal map blending methods from: http://blog.selfshadow.com/sandbox/normals.html
- Added more profile timers

799 Diff Diff IonutCava picture IonutCava Thu 24 Nov, 2016 22:55:23 +0000

[IonutCava]
- Performance analysis guided optimizations.

795 Diff Diff IonutCava picture IonutCava Wed 23 Nov, 2016 17:14:33 +0000

[IonutCava]
- Remove ULL. Use U64 instead
- Various small bug fixes and typos.

794 Diff Diff IonutCava picture IonutCava Tue 22 Nov, 2016 16:44:26 +0000

[IonutCava]
- Change SDL_GL_Context management from a pool-based system to a thread_local variable type System
- Reworked SceneGraphNode child access for safer and faster iteration.
— Added a forEachChild with multiple overloads to apply a lambda expression over every child of the target SGN
- Slight optimization to Text rendering by batching all labels due for rendering and submitting them at all at once

790 Diff Diff IonutCava picture IonutCava Wed 02 Nov, 2016 17:06:20 +0000

[IonutCava]
- Fix a few crashes:
— Missing language file during startup causes crash instead of log + exit
— Closing application causes crash due to RenderTarget cleanup of the GPU Object arena
-— Still not fully fixed: leaking graphics resources on shutdown
- Make mat and vec constructors and assignment operators “noexcept” (helps with usage in containers)
- Add a “NonMovable” class, similar to the “NonCopyable” class to help with readability in certain situations

777 Diff Diff IonutCava picture IonutCava Fri 07 Oct, 2016 16:14:48 +0000

[IonutCava]
- Continue to implement CommandBuffer / RenderPass / RenderSubPass system.
— Rendering artefacts are still present.

772 IonutCava picture IonutCava Thu 29 Sep, 2016 15:50:57 +0000

[IonutCava]
- Better GPU Vendor / Renderer detection