Browse Source

Added RenderAPI manual
Other minor improvements to the documentation

BearishSun 9 năm trước cách đây
mục cha
commit
24341978b0
26 tập tin đã thay đổi với 283 bổ sung78 xóa
  1. 180 10
      Documentation/Manuals/Native/renderAPI.md
  2. 12 12
      Documentation/Manuals/Native/scripting.md
  3. 10 5
      Source/BansheeCore/Include/BsHardwareBufferManager.h
  4. 7 4
      Source/BansheeCore/Include/BsIndexBuffer.h
  5. 6 1
      Source/BansheeCore/Include/BsVertexBuffer.h
  6. 4 1
      Source/BansheeCore/Include/BsVertexDeclaration.h
  7. 2 1
      Source/BansheeCore/Include/BsVertexDeclarationRTTI.h
  8. 14 5
      Source/BansheeCore/Source/BsHardwareBufferManager.cpp
  9. 14 8
      Source/BansheeCore/Source/BsIndexBuffer.cpp
  10. 1 3
      Source/BansheeCore/Source/BsMesh.cpp
  11. 1 3
      Source/BansheeCore/Source/BsMeshHeap.cpp
  12. 5 4
      Source/BansheeCore/Source/BsVertexBuffer.cpp
  13. 7 2
      Source/BansheeCore/Source/BsVertexDeclaration.cpp
  14. 1 1
      Source/BansheeD3D11RenderAPI/Include/BsD3D11HardwareBufferManager.h
  15. 1 1
      Source/BansheeD3D11RenderAPI/Include/BsD3D11IndexBuffer.h
  16. 2 2
      Source/BansheeD3D11RenderAPI/Source/BsD3D11HardwareBufferManager.cpp
  17. 2 2
      Source/BansheeD3D11RenderAPI/Source/BsD3D11IndexBuffer.cpp
  18. 1 1
      Source/BansheeD3D9RenderAPI/Include/BsD3D9HardwareBufferManager.h
  19. 1 1
      Source/BansheeD3D9RenderAPI/Include/BsD3D9IndexBuffer.h
  20. 3 3
      Source/BansheeD3D9RenderAPI/Source/BsD3D9HardwareBufferManager.cpp
  21. 2 2
      Source/BansheeD3D9RenderAPI/Source/BsD3D9IndexBuffer.cpp
  22. 1 1
      Source/BansheeGLRenderAPI/Include/BsGLHardwareBufferManager.h
  23. 1 1
      Source/BansheeGLRenderAPI/Include/BsGLIndexBuffer.h
  24. 2 2
      Source/BansheeGLRenderAPI/Source/BsGLHardwareBufferManager.cpp
  25. 2 2
      Source/BansheeGLRenderAPI/Source/BsGLIndexBuffer.cpp
  26. 1 0
      Source/BansheeMono/Include/BsMonoUtil.h

+ 180 - 10
Documentation/Manuals/Native/renderAPI.md

@@ -4,7 +4,7 @@ Render API									{#renderAPI}
 
 Render API is an interface that allows you to perform low-level rendering operations akin to DirectX or OpenGL. In Banshee this API is provided through the @ref BansheeEngine::RenderAPI "RenderAPI" for the simulation thread, and @ref BansheeEngine::RenderAPICore "RenderAPICore" for the core thread. If you are confused by the dual nature of  objects, read the [core thread](@ref coreThread) manual. 
 
-For the remainder of this manual we'll focus on the core thread portion of the API, but both provide essentially identical functionality, with the main difference that the simulation thread one expects a @ref BansheeEngine::CoreThreadAccessor "CoreAccessor" as input, and the execution of the actual commands is delayed.
+For the remainder of this manual we'll focus on the core thread portion of the API, but both provide essentially identical functionality, with the main difference that the simulation thread one expects a @ref BansheeEngine::CoreThreadAccessor "CoreAccessor" as input, and the execution of the actual commands is delayed until they reach the core thread.
 
 Render API lets you manipulate the GPU pipeline by setting various states (depth stencil, blend and rasterizer), binding GPU programs, textures and executing draw calls. In this manual we'll cover how to use this API to perform rendering manually. 
 
@@ -41,7 +41,7 @@ Once you are done rendering make sure to call @ref BansheeEngine::RenderAPICore:
 
 A simple example covering all these commands:
 ~~~~~~~~~~~~~{.cpp}
-SPtr<RenderTarget> myRt = ...; // Assuming we created this earlier, and its a double-buffered window
+SPtr<RenderTarget> myRt = ...; // Assuming we created this earlier, and it's a double-buffered window
 
 RenderAPICore& rapi = RenderAPICore::instance();
 rapi.setRenderTarget(myRt);
@@ -54,23 +54,193 @@ rapi.swapBuffers();
 ~~~~~~~~~~~~~
  
 # Pipeline states {#renderAPI_b}
-Before executing the drawing operation you can optionally set up depth-stencil, rasterizer or blend states. If you do not set them, the default values will be used.
+Before executing the drawing operation you can optionally set up depth-stencil, rasterizer or blend states. If you do not set them, the default values will be used. The states allow you to customize the execution of the fixed (non-programmable) part of the GPU pipeline.
 
-Use @ref BansheeEngine::RenderAPICore::setDepthStencilState "RenderAPICore::setDepthStencilState" to set a @ref BansheeEngine::DepthStencilStateCore "DepthStencilState".
-Use @ref BansheeEngine::RenderAPICore::setBlendState "RenderAPICore::setBlendState" to set a @ref BansheeEngine::BlendStateCore "BlendState".
-Use @ref BansheeEngine::RenderAPICore::setRasterizerState "RenderAPICore::setRasterizerState" to set a @ref BansheeEngine::RasterizerStateCore "RasterizerState".
+States can be created by:
+ - @ref BansheeEngine::DepthStencilStateCore "DepthStencilStateCore" - Populate @ref BansheeEngine::DEPTH_STENCIL_STATE_DESC "DEPTH_STENCIL_STATE_DESC" and call @ref BansheeEngine::DepthStencilStateCore::create "DepthStencilStateCore::create" 
+ - @ref BansheeEngine::BlendStateCore "BlendStateCore" - Populate @ref BansheeEngine::BLEND_STATE_DESC "BLEND_STATE_DESC" and call @ref BansheeEngine::BlendStateCore::create "BlendStateCore::create" 
+ - @ref BansheeEngine::RasterizerStateCore "RasterizerStateCore" - Populate @ref BansheeEngine::RASTERIZER_STATE_DESC "RASTERIZER_STATE_DESC" and call @ref BansheeEngine::RasterizerStateCore::create "RasterizerStateCore::create" 
+ 
+They can then be bound to the pipeline by calling:
+ - @ref BansheeEngine::RenderAPICore::setDepthStencilState "RenderAPICore::setDepthStencilState" for @ref BansheeEngine::DepthStencilStateCore "DepthStencilStateCore"
+ - @ref BansheeEngine::RenderAPICore::setBlendState "RenderAPICore::setBlendState" for @ref BansheeEngine::BlendStateCore "BlendStateCore".
+ - @ref BansheeEngine::RenderAPICore::setRasterizerState "RenderAPICore::setRasterizerState" for @ref BansheeEngine::RasterizerStateCore "RasterizerStateCore".
 
-We won't explain what each of the states does. For that you can check out the class documentation of the states themselves, or familiarize yourself with the modern GPU pipeline in general, as the states mirror it exactly.
+We won't explain what each of the state's does. For that you can check out the class documentation of the states themselves, or familiarize yourself with the modern GPU pipeline in general, as the states mirror it exactly.
 
 # GPU programs {#renderAPI_c}
+Before drawing you must bind at least a vertex and a fragment GPU program. Optionally you can also bind geometry, hull or domain programs. While pipeline states allow you to control the fixed portions of the pipeline, GPU programs are fully programmable. To learn how to create GPU programs read the [manual](@ref gpuPrograms).
+
+You can bind a GPU program by calling @ref BansheeEngine::RenderAPICore::bindGpuProgram() "RenderAPICore::bindGpuProgram". You can also use @ref BansheeEngine::RenderAPICore::unbindGpuProgram() "RenderAPICore::unbindGpuProgram" to remove the GPU program from the pipeline, or @ref BansheeEngine::RenderAPICore::isGpuProgramBound() "RenderAPICore::isGpuProgramBound" to check if one is currently bound to a specific slot.
+
+For example:
+~~~~~~~~~~~~~{.cpp}
+SPtr<GpuProgramCore> fragmentProgram = ...;
+SPtr<GpuProgramCore> vertexProgram = ...;
+
+RenderAPICore& rapi = RenderAPICore::instance();
+rapi.bindGpuProgram(vertexProgram);
+rapi.bindGpuProgram(fragmentProgram);
+... execute some draw calls ...
+
+~~~~~~~~~~~~~
+
+With most GPU programs you will also likely want to customize their execution by assigning them some parameters.
 
 ## GPU program parameters {#renderAPI_c_a}
+Most GPU programs also accept a number of parameters, whether textures, buffers, sampler states or primitive values like floats or integers. Parameters can be split into two categories:
+ - Object - Textures, sampler states
+ - Data - Float, int, bool (and their vectors and arrays)
+ 
+In order to find out which parameters does a certain GPU program expect, as well as their type and other information, read the [GPU program](@ref gpuPrograms) manual. 
+ 
+### Object parameters {#renderAPI_c_a_a} 
+To assign a texture to a GPU program call @ref BansheeEngine::RenderAPICore::setTexture "RenderAPICore::setTexture". You will need to provide a GPU program type to assign the texture to, and a slot to bind the texture in. Each GPU program will provide a list of slots onto which you can bind textures in its parameter descriptor. 
+
+By default the texture will be bound for sampling. You can customize how is the texture sampled by creating a @ref BansheeEngine::SamplerStateCore "SamplerStateCore", by populating the @ref BansheeEngine::SAMPLER_STATE_DESC "SAMPLER_STATE_DESC" and calling @ref BansheeEngine::SamplerStateCore::create "SamplerStateCore::create". The state can then be bound to the pipeline by calling @ref BansheeEngine::RenderAPICore::setSamplerState "RenderAPICore::setSamplerState" which accepts similar parameters to @ref BansheeEngine::RenderAPICore::setTexture "RenderAPICore::setTexture".
+
+You can also bind a texture for both reading and writing by calling @ref BansheeEngine::RenderAPICore::setLoadStoreTexture "RenderAPICore::setLoadStoreTexture". Such textures are known as unordered-access (UAV) in DirectX, and load-store in OpenGL and are often used for compute operations (explained later). Be aware that the texture must have been created with the @ref BansheeEngine::TU_LOADSTORE "TU_LOADSTORE" flag in order to be bindable as a load-store texture. Load-store textures also cannot have multiple surfaces (i.e. faces or mip-maps) so you must choose which one to bind when calling @ref BansheeEngine::RenderAPICore::setLoadStoreTexture "RenderAPICore::setLoadStoreTexture".
+ 
+To learn more about textures read the [texture](@ref textures) manual.
 
-# Vertices {#renderAPI_d}
+An example binding a texture and its sampler state:
+~~~~~~~~~~~~~{.cpp}
+
+// Use nearest neighbor filtering when sampling
+SAMPLER_STATE_DESC ssDesc;
+ssDesc.magFilter = FO_POINT;
+ssDesc.minFilter = FO_POINT;
+ssDesc.mipFilter = FO_POINT;
+
+SPtr<SamplerStateCore> mySamplerState = SamplerStateCore::create(ssDesc);
+SPtr<TextureCore> myTexture = ...;
+
+RenderAPICore& rapi = RenderAPICore::instance();
+
+... bind GPU program ...
+
+// Bind the texture and sampler state to the 0th slot of the currently bound fragment program
+rapi.setTexture(GPT_FRAGMENT_PROGRAM, 0, myTexture);
+rapi.setSamplerState(GPT_FRAGMENT_PROGRAM, 0, mySamplerState);
+
+... execute some draw calls ...
+
+~~~~~~~~~~~~~
+
+### Data parameters {#renderAPI_c_a_b}
+Data parameters are bound to calling @ref BansheeEngine::RenderAPICore::setConstantBuffers "RenderAPICore::setConstantBuffers". You can only bind all data parameters at once. [GPU program](@ref gpuPrograms) manual has a lot more information about GPU parameters.
+
+Optionally you can call @ref BansheeEngine::RenderAPICore::setGpuParams "RenderAPICore::setGpuParams" which will bind both object and data parameters in the @ref BansheeEngine::GpuParamsCore "BansheeEngine::GpuParamsCore" object.
+
+For example:
+~~~~~~~~~~~~~{.cpp}
+SPtr<GpuProgramCore> program = ...;
+SPtr<GpuParamsCore> params = program->createParameters();
+
+... set param values ...
+
+RenderAPICore& rapi = RenderAPICore::instance();
+
+... bind GPU program ...
+
+// Set all data parameters for the currently bound fragment program
+rapi.setConstantBuffers(GPT_FRAGMENT_PROGRAM, params);
+
+... execute some draw calls ...
+
+~~~~~~~~~~~~~
 
-# Indices {#renderAPI_e}
+# Vertex buffer {#renderAPI_d}
+@ref BansheeEngine::VertexBufferCore "Vertex buffer" is a buffer that contains all vertices of the object we wish to render. When drawing the vertices will be interpreted as primitives (either points, lines or triangles) and rendered. Each vertex can have one or multiple properties associated with it.
+
+To create a vertex buffer call @ref BansheeEngine::VertexBufferCore::create "VertexBufferCore::create". You need to know the size of an individual vertex (determined by the properties each vertex requires) and the number of vertices. Optionally if your vertex buffer is used for output from the geometry GPU program you can toggle on the `streamOut` parameter.
+
+Once the vertex buffer is created you will want to populate it with some data (detailed below) and then bind it to the pipeline using @ref BansheeEngine::RenderAPICore::setVertexBuffers "RenderAPICore::setVertexBuffers". You can bind one or multiple vertex buffers at once. They all must have the same vertex counts but can have different properties, which will all be fed to the pipeline when rendering.
+
+Creation of an example vertex buffer:
+~~~~~~~~~~~~~{.cpp}
+// Create a vertex buffer containing 8 vertices with just a vertex position
+SPtr<VertexBufferCore> vb = VertexBufferCore::create(sizeof(Vector3), 8);
+
+RenderAPICore& rapi = RenderAPICore::instance();
+rapi.setVertexBuffers(0, { vb });
+~~~~~~~~~~~~~
+
+## Reading/writing {#renderAPI_d_a}
+@ref BansheeEngine::VertexBufferCore "VertexBuffer" provides a couple of way to read and write data from/to it:
+ - @ref BansheeEngine::VertexBufferCore::lock "VertexBufferCore::lock" locks a specific region of the vertex buffer and returns a pointer you can then use for reading and writing. Make sure to specify valid @ref BansheeEngine::GpuLockOptions "GpuLockOptions" signaling whether you are planning on read or writing from the buffer. Once done call @ref BansheeEngine::VertexBufferCore::unlock "VertexBufferCore::unlock" to make the locked region accessible to the GPU again.
+ - @ref BansheeEngine::VertexBufferCore::readData "VertexBufferCore::readData" and @ref BansheeEngine::VertexBufferCore::writeData "VertexBufferCore::writeData" to write or read entire blocks at once, but are more or less similar to the previous method.
+ - @ref BansheeEngine::VertexBufferCore::copyData "VertexBufferCore::copyData" can be used to efficiently copy data between two vertex buffers.
+
+An example of writing to the vertex buffer:
+~~~~~~~~~~~~~{.cpp}
+// Create a vertex buffer containing 8 vertices with just a vertex position
+SPtr<VertexBufferCore> vb = VertexBufferCore::create(sizeof(Vector3), 8);
+
+Vector3* positions = (Vector3)vb->lock(0, sizeof(Vector3) * 8, GBL_WRITE_ONLY_DISCARD);
+... write to the positions array ...
+vb->unlock();
+~~~~~~~~~~~~~
+
+When your vertices contain multiple properties it can be difficult to keep track of which offset to write which property, or determine the stride between two vertices. For this purpose you can use @ref BansheeEngine::VertexDataDesc "VertexDataDesc" which allows you to easily set up vertex properties like so:
+~~~~~~~~~~~~~{.cpp}
+// Create a vertex with a position, normal and UV coordinates
+SPtr<VertexDataDesc> vertexDesc = VertexDataDesc::create();
+vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
+vertexDesc->addVertElem(VET_FLOAT3, VES_NORMAL);
+vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
+~~~~~~~~~~~~~
+
+You can then use methods like @ref BansheeEngine::VertexDataDesc::getElementSize "VertexDataDesc::getElementSize" to learn the size of a particular element, @ref BansheeEngine::VertexDataDesc::getVertexStride "VertexDataDesc::getVertexStride" to learn the stride between elements. You can also retrieve detailed per-property information by iterating over all properties with @ref BansheeEngine::VertexDataDesc::getNumElements "VertexDataDesc::getNumElements" and @ref BansheeEngine::VertexDataDesc::getElement "VertexDataDesc::getElement". These methods return a @ref BansheeEngine::VertexElement "VertexElement" which can be used for finding out the offset of the individual element.
+
+To learn more about vertex descriptors read the [mesh](@ref meshes) manual.
+
+## Vertex declaration {#renderAPI_d_b}
+Before a vertex buffer can be used for rendering, you need to tell the pipeline in what format are its vertices structured in. You do that by creating a @ref BansheeEngine::VertexDeclarationCore "VertexDeclarationCore" object using the @ref BansheeEngine::VertexDataDesc "VertexDataDesc" we described in the previous section. This object can then be passed to @ref BansheeEngine::RenderAPICore::setVertexDeclaration "RenderAPICore::setVertexDeclaration" to bind it to the pipeline.
+
+For example:
+~~~~~~~~~~~~~{.cpp}
+SPtr<VertexDataDesc> vertexDesc = ...; // Creating vertex desc as above
+SPtr<VertexDeclarationCore> vertexDecl = VertexDeclarationCore::create(vertexDesc);
+
+RenderAPICore& rapi = RenderAPICore::instance();
+rapi.setVertexDeclaration(vertexDecl);
+~~~~~~~~~~~~~
+
+It is important that the vertex declaration contains properties needed by the bound vertex GPU program, as well as that it matches the vertex layout in the vertex buffer. See the [gpu program](@ref gpuPrograms) manual to learn how to retrieve vertex properties expected by a GPU program.
+
+# Index buffer {#renderAPI_e}
+Normally when you draw data from a vertex buffer, the vertices are assumed to form primitives sequentially (e.g. every three vertices is a triangle). By using an @ref BansheeEngine::IndexBufferCore "index buffer" you an provide an additional layer of abstraction. Index buffer is fully optional, but when bound it will be used for forming primitives instead of the vertex buffer (i.e. every three indices will form a triangle). Each entry in an index buffer points to a vertex in the vertex buffer. This level of abstraction allows you to re-use the same vertex in multiple primitives, as well as create more optimal vertex order for GPU processing.
+
+To create an index buffer call @ref BansheeEngine::IndexBufferCore::create "IndexBufferCore::create". It expects a number of indices, and the type of indices. Index type can be either 16- or 32-bit. To bind an index buffer to the pipeline call @ref BansheeEngine::RenderAPICore::setIndexBuffer "RenderAPICore::setIndexBuffer".
+
+Reading and writing from/to the index buffer has the identical interface to the vertex buffer, so we won't show it again.
 
 # Drawing {#renderAPI_f}
+Once all the previous states, programs and buffers have been set up, we can finally render our object. First of we must set up the type of primitives we wish to render by calling @ref BansheeEngine::RenderAPICore::setDrawOperation "RenderAPICore::setDrawOperation" with a @ref BansheeEngine::DrawOperationType "DrawOperationType" specifying the primitive type. This determines how the the vertices (or indices) in our buffers interpreted.
+
+After that you can issue a @ref BansheeEngine::RenderAPICore::draw "RenderAPICore::draw" call if rendering without an index buffer. It expects the vertex index to start rendering from, and the number of vertices to render. The number of vertices must be divisible by the number of vertices expected by the @ref BansheeEngine::DrawOperationType "DrawOperationType" you're using (e.g. three for triangles, two for lines, one for points). The vertices will then be pulled from the vertex buffers, processed by the fixed pipeline controlled by the states, and by the programmable pipeline controlled by the GPU programs and the output image will be rendered to the bound render target.
+
+If using an index buffer you should issue a @ref BansheeEngine::RenderAPICore::drawIndexed "RenderAPICore::drawIndexed" call. Aside from vertex offset/count, it also expects an offset into the index buffer to start rendering from, and number of indices to render from. In this case the vertex offset will be added to every read index, allowing you to re-use the index buffer for potentially different geometry. 
+ 
+And this wraps up the rendering pipeline. After this step your object should be rendered to your render target and ready to display. 
  
 # Compute {#renderAPI_g}
-TODO - Explain compute pipeline
+The compute pipeline is a very simple pipeline that can be used for general purpose calculations. It is separate from the render pipeline we have been describing so far, but uses the same functionality, just in a more limited way. You don't have to set states, render targets, vertex/index buffers and only one GPU program type is supported (compute GPU program).
+
+When the pipeline is set up you can execute it by calling @ref BansheeEngine::RenderAPICore::dispatchCompute "RenderAPICore::dispatchCompute". You should provide it a three dimensional number that determines how many instances of the currently bound GPU program to execute. The total number of executions will be X * Y * Z.
+
+Since compute pipeline doesn't support render targets, you will want to use load-store textures for output. An example of a simple compute pipeline:
+~~~~~~~~~~~~~{.cpp}
+SPtr<GpuProgramCore> computeProgram = ...;
+SPtr<TextureCore> loadStoreTexture = ...;
+
+RenderAPICore& rapi = RenderAPICore::instance();
+rapi.bindGpuProgram(computeProgram);
+rapi.setLoadStoreTexture(GPT_COMPUTE_PROGRAM, 0, true, loadStoreTexture, TextureSurface(0, 0));
+rapi.dispatchCompute(512, 512);
+
+... read from our texture to get the result ...
+~~~~~~~~~~~~~
+
+We won't go any deeper about the details of the compute pipeline as this information can be found by learning about the GPU pipeline in general from other sources.

+ 12 - 12
Documentation/Manuals/Native/scripting.md

@@ -10,12 +10,12 @@ Before we delve into the specifics of Banshee's scripting you should understand
 
 Because using Mono directly is complex (mostly due to its lack of documentation), Banshee provides a set of easy to use wrappers for almost all of Mono related functionality. 
 
-@ref BansheeMono is a plugin that wraps the functionality of the Mono runtime. Here is where the Mono runtime is started and assemblies are loaded (and unloaded), while also giving you detailed information about all loaded classes and a way to communicate with managed code.
+BansheeMono is a plugin that wraps the functionality of the Mono runtime. Here is where the Mono runtime is started and assemblies are loaded (and unloaded), while also giving you detailed information about all loaded classes and a way to communicate with managed code.
 
 The main entry point is the @ref BansheeEngine::MonoManager "MonoManager" class which allows you to start the runtime and load assemblies. The most important method here is @ref BansheeEngine::MonoManager::loadAssembly "MonoManager::loadAssembly". It takes as assembly path to load and returns a @ref BansheeEngine::MonoAssembly "MonoAssembly" object. 
 
 ## MonoAssembly 	{#scripting_a_a}
-@ref BansheeEngine::MonoAssembly "MonoAssembly" gives you access to all classes in the assembly. You can retrieve all clases using @ref BansheeEngine::MonoAssembly::getAllClasses "MonoAssembly::getAllClasses", or retrieve a specific one by calling @ref BansheeEngine::MonoAssembly::getClass(const String&, const String&) "MonoAssembly::getClass(namespace, typename)". Both of these methods return a @ref BansheeEngine::MonoClass "MonoClass" object.
+@ref BansheeEngine::MonoAssembly "MonoAssembly" gives you access to all classes in the assembly. You can retrieve all clases using @ref BansheeEngine::MonoAssembly::getAllClasses "MonoAssembly::getAllClasses", or retrieve a specific one by calling @ref BansheeEngine::MonoAssembly::getClass(const String&, const String&) const "MonoAssembly::getClass(namespace, typename)". Both of these methods return a @ref BansheeEngine::MonoClass "MonoClass" object.
 
 ## MonoClass 	{#scripting_a_b}
 @ref BansheeEngine::MonoClass "MonoClass" gives you access to all methods, fields, properties and attributes of a specific class. It also allows you to register "internal" methods. These methods allow the managed code to call C++ code, and we'll go into them later.
@@ -32,7 +32,7 @@ This class provides information about about a managed method, as well as giving
 To invoke a method you may use multiple approaches:
  - @ref BansheeEngine::MonoMethod::invoke "MonoMethod::invoke" - Calls the exact method on a specific managed object, with the provided parameters. We'll take about how managed objects are referenced in native code later, as well as how passing data between C++ and managed code works.
  - @ref BansheeEngine::MonoMethod::invokeVirtual "MonoMethod::invokeVirtual" - Calls the method polymorphically. Determines the actual type of the provided managed object instance and calls an overriden method if available.
- - @ref BansheeEngine::MonoMethod::getThunk "MonoMethod::getThunk" - Returns a C++ function pointer accepting a managed object, zero or more parameters and an exception object. You can then call the function pointer like you would a C++ function. This is equivalent to @ref BansheeEngine::MonoMethod::invoke "MonoMethod::invoke" but is significantly faster. A helper method @ref BansheeEngine::MonoUtil::invokeThunk "MonoUtil::invokeThunk" is provided - it is suggested you use it instead of calling thunks manually (it handles exceptions internally).
+ - @ref BansheeEngine::MonoMethod::getThunk const "MonoMethod::getThunk" - Returns a C++ function pointer accepting a managed object, zero or more parameters and an exception object. You can then call the function pointer like you would a C++ function. This is equivalent to @ref BansheeEngine::MonoMethod::invoke "MonoMethod::invoke" but is significantly faster. A helper method @ref BansheeEngine::MonoUtil::invokeThunk<T, Args> "MonoUtil::invokeThunk" is provided - it is suggested you use it instead of calling thunks manually (it handles exceptions internally).
 
 When calling static methods you should provide a null value for the managed object instance.
 
@@ -40,7 +40,7 @@ When calling static methods you should provide a null value for the managed obje
 Similar to methods, field information can be retrieved from @ref BansheeEngine::MonoClass "MonoClass" by calling @ref BansheeEngine::MonoClass::getField "MonoClass::getField" or @ref BansheeEngine::MonoClass::getAllFields "MonoClass::getAllFields". The returned value is a @ref BansheeEngine::MonoField "MonoField" which provides information about the field and allows you to retrieve and set values in the field using @ref BansheeEngine::MonoField::getValue "MonoField::getValue" / @ref BansheeEngine::MonoField::setValue "MonoField::setValue". This works similar to how methods are invoked and is explained in more detail later.
 
 ## MonoProperty {#scripting_a_e}
-Properties are very similar to fields, retrieved from @ref BansheeEngine::MonoClass "MonoClass" by calling @ref BansheeEngine::MonoClass::getProperty "MonoClass::getProperty" or @ref BansheeEngine::MonoClass::getAllProperties "MonoClass::getAllProperties". The returned value is a @ref BansheeEngine::MonoProperty "MonoProperty" which provides information about the property and allows you to retrieve and set values in it. The main difference is that properties in C# can be indexed (like arrays) and therefore a two set of set/get methods are provided, one accepting an index and other one not. It's up to the user to know which one to call. The methods are @ref BansheeEngine::MonoProperty::get "MonoProperty::get" / @ref BansheeEngine::MonoProperty::set "MonoProperty::set" and @ref BansheeEngine::MonoProperty::getIndexed "MonoProperty::getIndexed" / @ref BansheeEngine::MonoProperty::setIndexed "MonoProperty::setIndexed".
+Properties are very similar to fields, retrieved from @ref BansheeEngine::MonoClass "MonoClass" by calling @ref BansheeEngine::MonoClass::getProperty "MonoClass::getProperty". The returned value is a @ref BansheeEngine::MonoProperty "MonoProperty" which provides information about the property and allows you to retrieve and set values in it. The main difference is that properties in C# can be indexed (like arrays) and therefore a two set of set/get methods are provided, one accepting an index and other one not. It's up to the user to know which one to call. The methods are @ref BansheeEngine::MonoProperty::get "MonoProperty::get" / @ref BansheeEngine::MonoProperty::set "MonoProperty::set" and @ref BansheeEngine::MonoProperty::getIndexed "MonoProperty::getIndexed" / @ref BansheeEngine::MonoProperty::setIndexed "MonoProperty::setIndexed".
 
 ## Attributes {#scripting_a_f}
 Attributes provide data about a class, method or field provided at runtime, which usually allows such objects to be specialized in some regard. Attributes don't have their own wrapper, because they are esentially normal managed objects and you can work with them as such.
@@ -92,7 +92,7 @@ The first step is to define a stub method in managed code, like so:
 private static extern float Internal_GetSomeValue(MyObject obj);
 ~~~~~~~~~~~~~
 	
-You then hook up this method with managed code by calling @ref BansheeEngine::MonoClass::addInternalMethod "MonoClass::addInternalMethod". In this specific case it would be `myClass->addInternalMethod("Internal_GetSomeValue", &myNativeFunction)`, assuming `myClass` is a @ref BansheeEngine::MonoClass "MonoClass" of the type that contains the stub method. After this call any call to the managed stub method will call the provided native function `myNativeFunction`. You should take care to properly handle parameter passing as described above.
+You then hook up this method with managed code by calling @ref BansheeEngine::MonoClass::addInternalCall "MonoClass::addInternalCall". In this specific case it would be `myClass->addInternalCall("Internal_GetSomeValue", &myNativeFunction)`, assuming `myClass` is a @ref BansheeEngine::MonoClass "MonoClass" of the type that contains the stub method. After this call any call to the managed stub method will call the provided native function `myNativeFunction`. You should take care to properly handle parameter passing as described above.
 
 Take a look at @ref BansheeEngine::ScriptGUISkin "ScriptGUISkin" implementation for a simple example of how exactly does this work. 
 
@@ -134,7 +134,7 @@ The two last method definitions are called from C# (via an internal call, see th
 ### initRuntimeData ### {#scripting_b_a_a}
 `initRuntimeData` is a static method that every `ScriptObject` needs to implement. It takes care of hooking up managed internal methods to C++ functions. It gets called automatically whenever the assembly containing the related managed class is loaded. 
 
-Every `ScriptObject` provides a static @ref BansheeEngine::ScriptObject<Type, Base>::metaData "metaData" structure you can use for retrieving the @ref BansheeEngine::MonoClass "MonoClass" of the related managed class. You can use that @ref BansheeEngine::MonoClass "MonoClass" to register internal methods to it (as described earlier). For example a basic `initRuntimeData()` might look like so:
+Every `ScriptObject` provides a static @ref BansheeEngine::ScriptObject<Type, Base>::getMetaData "metaData" structure you can use for retrieving the @ref BansheeEngine::MonoClass "MonoClass" of the related managed class. You can use that @ref BansheeEngine::MonoClass "MonoClass" to register internal methods to it (as described earlier). For example a basic `initRuntimeData()` might look like so:
 ~~~~~~~~~~~~~{.cpp}
 void ScriptMyObject::initRuntimeData()
 {
@@ -171,10 +171,10 @@ MonoObject* ScriptMyObject::create()
 	
 In this case the method calls a parameterless constructor but you may specify parameters as needed.
 
-If you have a `MonoObject*` but need to retrieve its `ScriptObject` use @ref BansheeEngine::ScriptObject::toNative(MonoObject*) "toNative(MonoObject*)" static method. Within the interop object instance you can use @ref BansheeEngine::ScriptObject::getManagedInstance() "ScriptObject::getManagedInstance()" to retrieve the managed object.
+If you have a `MonoObject*` but need to retrieve its `ScriptObject` use @ref BansheeEngine::ScriptObject::toNative(MonoObject*) "toNative(MonoObject*)" static method. Within the interop object instance you can use @ref BansheeEngine::ScriptObjectBase::getManagedInstance() "ScriptObject::getManagedInstance()" to retrieve the managed object.
 
 ### Destroying script object instances ### {#scripting_b_a_c}
-When the managed object is destroyed (e.g. goes out of scope and gets garbage collected) the system will automatically take care of freeing the related ScriptObject. If you need to add onto or replace that functionality you can override @ref BansheeEngine::ScriptObject::_onManagedInstanceDeleted "ScriptObject::_onManagedInstanceDeleted" method.
+When the managed object is destroyed (e.g. goes out of scope and gets garbage collected) the system will automatically take care of freeing the related ScriptObject. If you need to add onto or replace that functionality you can override @ref BansheeEngine::ScriptObjectBase::_onManagedInstanceDeleted "ScriptObject::_onManagedInstanceDeleted" method.
 
 ## Managed wrapper object ## {#scripting_b_b}
 Creating the script interop object is one half of the job done. You also need to create the managed counterpart, however that is significantly simpler.
@@ -217,10 +217,10 @@ class MyScriptObject : public ScriptObject<MyScriptObject, PersistentScriptObjec
 ~~~~~~~~~~~~~	
 	
 This ensures that your object is treated properly during assembly refresh. Persistent object then needs to handle four different actions, represented by overrideable methods. These methods are called in order specified during assembly refresh.
- - @ref BansheeEngine::ScriptObject::beginRefresh() "ScriptObject::beginRefresh()" - Called just before the refresh starts. The object is still alive here and you can perform needed actions (e.g. saving managed object's contents).
- - @ref BansheeEngine::ScriptObject::_onManagedInstanceDeleted "ScriptObject::_onManagedInstanceDeleted()" - Called after assembly unload happened and the managed object was destroyed. You should override this to prevent the `ScriptObject` itself from being deleted if the assembly refresh is in progress (which is what the default implementation does). If assembly refresh is not in progress this method should delete the `ScriptObject` as normal because it likely got called due to standard reasons (managed object went out of scope).
- - @ref BansheeEngine::ScriptObject::createManagedInstance "ScriptObject::createManagedInstance()" - Creates the managed instance after new assemblies are loaded. You should override this if your managed class is constructed using a constructor with parameters. By default this will call @ref BansheeEngine::MonoClass::createInstance "MonoClass::createInstance()" using the parameterless constructor.
- - @ref BansheeEngine::ScriptObject::endRefresh() "ScriptObject::endRefresh()" - Called after all assemblies are loaded, and after all script interop objects were either destroyed (non-persistent) or had their managed instances created (persistent). Allows you to restore data stored in `beginRefresh()`, but that is optional.
+ - @ref BansheeEngine::ScriptObjectBase::beginRefresh() "ScriptObject::beginRefresh()" - Called just before the refresh starts. The object is still alive here and you can perform needed actions (e.g. saving managed object's contents).
+ - @ref BansheeEngine::ScriptObjectBase::_onManagedInstanceDeleted "ScriptObject::_onManagedInstanceDeleted()" - Called after assembly unload happened and the managed object was destroyed. You should override this to prevent the `ScriptObject` itself from being deleted if the assembly refresh is in progress (which is what the default implementation does). If assembly refresh is not in progress this method should delete the `ScriptObject` as normal because it likely got called due to standard reasons (managed object went out of scope).
+ - @ref BansheeEngine::ScriptObject::_createManagedInstance "ScriptObject::_createManagedInstance()" - Creates the managed instance after new assemblies are loaded. You should override this if your managed class is constructed using a constructor with parameters. By default this will call @ref BansheeEngine::MonoClass::createInstance "MonoClass::createInstance()" using the parameterless constructor.
+ - @ref BansheeEngine::ScriptObjectBase::endRefresh() "ScriptObject::endRefresh()" - Called after all assemblies are loaded, and after all script interop objects were either destroyed (non-persistent) or had their managed instances created (persistent). Allows you to restore data stored in `beginRefresh()`, but that is optional.
  
 See @ref BansheeEngine::ScriptSceneObject "ScriptSceneObject" and its base class @ref BansheeEngine::ScriptGameObjectBase "ScriptGameObjectBase" for example implementations of these methods.
 

+ 10 - 5
Source/BansheeCore/Include/BsHardwareBufferManager.h

@@ -41,10 +41,10 @@ namespace BansheeEngine
 		 * by the pipeline and vertices are drawn in the order specified in the index buffer.
 		 *
 		 * @param[in]	itype		Index type, determines size of an index.
-		 * @param[in]	numIndexes	Number of indexes can buffer can hold.
+		 * @param[in]	numIndices	Number of indexes can buffer can hold.
 		 * @param[in]	usage		Usage that tells the hardware how will be buffer be used. 
 		 */
-		virtual SPtr<IndexBuffer> createIndexBuffer(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
+		virtual SPtr<IndexBuffer> createIndexBuffer(IndexType itype, UINT32 numIndices, GpuBufferUsage usage);
 
 		/**
 		 * Creates an GPU parameter block that you can use for setting parameters for GPU programs. Parameter blocks may be
@@ -75,7 +75,7 @@ namespace BansheeEngine
 			GpuBufferType type, GpuBufferUsage usage, bool randomGpuWrite = false, bool useCounter = false);
 
 		/** Creates a new vertex declaration from a list of vertex elements. */
-		virtual SPtr<VertexDeclaration> createVertexDeclaration(const List<VertexElement>& elements);
+		virtual SPtr<VertexDeclaration> createVertexDeclaration(const SPtr<VertexDataDesc>& desc);
 	};
 
 	/**
@@ -92,7 +92,10 @@ namespace BansheeEngine
 		virtual SPtr<VertexBufferCore> createVertexBuffer(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false);
 
 		/** @copydoc HardwareBufferManager::createIndexBuffer */
-		virtual SPtr<IndexBufferCore> createIndexBuffer(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
+		virtual SPtr<IndexBufferCore> createIndexBuffer(IndexType itype, UINT32 numIndices, GpuBufferUsage usage);
+
+		/** @copydoc HardwareBufferManager::createVertexDeclaration */
+		virtual SPtr<VertexDeclarationCore> createVertexDeclaration(const SPtr<VertexDataDesc>& desc);
 
 		/** @copydoc HardwareBufferManager::createVertexDeclaration */
 		virtual SPtr<VertexDeclarationCore> createVertexDeclaration(const List<VertexElement>& elements);
@@ -106,7 +109,9 @@ namespace BansheeEngine
 
 	protected:
 		friend class IndexBuffer;
+		friend class IndexBufferCore;
 		friend class VertexBuffer;
+		friend class VertexBufferCore;
 		friend class VertexDeclaration;
 		friend class GpuParamBlockBuffer;
 		friend class GpuBuffer;
@@ -115,7 +120,7 @@ namespace BansheeEngine
 		virtual SPtr<VertexBufferCore> createVertexBufferInternal(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false) = 0;
 
 		/** @copydoc createIndexBuffer */
-		virtual SPtr<IndexBufferCore> createIndexBufferInternal(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage) = 0;
+		virtual SPtr<IndexBufferCore> createIndexBufferInternal(IndexType itype, UINT32 numIndices, GpuBufferUsage usage) = 0;
 
 		/** @copydoc createGpuParamBlockBuffer */
 		virtual SPtr<GpuParamBlockBufferCore> createGpuParamBlockBufferInternal(UINT32 size, GpuParamBlockUsage usage = GPBU_DYNAMIC) = 0;

+ 7 - 4
Source/BansheeCore/Include/BsIndexBuffer.h

@@ -29,7 +29,7 @@ namespace BansheeEngine
 		IndexType getType() const { return mIndexType; }
 
 		/**	Returns the number of indices this buffer can hold. */
-		UINT32 getNumIndices() const { return mNumIndexes; }
+		UINT32 getNumIndices() const { return mNumIndices; }
 
 		/**	Returns the size of a single index in bytes. */
 		UINT32 getIndexSize() const { return mIndexSize; }
@@ -39,7 +39,7 @@ namespace BansheeEngine
 		friend class IndexBufferCore;
 
 		IndexType mIndexType;
-		UINT32 mNumIndexes;
+		UINT32 mNumIndices;
 		UINT32 mIndexSize;
 	};
 
@@ -60,7 +60,7 @@ namespace BansheeEngine
 		SPtr<IndexBufferCore> getCore() const;
 
 		/** @copydoc HardwareBufferManager::createIndexBuffer */
-		static SPtr<IndexBuffer> create(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage);
+		static SPtr<IndexBuffer> create(IndexType itype, UINT32 numIndices, GpuBufferUsage usage = GBU_STATIC);
 
 	protected:
 		friend class HardwareBufferManager;
@@ -84,12 +84,15 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT IndexBufferCore : public CoreObjectCore, public HardwareBuffer
 	{
 	public:
-		IndexBufferCore(IndexType idxType, UINT32 numIndexes, GpuBufferUsage usage);
+		IndexBufferCore(IndexType idxType, UINT32 numIndices, GpuBufferUsage usage);
 		virtual ~IndexBufferCore() { }
 
 		/**	Returns information about the index buffer. */
 		const IndexBufferProperties& getProperties() const { return mProperties; }
 
+		/** @copydoc HardwareBufferManager::createIndexBuffer */
+		static SPtr<IndexBufferCore> create(IndexType itype, UINT32 numIndices, GpuBufferUsage usage = GBU_STATIC);
+
 	protected:
 		IndexBufferProperties mProperties;
 	};

+ 6 - 1
Source/BansheeCore/Include/BsVertexBuffer.h

@@ -46,7 +46,8 @@ namespace BansheeEngine
 		SPtr<VertexBufferCore> getCore() const;
 
 		/** @copydoc HardwareBufferManager::createVertexBuffer */
-		static SPtr<VertexBuffer> create(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false);
+		static SPtr<VertexBuffer> create(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage = GBU_STATIC, 
+			bool streamOut = false);
 
 		static const int MAX_SEMANTIC_IDX = 8;
 	protected:
@@ -79,6 +80,10 @@ namespace BansheeEngine
 		/**	Returns information about the vertex buffer. */
 		const VertexBufferProperties& getProperties() const { return mProperties; }
 
+		/** @copydoc HardwareBufferManager::createVertexBuffer */
+		static SPtr<VertexBufferCore> create(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage = GBU_STATIC,
+			bool streamOut = false);
+
 	protected:
 		VertexBufferProperties mProperties;
 	};

+ 4 - 1
Source/BansheeCore/Include/BsVertexDeclaration.h

@@ -155,7 +155,7 @@ namespace BansheeEngine
 		SPtr<VertexDeclarationCore> getCore() const;
 
 		/** @copydoc HardwareBufferManager::createVertexDeclaration */
-		static SPtr<VertexDeclaration> create(const List<VertexElement>& elements);
+		static SPtr<VertexDeclaration> create(const SPtr<VertexDataDesc>& desc);
 
     protected:
 		friend class HardwareBufferManager;
@@ -220,6 +220,9 @@ namespace BansheeEngine
 		 */
 		Vector<VertexElement> getMissingElements(const SPtr<VertexDeclarationCore>& shaderDecl);
 
+		/** @copydoc HardwareBufferCoreManager::createVertexDeclaration */
+		static SPtr<VertexDeclarationCore> create(const SPtr<VertexDataDesc>& desc);
+
     protected:
 		friend class HardwareBufferCoreManager;
 

+ 2 - 1
Source/BansheeCore/Include/BsVertexDeclarationRTTI.h

@@ -6,6 +6,7 @@
 #include "BsRTTIType.h"
 #include "BsVertexBuffer.h"
 #include "BsHardwareBufferManager.h"
+#include "BsVertexDataDesc.h"
 
 namespace BansheeEngine
 {
@@ -63,7 +64,7 @@ namespace BansheeEngine
 
 		SPtr<IReflectable> newRTTIObject() override
 		{
-			return HardwareBufferManager::instance().createVertexDeclaration(List<VertexElement>());
+			return HardwareBufferManager::instance().createVertexDeclaration(VertexDataDesc::create());
 		}
 
 		const String& getRTTIName() override

+ 14 - 5
Source/BansheeCore/Source/BsHardwareBufferManager.cpp

@@ -5,6 +5,7 @@
 #include "BsGpuBuffer.h"
 #include "BsVertexDeclaration.h"
 #include "BsGpuParamBlockBuffer.h"
+#include "BsVertexDataDesc.h"
 
 namespace BansheeEngine 
 {
@@ -16,9 +17,9 @@ namespace BansheeEngine
     {
     }
 
-	SPtr<VertexDeclaration> HardwareBufferManager::createVertexDeclaration(const List<VertexElement>& elements)
+	SPtr<VertexDeclaration> HardwareBufferManager::createVertexDeclaration(const SPtr<VertexDataDesc>& desc)
     {
-		VertexDeclaration* decl = new (bs_alloc<VertexDeclaration>()) VertexDeclaration(elements);
+		VertexDeclaration* decl = new (bs_alloc<VertexDeclaration>()) VertexDeclaration(desc->createElements());
 
 		SPtr<VertexDeclaration> declPtr = bs_core_ptr<VertexDeclaration>(decl);
 		declPtr->_setThisPtr(declPtr);
@@ -37,11 +38,11 @@ namespace BansheeEngine
 		return vbuf;
 	}
 
-	SPtr<IndexBuffer> HardwareBufferManager::createIndexBuffer(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage)
+	SPtr<IndexBuffer> HardwareBufferManager::createIndexBuffer(IndexType itype, UINT32 numIndices, GpuBufferUsage usage)
 	{
-		assert (numIndexes > 0);
+		assert (numIndices > 0);
 
-		SPtr<IndexBuffer> ibuf = bs_core_ptr<IndexBuffer>(new (bs_alloc<IndexBuffer>()) IndexBuffer(itype, numIndexes, usage));
+		SPtr<IndexBuffer> ibuf = bs_core_ptr<IndexBuffer>(new (bs_alloc<IndexBuffer>()) IndexBuffer(itype, numIndices, usage));
 		ibuf->_setThisPtr(ibuf);
 		ibuf->initialize();
 		return ibuf;
@@ -85,6 +86,14 @@ namespace BansheeEngine
 		return vbuf;
 	}
 
+	SPtr<VertexDeclarationCore> HardwareBufferCoreManager::createVertexDeclaration(const SPtr<VertexDataDesc>& desc)
+	{
+		SPtr<VertexDeclarationCore> declPtr = createVertexDeclarationInternal(desc->createElements());
+		declPtr->initialize();
+
+		return declPtr;
+	}
+
 	SPtr<VertexDeclarationCore> HardwareBufferCoreManager::createVertexDeclaration(const List<VertexElement>& elements)
 	{
 		SPtr<VertexDeclarationCore> declPtr = createVertexDeclarationInternal(elements);

+ 14 - 8
Source/BansheeCore/Source/BsIndexBuffer.cpp

@@ -6,8 +6,8 @@
 
 namespace BansheeEngine 
 {
-	IndexBufferProperties::IndexBufferProperties(IndexType idxType, UINT32 numIndexes)
-		:mIndexType(idxType), mNumIndexes(numIndexes)
+	IndexBufferProperties::IndexBufferProperties(IndexType idxType, UINT32 numIndices)
+		:mIndexType(idxType), mNumIndices(numIndices)
 	{
 		switch (mIndexType)
 		{
@@ -20,10 +20,15 @@ namespace BansheeEngine
 		}
 	}
 
-	IndexBufferCore::IndexBufferCore(IndexType idxType, UINT32 numIndexes, GpuBufferUsage usage)
-		:HardwareBuffer(usage, false), mProperties(idxType, numIndexes)
+	IndexBufferCore::IndexBufferCore(IndexType idxType, UINT32 numIndices, GpuBufferUsage usage)
+		:HardwareBuffer(usage, false), mProperties(idxType, numIndices)
 	{ 
-		mSizeInBytes = mProperties.mIndexSize * mProperties.mNumIndexes;
+		mSizeInBytes = mProperties.mIndexSize * mProperties.mNumIndices;
+	}
+
+	SPtr<IndexBufferCore> IndexBufferCore::create(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage)
+	{
+		return HardwareBufferCoreManager::instance().createIndexBufferInternal(itype, numIndexes, usage);
 	}
 
     IndexBuffer::IndexBuffer(IndexType idxType, UINT32 numIndexes, GpuBufferUsage usage) 
@@ -39,11 +44,12 @@ namespace BansheeEngine
 
 	SPtr<CoreObjectCore> IndexBuffer::createCore() const
 	{
-		return HardwareBufferCoreManager::instance().createIndexBufferInternal(mProperties.mIndexType, mProperties.mNumIndexes, mUsage);
+		return HardwareBufferCoreManager::instance().createIndexBufferInternal(mProperties.mIndexType, 
+			mProperties.mNumIndices, mUsage);
 	}
 
-	SPtr<IndexBuffer> IndexBuffer::create(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage)
+	SPtr<IndexBuffer> IndexBuffer::create(IndexType itype, UINT32 numIndices, GpuBufferUsage usage)
 	{
-		return HardwareBufferManager::instance().createIndexBuffer(itype, numIndexes, usage);
+		return HardwareBufferManager::instance().createIndexBuffer(itype, numIndices, usage);
 	}
 }

+ 1 - 3
Source/BansheeCore/Source/BsMesh.cpp

@@ -42,9 +42,7 @@ namespace BansheeEngine
 		mVertexData = SPtr<VertexData>(bs_new<VertexData>());
 
 		mVertexData->vertexCount = mProperties.mNumVertices;
-
-		List<VertexElement> elements = mVertexDesc->createElements();
-		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(elements);
+		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(mVertexDesc);
 
 		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
 		{

+ 1 - 3
Source/BansheeCore/Source/BsMeshHeap.cpp

@@ -296,9 +296,7 @@ namespace BansheeEngine
 		mVertexData = SPtr<VertexData>(bs_new<VertexData>());
 
 		mVertexData->vertexCount = mNumVertices;
-		List<VertexElement> elements = mVertexDesc->createElements();
-
-		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(elements);
+		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(mVertexDesc);
 
 		// Create buffers and copy data
 		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)

+ 5 - 4
Source/BansheeCore/Source/BsVertexBuffer.cpp

@@ -1,11 +1,7 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsVertexBuffer.h"
-#include "BsColor.h"
-#include "BsException.h"
 #include "BsHardwareBufferManager.h"
-#include "BsRenderAPI.h"
-#include "BsVertexDeclarationRTTI.h"
 
 namespace BansheeEngine 
 {
@@ -21,6 +17,11 @@ namespace BansheeEngine
 		mSizeInBytes = mProperties.mVertexSize * mProperties.mNumVertices;
 	}
 
+	SPtr<VertexBufferCore> VertexBufferCore::create(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut)
+	{
+		return HardwareBufferCoreManager::instance().createVertexBufferInternal(vertexSize, numVerts, usage, streamOut);
+	}
+
 	VertexBuffer::VertexBuffer(UINT32 vertexSize, UINT32 numVertices, GpuBufferUsage usage, bool streamOut)
 		: mProperties(numVertices, vertexSize), mUsage(usage), mStreamOut(streamOut)
     {

+ 7 - 2
Source/BansheeCore/Source/BsVertexDeclaration.cpp

@@ -220,6 +220,11 @@ namespace BansheeEngine
 		CoreObjectCore::initialize();
 	}
 
+	SPtr<VertexDeclarationCore> VertexDeclarationCore::create(const SPtr<VertexDataDesc>& desc)
+	{
+		return HardwareBufferCoreManager::instance().createVertexDeclaration(desc);
+	}
+
 	bool VertexDeclarationCore::isCompatible(const SPtr<VertexDeclarationCore>& shaderDecl)
 	{
 		const List<VertexElement>& shaderElems = shaderDecl->getProperties().getElements();
@@ -286,9 +291,9 @@ namespace BansheeEngine
 		return HardwareBufferCoreManager::instance().createVertexDeclarationInternal(mProperties.mElementList);
 	}
 
-	SPtr<VertexDeclaration> VertexDeclaration::create(const List<VertexElement>& elements)
+	SPtr<VertexDeclaration> VertexDeclaration::create(const SPtr<VertexDataDesc>& desc)
 	{
-		return HardwareBufferManager::instance().createVertexDeclaration(elements);
+		return HardwareBufferManager::instance().createVertexDeclaration(desc);
 	}
 
 	/************************************************************************/

+ 1 - 1
Source/BansheeD3D11RenderAPI/Include/BsD3D11HardwareBufferManager.h

@@ -23,7 +23,7 @@ namespace BansheeEngine
 			GpuBufferUsage usage, bool streamOut = false) override;
 
 		/** @copydoc HardwareBufferCoreManager::createIndexBufferInternal */
-		SPtr<IndexBufferCore> createIndexBufferInternal(IndexType itype, UINT32 numIndexes, 
+		SPtr<IndexBufferCore> createIndexBufferInternal(IndexType itype, UINT32 numIndices, 
 			GpuBufferUsage usage) override;
 
 		/** @copydoc HardwareBufferCoreManager::createGpuParamBlockBufferInternal  */

+ 1 - 1
Source/BansheeD3D11RenderAPI/Include/BsD3D11IndexBuffer.h

@@ -16,7 +16,7 @@ namespace BansheeEngine
 	class BS_D3D11_EXPORT D3D11IndexBufferCore : public IndexBufferCore
 	{
 	public:
-		D3D11IndexBufferCore(D3D11Device& device, IndexType idxType, UINT32 numIndexes, GpuBufferUsage usage);
+		D3D11IndexBufferCore(D3D11Device& device, IndexType idxType, UINT32 numIndices, GpuBufferUsage usage);
 
 		~D3D11IndexBufferCore();
 

+ 2 - 2
Source/BansheeD3D11RenderAPI/Source/BsD3D11HardwareBufferManager.cpp

@@ -23,9 +23,9 @@ namespace BansheeEngine
 	}
 
 	SPtr<IndexBufferCore> D3D11HardwareBufferCoreManager::createIndexBufferInternal(IndexType itype,
-		UINT32 numIndexes, GpuBufferUsage usage)
+		UINT32 numIndices, GpuBufferUsage usage)
 	{
-		SPtr<D3D11IndexBufferCore> ret = bs_shared_ptr_new<D3D11IndexBufferCore>(mDevice, itype, numIndexes, usage);
+		SPtr<D3D11IndexBufferCore> ret = bs_shared_ptr_new<D3D11IndexBufferCore>(mDevice, itype, numIndices, usage);
 		ret->_setThisPtr(ret);
 
 		return ret;

+ 2 - 2
Source/BansheeD3D11RenderAPI/Source/BsD3D11IndexBuffer.cpp

@@ -6,8 +6,8 @@
 
 namespace BansheeEngine
 {
-	D3D11IndexBufferCore::D3D11IndexBufferCore(D3D11Device& device, IndexType idxType, UINT32 numIndexes, GpuBufferUsage usage)
-		:IndexBufferCore(idxType, numIndexes, usage), mDevice(device), mBuffer(nullptr)
+	D3D11IndexBufferCore::D3D11IndexBufferCore(D3D11Device& device, IndexType idxType, UINT32 numIndices, GpuBufferUsage usage)
+		:IndexBufferCore(idxType, numIndices, usage), mDevice(device), mBuffer(nullptr)
 	{
 
 	}

+ 1 - 1
Source/BansheeD3D9RenderAPI/Include/BsD3D9HardwareBufferManager.h

@@ -19,7 +19,7 @@ namespace BansheeEngine
 		SPtr<VertexBufferCore> createVertexBufferInternal(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false) override;
 
 		/** @copydoc HardwareBufferCoreManager::createIndexBufferInternal */
-		SPtr<IndexBufferCore> createIndexBufferInternal(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage) override;
+		SPtr<IndexBufferCore> createIndexBufferInternal(IndexType itype, UINT32 numIndices, GpuBufferUsage usage) override;
 
 		/** @copydoc	HardwareBufferCoreManager::createVertexDeclarationInternal */
 		SPtr<VertexDeclarationCore> createVertexDeclarationInternal(const List<VertexElement>& elements) override;

+ 1 - 1
Source/BansheeD3D9RenderAPI/Include/BsD3D9IndexBuffer.h

@@ -27,7 +27,7 @@ namespace BansheeEngine
 		};
 
     public:
-		D3D9IndexBufferCore(IndexType idxType, UINT32 numIndexes, GpuBufferUsage usage);
+		D3D9IndexBufferCore(IndexType idxType, UINT32 numIndices, GpuBufferUsage usage);
 		~D3D9IndexBufferCore();
 
 		/** @copydoc IndexBufferCore::readData */

+ 3 - 3
Source/BansheeD3D9RenderAPI/Source/BsD3D9HardwareBufferManager.cpp

@@ -20,11 +20,11 @@ namespace BansheeEngine
 		return ret;
 	}
 
-	SPtr<IndexBufferCore> D3D9HardwareBufferCoreManager::createIndexBufferInternal(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage)
+	SPtr<IndexBufferCore> D3D9HardwareBufferCoreManager::createIndexBufferInternal(IndexType itype, UINT32 numIndices, GpuBufferUsage usage)
 	{
-		assert(numIndexes > 0);
+		assert(numIndices > 0);
 
-		SPtr<D3D9IndexBufferCore> ret = bs_shared_ptr_new<D3D9IndexBufferCore>(itype, numIndexes, usage);
+		SPtr<D3D9IndexBufferCore> ret = bs_shared_ptr_new<D3D9IndexBufferCore>(itype, numIndices, usage);
 		ret->_setThisPtr(ret);
 
 		return ret;

+ 2 - 2
Source/BansheeD3D9RenderAPI/Source/BsD3D9IndexBuffer.cpp

@@ -11,8 +11,8 @@
 
 namespace BansheeEngine 
 {
-	D3D9IndexBufferCore::D3D9IndexBufferCore(IndexType idxType, UINT32 numIndexes, GpuBufferUsage usage)
-		: IndexBufferCore(idxType, numIndexes, usage), mSystemMemoryBuffer(nullptr)
+	D3D9IndexBufferCore::D3D9IndexBufferCore(IndexType idxType, UINT32 numIndices, GpuBufferUsage usage)
+		: IndexBufferCore(idxType, numIndices, usage), mSystemMemoryBuffer(nullptr)
 	{ }
 
 	D3D9IndexBufferCore::~D3D9IndexBufferCore()

+ 1 - 1
Source/BansheeGLRenderAPI/Include/BsGLHardwareBufferManager.h

@@ -27,7 +27,7 @@ namespace BansheeEngine
 			UINT32 numVerts, GpuBufferUsage usage, bool streamOut = false) override;
 
 		/** @copydoc HardwareBufferCoreManager::createIndexBufferInternal */
-		SPtr<IndexBufferCore> createIndexBufferInternal(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage) override;
+		SPtr<IndexBufferCore> createIndexBufferInternal(IndexType itype, UINT32 numIndices, GpuBufferUsage usage) override;
 
 		/** @copydoc HardwareBufferCoreManager::createGpuParamBlockBufferInternal */
 		SPtr<GpuParamBlockBufferCore> createGpuParamBlockBufferInternal(UINT32 size, GpuParamBlockUsage usage = GPBU_DYNAMIC) override;

+ 1 - 1
Source/BansheeGLRenderAPI/Include/BsGLIndexBuffer.h

@@ -15,7 +15,7 @@ namespace BansheeEngine
     class BS_RSGL_EXPORT GLIndexBufferCore : public IndexBufferCore
     {
     public:
-		GLIndexBufferCore(IndexType idxType, UINT32 numIndexes, GpuBufferUsage usage);
+		GLIndexBufferCore(IndexType idxType, UINT32 numIndices, GpuBufferUsage usage);
 		~GLIndexBufferCore();
 
 		/** @copydoc IndexBufferCore::readData */

+ 2 - 2
Source/BansheeGLRenderAPI/Source/BsGLHardwareBufferManager.cpp

@@ -19,9 +19,9 @@ namespace BansheeEngine
 		return ret;
 	}
 
-	SPtr<IndexBufferCore> GLHardwareBufferCoreManager::createIndexBufferInternal(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage)
+	SPtr<IndexBufferCore> GLHardwareBufferCoreManager::createIndexBufferInternal(IndexType itype, UINT32 numIndices, GpuBufferUsage usage)
 	{
-		SPtr<GLIndexBufferCore> ret = bs_shared_ptr_new<GLIndexBufferCore>(itype, numIndexes, usage);
+		SPtr<GLIndexBufferCore> ret = bs_shared_ptr_new<GLIndexBufferCore>(itype, numIndices, usage);
 		ret->_setThisPtr(ret);
 
 		return ret;

+ 2 - 2
Source/BansheeGLRenderAPI/Source/BsGLIndexBuffer.cpp

@@ -7,8 +7,8 @@
 
 namespace BansheeEngine 
 {
-	GLIndexBufferCore::GLIndexBufferCore(IndexType idxType, UINT32 numIndexes, GpuBufferUsage usage)
-		:IndexBufferCore(idxType, numIndexes, usage), mZeroLocked(false)
+	GLIndexBufferCore::GLIndexBufferCore(IndexType idxType, UINT32 numIndices, GpuBufferUsage usage)
+		:IndexBufferCore(idxType, numIndices, usage), mZeroLocked(false)
 	{  }
 
 	GLIndexBufferCore::~GLIndexBufferCore()

+ 1 - 0
Source/BansheeMono/Include/BsMonoUtil.h

@@ -148,6 +148,7 @@ namespace BansheeEngine
 			}
 		}
 
+		/** Invokes a thunk retrieved from MonoMethod::getThunk const and automatically handles exceptions. */
 		template<class T, class... Args>
 		static void invokeThunk(T* thunk, Args... args)
 		{