Git Product home page Git Product logo

devsh-graphics-programming / nabla Goto Github PK

View Code? Open in Web Editor NEW
436.0 14.0 48.0 1.88 GB

Vulkan, OptiX and CUDA Interoperation Modular Rendering Library and Framework for PC/Linux/Android

Home Page: http://devsh.eu

License: Apache License 2.0

CMake 2.68% C++ 85.61% GLSL 7.26% C 0.82% Python 0.32% Java 0.04% HLSL 3.17% Groovy 0.04% Dockerfile 0.06% Batchfile 0.01%
vulkan raytracing graphics-engine graphics-library optix optix-denoiser cuda-opengl pbr path-tracing spir-v

nabla's Introduction

Nabla

License

Nabla (previously called IrrlichtBaW ) is a new renovated version of older Irrlicht engine. The name change to Nabla allows for using Nabla side by side with the legacy Irrlicht and IrrlichtBaW engines. The project currently aims for a thread-able and Vulkan-centered API, the Vulkan backend is almost complete, and OpenGL and ES backends are currently in maintenance mode.

This framework has been kindly begun by the founder @devshgraphicsprogramming of Devsh Graphics Programming Sp. z O.O. and was almost entirely sponsored by Build A World Aps in its early days, now it has been picked up by Ditt B.V..

(Get Hired) Jobs and Internships

If you are a programmer with a passion for High Performance Computing, Mathematics and Computer Graphics

If you can be in charge of your own time managment and work 4-day work weeks 100% remotely

Then make something impressive using Nabla, open a PR and contact us ([email protected] or discord) with your CV.

We would also be happy to sponsor your master or bachelor thesis as long as:

  • You are an above average student with an interest in Graphics
  • It will be written in English
  • It will produce contributions to Nabla which we can license under Apache 2.0

For internships contact us with:

  • CV in english
  • A neat description of any paperwork you'll need (schools/universities) Most importantly contact us at least 3 weeks in advance of your internship organisation deadline!

(Hire Us) Contracting

The members of Devsh Graphics Programming Sp. z O.O. (Company Registration (KRS) #: 0000764661) are available (individually or collectively) for contracts on projects of various scopes and timescales, especially on foreign frameworks, codebases and third-party 3D frameworks.

We provide expertise in:

  • OpenGL
  • OpenGL ES
  • WebGL
  • WebGPU
  • Vulkan
  • OpenCL
  • CUDA
  • D3D12 and D3D11
  • computer vision
  • Audio programming
  • DSP
  • video encoding and decoding
  • High Performance Computing

Our language of choice is C++20 however we're also amenable to C#, Java, Python and related languages.

Contact [email protected] with inquires into contracting.

Showcase

Screenshots

Our Production Mitsuba Compatible Path Tracer made for Ditt B.V.

Currently working on the ditt branch, in the process of being ported to Vulkan KHR Raytracing.

You can download a stable build here

Main Features

  • Frontend API with Vulkan as First Class Citizen
  • Thread safe and context pollution safe OpenGL
  • Asset management pipeline
  • Automatic pipeline layout creation
  • Shader introspection
  • Using SPIR-V shaders in OpenGL and ES
  • Libraries of GLSL shader functions
  • Compute shaders
  • Virtual Texturing
  • Virtual Geometry (programmable and non programmble fetching) with triangle batching
  • CUDA and Vulkan interop
  • CPU asset manipulation (image filtering, image format transcoding, mesh optimization and manipulation)
  • GPU driven Scene Graph
  • Material Compiler for Path Tracing UberShaders

Main Delivered Extensions

  • Auto Exposure
  • Tonemapper
  • Mitsuba scene loader (auto-generated shaders)
  • Fastest blur on the planet
  • OptiX interop
  • Bullet physics beginner integration
  • GPU Radix Sort

Platforms

  • Windows

  • Linux

  • Android 7.0 +

  • Mac OS

  • iOS

Build summary

Release RWDI Debug
Windows MSVC x64
Android Clang x86_64
Linux GCC x64

Quick start

Use Nabla from package

TODO - soon

Build Nabla with Docker

TODO - soon

Build Nabla manually

Minimal required dependencies

Cloning the project

git clone [email protected]:Devsh-Graphics-Programming/Nabla.git <target directory>

Force HTTPS protocol (optional)

We support cloning Nabla with ssh only, however you can still force clone with https for whole repository and it's all submodules by overriding project git config setup.

git init
git config --project protocol.*.allow always
git config --project url."https://github.com/".insteadOf "[email protected]:"
git remote add origin https://github.com/Devsh-Graphics-Programming/Nabla.git
git fetch origin master
git checkout master

Configure & Generate with CMake

Target platform

Check individual instructions for building for a particular platform in ./docs/build directory before going further. For each platform it is assumed minimal required dependencies are installed and additional may be specified depending on the target.

Submodules

CMake will update all required submodules for you by default but it doesn't mean the initialization & update attempt will be successful (it is often not when performed on a shaky internet connection, so you may end up with dirty, locked or un-versioned submodules) - if not successful then try to re-configure CMake again. We have a few options for managing submodules by CMake, for more details and description check the update submodule script. For example sometimes it may appear that there won't be any files in submodules' directories because of an update fail or dirty git cache, you could fix it and bring them back by enabling NBL_FORCE_ON_UPDATE_GIT_SUBMODULE CMake option. Note that we do not recommend to initialize and update submodules by hand in cmd because of private submodules in the repository.

More options

You can disable generating projects for examples with NBL_BUILD_EXAMPLES. It's recommended to build Nabla as shared library however you can also build as static library by turning on NBL_STATIC_BUILD.

CMake presets

We have customised presets which may be handy to configure Nabla project for a target platform with predefined & common configurations.

Caveats and Particular Behaviour

Hardcoded Caps

Max Descriptor Sets is always 4

Debugging with RenderDoc

Non-programmatic OpenGL catpures will be delimited inconsistently

Due to our no-pollution opengl state isolation policy, we have 1 queue or swapchain = 1 thread = 1 gl context + 1 master context and thread for device calls.

Renderdoc therefore serializes all calls, and presents them inside the capture in interleaved order (records them on a single timeline "as they happened").

Furthermore it has no idea what constitutes a frame, because swap-buffers call happens on a separate thread than all the other API calls. So use the IGPUQueue start/end capture methods!

RenderDoc flips images for display in the ImageViewer tab on OpenGL captures

Ctrl+F `localRenderer in https://github.com/baldurk/renderdoc/blob/4103f6a5455b9734e9bf74e254577f5c03188136/renderdoc/core/image_viewer.cpp

OpenGL/Vulkan Inconsistencies

In certain cases same calls to Vulkan and OpenGL might result in y-flipped image relevant to the other API.

Both APIs write (-1,-1) in NDC space to (0,0) in image space (two wrongs make right), and memory-wise (0,0) always represents the lowest byte in memory.

This inconsistency comes from swapchain presentation. When presenting the swapchain, the image location (0,0) corresponds to bottom-left in OpenGL and top-left in Vulkan.

Solution by Surface Transforms

We solve this inconsistency by using surface transforms; This transforms are relative to presentation engine’s natural orientation. and we report HORIZONTAL_MIRROR_180 support in our OpenGL backend and defer handling these rotations (relative to natural orientaion) to the user.

We provide helper functions in both GLSL and C++ Nabla codebase to consider surface transforms, See surface_transform.glsl

Note that it is common to apply surface transformation to projection matrices to account for this fact. See getSurfaceTransformationMatrix and Android Developers Guide to Pre-rotation

Use ISwapchain getSurfaceTransform() to get the transformation from swapchain.

Continuous integration

Nabla Python Framework

CPU & GPU local tests shipped with the repository

Description

Nabla aims to implement full CPU & GPU tests used by our CI in-house infrastructure groovy pipelines in relocatable way allowing users to execute and debug the tests locally on their own devices as well. Each test is a Python module which part of it gets created with the CMake build system configuration. A test is defined and created as a module by

  • top json configuration file
  • interface Python script

Top json configuration file contains run & build info, array of profiles and json inputs for a Python testing module. The file is processed and validated by CMake to create output profiles bound to the Python module. Single profile contains data used by the module to execute tests with and the implementation of the test is located in interface Python script - the script overrides common abstract interface defined as a integral part of Nabla Python framework module. The description is abstract and doesn't contain specific details, join our discord if you have any questions!

Development & Debug

Each valid Python module contains autogenerated .vscode's launch.json and settings.json to make development easy. You just need to Open with Codein the module's directory. Make sure to install Python extension there to enable IntelliSense (Pylance), Linting, Debugging (multi-threaded, remote), code formatting, refactoring, unit tests, and more.

A target for which Python module is available for testing lists a special Python Framework section located in its solution's project file structure (Visual Studio only!) containing Nabla Python Framework sources, target's interface Python script, autogenerated json profiles and autogenerated __main__.py module script. Unfortunately pure Visual Studio works so-so with Python (issues with search module paths defined as searchPath .pyproj's property, issues with IntelliSense and Debugging) - we encourage to use Visual Studio Code if you need to Debug an interface or develop it.

Runtime

Command line

To run all tests bound to a module with a command line you just need to execute python3 -m <module_reference>. You can also specify special arguments to have more control over the test execution, for more details see template module script

Visual Studio

You need to open a target's solution. To launch all tests bound to a module a module's __main__.py file located in Python Framework section must be selected and Debug -> Execute File in Python interactive executed.

Visual Studio Code

You need to open module's directory as workspace with Open with Code , select Run and Debug icon, select __main__.py file and run it.

License

Nabla is released under the Apache 2.0 license. See LICENSE.md for more details.

Documentation

(WIP/TODO)

Official Support (Discord)

Permanent members of Devsh Graphics Programming Sp. z O.O. use this to organise publicly visible work. Join to the server to get into more details.

Credits and Attribution

The authors of Nabla are:

Past Authors and Contributors:

  • Krzysztof Szenk @crisspl (Senior Programmer: Everything in Nabla has been touched by his golden hands!)
  • Danylo Sadivnychyi @sadiuk (Junior Programmer: Android system interfaces and buildsystem, FFT Ocean)
  • Cyprian Skrzypczak @Hazardu (embeded resources and optimalizations)
  • @khom-khun (Bullet Physics Extension + Example and the irrBaW-test repository of easy to understand demos)
  • Søren Gronbech
  • @florastamine Nguyễn Ngọc Huy (sRGB-Correct Image Loaders, CEGUI and BRDF Explorer GUI)
  • @manhnt9 Nguyễn Tiến Mạnh (CEGUI, Build System and Radeon Rays Proof-of-Concept Integration in Prime Engine X with IrrlichtBaW back-end)

Words of appreciation for developers whose software has been used in Nabla, currently and in the past:

nabla's People

Contributors

achalpandeyy avatar anastaziuk avatar anonn10 avatar atkurtul avatar bane9 avatar crisspl avatar cskrzypczak avatar dariusz1989 avatar deprilula28 avatar devshgraphicsprogramming avatar devshgraphicsprogrammingjenkins avatar erfan-ahmadi avatar fletterio avatar hazardu avatar hiradyazdan avatar khomsidakhun avatar kpentaris avatar manhnt9 avatar mhk2012 avatar mohammadfakhreddin avatar nahiim avatar numberzero avatar pjbomb2 avatar pollend avatar przemog1 avatar sadiuk avatar sunho avatar theoreticalphysicsftw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nabla's Issues

Feature full Windows

Description

Allow for resizes, minimizes, maximizes and rotations (mobile).

Some platforms' implementations wont allow for certain things, so capabilities must be queryable at runtime and most operations should return a bool or an enum to notify of success (please no static capability sets via inheritance).

One example is a resize, which may not be achievable to the requested size, so the actual size after the operation (same as current if nothing done) needs to be returned)

Solution proposal

To be implemented separately in every derived window class for Win32, X11, Wayland, derivations of ForeignWindow (SDL2 which we shall use for Android)

Probably an window event callback needs to be able to be hooked up (at least to notify of an On-Resize).

Additional context

The window functions from the IrrlichtDevice need to die
https://github.com/Crisspl/Nabla/blob/vulkan/include/IrrlichtDevice.h#L191
https://github.com/Crisspl/Nabla/blob/vulkan/include/IrrlichtDevice.h#L114

`system` namespace

Description

WIP

Solution proposal

To be done on Crisspl's vulkan branch

Additional context

Stuff currently in the io namespace and other things which shall be in the system namespace:
https://github.com/Crisspl/Nabla/blob/vulkan/include/IFileSystem.h
https://github.com/Crisspl/Nabla/blob/vulkan/include/IFileList.h
https://github.com/Crisspl/Nabla/blob/vulkan/include/IFileArchive.h
~~ https://github.com/Crisspl/Nabla/blob/vulkan/include/ILogger.h [rewrite to use string_view, customize the output channel, dont make it a global etc.] ~~
https://github.com/Crisspl/Nabla/blob/vulkan/include/path.h [all functionality to be deleted]
https://github.com/Crisspl/Nabla/blob/vulkan/include/IrrlichtDevice.h#L69 [yield and sleep need to be deleted]
https://github.com/Crisspl/Nabla/blob/vulkan/include/IrrlichtDevice.h#L96 [logger and OS operator need to move]
https://github.com/Crisspl/Nabla/blob/vulkan/include/IrrlichtDevice.h#L110 [timer needs a rewrite]
https://github.com/Crisspl/Nabla/blob/vulkan/include/IOSOperator.h
https://github.com/Crisspl/Nabla/blob/vulkan/include/ITimer.h [timer needs a rewrite]

Got rewritten Can stay as-is right now, but candidate for rewrite in the future (stays in the include directory, does not move to nbl/system)
https://github.com/Crisspl/Nabla/blob/vulkan/include/IReadFile.h
https://github.com/Crisspl/Nabla/blob/vulkan/include/IWriteFile.h

Build Nabla out of source

image

We need to adjust CMake code to be able to build out of source tree, where ${CMAKE_BINARY_DIR} isn't placed in ${CMAKE_SOURCE_DIR} because it leads to erros.

Native windows event handling

Description

This issue covers native window event handling support on several operating systems, including Windows, Linux(X11, Wayland) and Android. It also contains suggestions for possible lightweight cross-platform libraries which can be used in Nabl to simplify this process.

Native Implementations

Windows

Window event handling on Windows works in a very straightforward manner: you define 2 things:

  1. An event loop - the loop which catches all the messages the application should receive? translates them and calls the window procedure.
  2. A window procedure - the callback which will be called by the event loop with the proper event type and handle it.

So the actual code that will allow you to handle events looks like this:

#include "Windows.h"

Define a window procedure:

LRESULT stdcall MainWindowProc(HWND hwnd, uint uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg)
	{
		case WM_CLOSE: // User closes the window
			PostQuitMessage(0);
			break;
		case WM_SIZING: // User resizes the window
			//Handle resizing
			break;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

And an event loop in the main function:

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	HWND hwnd;
	// Create window
	// ...
	// ...
	ShowWindow(hwnd, SW_SHOW);
	UpdateWindow(hwnd);
	
	MSG msg; // the message we'll receive
	
	while(GetMessage(&msg, nullptr, 0, 0))
	{
		TraslateMessage(&msg);
		DispatchMessage(&msg);
	}
}

Linux

X11

The X11 event handling looks pretty similar to how it works on Windows. However, here you do not define a callback(like the MainWindowProc), but do all the dirty work iside the main function.

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>

First you define stuff like window, display etc for the X11 window application to work.

Display *dis = XOpenDisplay((char *)0);;

unsigned long black, white;
black=BlackPixel(dis,screen);
white=WhitePixel(dis, screen); 

Window win = XCreateSimpleWindow(dis,DefaultRootWindow(dis),0,0, 200, 300, 5, white, black);

Then you need an event loop to wait for events and handle them.
Since, unlike on Windows, the event types are not as specific (e.g. ConfigureNotify event means that the window could be either moved, or resized, or the border width was changed or all 3 at once), you either need to store the previous window state, or update all possible properties:
Option 1:

XEvent event;
while(1)
{
	XNextEvent(dis, &event);
	//Since 
	if(event.type == ConfigureNotify)
	{
		XResizeWindow(dis, win, event.width, event.height);
		XMoveWindow(dis, win, event.x, evennt.y);
		//... All possible event handlings
		//... 
		//...
	}
}

Option 2:

XEvent event;
while(1)
{
	XNextEvent(dis, &event);
	//Since 
	if(event.type == ConfigureNotify && event.width != prevWidth || event.height != prevHeight)
	{
		// Update prevWidth, prevHeight
		XResizeWindow(dis, win, event.width, event.height);
		//...
		//...
	}
}

Wayland

With wayland the situation is not as pleasant as with previous systems. Here you do not get nice events that can tell you what exactly happened to your window, but define listeners for simple events like mouse pointer moving, clicking, entering/leaving the window surface, etc. All the other stuff should be handled manually.

Let's go through main ideas behing window event handling.
Before we connect all the stuff in main, lets create a listener for a pointer:

// Mouse enter the window surface
static void pointer_handle_enter(void *data, struct wl_pointer *pointer,
                     uint32_t serial, struct wl_surface *surface,
                     wl_fixed_t sx, wl_fixed_t sy)
{
    fprintf(stderr, "Pointer entered surface %p at %d %d\n", surface, sx, sy);
}

// Mouse leave the window surface
static void pointer_handle_leave(void *data, struct wl_pointer *pointer,
                     uint32_t serial, struct wl_surface *surface)
{
    fprintf(stderr, "Pointer left surface %p\n", surface);
}

// Mouse move
static void pointer_handle_motion(void *data, struct wl_pointer *pointer,
                      uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
{
    printf("Pointer moved at %d %d\n", sx, sy);
}

// Mouse click
static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
                      uint32_t serial, uint32_t time, uint32_t button,
                      uint32_t state)
{
    printf("Pointer button click\n");
    
	// !!!! This is where you can perform window resizing, moving and stuff.
    
	if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED)
	wl_shell_surface_move(shell_surface,
			      seat, serial);
    
}

// This one seems to be a one-axis gesture like the left-to-right swipe
static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
                    uint32_t time, uint32_t axis, wl_fixed_t value)
{
        printf("Pointer handle axis\n");
}


static const wl_pointer_listener pointer_listener = {
    pointer_handle_enter,
    pointer_handle_leave,
    pointer_handle_motion,
    pointer_handle_button,
    pointer_handle_axis,
};

Then there goes a LOT of code that registers all those listeners, and then we bind all the stuff in the main:
Note: for simplicity i removed a lot of code and error handling so this code will not actually work.

int main()
{
	wl_display* display = wl_display_connect(NULL);

	// Some other stuff, unrelated to this issue....
	
    wl_surface* surface = wl_compositor_create_surface(compositor);
   
	// In Wayland there should be a shell surface on top of the actuall surface that catches pointer events.
    wl_shell_surface shell_surface = wl_shell_get_shell_surface(shell, surface);
    wl_shell_surface_set_toplevel(shell_surface);

    
    wl_shell_surface_add_listener(shell_surface,
			      &shell_surface_listener, NULL);

    init_egl();
    create_window();

	// The event loop itself
    while (wl_display_dispatch(display) != -1) {
	;
    }

    wl_display_disconnect(display);
}

A complete tutorial on wayland events is here
A simple program program that tracks when a window is moved can be found here.

Android

Android provides C++ programming capabilities via the JNI (Java native interface) - basically a set of java-like functions in C++.
Window (and other kinds of) events are processesed by defining two event handlers in the entry point and registering them:

#include <EGL/egl.h>
#include <GLES/gl.h>


#include <android/sensor.h>
#include <android/log.h>
#include <android_native_app_glue>
void android_main(struct android_app* state) {
	engine engine;
	
	memset(&engine, 0, sizeof(engine));
	state->userData = &engine;
	state->onAppCmd = applicationCommandHandler;
	state->onInputEvent = inputHandler;
	engine.app = state;
}

Where the applicationCommandFunc is the callback which processes events like window initialization, window termination etc and the inputHandler is the function which recieves and processes input events like key presses.
Here I've posted possible implementations of those two:

void applicationCommandHandler(android_app *app, int32_t cmd)
{
    switch (cmd)
    {
    case APP_CMD_INIT_WINDOW:
        initialize();
        break;
    case APP_CMD_TERM_WINDOW:
        finalize();
        break;
    default:
        break;
    }
}
int32_t inputHandler(android_app *app, AInputEvent *inputEvent)
{
    if (AInputEvent_getType(inputEvent) == AINPUT_EVENT_TYPE_KEY &&
        AKeyEvent_getKeyCode(inputEvent) == AKEYCODE_BACK)
    {
        ANativeActivity_finish(app->activity);
        return 1;
    }

    if (AInputEvent_getType(inputEvent) == AINPUT_EVENT_TYPE_MOTION)
    {
        // TODO: Handle touch event...
        return 1;
    }

    return 0;
}

Add custom sample locations and coverage reduction modes

Shared source for Shader Lang and C++

Since engine utilises glsl in many places, I suggest switch to glm instead of own math library. Advantage is that lots of optimisations already done and tested in that library, and when you decide go mobile it will be ready to use and optimised.

Future Hardware Support Matrix

Description

It would be useful to know what hardware exactly we're aiming to support and have some CI for it.

Description of the related problem

We should have a clear cutoff point for hardware, and acquire the old hardware for our CI farm.

Solution proposal

Public:

  • OpenGL 4.5 and above with certain mandatory extensions
  • ES 3.1 and above with certain mandatory extensions
  • Vulkan 1.1 (might actually make it 1.2)
  • WebGPU preview

WebGL will not be supported.

Free but Private (extension/branch available to licensed developers):

  • PS5's GNM
  • DirectX 12 with SM 6.5
  • NVN
  • Tesla Model S 2021

Windows

OS: latest 10
CPU: Anything with SSE4.2
GPU:

  • Nvidia Maxwell and newer
  • AMD Gcn 4 and newer
  • Intel Apollo Lake and Skylake and newer

Linux

OS: Anything with GCC 8.x
CPU: Anything with SSE4.2 (maybe ARM as well at some point in the future)
GPU:

  • Nvidia Maxwell and newer
  • AMD Gcn4 and newer
  • Intel:
    • OpenGL and ES backend, Haswell HD Graphics and newer
    • Vulkan, Apollo Lake and Skylake and newer

Android

OS: Android API level 28
CPU: x86_64 first, then 64bit ARM
GPU:

  • Intel Gemini Lake and newer

ChromeOS

Everything as Android, except the only API available is OpenGL ES 3.1 with requirement for OES_texture_view

macOS

OS: High Sierra and newer
CPU: x86_64 first, then M1/M2 as well
GPU:

  • AMD Gcn 5 and newer
  • Intel HD Graphics 6000 and newer

The requirement for AMD GCN architecture excludes the first Mac Mini, most of the 3rd gen Macbook Pro lineup and most of the pre-2017 iMac models with Radeon Graphics.
Yes you can now congratulate yourself for buying a literal $6000 trashcan.

iOS

SoC: A11 and above

Mesh packers dont really shrink, GPU MeshPacker doesnt copy the allocator state from CPU etc.

Describe the bug

Mesh packers actual allocators (together with reserved space) should be remade after a shrink (there's a special move ctor for this sort of operation).

There's also a bit more on the wishlist in the comments in the following commit:
da60a7b

Expected vs observed behavior

I should still be able to carry out allocations in a GPU mesh packer (the allocator state should be a copy of the CPU mesh packer state at GPU construction time).

When shrink is called, allocator address space shrinks and so does reserved space.

Environment

Irrelevant.

Command buffers, queues, queue families

First of all: cmd buffers, queues and families are purely GPU objects, so I see no point in having CPU and GPU counterparts.

Command pools

ICommandBuffer design is in the UML, however command buffers comes along with command pools. Command pools are opaque Vulkan objects used to minimize cost of acquaring/allocating resources for a set of cmd buffers assigned to a cmd pool. Also they in case of concurrency they require external synchronization. So what I'm thinking is that we don't expose command pools for users at all. Instead [under Vulkan backend], under the hood there can be created one command pool per queue family per thread. This can be done dynamically (when there's a need for such, i.e. cmd buffer is created by some thread using some queue family). This obviously means that all command buffers created by thread X and using queue family at index Y are "bounded to" the same command pool. In GL backend command pools would be non-existent at all.

Major engine API change needed (maybe not that major)

I think we'll need to redefine what device is in Nabla. Currently is the main class to which (upon creation) we're passing what backend we want to use, then it's creating IVideoDriver, IAssetManager, IFileSystem etc... AFAIK Nabla doesnt let user choose the device, not even talking about using more than one device (GPU) at a time. There should be such possibility and then by device we mean something that will hold VkPhysicalDevice handle. device will create driver object that will hold VkDevice handle and, while creating, deciding what queue objects will be created (and more).

Queue families

Same as Vulkan API does it. We can even use the same struct VkQueueFamilyProperties. We can query all queue families offered by current physical device with vkGetPhysicalDeviceQueueFamilyProperties. So at engine startup we query those to smart_refctd_dynamic_array or something and let user device->getQueueFamilyProperties() them. There's no need for anything like IQueueFamily engine-API objects.
In result API normalization between backends boils down to what is returned from getQueueFamilyProperties(). For Vulkan it's obvious. For GL we can for example report that there exists just one queue family with all (https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkQueueFlagBits.html) capabilities with one queue. I dont know. Is there a way to query such things via GL API? Like whether our device supports graphics (maybe it's compute-only)? Not even asking about specific queues and their capabilities, I'm sure OpenGL hides it from user.

Queues

If queue family properties are queried from device as described above (via get*()), then obviously driver creation must be deferred (not instantly created on device construction). IQueue objects are then created automatically by engine based on info given for driver creation (VkDeviceQueueCreateInfos). Driver should have an API function to access them.

Actual UMLs and more design I'll post tomorrow.

Swapchains and surfaces

Description

What's happening in Vulkan

Swapchain is created from surface and other params like minImageCount. Swapchain images can be gathered from the swapchain. Then we're creating as many FBOs as there are images (and obvs attaching one image to each) and render to an fbo of number queried from vkAcquireNextImageKHR

What's happening in OpenGL

No direct access to swapchain images, no explicit swapchain actually. In SDL2 double-buffering and swapping is done with a single call (SDL_Flip(surface) or SDL_RenderPresent(renderer) -- not sure, Magnum uses SDL_Flip but SDL2 migration guide says it's been replaced with SDL_RenderPresent, however i dont know what is that renderer yet)
https://wiki.libsdl.org/MigrationGuide
https://github.com/mosra/magnum/blob/master/src/Magnum/Platform/Sdl2Application.cpp#L439

Conclusion

Swapchain and surface have to be one thing in our API.
OpenGL impl should be pretty straight forward then, however...
On Vulkan.. Swapchain/Surface API cannot expose images because in you OpenGL cannot do this. So:
A) do under-the-hood blits into swapchian images in Vulkan, or
B) make Swapchain/Surface API expose images, so that things are getting easy in Vulkan, but in OpenGL we're doing under-the-hood blits into default framebuffer (seems like much better option tbh)

Anyway seems like Swapchain and Surface need to get together into a single interface

Description of the related problem

Solution proposal

Additional context

`layout (offset = n)` decorations are not respected for more than 1 elements of `struct` type

An example:

struct ScanPushConstants
{
    uint stride;
    uint element_count_pass;
    uint element_count_total;
};

struct SortPushConstants
{
    uint shift;
    uint element_count_total;
};

layout(push_constant) uniform PushConstants
{
    layout (offset = 0) ScanPushConstants params_scan;
    layout (offset = 12) SortPushConstants params_sort;
} pc;
  • SortPushConstants::shift and SortPushConstants::element_count_total gets the same values as first two members of ScanPushConstants

  • if you just put everything into one block like following, it works perfectly, with the same C++ code

layout(push_constant) uniform PushConstants
{
    layout (offset = 0)  uint scan_stride;
    layout (offset = 4)  uint scan_element_count_pass;
    layout (offset = 8)  uint scan_element_count_total;
    layout (offset = 12) uint  sort_shift;
    layout (offset = 16) uint  sort_element_count_total;
} pc;

C++ code in question,

const asset::SPushConstantRange pc_range[2] =
{ 
    { asset::ISpecializedShader::ESS_COMPUTE, 0u, sizeof(ScanPushConstants) },
    { asset::ISpecializedShader::ESS_COMPUTE, 12u, sizeof(SortPushConstants) },
};
auto pipeline_layout = driver->createGPUPipelineLayout(pc_range, pc_range + 2u, std::move(scan_ds_layout), std::move(sort_ds_layout));

..

driver->pushConstants(pipeline_layout.get(), asset::ISpecializedShader::ESS_COMPUTE, pc_range[0].offset, pc_range[0].size, &scan_pc);
driver->pushConstants(pipeline_layout.get(), asset::ISpecializedShader::ESS_COMPUTE, pc_range[1].offset, pc_range[1].size, &sort_pc);

This branch could be cloned and build to reproduce the bug

Here is a Renderdoc capture


Following could be related:

Example 22 crashes in random places in Debug build on MSVC

Describe the bug

Reads from bad pointers

Steps to Reproduce

Start ex 22 with the staircase scene, Continue when NBL_DEBUG_BREAK_IF is triggered because of unsupported XML tags.

After taking a while, the program will crash.

Expected vs observed behavior

No crashing, same visuals as RelWithDebInfo

Environment

  • OS: Windows 10
  • CPU: some mobile i7 with 6 cores
  • GPU: RTX 2070
  • GPU driver version: no idea
  • Compiler: MSVC
  • branch: raytracing
  • commit hash: 78808d4

Steam Input API

Description

This article covers the functionality of the Steam Input API.

Overview

The Steam Input API is designed to allow you to easily enable full support for Steam Input devices (I assume that the device list hasn't been updated in a while because there is no PS5 controller listed, which is 100% supported) in your game. Let's go over some concepts of the API.

Steam Input Configurator

Steam Input Configurator (SIC) is an intermediate layer, built into the client that translates the input, passed by the input device into the output, defined by the user, depending on the SIC mode.

SIC Modes

SIC supports two modes of translation: legacy and native.

Legacy Mode

Legacy Mode is the compatability mode, designed for games that do not implement the steam input API. In this case SIC just translates one physical input into some other physical input (e.g. X key -> Alt key). This mode works on any supported input device.
Legacy mode is great, but it has several drawbacks. One of them is that the game doesn't know about the existance of SIC, it just receives raw physical input, so it's hard to match up the on-screen glyphs.

Native Mode

In Native Mode, the game receives input data from the controller in the form of actions (so the game does not receive the action like "Button X was pressed, but the action "Jump""). In this case the game has no idea about what "buttons" are pressed by the controller. All the configuration is managed by the SIC. That being said, the game can also receive from the SIC the info about what key was actually triggered (this is done for the on-screen glyphs like "Press the X button).

Steam Input API

The Steam Input API (SIAPI) is the API that allows developers communicate with the SIC in Native Mode. Players can set up fully customized input mappings for any game in their library, using native mode, legacy mode, or even a mix of both. These input mappings are called "controller configurations" and a player can make many different ones for a single game, as well as share them with other players online.
The API doesn't necessarily support Legacy Mode.

TL;DR

What Steam Input can do:

  • Provide a game/app with an interface to get key-agnostic events for PS4, PS5, Xbox, Steam, switch etc. gamepads.
  • Provide a game/app with the keys that triggered the given event, if needed.

What Steam Input cannot do:

  • Work with mouse/keyboard.
  • TODO

Answering some questions @devshgraphicsprogramming was curious about:

How do you get events from the gamepad:

  • The way the events are retrieved is by "IsEventTriggered()" principle (not an actual call, but a very simplified version).

Is there a way to send custom events to the controler:

  • TODO: I couldn't find info if there is a way to sent custom events, so this needs more research/asking people who know.

Does SteamInput syphon events on its own or do i pump them myself?

  • TODO

TODO

Still need to figure some things out, but it requires a thorough search through docs, so i'll postpone it till monday.

Native drag&drop handling

Description

This issue covers native drag & drop support on several operating systems, including Windows, Linux, macOS, IOS and Android. It also contains suggestions for possible lightweight cross-platform libraries which can be used in Nabla to simplify this process.

Native Implementations

Windows

Drag&Drop on windows works in a very easy manner. To start with, you need a window that will accept files and enable Drag&Drop.

#include <windows.h>
HWND window;
window = CreateWindow("Window class", "Drag&Drop test", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 960, nullptr, nullptr, nullptr, nullptr);
ShowWindow(window, SW_SHOWNORMAL); q
DragAcceptFiles(window, TRUE);

In WindowProc you also need to define proper drop handling:

LRESULT WINAPI WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
{
   if(message == WM_DROPFILES)
   {
      char filename[MAX_PATH];
      uint32_t num_of_files = DragQueryFile(lparam, 0xffffffff, nullptr, 0);
      for(int i = 0; i < num_of_files; i++)
      {
      	 DragQueryFiles(lparam, i, filename, MAX_PATH);
      	 std::cout << filename << "\n";
      }
   }
}

Linux

X11

With X11 the sitution is much more complicated. Unlike on Windows, Linux has no drag & drop standart, so many organizations have implemented their own protocols, so the program, written for one protocol cannot communicate via Drag&Drop with those, written for different protocols.
Still there is one, most commonly used protocol - XDND.

To implement something minimal, lets make two processes:

#include <sys/types.h>
#include <X11/Xlib.h>
int main()
{
    pit_t pid = fork();
    if(pid_t == -1) return -1;
    createWindow(pid);
}

Where the createWindow function looks something like this:

void createWindow(pid_t pid)
{
  // Distribute parent/child process duties...

  Display *display = XOpenDisplay(NULL); 
  Window window = XCreateSimpleWindow(display, RootWindow(display, N), 0, 0, 1, 1, 0, BlackPixel(display, N), WhitePixel(display, N));
  
  // Then goes the initialization of atoms and stuff...
  // ...
  // ...
  Atom 	XdndDrop = XInternAtom(display, "XdndDrop", False);
  // ...

  bool keep_listening = true;
  XEvent event;
  while(keep_listening)
  {
    XNextEvent(display, &event);
    if(event.xclient.message_type == XdndDrop)
    {
      // Extract event data... 
    }
  }
}

You can view the full code of drag & drop handling example with X11 here.

Wayland

If you think that X11 is the only counter-intuitive part of cross-platform drag & drop implementation, you're totally wrong, because it also can be applied to wayland interface.

To get access to the clipboard and drag & drop interfaces, clients can bind to the wl_data_device_manager. We’ll also need to bind to a seat:

static struct wl_data_device_manager *data_device_manager = NULL;
static struct wl_seat *seat = NULL;

static void registry_handle_global(void *data, struct wl_registry *registry,
		uint32_t name, const char *interface, uint32_t version) {
	if (strcmp(interface, wl_data_device_manager_interface.name) == 0) {
		data_device_manager = wl_registry_bind(registry, name,
			&wl_data_device_manager_interface, 3);
	} else if (strcmp(interface, wl_seat_interface.name) == 0 && seat == NULL) {
		seat = wl_registry_bind(registry, name, &wl_seat_interface, 1);
	}
}

After binding, we’ll need to create a wl_data_device object to interact with the clipboard and drag & drop on a particular seat:

struct wl_data_device *data_device = wl_data_device_manager_get_data_device(data_device_manager, seat);

and a data source listener with the source itself:

static const struct wl_data_source_listener data_source_listener = {
	// .send and .cancelled are the same as the clipboard case
	.target = data_source_handle_target,
	.action = data_source_handle_action,
};

struct wl_data_source *source =
	wl_data_device_manager_create_data_source(data_device_manager);
wl_data_source_add_listener(source, &data_source_listener, NULL);
wl_data_source_offer(source, "text/plain");

wl_data_source_set_actions(source, WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | WL_DATA_MANAGER_DND_ACTION_COPY);

Note that wl_data_source_offer allows you to specify the data format.

Also create a surface (drag & drop area):

struct wl_surface *icon = NULL;
wl_data_device_start_drag(data_device, source, origin, icon,
	pointer_button_serial); 

After that, you can perform event handling, covered in-depth here.

macOS

On macOS the d&d features are implemented pretty easily. Actually there are several ways to do that, but they're all pretty similar so I'm only gonna cover one of them.
First you need to create class, derived from NSView and specify the formats you want d&d to work with:

class TestView: NSView {
    let supportedTypes: [NSPasteboard.PasteboardType] = [.tiff, .color, .string, .fileURL]
}

Then allow the view accept these formats by overriding the registerForDraggedTypes method:

override func awakeFromNib() {
    self.registerForDraggedTypes(supportedTypes)
}

The next method will allow you to detect when the draggable object enters the dropping area (TestView):

override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
    let canReadPasteboardObjects = sender.draggingPasteboard.canReadObject(forClasses: [NSImage.self, NSColor.self, NSString.self, NSURL.self], options: nil)
    if canReadPasteboardObjects {
        return .copy
    }
 
    return NSDragOperation()
}

To implement the actual drop operation, override the next method:

override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
   guard let pasteboardObjects = sender.draggingPasteboard.readObjects(forClasses: [NSImage.self, NSColor.self, NSString.self, NSURL.self], options: nil), pasteboardObjects.count > 0 else { return false }
   pasteboardObjects.forEach { (object) in // go through every object that's being dragged

      if let image = object as? NSImage {
        avatarInfo.setImageData(using: image)
      }
      
      if let color = object as? NSColor {
        avatarInfo.setColorData(using: color)
      }
      
      if let quote = object as? NSString {
        avatarInfo.quote = quote as String
      }
      
      if let url = object as? NSURL {
        self.handleFileURLObject(url as URL)
      }
   }
}

IOS

Android

OpenGL command buffer recording optimizations

Description

Right now cmd buffer records commands into an std::vector making little use of the command pool's memory blocks except for placing variable length arguments into it, it also uses the GeneralpurposeAddressAllocator which is the most robust but also the slowest.

Furthermore it records the OpenGL commands' arguments it would like to perform, but leaves out the state caching to the state tracker in the submission queue thread. In Vulkan (and Nabla) command buffers always start out in the initial state, so its possible to use the state tracker up-front when recording and only record the OpenGL commands that will actually be needed (this has a huge impact on binds).

Solution proposal

  • Use the OpenGL state tracker locally within the context of cmd buffer recording (one tracker per cmdbuffer).
  • Only record the commands that will result in an actual state change
  • Instead of using a member vector, encode the commands as a linked list with backing memory provided by the pool
  • Use a PoolAddressAllocator for the commands instead of the Generalpurpose, and whenever unbounded length arguments to a command are possible, split them up into more linked list nodes

Additional context

Only do it if profiler shows a lot of time spent in commandbuffer recording.

CMake libraries' config - POSTFIX

TODO - use CMake to add appropriate POSTFIX according to config

Some libraries don't have adjusted postfixes to the config and it may lead to helll when using Nabla as an external project.

image

Fragile CommandBuffers

Describe the bug

First bug is that one command buffer can influence the state of another, in ex 29 @sadiuk is setting the viewport in one cmdbuffer and submitting that before the renderloop, and somehow the viewport size seems to be propagated (use latest Renderdoc nightly build to capture frame 0 and 1).

Second bug is, I changed the commandbuffer recording order a little bit plus optimized the UBO update, and I get absolutely flooded with the following

OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:771:glGeneral.pglGetIntegerv(GL_FRAMEBUFFER_BINDING, reinterpret_cast<GLint*>(&bound)): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:771:glGeneral.pglGetIntegerv(GL_FRAMEBUFFER_BINDING, reinterpret_cast<GLint*>(&bound)): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502
OpenGL error: Error has been generated. GL error GL_INVALID_OPERATION in VertexArrayElementBuffer: (ID: 1306369058) buffer 1053253632 is not zero or the name of an existing buffer object
C:\work\master\src\nbl\video\IOpenGL_FunctionTable.h:861:glGeneral.pglGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFBO): error 0x502

Steps to Reproduce

Run ex 29

Expected vs observed behavior

Same visual output as the deferred_event_handler_fix branch

Environment

Combined Normal and Roughness Mip-map filter

Description

CLEAN, LEADR or any of the other techniques to be implemented as an IImageFilter based off the Mip-Mapping/Convolution filter.

Basically filter normals, derive a new roughness.

Deduce OpenGL VSync modes from Swapchain Presentation modes

Description

extGlSwapInterval(-1) used to be called in the engine at OpenGL initialization, now nothing is chosen at all.

Solution proposal

Call extGlSwapInterval with the following values:

  • 1 total VSync (when VK_PRESENT_MODE_FIFO_KHR is present)
  • 0 no VSync (probably VK_PRESENT_MODE_IMMEDIATE_KHR or MAILBOX, I believe this depends on double buffering or not)
  • -1 if late then tear (when VK_PRESENT_MODE_FIFO_RELAXED_KHR is present)

StreamInput Overview

Description

This issue covers features of the StreamInput future API.
Note: currently there is no info on how all these features will look like in the actual API (spec should be released in the next 12 months).

Overview

There are 3 main capability groups:

  1. Regular input control (keyboard, touchscreen etc).
  2. Sensor processing (Gyro, accelerometer, compass etc).
  3. Gesture and motion detection (Depth cameras).

OS-agnostic API. Some input devices support will be added via Khronos extensions.

Sensor processing capabilities:

  1. Sensor-agnostic input. Different devices have different sensors that provide the needed input, so the API allows developers abstract from low-level device-specific stuff and focus on the input itself.
  2. Handles almost eny sensors:
  • Multi-axis motion/position sensors, capacitive multi-touch surfaces.
  • RGB and Depth sensing cameras – including mono and stereo.
  • Microphone arrays for speech recognition etc.
  • Haptic devices, Biometric sensors etc.
  • etc.

The API is going to be graph-based: each input device is a separate node, and a combination of the input devices is a new kind of node - Filter Node. An app can access both high-level filter nodes and low-level device nodes.
A Filter Node can include image-processing (Can use APIs such as OpenCL and OpenMAX and receive data from external media frameworks).

That's it

This is literally the only data i managed to dig up about StreamInput. It doesn't even have a wikipedia page XD. Everything is taken from The Khronos StreamInput Overview Page.

Next Path Tracing Sprint

Ditt Features

  • Commandline renderserver mode (render into EXR with set number of samples)
  • Self-Intersection robust ray origins
  • Control camera speed (add it to the scene description)
  • Normal Map Support
  • Derivative Map scaling
  • Optimize sequence to fit RGB21_UINT, reorganise for locality, finish scramble advancement
  • Read max path depth from integrator, apply Russian Roulette
  • Resize the window after loading the scene so it is less than the desktop size, but also the correct aspect ratio

Extra Technical Features

  • Lower raster frequency than raytrace (draw every Nth frame, allow different primary sample counts to continuations)
  • MIS
  • Envmap support
  • Autoexposure
  • Tonemapping
  • NEE
  • Single BLAS and pretransformed vertices for non-instanced meshes (encode the draw+triangle ID into the indexbuffer value)
  • Heuristics for "deinstancing" meshbuffers (decide when it makes sense to pay double VRAM for positions and normals vs
  • Both Blooms

Sprint 2

  • Render multiple cameras when acting as a renderserver
  • GPU "bake" albedo textures for all materials
  • Multi-monitor VR-Cave mode
  • Optimize normal vertex attribute presence across all loaders in the engine
  • Render in four passes, with and without UVs (separate the vbuffer into bary+triID and bary deriv)
  • Occlusion Culling by @Przemog1
  • Support Opacity maps when constructing the vis buffer (stochastic alpha testing ;) )
  • Propagation rules in (or derived from) materials for AoVs
  • Denoiser re-integration
  • Fractional spp rendering, and control over spp per frame
  • RGB21_USCALED position encoding?

Sprint 3

  • Compute OBBs for lights
  • Schussler et. al Normalmaps and smooth shading normals
  • NEE++
  • Firefly rejection
  • Temporal denoiser
  • Cache and HTTP download models and textures
  • GPU assisted asset manipulation
  • Runtime GUI for adjustments

Vulkan

  • Drag&Drop scenes
  • Use anyhit for stochastic transparency

Add thread safe mutability for IAsset and eliminate a possible "double load" bug

Describe the bug

Prevent Double Loads of assets caused by multiple threads deciding to load an asset because all have queried the asset cache before either was done loading

Description of the related problem

Thread Safety

Assets should have a lock which should prevent read-accesses while an asset is being modified, and more than one thread/fiber modifying an asset.

Double Asset Loads

There is a possibility of a double load of an asset occuring if following events occur in this order:

  1. Thread A checks our thread-safe asset cache for path "huge.obj"
  2. Thread A decides to load the OBJ
  3. Thread B checks the asset cache for the same path
  4. Thread B decides to load the OBJ
  5. Thread A inserts loaded OBJ into cache
  6. Thread B inserts loaded OBJ into cache

Because the Cache is a multimap, both assets which are identical sit in the cache. This order of events is not the only one that produces the bug, other orders such as 123465, 123546, 132456, etc. will result in this problem.

Solution proposal

Thread Safety

Improve the Readers-Writers Lock in FW_Mutex to be more in line with std::recursive_lock APIs, at least the reading lock should be able to be recursive (writer lock not so much).

There should be an explicit method to:

  • acquire/release a reader lock
  • acquire/release a writer lock
  • upgrade/downgrade an already acquired reader lock to/from a writer lock without getting preempted

If writer lock has not been acquired then all the mutators of IAsset should assert.

However const-qualified functions should acquire the reader lock implicitly.

Double Asset Loads

We need to improve our cache container to be able to take "reservations" for keys, that is:

  1. If no concrete cached value or reservation has been made, proceed
    1a. Reserve a key value and place a dummy value indicating key has been reserved
    1b. Load the asset
    1c. Swap the reservation for the loaded asset
  2. If reservation has been already made, then wait until the asset has been loaded and reservation changes
  3. If concrete value is present then just return the asset

This might require a readers/writers lock, and/or sempahores/condition variables.

We need to analyze this design for the possibility of dead-locks because assets are DAGs and during the process of loading a single thread could put down multiple reservations.

Extension for a Water Rendering System

Description

Render water without the use of tessellation shaders, wholly in screen space.

Description of the related problem

Vertex throughput is a scarce resource, and rendering subpixel triangles is suboptimal.

LoD seams are also a problem.

Solution proposal

Render scene without water to a Lit color buffer + depth.
Take a copy of the depth buffer.

Group planar reflectors into "pools", assign each pool an ID.

Give quality choice for displacement and dynamic reflections (on/off).

Displacement Mapping (expensive)

Render occlusion meshes (same as normal meshes, but "pushed back" conservatively) into the depth attachment only, as a z-prepass.

Re-render the meshes with early-Z hint (reinforce with software test against old Z), this time with raymarched displacement #55 , do all the shading and refraction.

Special handling of the case "camera inside displacement hull" would be required.

Normal Mapping (cheap)

Render the meshes with forced early-Z, don't displace, just use the normal map (flat water).

Common for both

If dynamic reflections are enabled then "occlusion queries" will be performed while rendering, i.e. each pool will increment an atomic counter assigned to it in an SSBO for every visible pixel, and build a (possibly screen space) bounding box. The pool with the highest number of pixels will be assigned dynamic reflections, and a small compute shader will compute the view and cropped projection matrix of the planar reflector camera.

All the pools without dynamic reflections will sample a cubemap instead.

Make Nabla build as shared library, change the default cmake config to shared lib

Description

Shared libs config for Win32, Linux and Android.

Description of the related problem

Currently builds of Nabla incl. samples can be in excess of 50 GB, using .dll could cut it down by an order of magnitude,

Solution proposal

Produce 1 .dll/.so per namespace (also split up the static libs like this).

Dependencies are still to be linked statically into Nabla namespace libs (don't want DLL hell).

Additional context

To complete after appsincadd contract is finalized.

Factor large 1D dispatches into 2D and 3D

Description of the related problem

Old AMD and mobile GPUs love to make our lives difficulr by limiting the dispatch shape with constraint that the number of workgroups in the X-axis be <=64k.

Solution proposal

A new utility function in nbl::core that can split a T (either uint32_t or uint64_t) into 3 factors which when multiplied are either greater than or equal to the input.

For example a 64M input would be factored into (64k,1024,1).

The approximate 3-factor algorithm would have to do the following:

  • produce 3 natural (integer greater than 0) numbers less than or equal to the Maximum
  • start at each number equal to ceil(pow(input_size,1.f/3.f))
  • explore each candidate triple in the surface wdh = input_size (iterate in 2D over w,h in the range [1,MAX])

Furthermore all compute extensions and samples (included but not limited to FFT, Scan, RadixSort) will have to be adjusted to this (wg_count in the computed dispatch parameters and the use of gl_GlobalInvocationIndex,gl_WorkgroupID, etc.).

Additional context

#75 (comment)

Compile for ARMv8 64bit

Description

Get the thing compiling on ARM.

Description of the related problem

Nabla doesn't compile on ARM, which precludes it from running on the Nintendo Switch, Apple M1 based macs, iOS, Android and the Pi5.

Solution proposal

Debug a lot and trap unaligned memory accesses.

Rewrite the math lib to something that can compile GLSL code and uses both SSE4.2, AVX,AVX2, and NEON

Additional context

Widen the Android abi filter to arm64-v8a and x86_64.

Also make Nabla compile on ARM-linux.

Scene Management in Compute

Description

Description of the related problem

Solution proposal

Compute Shader for position update decoupled from framerate [REWRITE the WRITE UP]

Position Update Dispatch
Takes the requested relative user-control transform updates, and animation blends scheduled for this frame (animation blending rate is different per-node, and supplied from a buffer).

The user supplied relative matrices overwrite the target nodes' relative transforms (blend manager's relative transform modifications are pushed to TransformTreeManager before user sourced CPU relative transform modifications are pushed to TransformTreeManager).

The first blend for a node overwrites the target node relative transform, the following accumulate.
We map 1 invocation : 1 node, not 1 invocation : 1 blend.

Therefore the blendlists need to be kept together by nodeID via
https://github.com/Devsh-Graphics-Programming/Nabla/blob/scene_manager/include/nbl/builtin/glsl/transform_tree/modification_request_range.glsl

Nodes without parents should write to their global matrices directly as an optimization if possible.

Input:

  • Animation Blends <nodeID,keyframeRangeID/the range itself,start timestamp,weight,flags, such as whether to loop>
  • Animation Keyframes
  • Node attributes (update timestamp, relative transform, etc.)

Output:

  • Changed node attributes (modifiction timestamp, relative transform, etc.)
  • Root node global tforms

Improvement: Reduce blend rates for nodes that have small projections on the screen (far away), out of frustums, not visible by occlusion culling.

At this point a question poses itself, do we control the Animation Rate via comparing the current_timestamp-last_modified_timestamp>animation_rate_delta (which requires us to launch an invocation for every single animated node), or do we somehow bin/sort the nodes by update frequency (how!?) and dispatch only what we need ( would need a prefix sum dispatch before the main one).

Best thing would be to treat this like a particle system (have animation records jump between buckets), but then it makes it pretty hard to remove/pause/suspect/end already added animations (requires parallel searching in the deletion list).

Manual control of skeleton nodes is achieved via not having any animation blends.
Global matrix override achieved via not having/detaching from a parent.
Bind pose matrices handled via adding pseudo-children.

Compute Shader for bone translation

MeshPacker V2

Description

The aim is to facilitate the packing of meshe vertex and index data into IGPUBuffers.

The vertex data will use "programmable fetching"/"programmable pulling" as opposed to the hardware vertex inputs of MeshPackerV1, while maintaining the use of a hardware index buffer (for vertex pre and post transform cache).

This will allow us to pack all meshes together, not just certain subsets who's vertex formats match.

Common functionality should be factored out into MeshPackerBase to service both V1 and V2, especially the triangle "meshlet"/"cluster" division algorithm referenced in buildaworldnet/IrrlichtBAW#535

Description of the related problem

Multiple meshes need to be made to use the same pipeline in order to be feasible to be used with Multi Draw Indirect.

Attempting to leverage hardware vertex inputs leads to an NP-complete packing problem because we need to divide meshes into subsets that are compatible with each other.

This is why we skip hardware inputs (when you provide a pipeline to the user for the packed meshes, it shall have 0 vertex input attributes or bindings).

Solution proposal

Same allocate, optional shrink and then commit pattern should be followed.

Factor out the vertex data de-interleaving and conversion from other triangle topologies to TRIANGLE_LIST, from MeshPackerV1 into a common base.

Use a GeneralPurposeAllocator to allocate space for deinterleaved vertex data freely, now there are no constraints on the splitting of the buffer intro parts imposed by baseVertex (in V2 it should be 0 because vertex inputs wont be used).

The only constraint now is that alignment=sizeof(dataType), so 16 bit index buffer needs allocation alignment of 2 bytes, R8G8B8A8_UNORM vertex data needs alignment of 4 bytes, while R32G32B32A32_SFLOAT needs alignment of 16 bytes.

Data which cannot be fetched from an SSBO (mostly 24bit formats) or a UTB/STB shall not be supported (either convert of error out when allocating a mesh.

The user has a choice of either overriding their vertex fetching from

layout(location = X) in vec3 vPos;

void main()
{
    vec3 pos = vPos;
    ...
}

to either

// aliasing, all SSBO declarations map to the same descriptor in the descriptor set
layout(set = Y, binding = X) readonly buffer MeshPackedDataAsVec4
{
    vec4 vertexData[];
} asVec4;
layout(set = Y, binding = X) readonly buffer MeshPackedDataAsUvec2
{
    uvec2 vertexData[];
} asUvec2;

// could be an SSBO instead of UBO
layout(set = Y, binding = Z) uniform VertexDataOffsetTable
{
    int dataOffsetTable[];
} vertexPosition;

void main()
{
    vec3 pos = asVec4.vertexData[gl_VertexIndex+vertexPosition.dataOffsetTable[gl_DrawID]];
    ...
}

or

// no aliasing, extra descriptor bindings get used, but user gets "automagical" format conversions from UTB
// NOTE: `gsamplerBuffer` and `texelFetch` could be replaced with `gimageBuffer` and `imageRead` respectively for STB
layout(set = Y, binding = X+0) uniform samplerBuffer MeshPackedDataRGB32_SFLOAT;
layout(set = Y, binding = X+1) uniform usamplerBuffer MeshPackedDataRGBA16_UNORM;

// could be an SSBO instead of UBO
layout(set = Y, binding = Z) uniform VertexDataOffsetTable
{
    int dataOffsetTable[];
} vertexPosition;

void main()
{
    vec3 pos = texelFetch(MeshPackedDataRGB32_SFLOAT,int(gl_VertexIndex)+vertexPosition.dataOffsetTable[gl_DrawID]).xyz;
    ...
}

In all the above cases, its the user's responsability (outside the scope of the mesh packer):

  • to pick SSBO vs. UTB/STB
  • override the shader with which packed meshes/meshlets will be drawn
  • store the offsets of packed data
  • provide the shader with those offsets (either via push constant, table of UBO, or SSBO)

Additional context

We should probably define vec3 nbl_getVertexPosition(in uint vertexID) in all builtin shaders (MTL, default, Mitsuba, etc.), as well as vec3 nbl_getVertexNormal(in uint vertexID) and vec2 nbl_getUVCoordinate_X(in uint vertexID) (X denoting some number). This paired with appropriate macro guards (DEFINED and DECLARED) would be to facilitate easier overloads, like the overloads we currently allow for nbl_computeLighting or nbl_bsdf_cos_eval. The above GLSL example doesn't have the override mechanism demonstrated.

Feel free to ask any more questions.

Native clipboard handling

Description

This issue covers native clipboard support on several operating systems, including Windows, Linux, macOS, IOS and Android. It also contains suggestions for possible lightweight cross-platform libraries which can be used in Nabla to simplify this process.

Native Implementations

Windows

The clipboard support on Windows is very straightforward. A clipboard is a global buffer that can be used between applications to store the data of various formats.
In order to use the clipboard you must first open it:

#include <windows.h>
int32_t res = OpenClipboard(0);
assert(res != 0);

The only parameter is a handle to the window to be associated with the open clipboard. If this parameter is NULL, the open clipboard is associated with the current task.

To copy data into the clipboard, you first must clear the data, currently stored in it and then fill in the clipboard buffer:

ClearClipboard();
const char* data = "Data to be stored in clipboard";
const size_t data_size = strlen(data) + 1;
HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, data_size);
strcpy(GlobalLock(h), LPCSTR(data));
GlobalUnlock(h);
SetClipboardData(CF_TEXT, h);

The first input parameter for SetClipboardData is the data format. The documentation on supported clipboard formats on Windows can be seen here.

To get the data, currently stored in the clipboard, the process is even more simple:

const char* data = (const char*)GetClipboardData(CF_TEXT);

When you're done with clipboard, you must close it:

CloseClipboard();

Linux

General

The clipboard on Linux is supported via the X11 library. The clipboard managing process is a bit different then on Windows and a little more cumbersome.

The X11 library is a multi-buffer library, but the only two buffers we're gonna focus on are:

  1. Clipboard - the common copy-paste buffer.
  2. Primary - the implicit mouse selection feature buffer. Each time the user selects the text, it is being copied to the Primary buffer.

Unlike Windows, Linux clipboard buffers are not global objects, but application-side buffers. To change the buffer data, an application just changes its local data and notifies the server than it is the new owner of the buffer.
To get the data, currently stored in the clipboard, an application must request it from the current owner.

In code

The first two things you need to use the clipboard features are X11 server connection (display) and the window.

#include <X11/Xlib.h>
Display * display = XOpenDisplay(0);
Window window = XCreateSimpleWindow(display, RootWindow(display, N), 0, 0, 1, 1, 0, BlackPixel(display, N), WhitePixel(display, N));

We also need to create property atoms which are unique identifiers, associated with the properties:

Atom targets_atom = XInternAtom(display, "TARGETS", 0);
Atom text_atom = XInternAtom(display, "TEXT", 0);
Atom utf8 = XInternAtom(display, "UTF8_STRING", 1);
Atom selection = XInternAtom(display, "CLIPBOARD", 0); // Can also be "PRIMARY"

Then we set this application to be the owner of the buffer:

XSetSelectionOwner (display, selection, window, 0);
if (XGetSelectionOwner (display, selection) != window) return;

Some event handling:

XEvent event;
XNextEvent(display, &event);
if(event.type == SelectionRequest)
{
	XSelectionRequestEvent * xsr = &event.xselectionrequest;
	XSelectionEvent ev = {0};
	int R = 0;
	ev.type = SelectionNotify;
	ev.display = xsr->display; 
	ev.requestor = xsr->requestor;
	ev.selection = xsr->selection; 
	ev.time = xsr->time;
	ev.target = xsr->target;
	ev.property = xsr->property;
	if (ev.target == utf8)
		R = XChangeProperty(ev.display, ev.requestor, ev.property, utf8, 8, PropModeReplace, text, size);
	else ev.property = None;
	if ((R & 2) == 0) XSendEvent (display, ev.requestor, 0, 0, (XEvent *)&ev); // this actually copies the data to clipboard
}

The pasting process is a bit more simple:

const char* data_to_get = nullptr;
Atom utf8 = XInternAtom(display, "UTF8_STRING", True);
XEvent event;
int format;
unsigned long N, size;
char * data, * paste_data = 0;
Atom target;
Atom CLIPBOARD = XInternAtom(display, "CLIPBOARD", 0); // Can also be "PRIMARY"
Atom XSEL_DATA = XInternAtom(display, "XSEL_DATA", 0);

First request a buffer:

XConvertSelection(display, CLIPBOARD, utf8, XSEL_DATA, window, CurrentTime);
XSync(display, 0);
XNextEvent(display, &event);

Then wait until the owner prepares a buffer.

while (event.type != SelectionNotify)
{
	XNextEvent(display, &event);
}

And finally read buffer content from window property:

XGetWindowProperty(event.xselection.display, event.xselection.requestor, event.xselection.property, 0L,(~0L), 0, AnyPropertyType, &target, &format, &size, &N,(unsigned char**)&data);
if(target == utf8) {
	paste_data = strndup(data, size);
	XFree(data);
}

In the end you must delete the property:

XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);

Good resources about X11 clipboard copy-pasting

SO (The second answer), and The Minimal X11 Copy-Pasting Functionality Implementation

MacOS, IOS

For Mac OS(macOS 10.0+) Apple provides a nice interface of clipboard management - NSPasteboard.
Also there is a clipboard version, available on both MacOS and IOS - UIPasteboard

To use the pasteboard (it's called pasteboard on macOS/IOS, so I'll use that term further on) you need to get the global pasteboard object:

MacOS-only option

NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];

Option available on both MacOS and IOS

UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard];

Then, to copy text into the pasteboard, use these two lines:

NSString* string_to_write = @"Data to be stored in the pasteboard";
BOOl pasted = [pasteBoard setString:string_to_write forType:NSStringPboardType];

You can also store data of different format, using setData(_:forType:) method.

To get the text, currently stored in the pasteboard, do this:

NSString* data_from_pasteboard = [pasteBoard stringForType:NSStringPboardType];

Android

For android there is a good class that helps you manage clipboard - ClipboardManager

First create an instance of the ClipboardManager class:

ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 

Then create a ClipData class instance and provide it with some data and push it to the clipboard:

String text = "Text to be stored in the stored in the clipboard";
ClipData clip = ClipData.newPlainText(label, text);
clipboard.setPrimaryClip(clip);

It is also possible to set the data of different formats, using the static ClipData methods.

To get the data, stored in the clipboard:

ClipData data = getPrimaryClip();
CharSequence text = data.getPrimaryClip().getText();

Cross-platform Libraries for clipboard management

Apparently there are not many open-source cross-platform libraries for clipboard management.

  1. Clip (MIT) - A lightweight library that works with Windows, Linux and Mac OS. This one is probably the closest to ideal. No IOS/Android implementation though.
  2. Qt (GPL3, LGPL3) - Obviously not a good choice, the only advantage is that it supposts all 5 platforms.

IMO, the Clip library is the one to go with. I think it's not that big of a problem to make it work on IOS (even though it uses the way of clipboard management, not available in IOS), and the Android support is something that should be added on our own.

Finding GLSL headers with NBL_EMBED_BUILTIN_RESOURCES is sensitive to the CWD

Describe the bug

When running with a Current Working Directory different that the executable, the denoiser fails with

Parse status: XML_STATUS_OK
????: error: **REDACTED**/ShaderCommon.glsl:33: '#include' : Could not open file for header name: irr/builtin/glsl/colorspace/EOTF.glsl
????: error: **REDACTED**/ShaderCommon.glsl:34: '#include' : Could not open file for header name: irr/builtin/glsl/colorspace/encodeCIEXYZ.glsl
????: error: **REDACTED**/ShaderCommon.glsl:35: '#include' : Could not open file for header name: irr/builtin/glsl/colorspace/decodeCIEXYZ.glsl
????: error: **REDACTED**/ShaderCommon.glsl:36: '#include' : Could not open file for header name: irr/builtin/glsl/colorspace/OETF.glsl
????: error: **REDACTED**/ShaderCommon.glsl:51: '#include' : Could not open file for header name: irr/builtin/glsl/ext/LumaMeter/impl.glsl
????: error: **REDACTED**/ShaderCommon.glsl:70: '#include' : Could not open file for header name: irr/builtin/glsl/ext/LumaMeter/common.glsl

Steps to Reproduce

Run any example compiled with NBL_EMBED_BUILTIN_RESOURCES with a different CWD.

Expected vs observed behavior

When engine is compiled with NBL_EMBED_BUILTIN_RESOURCES , GLSL headers with absolute paths should always be found.

Environment

Reported on Windows so far.

Tessendorf Water simulation via ext::FFT

Description

Initialization:

  • Generate the spectrum as in the paper.

Simulation:

  • Animate the spectrum (rotate the phases)
  • do an inverse FFT
  • output a displacement and normal map
  • possibly mip-map the displacement and normal map + roughness

Incorrect working of `nbl_glsl_workgroupExclusvieMin`

Values returned by nbl_glsl_workgroupExclusiveMin are shifted by one place to the right,
so, result[0] = identity, result[1] = identity, and result[2] is what result[1] should have been and so on..

Steps to Reproduce

  1. Clone and build this

Need testing of Wayland window and surface

Description

Need to test Wayland window and Wayland EGL surface. For it, EGL functions must be loaded from .so (test this as well if this is working correctly -- see src/nbl/video/CEGLCaller.h). To be able to use Wayland, one has to choose to run Wayland session while logging into Linux.
Tests should happen on Intel GPU, since Nvidia apparently doesnt support Wayland: https://forums.developer.nvidia.com/t/how-do-i-run-wayland-on-nvidia-geforce-rtx-2070/157870 (it's (almost?) impossible to run Wayland session on NV drivers)

Additional context

Use my vulkan branch. Best to ask me about specific commit to checkout for tests (the branch is continuosly used for development). Make sure to uncomment what was commented out in this commit Crisspl@16b83e7 and uncomment #define _NBL_TEST_WAYLAND in include/nbl/core/compile_config.h.

CommandPool Reset

Description

From the quick read of criss_android branch I didnt find a commandpool reset function/method.

Description of the related problem

Creating a resettable commandbuffer requires a special flag on the pool which apparently slows down its allocator (I think linear can be used when you never plan on reclaiming resources).

On another hand, the pool can always be reset without any special flags, and this is supposedly the fastest method.

With this functionality we could improve @sadiuk's CommonAPI example utilities to create SC_IMG_COUNT command pools, and expect the user to use a different pool for every frame and reset them before every frame.

Solution proposal

Implement a pool reset functionality, but it will have to kill/put the allocated commandbuffers in the invalid state (or intial, no idea... read the Vulkan spec).

Additional context

buildaworldnet/IrrlichtBAW#115

Raytracing Roadmap

Bugs and Hacky Workaround removal

  • Sporadic UIAutomationCore crash (OpenCL timeout)
  • Cache the sample sequence properly (record the params) and change its locality
  • Solve the weird coloured fireflies issue
  • Instancing transform bugs (stuff gets thrown all over the scene)

Minimum Usability

  • Read Max Samples from the XML file
  • Implement Russian Roulette and read it from the XML as well
  • Robust Intersections
  • Implement Rejection Sampled NEE & Multiple Importance Sampling
  • Scramble key advancement
  • Denoiser Integration (optionally enabled)
  • Autoexposure Integration
  • Tonemapping Integration
  • Saving intermediate outputs when screenshotting
  • Envmap light source and importance sampling
  • Fast and FFT bloom choice

Tests

  • test divergence between Mitsuba, ex 42 and ex 22 in daily_pt.xml
  • yank up the max bounces and see if it causes a problem

Ease of Use

  • Unify raygen.comp and closestHit.comp
  • Extend nbl::system to be able to download textures and meshes over HTTP/URL
  • Integrate NVENC/libvpx for producing video captures while rendering (CPU solution preferred)
  • Cloud XR

Quality and Convergence with no bias

  • OBB computation for light source meshes
  • Blue Noise Sampling via Heitz's techniques of scramble key ordering
  • Schussler et al. BxDF fixes for bumpmaps and smooth shading normals
  • CLEAR/LEADR/Toksvig (produce roughness map while mipmap filtering bumpmap)

Easy Quality Wins

  • Covariance Rendering (possible memory bandwidth win of >15% by using mipmaps)
  • Light Path Expressions || Reweighting Firefly Samples
  • GSAA (increase roughness of curvy surfaces)
  • A-SVGF

Uber Quality

  • ReSTIR
  • Adaptive Sampling
  • Spatial and Temporal Denoising (Nvidia SDK, ProRender, Intel, Renderman-like 7 frame AI?)
  • Local TMO

Load Time Optimizations

  • Converted Asset Cache
  • Polyphase Mip Mapping
  • commit on GPU Virtual Texture and Virtual Geometry

Memory Optimizations

  • Basis-U compressed prefiltered textures in the cache
  • Compress geometry position attribute into 64bits

Rendering Optimizations

  • Pretransform (de-instance) if memory allows
  • Single BLAS for static scene elements
  • Selectively disable normals and reonstruct from position derivatives
  • dont fetch UVs or compute some derivatives if no texture precomp stream
  • Dont jitter and re-rasterize every frame if camera is still and we're accumulating
  • Occlusion and Triangle Culling when rasterizing
  • Vulkan Raytracing port
  • Path Guiding
  • Descriptor Indexing
  • Bidirectional or Global integrators such as VCM or UBP
  • Manifold NEE for caustics or lightsources embedded in bulbs

Risky Optimizations

  • Optimize rejection sampling to do spherical convex hulls of light source or clipping to the hemisphere
  • Material Compiler made out of RTX callables
  • Last Krivanek paper MIS weights out of the [0,1] range
  • Replace all scene BxDFs with LTC (texturing is problematic)
  • Combined product sampling of LTC and light (requires the above) probably via composed warps
  • LTC product path guiding

Endgame

  • Baking (DDGI or Spherical Gaussian lightmaps)
  • Animations & Temporal Tracing
  • Subsurface Scattering (level up the BxDFs)
  • Subdivision NEE for rendering of skin lit up by office lights
  • PN-Triangle intersection
  • Hair Rendering (geometry and BxDF)
  • Geometry LoDs
  • Out of Core Rendering (streaming Moana, here we come!)
  • Spectral Rendering with Herowavelengths and resolving to multiple colourspaces simultaneously

Asset Pipeline V3: Concurrency and Separation of `IAssetMetadata` from `IAsset`

Description

  • [Correctness] Add thread safe mutability for IAsset and eliminate a possible "double load" bug
  • [Performance] Prevent Double Loads of assets caused by multiple threads deciding to load an asset because all have queried the asset cache before either was done loading
  • [Performance] Make SAssetBundle hold the metadata, not the IAsset

Description of the related problem

Thread Safety

Assets should have a lock which should prevent read-accesses while an asset is being modified, and more than one thread/fiber modifying an asset.

Double Asset Loads

There is a possibility of a double load of an asset occuring if following events occur in this order:

  1. Thread A checks our thread-safe asset cache for path "huge.obj"
  2. Thread A decides to load the OBJ
  3. Thread B checks the asset cache for the same path
  4. Thread B decides to load the OBJ
  5. Thread A inserts loaded OBJ into cache
  6. Thread B inserts loaded OBJ into cache

Because the Cache is a multimap, both assets which are identical sit in the cache. This order of events is not the only one that produces the bug, other orders such as 123465, 123546, 132456, etc. will result in this problem.

Change the owner of asset metadata

Right now we have needless asset duplication if we want to convey different metadata with an asset that is 100% content ideantical, this especially impacts pipelines such as those returned by the MTL loader.

This results in unnecessary clone calls and multiple assets in the associative CPU2GPU cache, as well as multiple GPU objects which introduce many state changes.

The original design wanted the flexibility of attaching specific purpose metadata to each object in the DAG (especially pipelines for shader inputs and meshes for instancing data), however it has become evident that most of the time we're having many DAG objects point to the same metadata objects and a global metadata object would achieve everything we have so far (even specific metadata to IAsset in the DAG pairings).

Solution proposal

Thread Safety

Improve the Readers-Writers Lock in FW_Mutex to be more in line with std::recursive_lock APIs, at least the reading lock should be able to be recursive (writer lock not so much).

There should be an explicit method to:

  • acquire/release a reader lock
  • acquire/release a writer lock
  • upgrade/downgrade an already acquired reader lock to/from a writer lock without getting preempted

If writer lock has not been acquired then all the mutators of IAsset should assert.

However const-qualified functions should acquire the reader lock implicitly.

Double Asset Loads

We need to improve our cache container to be able to take "reservations" for keys, that is:

  1. If no concrete cached value or reservation has been made, proceed
    1a. Reserve a key value and place a dummy value indicating key has been reserved
    1b. Load the asset
    1c. Swap the reservation for the loaded asset
  2. If reservation has been already made, then wait until the asset has been loaded and reservation changes
  3. If concrete value is present then just return the asset

This might require a readers/writers lock, and/or sempahores/condition variables.

We need to analyze this design for the possibility of dead-locks because assets are DAGs and during the process of loading a single thread could put down multiple reservations.

Change the owner of asset metadata

Rename IAssetMetadata to IAssetBundleMetadata, remove it from the IAsset but add it to SAssetBundle.

Pipeline and Mesh specific metadata can be rephrased and recreated in the context of global metadata objects (have the global metadata keep maps of simple structs, etc.).

Simplify the whole system so there's only one global metadata type per loader.

Implement "restore from dummy" in all asset loaders via an asset loader base class

Zauwazylismy drugi problem z @criss , mianowicie ze jakis tam loader byc moze bedzie musial zrobic inspekcje dependent asseta (np. popatrzec w pixele tekstury, introspectowac shader, extrakcja info z descriptor seta) ktora wymaga aby ten asset nie byl dummy.

Problem taki ze nie mozna poprostu zrobic wszystkiego speculatively CPU_PERSISTENT bo mielibysmy ten sam problem co w IrrlichtBaW, tzn. ze wszystkie dane co moglyby byc GPU-only siedza na CPU jako kopie i zabieraja RAM.

Dlatego zrobilismy funckje restoreFrom dla kazdego asseta.

Wtedy "access to dependent asset required not to be a dummy, which is not builtin and IMMUTABLE, workflow" wyglada tak:

  1. getAssetvia override
  2. If asset was not found at all (dummy or not) then handle the load failure with override as usual
  3. if you don't require to be able to introspect the returned asset or its not a dummy then continue as usual
  4. getAsset again but with the DUPLICATE and DONT_CACHE flag (for as many levels as you need, usually only the first)
  5. if step 4 fails to return a non-dummy asset then handle the load failure with override as usual
  6. take your original asset from step 1 and call canBeRestoredFrom using asset from stop 4 as parameter
  7. if 6 returns true then call restoreFrom on asset from step 1 and use asset from stop 4 as parameter
  8. Drop asset from step 4 (it has now swapped its mutable contents with asset from step 1)
  9. continue as you would if you succeeded at step 3 right away

A przedtem wygladal tak:

  1. getAsset via override
  2. if asset is not found, handle finding failure with override
  3. dont check if its not a dummy and crash if you want to do something with it that requires it not be a dummy

P.S. Useful to solve alongside #50

Material Compiler GLSL includes are in the wrong place

Describe the bug

The headers have paths like this irr/builtin/material_compiler/glsl/

Expected vs observed behavior

The headers should have paths like this irr/builtin/glsl/material_compiler/ with the glsl folder first.

Extra

Tackle and fix in #22

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.