Explorar el Código

Work on developer manuals

BearishSun hace 9 años
padre
commit
7777c4cd77

BIN
Documentation/Manuals/Native/Images/Architecture.png


BIN
Documentation/Manuals/Native/Images/ArchitectureSimple.png


+ 25 - 28
Documentation/Manuals/Native/architecture.md

@@ -13,11 +13,13 @@ Banshee is implemented throughout many separate libraries. Spreading the engine
 All the libraries can be separated into four main categories:
  - Layers - These are the core libraries of the engine. Each layer is built on top of the previous layer and provides higher level and more specific functionality than the other.
  - Plugins - These are separate, independant, and in most cases optional libraries containing various high level systems. They always depend on a specific layer, depending how high level the system they implement is. You are able to design your own plugins that completely replace certain portion of the engine functionality without having to modify the engine itself (e.g. use OpenGL instead of DirectX)
- - Scripting - These are libraries used for interop between the C++ core and the scripting language, as well as the managed scripting libraries themselves. Generally these can also be counted as plugins, but they are a bit more tightly coupled with the engine core.
+ - Scripting - These are libraries used for interop between the C++ core and a scripting language, as well as the managed scripting libraries themselves. Generally these can also be counted as plugins, but they are a bit more tightly coupled with the engine core.
  - Executable - These are small pieces of code meant to initialize and start up the engine/editor.
  
-To give you a better idea here is a diagram showing how all the libraries connect:
+To give you a better idea here is a diagram showing how all the libraries connect. You can use this for reference when we talk about the individual library purposes later on.
 ![Banshee's libraries](ArchitectureSimple.png)  
+
+> Note that BansheeEditor layer and scripting libraries are only available when compiling the full Banshee runtime, and are not present in bsFramework.
  
 # Layers #										{#arch_layers}
 The layers contain the core of the engine. All the essentials and all the abstract interfaces for plugins belong here. The engine core was split into multiple layers for two reasons:
@@ -27,30 +29,28 @@ The layers contain the core of the engine. All the essentials and all the abstra
 Lower layers were designed to be more general purpose than higher layers. They provide very general techniques usually usable in various situations, and they attempt to cater to everyone. On the other hand higher layers provide a lot more focused and specialized techniques. This might mean relying on very specific rendering APIs, platforms or plugins but it also means using newer, fancier and maybe not as widely accepted techniques (e.g. some new rendering algorithm or a shader).
 
 Going from the lowest to highest the layers are:
-## BansheeUtility ##					
+## BansheeUtility ## {#arch_utility}
 This is the lowest layer of the engine. It is a collection of very decoupled and separate systems that are likely to be used throughout all of the higher layers. Essentially a collection of tools that are in no way tied into a larger whole. Most of the functionality isn't even game engine specific, like providing [file-system access](@ref bs::FileSystem), [file path parsing](@ref bs::Path), [events](@ref bs::Event), [math library](@ref bs::Math), [RTTI system](@ref bs::RTTITypeBase), [threading primitives and managers](@ref bs::ThreadPool), among various others.
 
-See the [utilities](@ref utilities) manual for an overview of all the most important systems in this layer. 
-
-## BansheeCore ##		
-This layer builds upon the utility layer by providing abstract interfaces for most of the engine systems. The interfaces themselves are implemented in the form of plugins, and are not part of the layer itself (for the most part). This layer glues all the engine's systems together and provides a foundation that the engine is built on. The layer tries to be generic and include only functionality that is common, while leaving more specialized functionality for higher layers. Some systems provided by this layer are @ref bs::RenderAPI "render API wrapper", @ref bs::Resources "resource management", @ref bs::Importer "asset import", @ref bs::Input "input", @ref bs::Physics "physics" and more.
+## BansheeCore ## {#arch_core}
+This layer builds upon the utility layer by providing abstract interfaces for most of the engine systems. It is the largest layer in Banshee containing systems like @ref bs::RenderAPI "render API", @ref bs::Resources "resource management", @ref bs::Importer "asset import", @ref bs::Input "input", @ref bs::Physics "physics" and more. Implementations of its interfaces are for the most part implemented as plugins, and not part of the layer itself. The layer tries to be generic and include only functionality that is common, while leaving more specialized functionality for higher layers.
 
-## %BansheeEngine ##				
+## BansheeEngine ## {#arch_engine}			
 This layer builds upon the abstraction provided by the core layer and provides actual implementations of the core layer interfaces. Since most of the interfaces are implemented as plugins this layer doesn't contain too much of its own code, but is rather in charge of linking everything together. Aside from linking plugins together it also contains some specialized code, like the @ref bs::GUIManager "GUI" and @ref bs::ScriptManager "script" managers, as well as various other functionality that was not considered generic enough to be included in the core layer.
 
-## BansheeEditor ##					
+## BansheeEditor ##	{#arch_editor}
 And finally the top layer is the editor. It builts upon everything else so far and provides various editor specific features like the project library, build system, editor window management, scene view tools and similar. Large portions of the editor are implemented in the scripting code, and this layer provides more of a set of helper tools used by the scripting system. If you are going to work with this layer you will also be working closely with the scripting interop code and the scripting code (see below).
 
 # Plugins #										{#arch_plugins}
 Banshee provides a wide variety of plugins out of the box. The plugins are loaded dynamically and allow you to change engine functionality completely transparently to other systems (e.g. you can choose to load an OpenGL renderer instead of a DirectX one). Some plugins are completely optional and you can choose to ignore them (e.g. importer plugins can usually be ignored for game builds). Most importantly the plugins segregate the code, ensuring the design of the engine is decoupled and clean. Each plugin is based on an abstract interface implemented in one of the layers (for the most part, BansheeCore and %BansheeEngine layers).
 
 ## Render API ##								{#arch_rapi}		
-Render API plugins allow you to use a different backend for performing hardware accelerated rendering. @ref bs::RenderAPI "RenderAPI" handles low level rendering, including features like vertex/index buffers, creating rasterizer/depth/blend states, shader programs, render targets, textures, draw calls and similar. See the [render API](@ref renderAPI) manual to learn more about it.
+Render API plugins allow you to use a different backend for performing hardware accelerated rendering. @ref bs::RenderAPI "RenderAPI" handles low level rendering, including features like vertex/index buffers, creating rasterizer/depth/blend states, shader programs, render targets, textures, draw calls and similar. 
 
 The following plugins all have their own implementations of the @ref bs::RenderAPI "RenderAPI" interface, as well as any related types (e.g. @ref bs::VertexBuffer "VertexBuffer", @ref bs::IndexBuffer "IndexBuffer"):
  - **BansheeD3D11RenderAPI** - Provides implementation of the @ref bs::RenderAPI "RenderAPI" interface for DirectX 11. 
- - **BansheeD3D9RenderAPI**	- Provides implementation of the @ref bs::RenderAPI "RenderAPI" interface for DirectX 9. 
- - **BansheeGLRenderAPI** - Provides implementation of the @ref bs::RenderAPI "RenderAPI" interface for OpenGL 4.3.
+ - **BansheeVulkanRenderAPI**	- Provides implementation of the @ref bs::RenderAPI "RenderAPI" interface for Vulkan. 
+ - **BansheeGLRenderAPI** - Provides implementation of the @ref bs::RenderAPI "RenderAPI" interface for OpenGL 4.5.
 
 ## Importers ##									{#arch_importers}		
 Importers allow you to convert various types of files into formats easily readable by the engine. Normally importers are only used during development (e.g. in the editor), and the game itself will only use previously imported assets (although ultimately that's up to the user).
@@ -66,25 +66,27 @@ All importers implement a relatively simple interface represented by the @ref bs
 ### BansheeOISInput ###							{#arch_ois}
 Handles raw mouse/keyboard/gamepad input for multiple platforms. All input plugins implement the @ref bs::RawInputHandler "RawInputHandler" interface. Uses the OIS library specifically modified for Banshee (source code available with Banshee's dependencies). 
 
-Be aware that there is also an @ref bs::OSInputHandler "OSInputHandler" that is used for non-game specific purposes (e.g. tracking cursor, text input), but that is part of the engine core instead of a plugin.
-
-### BansheePhysX ###				
+### BansheePhysX ###				{#arch_physx}
 Handles physics: rigidbodies, colliders, triggers, joints, character controller and similar. Implements the @ref bs::Physics "Physics" interface and any related classes (e.g. @ref bs::Rigidbody "Rigidbody", @ref bs::Collider "Collider"). Uses NVIDIA PhysX as the backend.
 
-### BansheeMono ###					
-Provides access to the C# scripting language using the Mono runtime. This allows the C++ code to call into C# code, and vice versa, as well as providing various meta-data about the managed code, and other functionality. All the script interop libraries (listed below) depend on this plugin. See the [scripting](@ref scripting) manual to learn more about this layer.
+### BansheeMono ###					{#arch_mono}
+Provides access to the C# scripting language using the Mono runtime. This allows the C++ code to call into C# code, and vice versa, as well as providing various meta-data about the managed code, and other functionality. All the script interop libraries (listed below) depend on this plugin. 
 
-### RenderBeast ###					
-Banshee's default renderer. Implements the @ref bs::ct::Renderer "Renderer" interface. This plugin might seem similar to the render API plugins mentioned above but it is a higher level system. While render API plugins provide low level access to rendering functionality the renderer handles rendering of all scene objects in a specific manner without requiring the developer to issue draw calls manually. A specific set of options can be configured, both globally and per object that control how an object is rendered, as well as specifying completely custom materials. e.g. the renderer will handle physically based rendering, HDR, shadows, global illumination and similar features.
+### OpenAudio ###	{#arch_oa}
+Provides implementation of the audio system using the OpenAL library for audio playback, as well as FLAC, Ogg and Vorbis libraries for audio format import.
 
-See the [renderer](@ref renderer) manual to learn more about how the renderer works and how to implement your own.
+### FMOD ### {#arch_fmod}
+Provides implementation of the audio system using the FMOD library. Provides audio playback and audio file import for many formats.
+
+### RenderBeast ###		 {#arch_renderBeast}			
+Banshee's default renderer. Implements the @ref bs::ct::Renderer "Renderer" interface. This plugin might seem similar to the render API plugins mentioned above but it is a higher level system. While render API plugins provide low level access to rendering functionality the renderer handles rendering of all scene objects in a specific manner without requiring the developer to issue draw calls manually. A specific set of options can be configured, both globally and per object that control how an object is rendered, as well as specifying completely custom materials. e.g. the renderer will handle physically based rendering, HDR, shadows, global illumination and similar features.
 
 # Scripting #									{#arch_scripting}
 Scripting libraries can be placed into two different categories: 
- - Interop libraries written in C++. These provide glue code between C++ and C# (e.g. converting types, managing objects and similar). These are prefixed with the letter *S*.
+ - Interop libraries written in C++. These provide glue code between C++ and managed code (e.g. converting types, managing objects and similar). These are prefixed with the letter *S*.
  - Managed libraries containing actual managed code. These are prefixed with the letter *M*.
  
-Whenever adding a new type that exists in both script and managed code you will need to access both of these library categories. Read the [scripting](@ref scripting) manual to learn about exposing C++ code to scripts.
+Whenever adding a new type that exists in both script and managed code you will need to access both of these library categories. 
 
 Interop libraries:
  - **SBansheeEngine** - Provides glue code between %BansheeEngine layer and the scripting code in MBansheeEngine.
@@ -92,9 +94,4 @@ Interop libraries:
 
 Managed assemblies:
  - **MBansheeEngine**	- Provides most of the high-level C++ engine API available in %BansheeEngine layer (e.g. scene object model, resources, GUI, materials, etc.) as a high-level C# scripting API. Certain portions of the API are provided in pure C# (like the math library) while most just wrap their C++ counterparts.
- - **MBansheeEditor** - Provides all editor specific functionality from the BansheeEditor layer as a C# scripting API (e.g. project library, building, scene view, etc.). Also implements a large number of editor features in pure C# on top of the provided engine and editor APIs (e.g. specific editor windows and tools).
- 
-# Complete architecture #			{#arch_complete}
-See the diagram below to give you a better idea of the full architecture of Banshee. The diagram is not complete, but rather meant as a way to qive you a rough idea of where everything is, to make it easier to navigate the engine.
-
-![Architecture](@ref Architecture.png) 
+ - **MBansheeEditor** - Provides all editor specific functionality from the BansheeEditor layer as a C# scripting API (e.g. project library, building, scene view, etc.). Also implements a large number of editor features in pure C# on top of the provided engine and editor APIs (e.g. specific editor windows and tools).

+ 134 - 50
Documentation/Manuals/Native/coreThread.md

@@ -2,16 +2,16 @@ Core Thread								{#coreThread}
 ===============
 [TOC]
 
-Banshee is a multi-threaded engine that has two primary threads. One is the main thread on which the application is started, this is where your game code runs and what majority of users will be working with, we call this the **simulation** thread. The second thread is the rendering thread, this is where all calls to render API (like DirectX/OpenGL) are made. This thread also deals with the OS (like the main message loop). We call this the **core** thread.
+Banshee is a multi-threaded engine that has two primary threads. One is the main thread on which the application is started, this is where your game code runs and what majority of users will be working with, we call this the **simulation** thread. The second thread is the rendering thread, this is where all calls to render API (like Vulkan/DirectX/OpenGL) are made. This thread also deals with the OS (like the main message loop). We call this the **core** thread.
 
 Various other operations can use threads other than the two primary ones (async resource loading, physics, animation, etc.) in the form of worker threads or tasks. But we won't touch on those as they act as standard threads and the system using them has full control.
 
 Dealing with the core thread on the other hand requires some knowledge of how it interacts with the simulation thread. The core threads deals with:
- - Render API calls (DirectX/OpenGL)
+ - Render API calls (Vulkan/DirectX/OpenGL)
  - Renderer
  - OS functionality (window creation, main message loop)
 
-Here are some examples of when the simulation thread needs to interact with the core:
+Here are some examples of when the simulation thread needs to interact with the core thread:
  - You add a new renderable object to the scene. The simulation thread needs to notify the renderer.
  - You modify a property on a renderable/camera/light object. The simulation thread needs to notify the renderer.
  - You create a resource like a mesh or a texture. The simulation thread must schedule resource creation with the render API (i.e. creating vertex/pixel buffers for mesh, texture surfaces for texture).
@@ -24,78 +24,165 @@ As you can see the communication is one directional. Simulation thread calls int
 # Command queue {#coreThread_a}
 All the operations listed above happen with the help of a command queue. When simulation thread needs to notify the core thread about something it queues a command, which is then eventually received and processed by the core thread.
 
-@ref bs::CoreThread "CoreThread" manages the command queues. Use @ref bs::CoreThread::queueCommand "CoreThread::queueCommand" to queue a new command.
+@ref bs::CoreThread "CoreThread" manages all operations on the command queues. Use @ref bs::CoreThread::queueCommand "CoreThread::queueCommand()" to send a new command to the core thread.
 
-Each thread has its own command queue, so calling this method from multiple threads will fill up different command queues.
+~~~~~~~~~~~~~{.cpp}
+void doSomething()
+{ }
+
+// Queue doSomething method to be executed on the core thread
+gCoreThread().queueCommand(&doSomething);
+~~~~~~~~~~~~~
+
+Note that each thread has its own internal command queue. So calling this method from different threads will fill up their separate command queues. This is important because queuing the command does not actually make it sent to the core thread yet. Instead you must submit the commands after you are done queuing.
 
 ## Submitting commands {#coreThread_a_a}
-Commands that are queued aren't yet visible to the core thread. In order to make the command visible you must call @ref bs::CoreThread::submit "CoreThread::submit", which will submit all the commands for the current thread's command queue. You may also call @ref bs::CoreThread::submitAll "CoreThread::submitAll" to submit queues for all threads.
+Commands that are queued aren't yet visible to the core thread. In order to make them visible you must call @ref bs::CoreThread::submit "CoreThread::submit()", which will submit all the commands for the current thread's command queue. You may also call @ref bs::CoreThread::submitAll "CoreThread::submitAll()" to submit queues for all threads.
+
+~~~~~~~~~~~~~{.cpp}
+// Submit all commands queued since the last submit call
+gCoreThread().submit();
+~~~~~~~~~~~~~
+
+By default commands are also submitted automatically at the end of every frame, just before rendering. Therefore normally you do not need to submit commands manually.
 
-By default commands are also submitted at the end of every frame, just before rendering. Therefore normally you do not need to submit commands manually.
+The most common case for submitting commands manually is when you need the results of the command right away. In such a case you can call **CoreThread::submit()** or **CoreThread::submitAll()** with the parameter @p blockUntilComplete set to true. This will block the calling thread until the command finishes executing. Note that this is an expensive operation and shouldn't be done in performance critical code.
 
-The most common case for submitting commands manually is when you need the results of the command right away. In such a case you can call @ref bs::CoreThread::submit "CoreThread::submit" or @ref bs::CoreThread::submitAll "CoreThread::submitAll" with the parameter @p blockUntilComplete set to true. This will block the calling thread until the command finishes executing. Not that this is expensive and shouldn't be done in performance critical code.
+~~~~~~~~~~~~~{.cpp}
+// Submit all commands queued since the last submit call and wait until they're done executing
+gCoreThread().submit(true);
+~~~~~~~~~~~~~
 
 ## Internal queue {#coreThread_a_b}
-Internal command queue is different from the per-thread command queues because that's the only command queue that the core thread actually sees. For example, when you call @ref bs::CoreThread::submit "CoreThread::submit" the system takes all the commands from the per-thread command queue and moves them in the internal command queue, making them visible to the core thread.
+Internal command queue is different from the per-thread command queues because that's the only command queue that the core thread actually sees. For example, when you call **CoreThread::submit()** the system takes all the commands from the per-thread command queue and moves them to the internal command queue, making them visible to the core thread.
+
+You may directly queue commands on the internal command queue by calling **CoreThread::queueCommand()** with the @ref bs::CTQF_InternalQueue "CTQF_InternalQueue" flag. When such a command is submitted it is immediately visible to the core thread and does not require a separate call to **CoreThread::submit()**. 
+
+If you wish to block the calling thread until the internally queued command finishes executing you may provide the @ref bs::CTQF_BlockUntilComplete "CTQF_BlockUntilComplete" flag.
 
-Optionally you may directly queue commands on the internal command queue by calling @ref bs::CoreThread::queueCommand "CoreThread::queueCommand" with the @ref bs::CTQF_InternalQueue "CTQF_InternalQueue" flag. When such a command is submitted it is immediately visible to the core thread. You may also optionally provide the @ref bs::CTQF_BlockUntilComplete "CTQF_BlockUntilComplete" if you wish to block the calling thread until the command finishes executing.
+~~~~~~~~~~~~~{.cpp}
+void doSomething()
+{ }
+
+// Submit a command directly on the internal queue
+gCoreThread().queueCommand(&doSomething, CTQF_InternalQueue);
+~~~~~~~~~~~~~
 
-There is only one internal command queue, so different threads can write to it in an interleaved manner, unlike with normal threads. Note that internal command queue is slower than per-thread queues and you should prefer to use them instead.
+There is only one internal command queue, so different threads can write to it in an interleaved manner, unlike with per-thread queues. Note that internal command queue is slower than per-thread queues and you should prefer them instead.
 
-Also note that since command queued on the internal command queue are seen by the core thread immediately, they will execute before commands previously queued on normal per-thread queues, unless they were submitted.
+Also note that since commands queued on the internal command queue are seen by the core thread immediately, they will execute before commands previously queued on per-thread queues, unless they were submitted before you queued the command on the internal queue.
 
 ## Returning values {#coreThread_a_c}
-Sometimes a queued command needs to return a value to the simulation thread (for example, when reading pixels from a texture). This can be performed by calling @ref bs::CoreThread::queueReturnCommand "CoreThread::queueReturnCommand". Aside from the return value it operates in the same manner as @ref bs::CoreThread::queueCommand "CoreThread::queueCommand".
+Sometimes a queued command needs to return a value to the simulation thread (for example, when reading pixels from a texture). This can be performed by calling @ref bs::CoreThread::queueReturnCommand "CoreThread::queueReturnCommand()". Aside from the return value it operates in the same manner as **CoreThread::queueCommand()**.
+
+Since we don't know when will the core thread execute a queued command, we have no guarantees when will its return value be available. Therefore this method will return an @ref bs::AsyncOp "AsyncOp" object. This object can be used for checking if the return value is available by calling @ref bs::AsyncOp::hasCompleted "AsyncOp::hasCompleted()". If the return value is available you can retrieve it via @ref bs::AsyncOp::getReturnValue<T> "AsyncOp::getReturnValue<T>()".
+
+~~~~~~~~~~~~~{.cpp}
+void doSomethingAndReturn(AsyncOp& asyncOp)
+{
+	int result = 5 + 3;
+	asyncOp._completeOperation(result);
+}
+
+AsyncOp asyncOp = gCoreThread().queueReturnCommand(&doSomethingAndReturn);
+gCoreThread().submit();
+
+// do something ...
+
+if(asyncOp.hasCompleted()) // Or just block until done, as mentioned below
+{
+	String valueStr = toString(asyncOp.getReturnValue<int>());
+	gDebug().logWarning("Returned value: " + valueStr);
+}
+~~~~~~~~~~~~~
 
-Since the command was queued and we don't know when will the core thread execute, we have no guarantees when its return value will be available. Therefore this method will return an @ref bs::AsyncOp "AsyncOp" object. This object can be used for checking if the return value is available by calling @ref bs::AsyncOp::hasCompleted "AsyncOp::hasCompleted". If the return value is available you can retrieve it via @ref bs::AsyncOp::getReturnValue<T> "AsyncOp::getReturnValue<T>".
+As seen in the example, the callback method must accept an **AsyncOp** parameter, and set its data when done by calling @ref bs::AsyncOp::_completeOperation() "AsyncOp::_completeOperation()".
 
-@ref bs::AsyncOp "AsyncOp" also allow you to block the calling thread by calling @ref bs::AsyncOp::blockUntilComplete "AsyncOp::blockUntilComplete". This is similar to blocking directly on the @ref bs::CoreThread::submit "CoreThread::submit" or @ref bs::CoreThread::queueReturnCommand "CoreThread::queueReturnCommand" call, but can be more useful if you're not sure immediately if you need to wait for the result or not.
+**AsyncOp** also allows you to block the calling thread by calling @ref bs::AsyncOp::blockUntilComplete "AsyncOp::blockUntilComplete()". This is similar to blocking directly on the **CoreThread::submit()** or **CoreThread::queueReturnCommand()** calls, but can be more useful if you're not immediately sure if you need to wait for the result or not.
 
 # Core objects {#coreThread_b}
 Core objects are objects that need to exist on both simulation and core threads. Although you could technically handle such cases manually by using the command queue, it is useful to provide an interface that allows the user to work normally with an object without needing to know about the threading internals, and this is where core objects come in.
 
-For example, a @ref bs::Mesh "Mesh" is a core object because we want to allow the user to intuitively work with it on the simulation thread (without having to know about command queue or the core thread), but we also want to use it on the core thread (it needs to create index/vertex buffers on the GPU, and have a DirectX/OpenGL representation).
+For example, a @ref bs::Mesh "Mesh" is a core object because we want to allow the user to intuitively work with it on the simulation thread (without having to know about command queues or the core thread), but we also want to use it on the core thread (it needs to create index/vertex buffers on the GPU, and have a Vulkan/DirectX/OpenGL representation that can be used by the renderer).
 
 Every core object is split into two interfaces:
  - @ref bs::CoreObject "CoreObject" - Implementations of this interface represents the simulation thread counterpart of the object.
  - @ref bs::ct::CoreObject "ct::CoreObject" - Implementations of this interface represents the core thread counterpart of the object.
- 
-When a @ref bs::CoreObject "CoreObject" is created it internally queues the creation of its @ref bs::ct::CoreObject "ct::CoreObject" counterpart on the main command queue. Similar thing happens when it is destroyed, a destroy operation is queued and sent to the core thread. Objects used on the core thread are named the same as their simulation thread counterparts, but are in the **ct** namespace.
+  
+When a **CoreObject** is created it internally queues the creation of its **ct::CoreObject** counterpart on the command queue. Similar thing happens when it is destroyed, a destroy operation is queued and sent to the core thread. 
 
-Aside from initialization/destruction, core objects also support synchronization of data between the two threads (e.g. a @ref bs::Light "Light" is a core object, and when the user changes light radius, it is automatically synchronized to its core thread counterpart @ref bs::ct::Light "ct::Light").
+Aside from initialization/destruction, core objects also support synchronization of data between the two threads (e.g. a @ref bs::Light "Light" is a core object, and when the user changes light radius, it is automatically synchronized to its core thread counterpart @ref bs::ct::Light "ct::Light"). We talk more about this later.
+
+Both core thread counterpart class objects have the same name (e.g. **Mesh** or **Light**), but the core-thread counterpart is in the *ct* namespace. In fact, most classes meant to be used on the core thread (core objects or not), will be in the *ct* namespace.
 
 ## Creating your own core objects {#coreThread_b_a}
-To create a custom core object, you need to implement the @ref bs::CoreObject "CoreObject" class, which by default requires no methods to be implemented. 
+To create a custom core object, you need to implement the **CoreObject** class, and its core thread counterpart **ct::CoreObject**.
 
-When creating your core object its important to note they are only allowed to be referenced using specialized shared pointers, and require specific initialization steps. The shared pointer needs to be created using the @ref bs::bs_core_ptr_new<T> "bs_core_ptr_new<T>" method, followed by calls to @ref bs::CoreObject::_setThisPtr "CoreObject::_setThisPtr" and @ref bs::CoreObject::initialize "CoreObject::initialize". Due to this complex initialization procedure it is highly suggested that you create a static `create` method for your core object, which does every step automatically. For example:
 ~~~~~~~~~~~~~{.cpp}
-SPtr<MyCoreObject> MyCoreObject::create()
+class MyCoreObject : public CoreObject
 {
-	SPtr<MyCoreObject> myCoreObj = bs_core_ptr_new<MyCoreObject>();
-	myCoreObj->_setThisPtr(myCoreObj);
-	myCoreObj->initialize();
-	
-	return myCoreObj;
+	// ...
+};
+
+namespace ct
+{
+	class MyCoreObject : public CoreObject
+	{
+		// ...
+	};
 }
 ~~~~~~~~~~~~~
 
-You will also want to override @ref bs::CoreObject::createCore "CoreObject::createCore", which creates the core thread counterpart of your object. It should return a normal shared pointer to your implementation of @ref bs::ct::CoreObject "CoreObject".
+> Note that usually you want these two classes to share data and functionality (at least somewhat), and therefore you'll want to use base classes or templates to avoid redundant code.
+
+At minimum the **CoreThread** implementation requires an implementation of the @ref bs::CoreObject::createCore "CoreObject::createCore()" method, which creates and returns the core-thread counterpart of the object.
+
+~~~~~~~~~~~~~{.cpp}
+class MyCoreObject : public CoreObject
+{
+	SPtr<ct::CoreObject> createCore() override const 
+	{ 
+		SPtr<ct::MyCoreObject> ptr = bs_shared_ptr_new<ct::MyCoreObject>();
+		ptr->_setThisPtr(ptr);
+		
+		return ptr; 
+	}
+};
+~~~~~~~~~~~~~
+
+When creating your core object it's important to note they require specific initialization steps. As seen in the example, **ct::CoreThread** implementation needs to be created as a normal shared pointer, and the pointer instance must be assigned after creation by calling @ref bs::ct::CoreObject::_setThisPtr "ct::CoreObject::_setThisPtr()".
+
+For **CoreThread** implementation additional rules apply. Its shared pointer must be created using @ref bs::bs_core_ptr<T> "bs_core_ptr<T>" method, followed by a call to @ref bs::CoreObject::_setThisPtr "CoreObject::_setThisPtr()" and finally a call to @ref bs::CoreObject::initialize "CoreObject::initialize()". Due to the complex initialization procedure it is always suggested that you create a static `create` method that does these steps automatically. In fact **CoreObject** constructor is by default protected so you cannot accidently create it incorrectly.
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<MyCoreObject> MyCoreObject::create()
+{
+	// Because of the protected constructor we need to use placement new operator
+	MyCoreObject* ptr = new (bs_alloc<MyCoreObject>()) MyCoreObject();
 
-Once a core object is created you can use it as a normal object, while you can retrieve its core thread counterpart by calling @ref bs::CoreObject::getCore "CoreObject::getCore", which you can use on the core thread. Object creation/destruction will happen automatically on the valid thread, and you also get the ability to synchronize information between the two (see below).
+	SPtr<MyCoreObject> sptr = bs_core_ptr<MyCoreObject>(ptr);
+	sptr->_setThisPtr(sptr);
+	sptr->initialize();
+	
+	return sptr;
+}
+~~~~~~~~~~~~~
 
-### CoreObjectCore {#coreThread_b_a_a}
-To create the core thread counterpart of a @ref bs::CoreObject "CoreObject" you must implement the @ref bs::ct::CoreObject "ct::CoreObject" class. 
+Once a core object is created you can use it as a normal object, while you can retrieve its core thread counterpart by calling @ref bs::CoreObject::getCore "CoreObject::getCore()", which you can use on the core thread (e.g. when calling **CoreThread::queueCommand()**). Object creation/destruction will happen automatically on the valid thread, and you also get the ability to synchronize information between the two (see below).
 
-This object provides an @ref bs::CoreObject::initialize "CoreObject::initialize" method. You should perform any initialization in this method instead of the constructor, as it is guaranteed to be run on the core thread.
+### ct::CoreObject initialization {#coreThread_b_a_a}
+When creating the core thread counterpart object **ct::CoreObject** it is important to perform any initialization in the @ref bs::CoreObject::initialize "CoreObject::initialize()" method instead of the constructor. This is because the constructor will be executed on the simulation thread, but **CoreObject::initialize()** will be executed on the core thread.
 
-The destructor is always assumed to be executed on the core thread. For this reason you must ensure never to store references to CoreObjectCore on the simulation thread, because if they go out of scope there it will trigger an error. Similar rule applies to @ref bs::CoreObject "CoreObjects" as they shouldn't be stored on the core thread.
+The destructor is always assumed to be executed on the core thread. For this reason you must ensure never to store references to **ct::CoreObject** on the simulation thread, because if they go out of scope there it will trigger an error. Similar rule applies to **CoreObject** as it shouldn't be stored on the core thread.
 
 ### Synchronization {#coreThread_b_a_b}
-Earlier we mentioned that aside from handling construction/destruction the core objects also provide a way to synchronize between the two threads. The synchronization is always one way, from @ref bs::CoreObject "CoreObject" to @ref bs::ct::CoreObject "ct::CoreObject". 
+Earlier we mentioned that aside from handling construction/destruction the core objects also provide a way to synchronize between the two threads. The synchronization is always one way, from **CoreObject** to **ct::CoreObject**. 
+
+Synchronization should happen whenever some property on the **CoreObject** changes, that you would wish to make available on the core thread (e.g. a radius of a light source). To synchronize implement the @ref bs::CoreObject::syncToCore(FrameAlloc*) "CoreObject::syncToCore()" method, which generates the data for synchronization, and @ref bs::ct::CoreObject::syncToCore "ct::CoreObject::syncToCore()" which accepts it.
 
-Synchronization should happen whenever some property on the @ref bs::CoreObject "CoreObject" changes, that you would wish to make available on the core thread. To synchronize implement the @ref bs::CoreObject::syncToCore(FrameAlloc*) "CoreObject::syncToCore" method, which generates the data for synchronization, and @ref bs::ct::CoreObject::syncToCore "ct::CoreObject::syncToCore" which accepts it.
+The synchronized data is transfered between the objects in the form of raw bytes, within the @ref bs::CoreSyncData "CoreSyncData" structure. For convenience you can use @ref bs::rttiGetElemSize "rttiGetElemSize()" and @ref bs::rttiWriteElem "rttiWriteElem()" to encode fields into raw memory, and @ref bs::rttiReadElem "rttiReadElem()" to decode them. These are explained in more detail in the [advanced RTTI manual](@ref advancedRtti).
 
-The synchronized data is transfered between the objects in the form of raw bytes, within the @ref bs::CoreSyncData "CoreSyncData" structure. You can use @ref bs::rttiGetElemSize "rttiGetElemSize" and @ref bs::rttiWriteElem "rttiWriteElem" to encode fields into raw memory, and @ref bs::rttiReadElem "rttiReadElem" to decode them. See the manual about [rtti](@ref rtti) for more information about serialization. @ref bs::CoreObject::syncToCore(FrameAlloc*) "CoreObject::syncToCore" is provided an instance of @ref bs::FrameAlloc "FrameAlloc" which should be used for allocating the serialization buffer. This is an allocator that is fast and doesn't require explicit memory deallocation making it perfect for synchronization. A simple synchronization example would look like so:
+**CoreObject::syncToCore()** is provided an instance of @ref bs::FrameAlloc "FrameAlloc" which should be used for allocating the serialization buffer. This is an allocator that is fast and doesn't require explicit memory deallocation making it perfect for synchronization. A simple synchronization example would look like so:
 ~~~~~~~~~~~~~{.cpp}
 // CoreObject (creates the synchronization data)
 CoreSyncData MyCoreObject::syncToCore(FrameAlloc* allocator) 
@@ -125,27 +212,24 @@ void MyCoreObjectCore::syncToCore(const CoreSyncData& data)
 }
 ~~~~~~~~~~~~~
 
-Whenever you need to trigger synchronization you must call @ref bs::CoreObject::markCoreDirty "CoreObject::markCoreDirty" which notifies the system that synchronization is required. This will in turn trigger a call to @ref bs::CoreObject::syncToCore(FrameAlloc*) "CoreObject::syncToCore" method you implemented earlier. Synchronization happens automatically for all dirty core objects once per frame. Optionally you may call @ref bs::CoreObject::syncToCore() "CoreObject::syncToCore" to manually queue the synchronization.
-
-See implementation of @ref bs::Light "Light" and @ref bs::ct::Light "ct::Light" in "BsLight.cpp" for a simple example of synchronization.
+Whenever you need to trigger synchronization you must call @ref bs::CoreObject::markCoreDirty "CoreObject::markCoreDirty()" which notifies the system that synchronization is required. This will in turn trigger a call to **CoreObject::syncToCore** method you implemented earlier. Synchronization happens automatically for all dirty core objects once per frame. Optionally you may call @ref bs::CoreObject::syncToCore() "CoreObject::syncToCore()" to manually queue the synchronization on the per-thread command queue.
 
 ### Dependencies {#coreThread_b_a_c}
-Core objects might be dependant on other core objects. For example a @ref bs::Material "Material" is dependant on a @ref bs::Shader "Shader". Whenever the shader's object is marked as dirty the material might need to perform synchronization as well. In general whenever a dependancy core object is marked as dirty, its dependant will be synchronized as well.
+Core objects might be dependant on other core objects. For example a @ref bs::Material "Material" is dependant on a @ref bs::Shader "Shader". Whenever the shader's object is marked as dirty the material might need to perform synchronization as well. In general whenever a dependency core object is marked as dirty, its dependant will be synchronized as well.
 
-To add dependencies implement the @ref bs::CoreObject::getCoreDependencies "CoreObject::getCoreDependencies" method, which returns all currently valid dependencies. Whenever the dependencies change call @ref bs::CoreObject::markDependenciesDirty "CoreObject::markDependenciesDirty" so the system can refresh its dependency list.
+To add dependencies implement the @ref bs::CoreObject::getCoreDependencies "CoreObject::getCoreDependencies()" method, which returns all currently valid dependencies. Whenever the dependencies change call @ref bs::CoreObject::markDependenciesDirty "CoreObject::markDependenciesDirty()" so the system can refresh its dependency list.
 
 ## Deserialization {#coreThread_b_b}
-When creating RTTI for a @ref bs::CoreObject "CoreObject", as described in the [RTTI](@ref rtti) manual, you must take care not to fully initialize the object until deserialization of the object's fields is done.
+When creating RTTI for a **CoreObject** you must take care not to fully initialize the object until deserialization of the object's fields is done.
 
-Essentially this means that @ref bs::RTTITypeBase::newRTTIObject "RTTIType::newRTTIObject" must return a pointer to the core object on which @ref bs::CoreObject::initialize "CoreObject::initialize" hasn't been called yet. You must then call @ref bs::CoreObject::initialize "CoreObject::initialize" manually in @ref bs::RTTITypeBase::onDeserializationEnded "RTTIType::onDeserializationEnded".
+Essentially this means that @ref bs::RTTITypeBase::newRTTIObject "RTTIType::newRTTIObject()" must return a pointer to the core object on which **CoreObject::initialize()** hasn't been called yet. You must then call **CoreObject::initialize()** manually in @ref bs::RTTITypeBase::onDeserializationEnded "RTTIType::onDeserializationEnded()".
 
-This ensures that @ref bs::CoreObject::initialize "CoreObject::initialize" has all the relevant information when it is ran.
+This ensures that all information was properly deserialized before **CoreObject::initialize()** is ran.
 
 ## Other features {#coreThread_b_c}
 Core objects also have some other potentially useful features:
- - @ref bs::CoreObject::getInternalID "CoreObject::getInternalID" will return a globally unique ID for the core object
- - @ref bs::CoreObject::destroy "CoreObject::destroy" will destroy the core object and its core thread counterpart. You do not need to call this manually as it will be automatically called when the object goes out of scope (is no longer referenced). The core thread counterpart (@ref bs::ct::CoreObject "ct::CoreObject") will not be destroyed if something on the core thread is still holding a reference to it.
- - Override @ref bs::CoreObject::initialize "CoreObject::initialize" or @ref bs::CoreObject::destroy "CoreObject::destroy" methods instead of using the constructor/destructor. This ensures that your initialization code runs after things like serialization, and also allows you to call virtual methods.
- - You can construct a core object without a core thread counterpart. Simply don't override @ref bs::CoreObject::createCore "CoreObject::createCore".
- - You can construct a core object with a @ref bs::ct::CoreObject "CoreObject" that isn't initialized on the core thread by setting the @ref bs::CoreObject "CoreObject" constructor parameter `requiresCoreInit` to false.
- - Core objects always hold a shared pointer to themselves. Use @ref bs::CoreObject::getThisPtr "CoreObject::getThisPtr" to access it.
+ - @ref bs::CoreObject::getInternalID "CoreObject::getInternalID()" will return a globally unique ID for the core object
+ - @ref bs::CoreObject::destroy "CoreObject::destroy()" will destroy the core object and its core thread counterpart. You do not need to call this manually as it will be automatically called when the object goes out of scope (is no longer referenced). The core thread counterpart will not be destroyed if something on the core thread is still holding a reference to it.
+ - Override @ref bs::CoreObject::initialize "CoreObject::initialize()" or @ref bs::CoreObject::destroy "CoreObject::destroy()" methods instead of using the constructor/destructor. This ensures that your initialization code runs after things like serialization, and also allows you to call virtual methods.
+ - You can construct a core object without a core thread counterpart. Simply don't override @ref bs::CoreObject::createCore "CoreObject::createCore()". This is useful when creating resources, which all by default derive from **CoreObject** but simpler resources might not require core object features.
+ - Core objects always hold a shared pointer to themselves. Use @ref bs::CoreObject::getThisPtr "CoreObject::getThisPtr()" to access it.

+ 5 - 4
Documentation/Manuals/Native/manuals.md

@@ -72,13 +72,16 @@ A complete set of manuals covering all major functionality provided by Banshee,
  
 # Developer manuals
 A set of manuals covering advanced functionality intented for those wanting to extend the engine or tinker with the internals, rather than for normal users. You are expected to have read the user manuals first.
+- [Architecture overview](@ref architecture) 
+- **Low level rendering API**
+ - [Core thread](@ref coreThread)
+ - [GPU programs](@ref gpuPrograms)
+ - [Render API](@ref renderAPI)
 
 ## General guides
 Name                                      | Description
 ------------------------------------------|-------------
-[Architecture](@ref architecture)         | Gives you an overview of the entire architecture of Banshee. Useful starting point for those modifying engine internals as it provides a way to identify major systems.
 [Utilities](@ref utilities)               | Provides an overview of a variety of utility systems used throughout Banshee.
-[Core thread](@ref coreThread)            | Explains how core (rendering) thread works, how it interacts with simulation thread, what are core objects and how to create your own.
 [Resources](@ref resources)  			  | Explains how resources work, including saving, loading and creating brand new resource types.
 [Game objects](@ref gameObjects)          | Explains what are scene objects and components and how can you use them to create your scene.
 [Scripting](@ref scripting)               | Shows you how to interact with the scripting system, and how to expose C++ objects to the scripting API.
@@ -95,9 +98,7 @@ Name                                      | Description
 
 Name                                      | Description
 ------------------------------------------|-------------
-[Render API](@ref renderAPI)              | Explains how to use the render API to use the graphics pipeline and draw objects. 
 [Textures](@ref textures)                 | Shows you how to create, use and manipulate textures.
 [Meshes](@ref meshes)                     | Shows you how to create, use and manipulate meshes.
 [Render targets](@ref renderTargets)	  | Shows you how to create and use render textures and windows.
-[GPU programs](@ref gpuPrograms)		  | Shows you how to create and use GPU programs.
 [Materials](@ref materials)				  | Shows you how to create and use materials and shaders.