Parcourir la source

Getting rid of core thread accessors as they were confusing and of little practical use

BearishSun il y a 9 ans
Parent
commit
7fa57750e4
72 fichiers modifiés avec 876 ajouts et 865 suppressions
  1. BIN
      Documentation/Manuals/Native/Images/RenderWindow.png
  2. 39 0
      Documentation/Manuals/Native/User/windows.md
  3. 29 1
      Documentation/Manuals/Native/apiRefPages.md
  4. 1 1
      Documentation/Manuals/Native/coreThread.md
  5. 2 0
      Documentation/Manuals/Native/manuals.md
  6. 1 1
      Documentation/Manuals/Native/renderAPI.md
  7. 2 2
      Source/BansheeCore/CMakeSources.cmake
  8. 0 1
      Source/BansheeCore/Include/BsCoreApplication.h
  9. 5 4
      Source/BansheeCore/Include/BsCoreObject.h
  10. 6 4
      Source/BansheeCore/Include/BsCoreObjectManager.h
  11. 2 3
      Source/BansheeCore/Include/BsCorePrerequisites.h
  12. 167 178
      Source/BansheeCore/Include/BsCoreThread.h
  13. 13 18
      Source/BansheeCore/Include/BsCoreThreadQueue.h
  14. 24 32
      Source/BansheeCore/Include/BsMesh.h
  15. 4 4
      Source/BansheeCore/Include/BsMeshRTTI.h
  16. 120 44
      Source/BansheeCore/Include/BsRenderAPI.h
  17. 2 2
      Source/BansheeCore/Include/BsRenderTarget.h
  18. 41 46
      Source/BansheeCore/Include/BsRenderWindow.h
  19. 55 90
      Source/BansheeCore/Include/BsTexture.h
  20. 5 8
      Source/BansheeCore/Include/BsTextureRTTI.h
  21. 9 9
      Source/BansheeCore/Source/BsCoreApplication.cpp
  22. 8 9
      Source/BansheeCore/Source/BsCoreObject.cpp
  23. 4 4
      Source/BansheeCore/Source/BsCoreObjectManager.cpp
  24. 70 69
      Source/BansheeCore/Source/BsCoreThread.cpp
  25. 9 18
      Source/BansheeCore/Source/BsCoreThreadQueue.cpp
  26. 19 19
      Source/BansheeCore/Source/BsMesh.cpp
  27. 0 1
      Source/BansheeCore/Source/BsMeshManager.cpp
  28. 44 42
      Source/BansheeCore/Source/BsRenderAPI.cpp
  29. 2 2
      Source/BansheeCore/Source/BsRenderTarget.cpp
  30. 20 21
      Source/BansheeCore/Source/BsRenderWindow.cpp
  31. 31 49
      Source/BansheeCore/Source/BsTexture.cpp
  32. 1 1
      Source/BansheeCore/Source/BsViewport.cpp
  33. 2 1
      Source/BansheeCore/Source/Win32/BsWin32BrowseDialogs.cpp
  34. 2 2
      Source/BansheeD3D11RenderAPI/Include/BsD3D11Texture.h
  35. 2 2
      Source/BansheeD3D11RenderAPI/Source/BsD3D11Texture.cpp
  36. 3 3
      Source/BansheeEditor/Source/BsDockManager.cpp
  37. 1 1
      Source/BansheeEditor/Source/BsEditorWidgetManager.cpp
  38. 2 2
      Source/BansheeEditor/Source/BsEditorWindow.cpp
  39. 3 3
      Source/BansheeEditor/Source/BsEditorWindowBase.cpp
  40. 3 3
      Source/BansheeEditor/Source/BsGUIMenuBar.cpp
  41. 7 7
      Source/BansheeEditor/Source/BsGizmoManager.cpp
  42. 4 4
      Source/BansheeEditor/Source/BsHandleDrawManager.cpp
  43. 1 1
      Source/BansheeEditor/Source/BsMainEditorWindow.cpp
  44. 3 3
      Source/BansheeEditor/Source/BsSceneGrid.cpp
  45. 11 11
      Source/BansheeEditor/Source/BsScenePicking.cpp
  46. 3 3
      Source/BansheeEditor/Source/BsSelectionRenderer.cpp
  47. 2 2
      Source/BansheeEngine/Source/BsApplication.cpp
  48. 25 25
      Source/BansheeEngine/Source/BsBuiltinResources.cpp
  49. 3 3
      Source/BansheeEngine/Source/BsBuiltinResourcesHelper.cpp
  50. 7 10
      Source/BansheeEngine/Source/BsGUIManager.cpp
  51. 0 1
      Source/BansheeEngine/Source/BsGUIWidget.cpp
  52. 2 2
      Source/BansheeEngine/Source/BsRendererMaterialManager.cpp
  53. 1 1
      Source/BansheeEngine/Source/BsRendererUtility.cpp
  54. 2 2
      Source/BansheeEngine/Source/BsSplashScreen.cpp
  55. 2 2
      Source/BansheeEngine/Source/BsSpriteMaterial.cpp
  56. 3 5
      Source/BansheeFontImporter/Source/BsFontImporter.cpp
  57. 2 5
      Source/BansheeFreeImgImporter/Source/BsFreeImgImporter.cpp
  58. 2 2
      Source/BansheeGLRenderAPI/Include/BsGLTexture.h
  59. 2 2
      Source/BansheeGLRenderAPI/Source/BsGLTexture.cpp
  60. 2 2
      Source/BansheeVulkanRenderAPI/Include/BsVulkanTexture.h
  61. 2 2
      Source/BansheeVulkanRenderAPI/Source/BsVulkanTexture.cpp
  62. 3 17
      Source/ExampleProject/Source/Main.cpp
  63. 3 3
      Source/Game/Source/Main.cpp
  64. 1 1
      Source/MBansheeEditor/Windows/Scene/SceneWindow.cs
  65. 6 6
      Source/RenderBeast/Source/BsRenderBeast.cpp
  66. 3 3
      Source/SBansheeEditor/Source/BsScriptBuildManager.cpp
  67. 1 3
      Source/SBansheeEngine/Source/BsScriptAsyncOp.cpp
  68. 3 3
      Source/SBansheeEngine/Source/BsScriptMesh.cpp
  69. 1 1
      Source/SBansheeEngine/Source/BsScriptRenderTarget.cpp
  70. 6 13
      Source/SBansheeEngine/Source/BsScriptTexture2D.cpp
  71. 5 10
      Source/SBansheeEngine/Source/BsScriptTexture3D.cpp
  72. 5 10
      Source/SBansheeEngine/Source/BsScriptTextureCube.cpp

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


+ 39 - 0
Documentation/Manuals/Native/User/windows.md

@@ -0,0 +1,39 @@
+Windows					{#window}
+===============
+
+A window represents the final destination where the applications rendered output gets displayed to the user. It has a title, size and a position. Window can cover the entirety of the user's screen (fullscreen mode) or just part of it (windowed mode). In Banshee a window is represented using the @ref bs::RenderWindow "RenderWindow" class.
+
+![Render window](RenderWindow.png)  
+
+# Primary window
+When we initialized the application by calling **Application::startUp** in a previous chapter a primary window was created for us by default. You can access this window through @ref bs::Application::getPrimaryWindow "Application::getPrimaryWindow".
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<RenderWindow> primaryWindow = gApplication().getPrimaryWindow();
+~~~~~~~~~~~~~
+
+> **gApplication()** is just a shortcut for **Application::instance()** we used earlier.
+
+# Creating windows
+You can also create your own windows by filling out the @ref bs::RENDER_WINDOW_DESC "RENDER_WINDOW_DESC" structure and calling @ref bs::RenderWindow::create "RenderWindow::create".
+
+~~~~~~~~~~~~~{.cpp}
+RENDER_WINDOW_DESC desc;
+desc.videoMode = VideoMode(1280, 720);
+desc.fullscreen = false;
+desc.title = "Helper window".
+
+SPtr<RenderWindow> newWindow = RenderWindow::create(desc);
+~~~~~~~~~~~~~
+
+# Destroying windows
+You can destroy a window by calling @ref RenderWindow::destroy "RenderWindow::destroy". 
+
+~~~~~~~~~~~~~{.cpp}
+newWindow->destroy();
+~~~~~~~~~~~~~
+
+> Do not destroy the primary window, as it will result in undefined behaviour.
+
+# Manipulating windows
+

+ 29 - 1
Documentation/Manuals/Native/apiRefPages.md

@@ -4,4 +4,32 @@ Using a non-default queue index allows the GPU to perform operations on differen
 
 
 When a write operation is being performed it is the responsibility of the caller not to use that resource until that write has completed. This can be ensured by providing a sync mask to commands that accept it (such as RenderAPICore::executeCommands) with the bit corresponding to the queue index set. This way queues will know to wait until write completes. This is not required if the resource is being used on the same queue the write is being performed on, as operations within a queue are sequential.
 When a write operation is being performed it is the responsibility of the caller not to use that resource until that write has completed. This can be ensured by providing a sync mask to commands that accept it (such as RenderAPICore::executeCommands) with the bit corresponding to the queue index set. This way queues will know to wait until write completes. This is not required if the resource is being used on the same queue the write is being performed on, as operations within a queue are sequential.
 
 
-This value is a global queue index which encodes both the queue type and queue index. Retrieve it from CommandSyncMask::getGlobalQueueIdx().
+This value is a global queue index which encodes both the queue type and queue index. Retrieve it from CommandSyncMask::getGlobalQueueIdx().
+
+@page asyncMethod Core thread asynchronous methods
+This type of method doesn't execute immediately when called. Instead it is queued for execution and will be executed when the current frame ends. These methods generally need to perform some kind of communication between the main and core (rendering) threads, making direct calls impossible.
+
+You can force the core thread to start executing queued methods before the end of the current frame, by calling @ref bs::CoreThread::submit() "CoreThread::submit()". This guarantees the commands will start executing, but doesn't guarantee they will finish, as it might take the core thread some time to process all queued commands.
+
+If you wish to wait until your command finishes executing then set @p blockUntilComplete parameter of **CoreThread::submit()** to true. 
+
+An example that reads the texture data from the GPU:
+~~~~~~~~~~~~~{.cpp}
+SPtr<Texture> texture = ... some texture we created earlier ...;
+SPtr<PixelData> output = ... buffer to receive the data ...;
+texture->readData(output);
+
+// Assuming we need the data right away, we submit the 
+// core thread queue and block until the command executes
+gCoreThread().submit(true);
+
+// It's now safe to read the pixel data
+Color color = output->getColorAt(0, 0);
+
+~~~~~~~~~~~~~
+
+Optionally, if the method returns an @ref bs::AsyncOp "AsyncOp" object, you can call @ref bs::AsyncOp::blockUntilComplete "AsyncOp::blockUntilComplete" for the same result. However you must ensure that you don't call it before **CoreThread::submit()** has been called, otherwise the calling thread might deadlock as it waits for the operations to finish, even though it was never started.
+
+If the method provides a return value, you can use the provided **AsyncOp** object to retrieve it using @ref bs::AsyncOp::getReturnValue<T> "AsyncOp::getReturnValue<T>". Calling this is only valid if @ref bs::AsyncOp::hasCompleted "AsyncOp::hasCompleted" returns true. Return value is always available after you blocked using either of the ways mentioned above.
+
+Note that blocking is a very expensive operation and should not be done in performance critical code. If you need to wait until an async method completes, it is preferable to keep querying **AsyncOp::hasCompleted** and do something else until it returns true.

+ 1 - 1
Documentation/Manuals/Native/coreThread.md

@@ -4,7 +4,7 @@ Core Thread								{#coreThread}
 
 
 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 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, 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.
+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:
 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 (DirectX/OpenGL)

+ 2 - 0
Documentation/Manuals/Native/manuals.md

@@ -9,6 +9,8 @@ Manuals									{#manuals}
 - Resources
 - Resources
  - [Basics and import](@ref resourceBasicsAndImport)
  - [Basics and import](@ref resourceBasicsAndImport)
  - [Saving and loading](@ref resourceSavingAndLoading)
  - [Saving and loading](@ref resourceSavingAndLoading)
+- Graphics 
+ - [Windows](@ref windows)
  
  
 # Developer guides
 # Developer guides
 
 

+ 1 - 1
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 bs::RenderAPI "RenderAPI" for the simulation thread, and @ref bs::RenderAPICore "RenderAPICore" for the core thread. If you are confused by the dual nature of  objects, read the [core thread](@ref coreThread) manual. 
 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 bs::RenderAPI "RenderAPI" for the simulation thread, and @ref bs::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 bs::CoreThreadAccessor "CoreAccessor" as input, and the execution of the actual commands is delayed until they reach the core thread.
+For the remainder of this manual we'll focus on the core thread portion of the API, but both provide essentially identical functionality. The main difference that the execution of commands on the simulation thread isn't immediate, instead they are queued on an internal queue which is sent to the core thread at the end of the frame.
 
 
 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. 
 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. 
 
 

+ 2 - 2
Source/BansheeCore/CMakeSources.cmake

@@ -45,7 +45,7 @@ set(BS_BANSHEECORE_INC_PHYSICS
 )
 )
 
 
 set(BS_BANSHEECORE_INC_CORETHREAD
 set(BS_BANSHEECORE_INC_CORETHREAD
-	"Include/BsCoreThreadAccessor.h"
+	"Include/BsCoreThreadQueue.h"
 	"Include/BsCoreThread.h"
 	"Include/BsCoreThread.h"
 	"Include/BsCoreObjectManager.h"
 	"Include/BsCoreObjectManager.h"
 	"Include/BsCoreObject.h"
 	"Include/BsCoreObject.h"
@@ -159,7 +159,7 @@ set(BS_BANSHEECORE_SRC_CORETHREAD
 	"Source/BsCoreObject.cpp"
 	"Source/BsCoreObject.cpp"
 	"Source/BsCoreObjectManager.cpp"
 	"Source/BsCoreObjectManager.cpp"
 	"Source/BsCoreThread.cpp"
 	"Source/BsCoreThread.cpp"
-	"Source/BsCoreThreadAccessor.cpp"
+	"Source/BsCoreThreadQueue.cpp"
 	"Source/BsCoreObjectCore.cpp"
 	"Source/BsCoreObjectCore.cpp"
 )
 )
 
 

+ 0 - 1
Source/BansheeCore/Include/BsCoreApplication.h

@@ -4,7 +4,6 @@
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
 #include "BsModule.h"
 #include "BsModule.h"
-#include "BsCoreThreadAccessor.h"
 #include "BsRenderWindow.h"
 #include "BsRenderWindow.h"
 #include "BsEvent.h"
 #include "BsEvent.h"
 
 

+ 5 - 4
Source/BansheeCore/Include/BsCoreObject.h

@@ -83,8 +83,9 @@ namespace bs
 		 *
 		 *
 		 * @note	Call this if you have modified the object and need to make sure core thread has an up to date version. 
 		 * @note	Call this if you have modified the object and need to make sure core thread has an up to date version. 
 		 *			Normally this is done automatically at the end of a frame.
 		 *			Normally this is done automatically at the end of a frame.
+		 * @note	This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void syncToCore(CoreAccessor& accessor);
+		void syncToCore();
 
 
 	public: // ***** INTERNAL ******
 	public: // ***** INTERNAL ******
 		/** @name Internal
 		/** @name Internal
@@ -158,10 +159,10 @@ namespace bs
 		static void queueInitializeGpuCommand(const SPtr<CoreObjectCore>& obj);
 		static void queueInitializeGpuCommand(const SPtr<CoreObjectCore>& obj);
 
 
 		/**
 		/**
-		 * Queues object destruction command on the core thread. The command is added to the core thread accessor of this 
-		 * thread and will be executed after accessor commands are submitted and any previously queued commands are executed.
+		 * Queues object destruction command on the core thread. The command is added to the core thread queue of this 
+		 * thread and will be executed after qzeze commands are submitted and any previously queued commands are executed.
 		 *
 		 *
-		 * @note	It is up to the caller to ensure no other accessors attempt to use this object.
+		 * @note	It is up to the caller to ensure no other threads attempt to use this object.
 		 */
 		 */
 		static void queueDestroyGpuCommand(const SPtr<CoreObjectCore>& obj);
 		static void queueDestroyGpuCommand(const SPtr<CoreObjectCore>& obj);
 
 

+ 6 - 4
Source/BansheeCore/Include/BsCoreObjectManager.h

@@ -77,19 +77,21 @@ namespace bs
 
 
 		/**
 		/**
 		 * Synchronizes all dirty CoreObjects with the core thread. Their dirty data will be allocated using the global 
 		 * Synchronizes all dirty CoreObjects with the core thread. Their dirty data will be allocated using the global 
-		 * frame allocator and then queued for update using the provided core thread accessor.
+		 * frame allocator and then queued for update using the core thread queue for the calling thread.
 		 *
 		 *
 		 * @note	Sim thread only.
 		 * @note	Sim thread only.
+		 * @note	This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void syncToCore(CoreAccessor& accessor);
+		void syncToCore();
 
 
 		/**
 		/**
 		 * Synchronizes an individual dirty CoreObject with the core thread. Its dirty data will be allocated using the 
 		 * Synchronizes an individual dirty CoreObject with the core thread. Its dirty data will be allocated using the 
-		 * global frame allocator and then queued for update using the provided core thread accessor.
+		 * global frame allocator and then queued for update the core thread queue for the calling thread.
 		 *
 		 *
 		 * @note	Sim thread only.
 		 * @note	Sim thread only.
+		 * @note	This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void syncToCore(CoreObject* object, CoreAccessor& accessor);
+		void syncToCore(CoreObject* object);
 
 
 	private:
 	private:
 		/**
 		/**

+ 2 - 3
Source/BansheeCore/Include/BsCorePrerequisites.h

@@ -437,7 +437,7 @@ namespace bs
 	struct AUDIO_CLIP_DESC;
 	struct AUDIO_CLIP_DESC;
 
 
 	template<class T>
 	template<class T>
-	class CoreThreadAccessor;
+	class TCoreThreadQueue;
 	class CommandQueueNoSync;
 	class CommandQueueNoSync;
 	class CommandQueueSync;
 	class CommandQueueSync;
 }
 }
@@ -448,8 +448,7 @@ namespace bs
 
 
 namespace bs
 namespace bs
 {
 {
-	typedef CoreThreadAccessor<CommandQueueNoSync> CoreAccessor;
-	typedef CoreThreadAccessor<CommandQueueSync> SyncedCoreAccessor;
+	typedef TCoreThreadQueue<CommandQueueNoSync> CoreThreadQueue;
 }
 }
 
 
 /************************************************************************/
 /************************************************************************/

+ 167 - 178
Source/BansheeCore/Include/BsCoreThread.h

@@ -5,7 +5,7 @@
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
 #include "BsModule.h"
 #include "BsModule.h"
 #include "BsCommandQueue.h"
 #include "BsCommandQueue.h"
-#include "BsCoreThreadAccessor.h"
+#include "BsCoreThreadQueue.h"
 #include "BsThreadPool.h"
 #include "BsThreadPool.h"
 
 
 namespace bs
 namespace bs
@@ -14,186 +14,188 @@ namespace bs
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
+	/** Flags that control how is a command submitted to the command queue. */
+	enum CoreThreadQueueFlag
+	{
+		/** 
+		 * Default flag, meaning the commands will be added to the per-thread queue and only begin executing after
+		 * submit() has been called.
+		 */
+		CTQF_Default = 0,
+		/** 
+		 * Specifies that the queued command should be executed on the internal queue. Internal queue doesn't require
+		 * a separate CoreThread::submit() call, and the queued command is instead immediately visible to the core thread.
+		 * The downside is that the queue requires additional synchronization and is slower than the normal queue.
+		 */
+		CTQF_InternalQueue = 1 << 0,
+		/**
+		 * If true, the method will block until the command finishes executing on the core thread. Only relevant for the
+		 * internal queue commands since contents of the normal queue won't be submitted to the core thread until the
+		 * CoreThread::submit() call.
+		 */
+		CTQF_BlockUntilComplete = 1 << 1
+	};
+
+	typedef Flags<CoreThreadQueueFlag> CoreThreadQueueFlags;
+	BS_FLAGS_OPERATORS(CoreThreadQueueFlag)
+
 	/**
 	/**
 	 * Manager for the core thread. Takes care of starting, running, queuing commands and shutting down the core thread.
 	 * Manager for the core thread. Takes care of starting, running, queuing commands and shutting down the core thread.
-	 * 			
-	 * @note	
+	 * 				
 	 * How threading works:
 	 * How threading works:
-	 * 	- This class contains a queue which is filled by commands from other threads via queueCommand() and queueReturnCommand()  
-	 * 	- Commands are executed on the core thread as soon as they are queued (if core thread is not busy with previous commands)  
-	 * 	- Core thread accessors are helpers for queuing commands. They perform better than queuing each command directly 
-	 *    using queueCommand() or queueReturnCommand().
-	 * 	- Accessors contain a command queue of their own, and queuing commands in them will not automatically start 
-	 *    executing the commands like with queueCommand or queueReturnCommand. Instead you must manually call 
-	 *    submitAccessors() when you are ready to send their commands to the core thread. Sending commands "in bulk" like 
-	 *    this is what makes them faster than directly queuing commands.
-	 * 	- Synced accessor is a special type of accessor which may be accessed from any thread. Its commands are always 
-	 *    executed after all other non-synced accessors. It is primarily useful when multiple threads are managing the same
-	 *    resource and you must ensure proper order of operations. You should use normal accessors whenever possible as 
-	 *    synced accessors involve potentially slow synchronization operations.
+	 *  - Commands from various threads can be queued for execution on the core thread by calling queueCommand() or
+	 *    queueReturnCommand().
+	 *   - Internally each thread maintains its own separate queue of commands, so you cannot interleave commands from
+	 *     different threads.
+	 *   - There is also the internal command queue, which is the only queue directly visible from the core thread.
+	 *    - Core thread continually polls the internal command queue for new commands, and executes them in order they were
+	 *      submitted.
+	 *    - Commands queued on the per-thread queues are submitted to the internal command queue by calling submit(), at
+	 *      which point they are made visible to the core thread, and will begin executing.
+	 * 	  - Commands can also be submitted directly to the internal command queue (via a special flag), but with a 
+	 * 	    performance cost due to extra synchronization required.
 	 */
 	 */
 	class BS_CORE_EXPORT CoreThread : public Module<CoreThread>
 	class BS_CORE_EXPORT CoreThread : public Module<CoreThread>
 	{
 	{
-		/** Contains data about an accessor for a specific thread. */
-		struct AccessorContainer
+		/** Contains data about an queue for a specific thread. */
+		struct ThreadQueueContainer
 		{
 		{
-			SPtr<CoreThreadAccessor<CommandQueueNoSync>> accessor;
+			SPtr<TCoreThreadQueue<CommandQueueNoSync>> queue;
 			bool isMain;
 			bool isMain;
 		};
 		};
 
 
 		/** Wrapper for the thread-local variable because MSVC can't deal with a thread-local variable marked with dllimport or dllexport,  
 		/** Wrapper for the thread-local variable because MSVC can't deal with a thread-local variable marked with dllimport or dllexport,  
 		 *  and we cannot use per-member dllimport/dllexport specifiers because Module's members will then not be exported and its static
 		 *  and we cannot use per-member dllimport/dllexport specifiers because Module's members will then not be exported and its static
 		 *  members will not have external linkage. */
 		 *  members will not have external linkage. */
-		struct AccessorData
+		struct QueueData
 		{
 		{
-			static BS_THREADLOCAL AccessorContainer* current;
+			static BS_THREADLOCAL ThreadQueueContainer* current;
 		};
 		};
 
 
-public:
-	CoreThread();
-	~CoreThread();
-
-	/** Returns the id of the core thread.  */
-	ThreadId getCoreThreadId() { return mCoreThreadId; }
-
-	/**
-	 * Creates or retrieves an accessor that you can use for executing commands on the core thread from a non-core thread. 
-	 * The accessor will be bound to the thread you call this method on.
-	 * 			
-	 * @note		
-	 * Accessors contain their own command queue and their commands will only start to get executed once that queue is 
-	 * submitted to the core thread via submitAccessors() method.
-	 */
-	SPtr<CoreThreadAccessor<CommandQueueNoSync>> getAccessor();
-
-	/**
-	 * Retrieves an accessor that you can use for executing commands on the core thread from a non-core thread. There is 
-	 * only one synchronized accessor and you may access it from any thread you wish. Note however that it is much more 
-	 * efficient to retrieve a separate non-synchronized accessor for each thread you will be using it on.
-	 * 			
-	 * @note	
-	 * Accessors contain their own command queue and their commands will only start to get executed once that queue
-	 * is submitted to the core thread via submitAccessors() method.
-	 * @note			
-	 * Synced accessor commands are sent after all non-synced accessor commands are sent.
-	 */
-	SyncedCoreAccessor& getSyncedAccessor();
-
-	/** Queues all the accessor commands and starts executing them on the core thread. */
-	void submitAccessors(bool blockUntilComplete = false);
-
-	/**
-	 * Queues a new command that will be added to the global command queue. You are allowed to call this from any thread,
-	 * however be aware that it involves possibly slow synchronization primitives, so limit your usage.
-	 * 		
-	 * @param[in]	commandCallback		Command to queue.
-	 * @param[in]	blockUntilComplete	If true the thread will be blocked until the command executes. Be aware that there 
-	 *									may be many commands queued before it and they all need to be executed in order 
-	 *									before the current command is reached, which might take a long time.
-	 * 	
-	 * @see		CommandQueue::queueReturn()
-	 */
-	AsyncOp queueReturnCommand(std::function<void(AsyncOp&)> commandCallback, bool blockUntilComplete = false);
-
-	/**
-	 * Queues a new command that will be added to the global command queue.You are allowed to call this from any thread,
-	 * however be aware that it involves possibly slow synchronization primitives, so limit your usage.
-	 * 	
-	 * @param[in]	commandCallback		Command to queue.
-	 * @param[in]	blockUntilComplete	If true the thread will be blocked until the command executes. Be aware that there 
-	 *									may be many commands queued before it and they all need to be executed in order 
-	 *									before the current command is reached, which might take a long time.
-	 *
-	 * @see		CommandQueue::queue()
-	 */
-	void queueCommand(std::function<void()> commandCallback, bool blockUntilComplete = false);
-
-	/**
-	 * Called once every frame.
-	 * 			
-	 * @note	Must be called before sim thread schedules any core thread operations for the frame. 
-	 */
-	void update();
-
-	/**
-	 * Returns a frame allocator that should be used for allocating temporary data being passed to the core thread. As the 
-	 * name implies the data only lasts one frame, so you need to be careful not to use it for longer than that.
-	 * 			
-	 * @note	Sim thread only.
-	 */
-	FrameAlloc* getFrameAlloc() const;
-
-	/** 
-	 * Returns number of buffers needed to sync data between core and sim thread. Currently the sim thread can be one frame
-	 * ahead of the core thread, meaning we need two buffers. If this situation changes increase this number.
-	 *
-	 * For example:
-	 *  - Sim thread frame starts, it writes some data to buffer 0.
-	 *  - Core thread frame starts, it reads some data from buffer 0.
-	 *  - Sim thread frame finishes
-	 *  - New sim thread frame starts, it writes some data to buffer 1.
-	 *  - Core thread still working, reading from buffer 0. (If we were using just one buffer at this point core thread 
-	 *	  would be reading wrong data).
-	 *  - Sim thread waiting for core thread (application defined that it cannot go ahead more than one frame)
-	 *  - Core thread frame finishes.
-	 *  - New core thread frame starts, it reads some data from buffer 1.
-	 *  - ...
-	 */
-	static const int NUM_SYNC_BUFFERS = 2;
-private:
-	/**
-	 * Double buffered frame allocators. Means sim thread cannot be more than 1 frame ahead of core thread (If that changes
-	 * you should be able to easily add more).
-	 */
-	FrameAlloc* mFrameAllocs[NUM_SYNC_BUFFERS];
-	UINT32 mActiveFrameAlloc;
-
-	static AccessorData mAccessor;
-	Vector<AccessorContainer*> mAccessors;
-
-	volatile bool mCoreThreadShutdown;
-
-	HThread mCoreThread;
-	bool mCoreThreadStarted;
-	ThreadId mSimThreadId;
-	ThreadId mCoreThreadId;
-	Mutex mCommandQueueMutex;
-	Mutex mAccessorMutex;
-	Signal mCommandReadyCondition;
-	Mutex mCommandNotifyMutex;
-	Signal mCommandCompleteCondition;
-	Mutex mThreadStartedMutex;
-	Signal mCoreThreadStartedCondition;
-
-	CommandQueue<CommandQueueSync>* mCommandQueue;
-
-	UINT32 mMaxCommandNotifyId; /**< ID that will be assigned to the next command with a notifier callback. */
-	Vector<UINT32> mCommandsCompleted; /**< Completed commands that have notifier callbacks set up */
-
-	SyncedCoreAccessor* mSyncedCoreAccessor;
-
-	/** Starts the core thread worker method. Should only be called once. */
-	void initCoreThread();
-
-	/**	Main worker method of the core thread. Called once thread is started. */
-	void runCoreThread();
-
-	/** Shutdowns the core thread. It will complete all ready commands before shutdown. */
-	void shutdownCoreThread();
-
-	/**
-	 * Blocks the calling thread until the command with the specified ID completes. Make sure that the specified ID 
-	 * actually exists, otherwise this will block forever.
-	 */
-	void blockUntilCommandCompleted(UINT32 commandId);
-
-	/**
-	 * Callback called by the command list when a specific command finishes executing. This is only called on commands that
-	 * have a special notify on complete flag set.
-	 *
-	 * @param[in]	commandId	Identifier for the command.
-	 */
-	void commandCompletedNotify(UINT32 commandId);
+	public:
+		CoreThread();
+		~CoreThread();
+
+		/** Returns the id of the core thread.  */
+		ThreadId getCoreThreadId() { return mCoreThreadId; }
+
+		/** Submits the commands from all queues and starts executing them on the core thread. */
+		void submitAll(bool blockUntilComplete = false);
+
+		/** Submits the commands from the current thread's queue and starts executing them on the core thread. */
+		void submit(bool blockUntilComplete = false);
+
+		/**
+		 * Queues a new command that will be added to the command queue. Command returns a value.
+		 * 		
+		 * @param[in]	commandCallback		Command to queue.
+		 * @param[in]	flags				Flags that further control command submission.
+		 * @return							Structure that can be used to check if the command completed execution,
+		 *									and to retrieve the return value once it has.
+		 * 	
+		 * @see		CommandQueue::queueReturn()
+		 * @note	Thread safe
+		 */
+		AsyncOp queueReturnCommand(std::function<void(AsyncOp&)> commandCallback, CoreThreadQueueFlags flags = CTQF_Default);
+
+		/**
+		 * Queues a new command that will be to the global command queue. 
+		 * 	
+		 * @param[in]	commandCallback		Command to queue.
+		 * @param[in]	flags				Flags that further control command submission.
+		 *
+		 * @see		CommandQueue::queue()
+		 * @note	Thread safe
+		 */
+		void queueCommand(std::function<void()> commandCallback, CoreThreadQueueFlags flags = CTQF_Default);
+
+		/**
+		 * Called once every frame.
+		 * 			
+		 * @note	Must be called before sim thread schedules any core thread operations for the frame. 
+		 */
+		void update();
+
+		/**
+		 * Returns a frame allocator that should be used for allocating temporary data being passed to the core thread. As the 
+		 * name implies the data only lasts one frame, so you need to be careful not to use it for longer than that.
+		 * 			
+		 * @note	Sim thread only.
+		 */
+		FrameAlloc* getFrameAlloc() const;
+
+		/** 
+		 * Returns number of buffers needed to sync data between core and sim thread. Currently the sim thread can be one frame
+		 * ahead of the core thread, meaning we need two buffers. If this situation changes increase this number.
+		 *
+		 * For example:
+		 *  - Sim thread frame starts, it writes some data to buffer 0.
+		 *  - Core thread frame starts, it reads some data from buffer 0.
+		 *  - Sim thread frame finishes
+		 *  - New sim thread frame starts, it writes some data to buffer 1.
+		 *  - Core thread still working, reading from buffer 0. (If we were using just one buffer at this point core thread 
+		 *	  would be reading wrong data).
+		 *  - Sim thread waiting for core thread (application defined that it cannot go ahead more than one frame)
+		 *  - Core thread frame finishes.
+		 *  - New core thread frame starts, it reads some data from buffer 1.
+		 *  - ...
+		 */
+		static const int NUM_SYNC_BUFFERS = 2;
+	private:
+		/**
+		 * Double buffered frame allocators. Means sim thread cannot be more than 1 frame ahead of core thread (If that changes
+		 * you should be able to easily add more).
+		 */
+		FrameAlloc* mFrameAllocs[NUM_SYNC_BUFFERS];
+		UINT32 mActiveFrameAlloc;
+
+		static QueueData mPerThreadQueue;
+		Vector<ThreadQueueContainer*> mAllQueues;
+
+		volatile bool mCoreThreadShutdown;
+
+		HThread mCoreThread;
+		bool mCoreThreadStarted;
+		ThreadId mSimThreadId;
+		ThreadId mCoreThreadId;
+		Mutex mCommandQueueMutex;
+		Mutex mCoreQueueMutex;
+		Signal mCommandReadyCondition;
+		Mutex mCommandNotifyMutex;
+		Signal mCommandCompleteCondition;
+		Mutex mThreadStartedMutex;
+		Signal mCoreThreadStartedCondition;
+
+		CommandQueue<CommandQueueSync>* mCommandQueue;
+
+		UINT32 mMaxCommandNotifyId; /**< ID that will be assigned to the next command with a notifier callback. */
+		Vector<UINT32> mCommandsCompleted; /**< Completed commands that have notifier callbacks set up */
+
+		/** Starts the core thread worker method. Should only be called once. */
+		void initCoreThread();
+
+		/**	Main worker method of the core thread. Called once thread is started. */
+		void runCoreThread();
+
+		/** Shutdowns the core thread. It will complete all ready commands before shutdown. */
+		void shutdownCoreThread();
+
+		/** Creates or retrieves a queue for the calling thread. */
+		SPtr<TCoreThreadQueue<CommandQueueNoSync>> getQueue();
+
+		/**
+		 * Blocks the calling thread until the command with the specified ID completes. Make sure that the specified ID 
+		 * actually exists, otherwise this will block forever.
+		 */
+		void blockUntilCommandCompleted(UINT32 commandId);
+
+		/**
+		 * Callback called by the command list when a specific command finishes executing. This is only called on commands that
+		 * have a special notify on complete flag set.
+		 *
+		 * @param[in]	commandId	Identifier for the command.
+		 */
+		void commandCompletedNotify(UINT32 commandId);
 	};
 	};
 
 
 	/**
 	/**
@@ -223,19 +225,6 @@ private:
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	/** 
-	 * Creates or retrieves an accessor that you can use for executing commands on the core thread from a non-core thread. 
-	 * The accessor will be bound to the thread you call this method on. 
-	 */
-	BS_CORE_EXPORT CoreThreadAccessor<CommandQueueNoSync>& gCoreAccessor();
-
-	/**
-	 * Retrieves an accessor that you can use for executing commands on the core thread from a non-core thread. There is 
-	 * only one synchronized accessor and you may access it from any thread you wish. Note however that it is much more 
-	 * efficient to retrieve a separate non-synchronized accessor for each thread you will be using it on.
-	 */
-	BS_CORE_EXPORT CoreThreadAccessor<CommandQueueSync>& gSyncedCoreAccessor();
-
 	/** @} */
 	/** @} */
 }
 }
 
 

+ 13 - 18
Source/BansheeCore/Include/BsCoreThreadAccessor.h → Source/BansheeCore/Include/BsCoreThreadQueue.h

@@ -12,16 +12,12 @@ namespace bs
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	/**
-	 * Contains base functionality used for CoreThreadAccessor.
-	 * 			
-	 * @see		CoreThreadAccesor
-	 */
-	class BS_CORE_EXPORT CoreThreadAccessorBase
+	/** Contains base functionality used for CoreThreadQueue. */
+	class BS_CORE_EXPORT CoreThreadQueueBase
 	{
 	{
 	public:
 	public:
-		CoreThreadAccessorBase(CommandQueueBase* commandQueue);
-		virtual ~CoreThreadAccessorBase();
+		CoreThreadQueueBase(CommandQueueBase* commandQueue);
+		virtual ~CoreThreadQueueBase();
 
 
 		/**
 		/**
 		 * Queues a new generic command that will be added to the command queue. Returns an async operation object that you 
 		 * Queues a new generic command that will be added to the command queue. Returns an async operation object that you 
@@ -34,11 +30,11 @@ namespace bs
 
 
 		/**
 		/**
 		 * Makes all the currently queued commands available to the core thread. They will be executed as soon as the core 
 		 * Makes all the currently queued commands available to the core thread. They will be executed as soon as the core 
-		 * thread is ready. All queued commands are removed from the accessor.
+		 * thread is ready. All queued commands are removed from the queue.
 		 *
 		 *
 		 * @param[in]	blockUntilComplete	If true, the calling thread will block until the core thread finished executing
 		 * @param[in]	blockUntilComplete	If true, the calling thread will block until the core thread finished executing
 		 *									all currently queued commands. This is usually very expensive and should only be
 		 *									all currently queued commands. This is usually very expensive and should only be
-		 *									used in performance non-critical code.
+		 *									used in non-performance critical code.
 		 */
 		 */
 		void submitToCoreThread(bool blockUntilComplete = false);
 		void submitToCoreThread(bool blockUntilComplete = false);
 
 
@@ -50,24 +46,23 @@ namespace bs
 	};
 	};
 
 
 	/**
 	/**
-	 * Core thread accessor allows you to schedule core commands outside of the core thread. 
+	 * Queue that allows the calling thread to queue commands for execution on the core thread. Commands will only be
+	 * executed after they have been submitted to the core thread.
 	 * 			
 	 * 			
 	 * @note	Queued commands are only executed after the call to submitToCoreThread(), in the order they were submitted.
 	 * @note	Queued commands are only executed after the call to submitToCoreThread(), in the order they were submitted.
 	 */
 	 */
 	template <class CommandQueueSyncPolicy = CommandQueueNoSync>
 	template <class CommandQueueSyncPolicy = CommandQueueNoSync>
-	class BS_CORE_EXPORT CoreThreadAccessor : public CoreThreadAccessorBase
+	class BS_CORE_EXPORT TCoreThreadQueue : public CoreThreadQueueBase
 	{
 	{
 	public:
 	public:
 		/**
 		/**
 		 * Constructor.
 		 * Constructor.
 		 *
 		 *
-		 * @param[in]	threadId		Identifier for the thread that created the accessor.
+		 * @param[in]	threadId		Identifier for the thread that created the queue.
 		 */
 		 */
-		CoreThreadAccessor(ThreadId threadId)
-			:CoreThreadAccessorBase(bs_new<CommandQueue<CommandQueueSyncPolicy>>(threadId))
-		{
-
-		}
+		TCoreThreadQueue(ThreadId threadId)
+			:CoreThreadQueueBase(bs_new<CommandQueue<CommandQueueSyncPolicy>>(threadId))
+		{ }
 	};
 	};
 
 
 	/** @} */
 	/** @} */

+ 24 - 32
Source/BansheeCore/Include/BsMesh.h

@@ -72,11 +72,8 @@ namespace bs
 		void initialize() override;
 		void initialize() override;
 
 
 		/**
 		/**
-		 * Updates the mesh with new data. The actual write will be queued for later execution on the core thread. Provided 
-		 * data buffer will be locked until the operation completes.
+		 * Updates the mesh with new data. Provided data buffer will be locked until the operation completes.
 		 *
 		 *
-		 * @param[in]	accessor			Accessor to queue the operation on.
-		 * @param[in]	subresourceIdx		Index of the subresource to write to. Ignored for now.
 		 * @param[in]	data				Data of valid size and format to write to the subresource.
 		 * @param[in]	data				Data of valid size and format to write to the subresource.
 		 * @param[in]	discardEntireBuffer When true the existing contents of the resource you are updating will be
 		 * @param[in]	discardEntireBuffer When true the existing contents of the resource you are updating will be
 		 *									discarded. This can make the operation faster. Resources with certain buffer
 		 *									discarded. This can make the operation faster. Resources with certain buffer
@@ -84,47 +81,43 @@ namespace bs
 		 *									will fail.
 		 *									will fail.
 		 * @return							Async operation object you can use to track operation completion.
 		 * @return							Async operation object you can use to track operation completion.
 		 *
 		 *
-		 * @see		MeshCore::writeSubresource
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		AsyncOp writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const SPtr<MeshData>& data, 
-			bool discardEntireBuffer);
+		AsyncOp writeData(const SPtr<MeshData>& data, bool discardEntireBuffer);
 
 
 		/**
 		/**
-		 * Reads internal mesh data to the provided previously allocated buffer. The read is queued for execution on the 
-		 * core thread and not executed immediately. Provided data buffer will be locked until the operation completes.
+		 * Reads internal mesh data to the provided previously allocated buffer. Provided data buffer will be locked until
+		 * the operation completes.
 		 *
 		 *
-		 * @param[in]	accessor		Accessor to queue the operation on.
-		 * @param[in]	subresourceIdx	Index of the subresource to read from. Ignored for now.
-		 * @param[out]	data			Previously allocated buffer of valid size and format to read the data into. Can be
-		 *								allocated using allocateSubresourceBuffer().
+		 * @param[out]	data			Pre-allocated buffer of proper vertex/index format and size where data will be read
+		 *								to. You can use allocBuffer() to allocate a buffer of a correct format and size.
 		 * @return						Async operation object you can use to track operation completion.
 		 * @return						Async operation object you can use to track operation completion.
 		 *
 		 *
-		 * @see		MeshCore::readSubresource
+		 * @note	This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		AsyncOp readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const SPtr<MeshData>& data);
+		AsyncOp readData(const SPtr<MeshData>& data);
 
 
 		/**
 		/**
-		 * Allocates a buffer you may use for storage when reading a subresource. You need to allocate such a buffer if you
-		 * are calling readSubresource().
+		 * Allocates a buffer that exactly matches the size of this mesh. This is a helper function, primarily meant for
+		 * creating buffers when reading from, or writing to a mesh.
 		 * 			
 		 * 			
-		 * @param[in]	subresourceIdx	Only 0 is supported. You can only update entire mesh at once.
-		 *
 		 * @note	Thread safe.
 		 * @note	Thread safe.
 		 */
 		 */
-		SPtr<MeshData> allocateSubresourceBuffer(UINT32 subresourceIdx) const;
+		SPtr<MeshData> allocBuffer() const;
 
 
 		/**
 		/**
 		 * Reads data from the cached system memory mesh buffer into the provided buffer. 
 		 * Reads data from the cached system memory mesh buffer into the provided buffer. 
 		 * 		  
 		 * 		  
-		 * @param[in]	dest		Previously allocated buffer to read data into.
+		 * @param[out]	data		Pre-allocated buffer of proper vertex/index format and size where data will be read to. 
+		 *							You can use allocBuffer() to allocate a buffer of a correct format and size.
 		 *
 		 *
 		 * @note	
 		 * @note	
 		 * The data read is the cached mesh data. Any data written to the mesh from the GPU or core thread will not be 
 		 * The data read is the cached mesh data. Any data written to the mesh from the GPU or core thread will not be 
-		 * reflected in this data. Use readSubresource() if you require those changes. 
+		 * reflected in this data. Use readData() if you require those changes. 
 		 * @note
 		 * @note
 		 * The mesh must have been created with MU_CPUCACHED usage otherwise this method will not return any data.
 		 * The mesh must have been created with MU_CPUCACHED usage otherwise this method will not return any data.
 		 */
 		 */
-		void readData(MeshData& dest);
+		void readCachedData(MeshData& data);
 
 
 		/** Gets the skeleton required for animation of this mesh, if any is available. */
 		/** Gets the skeleton required for animation of this mesh, if any is available. */
 		SPtr<Skeleton> getSkeleton() const { return mSkeleton; }
 		SPtr<Skeleton> getSkeleton() const { return mSkeleton; }
@@ -305,9 +298,8 @@ namespace bs
 		SPtr<MorphShapes> getMorphShapes() const { return mMorphShapes; }
 		SPtr<MorphShapes> getMorphShapes() const { return mMorphShapes; }
 
 
 		/**
 		/**
-		 * Updates a part of the current mesh with the provided data.
+		 * Updates the current mesh with the provided data.
 		 *
 		 *
-		 * @param[in]	subresourceIdx		Index of the subresource to update, if the mesh has more than one.
 		 * @param[in]	data				Data to update the mesh with.
 		 * @param[in]	data				Data to update the mesh with.
 		 * @param[in]	discardEntireBuffer When true the existing contents of the resource you are updating will be 
 		 * @param[in]	discardEntireBuffer When true the existing contents of the resource you are updating will be 
 		 *									discarded. This can make the operation faster. Resources with certain buffer 
 		 *									discarded. This can make the operation faster. Resources with certain buffer 
@@ -317,20 +309,20 @@ namespace bs
 		 *									provided data.
 		 *									provided data.
 		 * @param[in]	queueIdx			Device queue to perform the write operation on. See @ref queuesDoc.
 		 * @param[in]	queueIdx			Device queue to perform the write operation on. See @ref queuesDoc.
 		 */
 		 */
-		virtual void writeSubresource(UINT32 subresourceIdx, const MeshData& data, bool discardEntireBuffer, 
-			bool updateBounds = true, UINT32 queueIdx = 0);
+		virtual void writeData(const MeshData& data, bool discardEntireBuffer, bool updateBounds = true, 
+			UINT32 queueIdx = 0);
 
 
 		/**
 		/**
-		 * Reads a part of the current resource into the provided @p data parameter. Data buffer needs to be pre-allocated.
+		 * Reads the current mesh data into the provided @p data parameter. Data buffer needs to be pre-allocated.
 		 *
 		 *
-		 * @param[in]	subresourceIdx		Index of the subresource to update, if the mesh has more than one.
-		 * @param[out]	data				Buffer that will receive the data. Should be allocated with 
-		 *									allocateSubresourceBuffer() to ensure it is of valid type and size.
+		 * @param[out]	data				Pre-allocated buffer of proper vertex/index format and size where data will be
+		 *									read to. You can use Mesh::allocBuffer() to allocate a buffer of a correct
+		 *									format and size.
 		 * @param[in]	deviceIdx			Index of the device whose memory to read. If the buffer doesn't exist on this
 		 * @param[in]	deviceIdx			Index of the device whose memory to read. If the buffer doesn't exist on this
 		 *									device, no data will be read.
 		 *									device, no data will be read.
 		 * @param[in]	queueIdx			Device queue to perform the read operation on. See @ref queuesDoc.
 		 * @param[in]	queueIdx			Device queue to perform the read operation on. See @ref queuesDoc.
 		 */
 		 */
-		virtual void readSubresource(UINT32 subresourceIdx, MeshData& data, UINT32 deviceIdx = 0, UINT32 queueIdx = 0);
+		virtual void readData(MeshData& data, UINT32 deviceIdx = 0, UINT32 queueIdx = 0);
 
 
 		/**
 		/**
 		 * Creates a new empty mesh. Created mesh will have no sub-meshes.
 		 * Creates a new empty mesh. Created mesh will have no sub-meshes.

+ 4 - 4
Source/BansheeCore/Include/BsMeshRTTI.h

@@ -29,20 +29,20 @@ namespace bs
 
 
 		SPtr<MeshData> getMeshData(Mesh* obj) 
 		SPtr<MeshData> getMeshData(Mesh* obj) 
 		{ 
 		{ 
-			SPtr<MeshData> meshData = obj->allocateSubresourceBuffer(0);
+			SPtr<MeshData> meshData = obj->allocBuffer();
 			int usage = obj->mUsage;
 			int usage = obj->mUsage;
 
 
 			if((usage & MU_CPUREADABLE) || BS_EDITOR_BUILD)
 			if((usage & MU_CPUREADABLE) || BS_EDITOR_BUILD)
 			{
 			{
-				obj->readSubresource(gCoreAccessor(), 0, meshData);
-				gCoreAccessor().submitToCoreThread(true);
+				obj->readData(meshData);
+				gCoreThread().submit(true);
 
 
 				return meshData;
 				return meshData;
 			}
 			}
 
 
 			if(usage & MU_CPUCACHED)
 			if(usage & MU_CPUCACHED)
 			{
 			{
-				obj->readData(*meshData);
+				obj->readCachedData(*meshData);
 				return meshData;
 				return meshData;
 			}
 			}
 
 

+ 120 - 44
Source/BansheeCore/Include/BsRenderAPI.h

@@ -23,8 +23,8 @@ namespace bs
 	class RenderAPIInfo;
 	class RenderAPIInfo;
 
 
 	/**
 	/**
-	 * Provides access to RenderAPICore from the simulation thread. All the commands get queued on the accessor provided
-	 * to each method and get be executed on the core thread later.
+	 * Provides access to RenderAPICore from the simulation thread. All the commands get queued on the core thread queue 
+	 * for the calling thread.
 	 *
 	 *
 	 * @see		RenderAPICore
 	 * @see		RenderAPICore
 	 *
 	 *
@@ -33,66 +33,142 @@ namespace bs
 	class BS_CORE_EXPORT RenderAPI
 	class BS_CORE_EXPORT RenderAPI
 	{
 	{
 	public:
 	public:
-		/** @see RenderAPICore::setGpuParams() */
-		static void setGpuParams(CoreAccessor& accessor, const SPtr<GpuParams>& gpuParams);
+		/** 
+		 * @see RenderAPICore::setGpuParams() 
+		 *
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void setGpuParams(const SPtr<GpuParams>& gpuParams);
 
 
-		/** @see RenderAPICore::setGraphicsPipeline() */
-		static void setGraphicsPipeline(CoreAccessor& accessor, const SPtr<GraphicsPipelineState>& pipelineState);
+		/** 
+		 * @see RenderAPICore::setGraphicsPipeline() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void setGraphicsPipeline(const SPtr<GraphicsPipelineState>& pipelineState);
 
 
-		/** @see RenderAPICore::setComputePipeline() */
-		static void setComputePipeline(CoreAccessor& accessor, const SPtr<ComputePipelineState>& pipelineState);
+		/** 
+		 * @see RenderAPICore::setComputePipeline() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void setComputePipeline(const SPtr<ComputePipelineState>& pipelineState);
 
 
-		/** @see RenderAPICore::setVertexBuffers() */
-		static void setVertexBuffers(CoreAccessor& accessor, UINT32 index, const Vector<SPtr<VertexBuffer>>& buffers);
+		/** 
+		 * @see RenderAPICore::setVertexBuffers() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void setVertexBuffers(UINT32 index, const Vector<SPtr<VertexBuffer>>& buffers);
 
 
-		/** @see RenderAPICore::setIndexBuffer() */
-		static void setIndexBuffer(CoreAccessor& accessor, const SPtr<IndexBuffer>& buffer);
+		/** 
+		 * @see RenderAPICore::setIndexBuffer() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void setIndexBuffer(const SPtr<IndexBuffer>& buffer);
 
 
-		/** @see RenderAPICore::setVertexDeclaration() */
-		static void setVertexDeclaration(CoreAccessor& accessor, const SPtr<VertexDeclaration>& vertexDeclaration);
+		/** 
+		 * @see RenderAPICore::setVertexDeclaration() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void setVertexDeclaration(const SPtr<VertexDeclaration>& vertexDeclaration);
 
 
-		/** @see RenderAPICore::setViewport() */
-		static void setViewport(CoreAccessor& accessor, const Rect2& area);
+		/** 
+		 * @see RenderAPICore::setViewport() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void setViewport(const Rect2& area);
 
 
-		/** @see RenderAPICore::setViewport() */
-		static void setStencilRef(CoreAccessor& accessor, UINT32 value);
+		/** 
+		 * @see RenderAPICore::setViewport() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void setStencilRef(UINT32 value);
 
 
-		/** @see RenderAPICore::setDrawOperation()  */
-		static void setDrawOperation(CoreAccessor& accessor, DrawOperationType op);
+		/** 
+		 * @see RenderAPICore::setDrawOperation()  
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void setDrawOperation(DrawOperationType op);
 
 
-		/** @see RenderAPICore::setScissorRect()  */
-		static void setScissorRect(CoreAccessor& accessor, UINT32 left = 0, UINT32 top = 0, UINT32 right = 800, UINT32 bottom = 600);
+		/** 
+		 * @see RenderAPICore::setScissorRect() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void setScissorRect(UINT32 left = 0, UINT32 top = 0, UINT32 right = 800, UINT32 bottom = 600);
 
 
-		/** @see RenderAPICore::setRenderTarget() */
-		static void setRenderTarget(CoreAccessor& accessor, const SPtr<RenderTarget>& target, 
-			bool readOnlyDepthStencil = false, bool preserveContents = false);
+		/** 
+		 * @see RenderAPICore::setRenderTarget() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil = false, 
+			bool preserveContents = false);
 
 
-		/** @see RenderAPICore::beginFrame() */
-		static void beginRender(CoreAccessor& accessor);
+		/** 
+		 * @see RenderAPICore::beginFrame() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void beginRender();
 
 
-		/** @see RenderAPICore::endFrame() */
-		static void endRender(CoreAccessor& accessor);
+		/** 
+		 * @see RenderAPICore::endFrame() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void endRender();
 
 
-		/** @see RenderAPICore::clearRenderTarget()  */
-		static void clearRenderTarget(CoreAccessor& accessor, UINT32 buffers, 
-			const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, UINT8 targetMask = 0xFF);
+		/** 
+		 * @see RenderAPICore::clearRenderTarget() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, 
+			UINT16 stencil = 0, UINT8 targetMask = 0xFF);
 
 
-		/** @see RenderAPICore::clearViewport() */
-		static void clearViewport(CoreAccessor& accessor, UINT32 buffers, const Color& color = Color::Black, 
-			float depth = 1.0f, UINT16 stencil = 0, UINT8 targetMask = 0xFF);
+		/** 
+		 * @see RenderAPICore::clearViewport() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0,
+			UINT8 targetMask = 0xFF);
 
 
-		/** @see RenderAPICore::swapBuffers() */
-		static void swapBuffers(CoreAccessor& accessor, const SPtr<RenderTarget>& target);
+		/** 
+		 * @see RenderAPICore::swapBuffers() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void swapBuffers(const SPtr<RenderTarget>& target);
 
 
-		/** @see RenderAPICore::draw() */
-		static void draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount = 0);
+		/** 
+		 * @see RenderAPICore::draw() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount = 0);
 
 
-		/** @see RenderAPICore::drawIndexed() */
-		static void drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, 
-			UINT32 vertexCount, UINT32 instanceCount = 0);
+		/** 
+		 * @see RenderAPICore::drawIndexed() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount, 
+			UINT32 instanceCount = 0);
 
 
-		/** @see RenderAPICore::dispatchCompute() */
-		static void dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1);
+		/** 
+		 * @see RenderAPICore::dispatchCompute() 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
+		 */
+		static void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1);
 
 
 		/** @copydoc RenderAPICore::getVideoModeInfo */
 		/** @copydoc RenderAPICore::getVideoModeInfo */
 		static const VideoModeInfo& getVideoModeInfo();
 		static const VideoModeInfo& getVideoModeInfo();

+ 2 - 2
Source/BansheeCore/Include/BsRenderTarget.h

@@ -158,9 +158,9 @@ namespace bs
 		/** 
 		/** 
 		 * @copydoc RenderTargetCore::setPriority 
 		 * @copydoc RenderTargetCore::setPriority 
 		 *
 		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void setPriority(CoreAccessor& accessor, INT32 priority);
+		void setPriority(INT32 priority);
 
 
 		/**
 		/**
 		 * Returns properties that describe the render target.
 		 * Returns properties that describe the render target.

+ 41 - 46
Source/BansheeCore/Include/BsRenderWindow.h

@@ -87,18 +87,14 @@ namespace bs
 	};
 	};
 
 
 	/**
 	/**
-	 * Render target specialization that allows you to render into window frame buffer(s).
-	 *
-	 * @note	Sim thread only. Retrieve core implementation from getCore() for core thread only functionality.
+	 * Operating system window with a specific position, size and style. Each window serves as a surface that can be
+	 * rendered into by RenderAPI operations.
 	 */
 	 */
     class BS_CORE_EXPORT RenderWindow : public RenderTarget
     class BS_CORE_EXPORT RenderWindow : public RenderTarget
     {
     {
     public:
     public:
 		virtual ~RenderWindow() { }
 		virtual ~RenderWindow() { }
 
 
-		/** @copydoc RenderTarget::destroy */
-		virtual void destroy() override;	
-
 		/**	Converts screen position into window local position. */
 		/**	Converts screen position into window local position. */
 		virtual Vector2I screenToWindowPos(const Vector2I& screenPos) const = 0;
 		virtual Vector2I screenToWindowPos(const Vector2I& screenPos) const = 0;
 
 
@@ -108,76 +104,76 @@ namespace bs
 		/**	
 		/**	
 		 * Resize the window to specified width and height in pixels. 
 		 * Resize the window to specified width and height in pixels. 
 		 *
 		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
 		 * @param[in]	width		Width of the window in pixels.
 		 * @param[in]	width		Width of the window in pixels.
 		 * @param[in]	height		Height of the window in pixels.
 		 * @param[in]	height		Height of the window in pixels.
 		 */
 		 */
-		void resize(CoreAccessor& accessor, UINT32 width, UINT32 height);
+		void resize(UINT32 width, UINT32 height);
 
 
 		/**	
 		/**	
 		 * Move the window to specified screen coordinates. 
 		 * Move the window to specified screen coordinates. 
 		 *
 		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
 		 * @param[in]	left		Position of the left border of the window on the screen.
 		 * @param[in]	left		Position of the left border of the window on the screen.
 		 * @param[in]	top			Position of the top border of the window on the screen.
 		 * @param[in]	top			Position of the top border of the window on the screen.
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void move(CoreAccessor& accessor, INT32 left, INT32 top);
+		void move(INT32 left, INT32 top);
 
 
-		/**	
-		 * Hide the window. (Does not destroy it, just hides it). 
-		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
+		/** 
+		 * Hides the window. 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void hide(CoreAccessor& accessor);
+		void hide();
 
 
-		/**	
+		/** 
 		 * Shows a previously hidden window. 
 		 * Shows a previously hidden window. 
-		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void show(CoreAccessor& accessor);
+		void show();
 
 
 		/** 
 		/** 
-		 * @copydoc RenderWindowCore::minimize 
-		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
+		 * @copydoc RenderWindowCore::minimize  
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void minimize(CoreAccessor& accessor);
+		void minimize();
 
 
 		/** 
 		/** 
 		 * @copydoc RenderWindowCore::maximize 
 		 * @copydoc RenderWindowCore::maximize 
-		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void maximize(CoreAccessor& accessor);
+		void maximize();
 
 
 		/** 
 		/** 
-		 * @copydoc RenderWindowCore::restore 
-		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
+		 * @copydoc RenderWindowCore::restore  
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void restore(CoreAccessor& accessor);
+		void restore();
 
 
 		/** 
 		/** 
 		 * @copydoc RenderWindowCore::setFullscreen(UINT32, UINT32, float, UINT32) 
 		 * @copydoc RenderWindowCore::setFullscreen(UINT32, UINT32, float, UINT32) 
-		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void setFullscreen(CoreAccessor& accessor, UINT32 width, UINT32 height, float refreshRate = 60.0f, UINT32 monitorIdx = 0);
+		void setFullscreen(UINT32 width, UINT32 height, float refreshRate = 60.0f, UINT32 monitorIdx = 0);
 
 
 		/** 
 		/** 
 		 * @copydoc RenderWindowCore::setFullscreen(const VideoMode&) 
 		 * @copydoc RenderWindowCore::setFullscreen(const VideoMode&) 
-		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void setFullscreen(CoreAccessor& accessor, const VideoMode& videoMode);
+		void setFullscreen(const VideoMode& videoMode);
 
 
-		/**
-		 * @copydoc RenderWindowCore::setWindowed
-		 *
-		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
+		/** 
+		 * @copydoc RenderWindowCore::setWindowed 
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		void setWindowed(CoreAccessor& accessor, UINT32 width, UINT32 height);
+		void setWindowed(UINT32 width, UINT32 height);
 
 
 		/**	Retrieves a core implementation of a render window usable only from the core thread. */
 		/**	Retrieves a core implementation of a render window usable only from the core thread. */
 		SPtr<RenderWindowCore> getCore() const;
 		SPtr<RenderWindowCore> getCore() const;
@@ -185,6 +181,9 @@ namespace bs
 		/**	Returns properties that describe the render window. */
 		/**	Returns properties that describe the render window. */
 		const RenderWindowProperties& getProperties() const;
 		const RenderWindowProperties& getProperties() const;
 
 
+		/** Closes and destroys the window. */
+		void destroy() override;
+
 		/**
 		/**
 		 * Creates a new render window using the specified options. Optionally makes the created window a child of another 
 		 * Creates a new render window using the specified options. Optionally makes the created window a child of another 
 		 * window.
 		 * window.
@@ -216,11 +215,7 @@ namespace bs
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	/**
-	 * Provides access to internal render window implementation usable only from the core thread.
-	 *
-	 * @note	Core thread only.
-	 */
+	/** Core thread counterpart of RenderWindow. */
 	class BS_CORE_EXPORT RenderWindowCore : public RenderTargetCore
 	class BS_CORE_EXPORT RenderWindowCore : public RenderTargetCore
 	{
 	{
 	public:
 	public:

+ 55 - 90
Source/BansheeCore/Include/BsTexture.h

@@ -129,40 +129,30 @@ namespace bs
 		/** Returns the number of array slices of the texture (if the texture is an array texture). */
 		/** Returns the number of array slices of the texture (if the texture is an array texture). */
 		UINT32 getNumArraySlices() const { return mDesc.numArraySlices; }
 		UINT32 getNumArraySlices() const { return mDesc.numArraySlices; }
 
 
+		/**
+		 * Allocates a buffer that exactly matches the format of the texture described by these properties, for the provided
+		 * face and mip level. This is a helper function, primarily meant for creating buffers when reading from, or writing
+		 * to a texture.
+		 * 			
+		 * @note	Thread safe.
+		 */
+		SPtr<PixelData> allocBuffer(UINT32 face, UINT32 mipLevel) const;
+
+	protected:
+		friend class TextureRTTI;
+		friend class Texture;
+
 		/**
 		/**
 		 * Maps a sub-resource index to an exact face and mip level. Sub-resource indexes are used when reading or writing
 		 * Maps a sub-resource index to an exact face and mip level. Sub-resource indexes are used when reading or writing
 		 * to the resource.
 		 * to the resource.
-		 * 			
-		 * @note	
-		 * Sub-resource index is only valid for the instance it was created on. You cannot use a sub-resource index from a
-		 * different texture and expect to get valid result. Modifying the resource so the number of sub-resources changes
-		 * invalidates all sub-resource indexes.
 		 */
 		 */
 		void mapFromSubresourceIdx(UINT32 subresourceIdx, UINT32& face, UINT32& mip) const;
 		void mapFromSubresourceIdx(UINT32 subresourceIdx, UINT32& face, UINT32& mip) const;
 
 
 		/**
 		/**
 		 * Map a face and a mip level to a sub-resource index you can use for updating or reading a specific sub-resource.
 		 * Map a face and a mip level to a sub-resource index you can use for updating or reading a specific sub-resource.
-		 * 			
-		 * @note	
-		 * Generated sub-resource index is only valid for the instance it was created on. Modifying the resource so the 
-		 * number of sub-resources changes, invalidates all sub-resource indexes.
 		 */
 		 */
 		UINT32 mapToSubresourceIdx(UINT32 face, UINT32 mip) const;
 		UINT32 mapToSubresourceIdx(UINT32 face, UINT32 mip) const;
 
 
-		/**
-		 * Allocates a buffer you may use for storage when reading or writing a sub-resource. You need to allocate such a 
-		 * buffer if you are calling readSubresource().
-		 *
-		 * You can retrieve a sub-resource index by calling mapToSubresourceIdx().
-		 * 			
-		 * @note	Thread safe.
-		 */
-		SPtr<PixelData> allocateSubresourceBuffer(UINT32 subresourceIdx) const;
-
-	protected:
-		friend class TextureRTTI;
-		friend class Texture;
-
 		TEXTURE_DESC mDesc;
 		TEXTURE_DESC mDesc;
 	};
 	};
 
 
@@ -176,53 +166,52 @@ namespace bs
     {
     {
     public:
     public:
 		/**
 		/**
-		 * Updates the texture with new data. The actual write will be queued for later execution on the core thread. 
-		 * Provided data buffer will be locked until the operation completes.
+		 * Updates the texture with new data. Provided data buffer will be locked until the operation completes.
 		 *
 		 *
-		 * @param[in]	accessor			Accessor to queue the operation on.
-		 * @param[in]	subresourceIdx		Index of the subresource to write. Retrieved from 
-		 *									TextureProperties::mapToSubresourceIdx().
 		 * @param[in]	data				Pixel data to write. User must ensure it is in format and size compatible with 
 		 * @param[in]	data				Pixel data to write. User must ensure it is in format and size compatible with 
 		 *									the texture.
 		 *									the texture.
+		 * @param[in]	face				Texture face to write to.	
+		 * @param[in]	mipLevel			Mipmap level to write to.				
 		 * @param[in]	discardEntireBuffer When true the existing contents of the resource you are updating will be 
 		 * @param[in]	discardEntireBuffer When true the existing contents of the resource you are updating will be 
 		 *									discarded. This can make the operation faster. Resources with certain buffer 
 		 *									discarded. This can make the operation faster. Resources with certain buffer 
 		 *									types might require this flag to be in a specific state otherwise the operation 
 		 *									types might require this flag to be in a specific state otherwise the operation 
 		 *									will fail.
 		 *									will fail.
 		 * @return							Async operation object you can use to track operation completion.
 		 * @return							Async operation object you can use to track operation completion.
+		 * 
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		AsyncOp writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const SPtr<PixelData>& data, 
-			bool discardEntireBuffer);
+		AsyncOp writeData(const SPtr<PixelData>& data, UINT32 face = 0, UINT32 mipLevel = 0,
+			bool discardEntireBuffer = false);
 
 
 		/**
 		/**
-		 * Reads internal texture data to the provided previously allocated buffer. The read is queued for execution on the
-		 * core thread and not executed immediately. Provided data buffer will be locked until the operation completes.
+		 * Reads internal texture data to the provided previously allocated buffer. Provided data buffer will be locked 
+		 * until the operation completes.
 		 *
 		 *
-		 * @param[in]	accessor			Accessor to queue the operation on.
-		 * @param[in]	subresourceIdx		Index of the subresource to read. Retrieved from
-		 *									TextureProperties::mapToSubresourceIdx().
-		 * @param[out]	data				Pre-allocated buffer of proper size and format where data will be read to. You 
-		 *									can use TextureProperties::allocateSubresourceBuffer() to allocate a valid 
-		 *									buffer.
-		 * @return							Async operation object you can use to track operation completion.
+		 * @param[out]	data		Pre-allocated buffer of proper size and format where data will be read to. You can use
+		 *							TextureProperties::allocBuffer() to allocate a buffer of a correct format and size.
+		 * @param[in]	face		Texture face to read from.
+		 * @param[in]	mipLevel	Mipmap level to read from.
+		 * @return					Async operation object you can use to track operation completion.
 		 *
 		 *
-		 * @see		TextureCore::readSubresource
+		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
 		 */
-		AsyncOp readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const SPtr<PixelData>& data);
+		AsyncOp readData(const SPtr<PixelData>& data, UINT32 face = 0, UINT32 mipLevel = 0);
 
 
 		/**
 		/**
 		 * Reads data from the cached system memory texture buffer into the provided buffer. 
 		 * Reads data from the cached system memory texture buffer into the provided buffer. 
 		 * 		  
 		 * 		  
-		 * @param[out]	dest		Previously allocated buffer to read data into.
-		 * @param[in]	mipLevel	(optional) Mipmap level to read from.
-		 * @param[in]	face		(optional) Texture face to read from.
+		 * @param[out]	data		Pre-allocated buffer of proper size and format where data will be read to. You can use
+		 *							TextureProperties::allocBuffer() to allocate a buffer of a correct format and size.
+		 * @param[in]	face		Texture face to read from.
+		 * @param[in]	mipLevel	Mipmap level to read from.
 		 *
 		 *
 		 * @note	
 		 * @note	
 		 * The data read is the cached texture data. Any data written to the texture from the GPU or core thread will not 
 		 * The data read is the cached texture data. Any data written to the texture from the GPU or core thread will not 
-		 * be reflected in this data. Use readSubresource() if you require those changes.
+		 * be reflected in this data. Use readData() if you require those changes.
 		 * @note
 		 * @note
 		 * The texture must have been created with TU_CPUCACHED usage otherwise this method will not return any data.
 		 * The texture must have been created with TU_CPUCACHED usage otherwise this method will not return any data.
 		 */
 		 */
-		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0);
+		void readCachedData(PixelData& data, UINT32 face = 0, UINT32 mipLevel = 0);
 
 
 		/**	Returns properties that contain information about the texture. */
 		/**	Returns properties that contain information about the texture. */
 		const TextureProperties& getProperties() const { return mProperties; }
 		const TextureProperties& getProperties() const { return mProperties; }
@@ -334,32 +323,6 @@ namespace bs
 		/** @copydoc CoreObjectCore::initialize */
 		/** @copydoc CoreObjectCore::initialize */
 		void initialize() override;
 		void initialize() override;
 
 
-		/**
-		 * Updates a part of the texture with the provided data.
-		 *
-		 * @param[in]	subresourceIdx		Index of the subresource to update, if the texture has more than one.
-		 * @param[in]	data				Data to update the texture with.
-		 * @param[in]	discardEntireBuffer When true the existing contents of the resource you are updating will be 
-		 *									discarded. This can make the operation faster. Resources with certain buffer 
-		 *									types might require this flag to be in a specific state otherwise the operation 
-		 *									will fail.
-		 * @param[in]	queueIdx			Device queue to perform the write operation on. See @ref queuesDoc.								
-		 */
-		virtual void writeSubresource(UINT32 subresourceIdx, const PixelData& data, bool discardEntireBuffer,
-									  UINT32 queueIdx = 0);
-
-		/**
-		 * Reads a part of the current resource into the provided @p data parameter. Data buffer needs to be pre-allocated.
-		 *
-		 * @param[in]	subresourceIdx		Index of the subresource to update, if the texture has more than one.
-		 * @param[out]	data				Buffer that will receive the data. Should be allocated with 
-		 *									allocateSubresourceBuffer() to ensure it is of valid type and size.
-		 * @param[in]	deviceIdx			Index of the device whose memory to read. If the buffer doesn't exist on this
-		 *									device, no data will be read.
-		 * @param[in]	queueIdx			Device queue to perform the read operation on. See @ref queuesDoc.
-		 */
-		virtual void readSubresource(UINT32 subresourceIdx, PixelData& data, UINT32 deviceIdx = 0, UINT32 queueIdx = 0);
-
 		/**
 		/**
 		 * Locks the buffer for reading or writing.
 		 * Locks the buffer for reading or writing.
 		 *
 		 *
@@ -391,12 +354,15 @@ namespace bs
 		 * You are allowed to copy from a multisampled to non-multisampled surface, which will resolve the multisampled
 		 * You are allowed to copy from a multisampled to non-multisampled surface, which will resolve the multisampled
 		 * surface before copying.
 		 * surface before copying.
 		 *
 		 *
-		 * @param[in]	srcSubresourceIdx	Index of the subresource to copy from.
-		 * @param[in]	destSubresourceIdx	Index of the subresource to copy to.
 		 * @param[in]	target				Texture that contains the destination subresource.
 		 * @param[in]	target				Texture that contains the destination subresource.
+		 * @param[in]	srcFace				Face to copy from.
+		 * @param[in]	srcMipLevel			Mip level to copy from.
+		 * @param[in]	dstFace				Face to copy to.
+		 * @param[in]	dstMipLevel			Mip level to copy to.
 		 * @param[in]	queueIdx			Device queue to perform the copy operation on. See @ref queuesDoc.
 		 * @param[in]	queueIdx			Device queue to perform the copy operation on. See @ref queuesDoc.
 		 */
 		 */
-		void copy(UINT32 srcSubresourceIdx, UINT32 destSubresourceIdx, const SPtr<TextureCore>& target, UINT32 queueIdx = 0);
+		void copy(const SPtr<TextureCore>& target, UINT32 srcFace = 0, UINT32 srcMipLevel = 0, UINT32 dstFace = 0,
+			UINT32 dstMipLevel = 0, UINT32 queueIdx = 0);
 
 
 		/**
 		/**
 		 * Reads data from the texture buffer into the provided buffer.
 		 * Reads data from the texture buffer into the provided buffer.
@@ -408,8 +374,8 @@ namespace bs
 		 *							no data will be read.
 		 *							no data will be read.
 		 * @param[in]	queueIdx	Device queue to perform the read operation on. See @ref queuesDoc.
 		 * @param[in]	queueIdx	Device queue to perform the read operation on. See @ref queuesDoc.
 		 */
 		 */
-		virtual void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
-							  UINT32 queueIdx = 0) = 0;
+		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
+							  UINT32 queueIdx = 0);
 
 
 		/**
 		/**
 		 * Writes data from the provided buffer into the texture buffer.
 		 * Writes data from the provided buffer into the texture buffer.
@@ -421,8 +387,8 @@ namespace bs
 		 *									performance of the write operation.
 		 *									performance of the write operation.
 		 * @param[in]	queueIdx			Device queue to perform the write operation on. See @ref queuesDoc.
 		 * @param[in]	queueIdx			Device queue to perform the write operation on. See @ref queuesDoc.
 		 */
 		 */
-		virtual void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
-							   UINT32 queueIdx = 0) = 0;
+		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
+							   UINT32 queueIdx = 0);
 
 
 		/**	Returns properties that contain information about the texture. */
 		/**	Returns properties that contain information about the texture. */
 		const TextureProperties& getProperties() const { return mProperties; }
 		const TextureProperties& getProperties() const { return mProperties; }
@@ -475,24 +441,23 @@ namespace bs
 	protected:
 	protected:
 		/** @copydoc lock */
 		/** @copydoc lock */
 		virtual PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
 		virtual PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
-								   UINT32 queueIdx = 0) = 0;
+			UINT32 queueIdx = 0) = 0;
 
 
 		/** @copydoc unlock */
 		/** @copydoc unlock */
 		virtual void unlockImpl() = 0;
 		virtual void unlockImpl() = 0;
 
 
-		/** 
-		 * API specific implementation of copy(). 
-		 *
-		 * @param[in]	srcFace			Face index to copy from.
-		 * @param[in]	srcMipLevel		Mip level to copy from.
-		 * @param[in]	destFace		Face index to copy to.
-		 * @param[in]	destMipLevel	Mip level to copy to.
-		 * @param[in]	target			Texture to copy to.
-		 * @param[in]	queueIdx		Global queue index to perform the copy on.
-		 */
+		/** @copydoc copy */
 		virtual void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, 
 		virtual void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, 
 			const SPtr<TextureCore>& target, UINT32 queueIdx = 0) = 0;
 			const SPtr<TextureCore>& target, UINT32 queueIdx = 0) = 0;
 
 
+		/** @copydoc readData */
+		virtual void readDataImpl(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
+			UINT32 queueIdx = 0) = 0;
+
+		/** @copydoc writeData */
+		virtual void writeDataImpl(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, 
+			bool discardWholeBuffer = false, UINT32 queueIdx = 0) = 0;
+
 		/************************************************************************/
 		/************************************************************************/
 		/* 								TEXTURE VIEW                      		*/
 		/* 								TEXTURE VIEW                      		*/
 		/************************************************************************/
 		/************************************************************************/

+ 5 - 8
Source/BansheeCore/Include/BsTextureRTTI.h

@@ -55,22 +55,21 @@ namespace bs
 			UINT32 face = (size_t)Math::floor(idx / (float)(obj->mProperties.getNumMipmaps() + 1));
 			UINT32 face = (size_t)Math::floor(idx / (float)(obj->mProperties.getNumMipmaps() + 1));
 			UINT32 mipmap = idx % (obj->mProperties.getNumMipmaps() + 1);
 			UINT32 mipmap = idx % (obj->mProperties.getNumMipmaps() + 1);
 
 
-			UINT32 subresourceIdx = obj->mProperties.mapToSubresourceIdx(face, mipmap);
-			SPtr<PixelData> pixelData = obj->mProperties.allocateSubresourceBuffer(subresourceIdx);
+			SPtr<PixelData> pixelData = obj->mProperties.allocBuffer(face, mipmap);
 
 
 			int usage = obj->getProperties().getUsage();
 			int usage = obj->getProperties().getUsage();
 
 
 			if (usage & TU_CPUREADABLE || BS_EDITOR_BUILD)
 			if (usage & TU_CPUREADABLE || BS_EDITOR_BUILD)
 			{
 			{
-				obj->readSubresource(gCoreAccessor(), subresourceIdx, pixelData);
-				gCoreAccessor().submitToCoreThread(true);
+				obj->readData(pixelData, face, mipmap);
+				gCoreThread().submit(true);
 
 
 				return pixelData;
 				return pixelData;
 			}
 			}
 
 
 			if(usage & TU_CPUCACHED)
 			if(usage & TU_CPUCACHED)
 			{
 			{
-				obj->readData(*pixelData, mipmap, face);
+				obj->readCachedData(*pixelData, face, mipmap);
 				return pixelData;
 				return pixelData;
 			}
 			}
 
 
@@ -153,9 +152,7 @@ namespace bs
 				UINT32 face = (size_t)Math::floor(i / (float)(texProps.getNumMipmaps() + 1));
 				UINT32 face = (size_t)Math::floor(i / (float)(texProps.getNumMipmaps() + 1));
 				UINT32 mipmap = i % (texProps.getNumMipmaps() + 1);
 				UINT32 mipmap = i % (texProps.getNumMipmaps() + 1);
 
 
-				UINT32 subresourceIdx = texProps.mapToSubresourceIdx(face, mipmap);
-
-				texture->writeSubresource(gCoreAccessor(), subresourceIdx, pixelData->at(i), false);
+				texture->writeData(pixelData->at(i), face, mipmap, false);
 			}
 			}
 
 
 			bs_delete(pixelData);
 			bs_delete(pixelData);

+ 9 - 9
Source/BansheeCore/Source/BsCoreApplication.cpp

@@ -87,9 +87,9 @@ namespace bs
 
 
 		// All CoreObject related modules should be shut down now. They have likely queued CoreObjects for destruction, so
 		// All CoreObject related modules should be shut down now. They have likely queued CoreObjects for destruction, so
 		// we need to wait for those objects to get destroyed before continuing.
 		// we need to wait for those objects to get destroyed before continuing.
-		CoreObjectManager::instance().syncToCore(gCoreAccessor());
+		CoreObjectManager::instance().syncToCore();
 		gCoreThread().update();
 		gCoreThread().update();
-		gCoreThread().submitAccessors(true);
+		gCoreThread().submitAll(true);
 
 
 		unloadPlugin(mRendererPlugin);
 		unloadPlugin(mRendererPlugin);
 
 
@@ -258,17 +258,17 @@ namespace bs
 				mIsFrameRenderingFinished = false;
 				mIsFrameRenderingFinished = false;
 			}
 			}
 
 
-			gCoreThread().queueCommand(std::bind(&CoreApplication::beginCoreProfiling, this));
-			gCoreThread().queueCommand(&Platform::_coreUpdate);
+			gCoreThread().queueCommand(std::bind(&CoreApplication::beginCoreProfiling, this), CTQF_InternalQueue);
+			gCoreThread().queueCommand(&Platform::_coreUpdate, CTQF_InternalQueue);
 
 
 			gCoreThread().update(); 
 			gCoreThread().update(); 
-			gCoreThread().submitAccessors(); 
+			gCoreThread().submitAll(); 
 
 
-			gCoreThread().queueCommand(std::bind(&CoreApplication::frameRenderingFinishedCallback, this));
+			gCoreThread().queueCommand(std::bind(&CoreApplication::frameRenderingFinishedCallback, this), CTQF_InternalQueue);
 
 
-			gCoreThread().queueCommand(std::bind(&RenderWindowCoreManager::_update, RenderWindowCoreManager::instancePtr()));
-			gCoreThread().queueCommand(std::bind(&QueryManager::_update, QueryManager::instancePtr()));
-			gCoreThread().queueCommand(std::bind(&CoreApplication::endCoreProfiling, this));
+			gCoreThread().queueCommand(std::bind(&RenderWindowCoreManager::_update, RenderWindowCoreManager::instancePtr()), CTQF_InternalQueue);
+			gCoreThread().queueCommand(std::bind(&QueryManager::_update, QueryManager::instancePtr()), CTQF_InternalQueue);
+			gCoreThread().queueCommand(std::bind(&CoreApplication::endCoreProfiling, this), CTQF_InternalQueue);
 
 
 			gProfilerCPU().endThread();
 			gProfilerCPU().endThread();
 			gProfiler()._update();
 			gProfiler()._update();

+ 8 - 9
Source/BansheeCore/Source/BsCoreObject.cpp

@@ -4,7 +4,6 @@
 #include "BsCoreObjectCore.h"
 #include "BsCoreObjectCore.h"
 #include "BsCoreThread.h"
 #include "BsCoreThread.h"
 #include "BsCoreObjectManager.h"
 #include "BsCoreObjectManager.h"
-#include "BsCoreThreadAccessor.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 
@@ -71,9 +70,9 @@ namespace bs
 
 
 				// Even though this object might not require initialization on the core thread, it will be used on it, therefore
 				// Even though this object might not require initialization on the core thread, it will be used on it, therefore
 				// do a memory barrier to ensure any stores are finished before continuing (When it requires init on core thread
 				// do a memory barrier to ensure any stores are finished before continuing (When it requires init on core thread
-				// we use the core accessor which uses a mutex, and therefore executes all stores as well, so we dont need to 
+				// we use the core queue which uses a mutex, and therefore executes all stores as well, so we dont need to 
 				// do this explicitly)
 				// do this explicitly)
-				std::atomic_thread_fence(std::memory_order_release);
+				std::atomic_thread_fence(std::memory_order_release); // TODO - Need atomic variable, currently this does nothing
 			}
 			}
 		}
 		}
 
 
@@ -86,9 +85,9 @@ namespace bs
 			mCoreSpecific->synchronize();
 			mCoreSpecific->synchronize();
 	}
 	}
 
 
-	void CoreObject::syncToCore(CoreAccessor& accessor)
+	void CoreObject::syncToCore()
 	{
 	{
-		CoreObjectManager::instance().syncToCore(this, accessor);
+		CoreObjectManager::instance().syncToCore(this);
 	}
 	}
 
 
 	void CoreObject::markCoreDirty(UINT32 flags)
 	void CoreObject::markCoreDirty(UINT32 flags)
@@ -117,27 +116,27 @@ namespace bs
 		// reference to the obj (saved in the bound function).
 		// reference to the obj (saved in the bound function).
 		// We could have called the function directly using "this" pointer but then we couldn't have used a shared_ptr for the object,
 		// We could have called the function directly using "this" pointer but then we couldn't have used a shared_ptr for the object,
 		// in which case there is a possibility that the object would be released and deleted while still being in the command queue.
 		// in which case there is a possibility that the object would be released and deleted while still being in the command queue.
-		gCoreAccessor().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
+		gCoreThread().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
 	}
 	}
 
 
 	AsyncOp CoreObject::queueReturnGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void(AsyncOp&)> func)
 	AsyncOp CoreObject::queueReturnGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void(AsyncOp&)> func)
 	{
 	{
 		// See queueGpuCommand
 		// See queueGpuCommand
-		return gCoreAccessor().queueReturnCommand(std::bind(&CoreObject::executeReturnGpuCommand, obj, func, _1));
+		return gCoreThread().queueReturnCommand(std::bind(&CoreObject::executeReturnGpuCommand, obj, func, _1));
 	}
 	}
 
 
 	void CoreObject::queueInitializeGpuCommand(const SPtr<CoreObjectCore>& obj)
 	void CoreObject::queueInitializeGpuCommand(const SPtr<CoreObjectCore>& obj)
 	{
 	{
 		std::function<void()> func = std::bind(&CoreObjectCore::initialize, obj.get());
 		std::function<void()> func = std::bind(&CoreObjectCore::initialize, obj.get());
 
 
-		CoreThread::instance().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
+		CoreThread::instance().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func), CTQF_InternalQueue);
 	}
 	}
 
 
 	void CoreObject::queueDestroyGpuCommand(const SPtr<CoreObjectCore>& obj)
 	void CoreObject::queueDestroyGpuCommand(const SPtr<CoreObjectCore>& obj)
 	{
 	{
 		std::function<void()> func = [&](){}; // Do nothing function. We just need the shared pointer to stay alive until it reaches the core thread
 		std::function<void()> func = [&](){}; // Do nothing function. We just need the shared pointer to stay alive until it reaches the core thread
 
 
-		gCoreAccessor().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
+		gCoreThread().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
 	}
 	}
 
 
 	void CoreObject::executeGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void()> func)
 	void CoreObject::executeGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void()> func)

+ 4 - 4
Source/BansheeCore/Source/BsCoreObjectManager.cpp

@@ -205,13 +205,13 @@ namespace bs
 		bs_frame_clear();
 		bs_frame_clear();
 	}
 	}
 
 
-	void CoreObjectManager::syncToCore(CoreAccessor& accessor)
+	void CoreObjectManager::syncToCore()
 	{
 	{
 		syncDownload(gCoreThread().getFrameAlloc());
 		syncDownload(gCoreThread().getFrameAlloc());
-		accessor.queueCommand(std::bind(&CoreObjectManager::syncUpload, this));
+		gCoreThread().queueCommand(std::bind(&CoreObjectManager::syncUpload, this));
 	}
 	}
 
 
-	void CoreObjectManager::syncToCore(CoreObject* object, CoreAccessor& accessor)
+	void CoreObjectManager::syncToCore(CoreObject* object)
 	{
 	{
 		struct IndividualCoreSyncData
 		struct IndividualCoreSyncData
 		{
 		{
@@ -281,7 +281,7 @@ namespace bs
 		};
 		};
 
 
 		if (syncData.size() > 0)
 		if (syncData.size() > 0)
-			accessor.queueCommand(std::bind(callback, syncData));
+			gCoreThread().queueCommand(std::bind(callback, syncData));
 	}
 	}
 
 
 	void CoreObjectManager::syncDownload(FrameAlloc* allocator)
 	void CoreObjectManager::syncDownload(FrameAlloc* allocator)

+ 70 - 69
Source/BansheeCore/Source/BsCoreThread.cpp

@@ -10,8 +10,8 @@ using namespace std::placeholders;
 
 
 namespace bs
 namespace bs
 {
 {
-	CoreThread::AccessorData CoreThread::mAccessor;
-	BS_THREADLOCAL CoreThread::AccessorContainer* CoreThread::AccessorData::current = nullptr;
+	CoreThread::QueueData CoreThread::mPerThreadQueue;
+	BS_THREADLOCAL CoreThread::ThreadQueueContainer* CoreThread::QueueData::current = nullptr;
 
 
 	CoreThread::CoreThread()
 	CoreThread::CoreThread()
 		: mActiveFrameAlloc(0)
 		: mActiveFrameAlloc(0)
@@ -19,7 +19,6 @@ namespace bs
 		, mCoreThreadStarted(false)
 		, mCoreThreadStarted(false)
 		, mCommandQueue(nullptr)
 		, mCommandQueue(nullptr)
 		, mMaxCommandNotifyId(0)
 		, mMaxCommandNotifyId(0)
-		, mSyncedCoreAccessor(nullptr)
 	{
 	{
 		for (UINT32 i = 0; i < NUM_SYNC_BUFFERS; i++)
 		for (UINT32 i = 0; i < NUM_SYNC_BUFFERS; i++)
 		{
 		{
@@ -40,14 +39,12 @@ namespace bs
 		shutdownCoreThread();
 		shutdownCoreThread();
 
 
 		{
 		{
-			Lock lock(mAccessorMutex);
+			Lock lock(mCoreQueueMutex);
 
 
-			for(auto& accessor : mAccessors)
-			{
-				bs_delete(accessor);
-			}
+			for(auto& queue : mAllQueues)
+				bs_delete(queue);
 
 
-			mAccessors.clear();
+			mAllQueues.clear();
 		}
 		}
 
 
 		if(mCommandQueue != nullptr)
 		if(mCommandQueue != nullptr)
@@ -90,7 +87,6 @@ namespace bs
 
 
 			mCoreThreadStarted = true;
 			mCoreThreadStarted = true;
 			mCoreThreadId = BS_THREAD_CURRENT_ID;
 			mCoreThreadId = BS_THREAD_CURRENT_ID;
-			mSyncedCoreAccessor = bs_new<CoreThreadAccessor<CommandQueueSync>>(BS_THREAD_CURRENT_ID);
 		}
 		}
 
 
 		mCoreThreadStartedCondition.notify_one();
 		mCoreThreadStartedCondition.notify_one();
@@ -106,7 +102,6 @@ namespace bs
 				{
 				{
 					if(mCoreThreadShutdown)
 					if(mCoreThreadShutdown)
 					{
 					{
-						bs_delete(mSyncedCoreAccessor);
 						TaskScheduler::instance().addWorker();
 						TaskScheduler::instance().addWorker();
 						return;
 						return;
 					}
 					}
@@ -143,102 +138,113 @@ namespace bs
 #endif
 #endif
 	}
 	}
 
 
-	SPtr<CoreThreadAccessor<CommandQueueNoSync>> CoreThread::getAccessor()
+	SPtr<TCoreThreadQueue<CommandQueueNoSync>> CoreThread::getQueue()
 	{
 	{
-		if(mAccessor.current == nullptr)
+		if(mPerThreadQueue.current == nullptr)
 		{
 		{
-			SPtr<CoreThreadAccessor<CommandQueueNoSync>> newAccessor = bs_shared_ptr_new<CoreThreadAccessor<CommandQueueNoSync>>(BS_THREAD_CURRENT_ID);
-			mAccessor.current = bs_new<AccessorContainer>();
-			mAccessor.current->accessor = newAccessor;
-			mAccessor.current->isMain = BS_THREAD_CURRENT_ID == mSimThreadId;
+			SPtr<TCoreThreadQueue<CommandQueueNoSync>> newQueue = bs_shared_ptr_new<TCoreThreadQueue<CommandQueueNoSync>>(BS_THREAD_CURRENT_ID);
+			mPerThreadQueue.current = bs_new<ThreadQueueContainer>();
+			mPerThreadQueue.current->queue = newQueue;
+			mPerThreadQueue.current->isMain = BS_THREAD_CURRENT_ID == mSimThreadId;
 
 
-			Lock lock(mAccessorMutex);
-			mAccessors.push_back(mAccessor.current);
+			Lock lock(mCoreQueueMutex);
+			mAllQueues.push_back(mPerThreadQueue.current);
 		}
 		}
 
 
-		return mAccessor.current->accessor;
+		return mPerThreadQueue.current->queue;
 	}
 	}
 
 
-	SyncedCoreAccessor& CoreThread::getSyncedAccessor()
+	void CoreThread::submitAll(bool blockUntilComplete)
 	{
 	{
-		return *mSyncedCoreAccessor;
-	}
-
-	void CoreThread::submitAccessors(bool blockUntilComplete)
-	{
-		Vector<AccessorContainer*> accessorCopies;
+		Vector<ThreadQueueContainer*> queueCopies;
 
 
 		{
 		{
-			Lock lock(mAccessorMutex);
+			Lock lock(mCoreQueueMutex);
 
 
-			accessorCopies = mAccessors;
+			queueCopies = mAllQueues;
 		}
 		}
 
 
 		// Submit workers first
 		// Submit workers first
-		AccessorContainer* mainAccessor = nullptr;
-		for (auto& accessor : accessorCopies)
+		ThreadQueueContainer* mainQueue = nullptr;
+		for (auto& queue : queueCopies)
 		{
 		{
-			if (!accessor->isMain)
-				accessor->accessor->submitToCoreThread(blockUntilComplete);
+			if (!queue->isMain)
+				queue->queue->submitToCoreThread(blockUntilComplete);
 			else
 			else
-				mainAccessor = accessor;
+				mainQueue = queue;
 		}
 		}
 
 
 		// Then main
 		// Then main
-		if (mainAccessor != nullptr)
-			mainAccessor->accessor->submitToCoreThread(blockUntilComplete);
+		if (mainQueue != nullptr)
+			mainQueue->queue->submitToCoreThread(blockUntilComplete);
+	}
 
 
-		// Then synced
-		mSyncedCoreAccessor->submitToCoreThread(blockUntilComplete);
+	void CoreThread::submit(bool blockUntilComplete)
+	{
+		getQueue()->submitToCoreThread(blockUntilComplete);
 	}
 	}
 
 
-	AsyncOp CoreThread::queueReturnCommand(std::function<void(AsyncOp&)> commandCallback, bool blockUntilComplete)
+	AsyncOp CoreThread::queueReturnCommand(std::function<void(AsyncOp&)> commandCallback, CoreThreadQueueFlags flags)
 	{
 	{
 		assert(BS_THREAD_CURRENT_ID != getCoreThreadId() && "Cannot queue commands on the core thread for the core thread");
 		assert(BS_THREAD_CURRENT_ID != getCoreThreadId() && "Cannot queue commands on the core thread for the core thread");
 
 
-		AsyncOp op;
-		UINT32 commandId = -1;
+		if (!flags.isSet(CTQF_InternalQueue))
+			return getQueue()->queueReturnCommand(commandCallback);
+		else
 		{
 		{
-			Lock lock(mCommandQueueMutex);
+			bool blockUntilComplete = flags.isSet(CTQF_BlockUntilComplete);
 
 
-			if(blockUntilComplete)
+			AsyncOp op;
+			UINT32 commandId = -1;
 			{
 			{
-				commandId = mMaxCommandNotifyId++;
-				op = mCommandQueue->queueReturn(commandCallback, true, commandId);
+				Lock lock(mCommandQueueMutex);
+
+				if (blockUntilComplete)
+				{
+					commandId = mMaxCommandNotifyId++;
+					op = mCommandQueue->queueReturn(commandCallback, true, commandId);
+				}
+				else
+					op = mCommandQueue->queueReturn(commandCallback);
 			}
 			}
-			else
-				op = mCommandQueue->queueReturn(commandCallback);
-		}
 
 
-		mCommandReadyCondition.notify_all();
+			mCommandReadyCondition.notify_all();
 
 
-		if(blockUntilComplete)
-			blockUntilCommandCompleted(commandId);
+			if (blockUntilComplete)
+				blockUntilCommandCompleted(commandId);
 
 
-		return op;
+			return op;
+		}
 	}
 	}
 
 
-	void CoreThread::queueCommand(std::function<void()> commandCallback, bool blockUntilComplete)
+	void CoreThread::queueCommand(std::function<void()> commandCallback, CoreThreadQueueFlags flags)
 	{
 	{
 		assert(BS_THREAD_CURRENT_ID != getCoreThreadId() && "Cannot queue commands on the core thread for the core thread");
 		assert(BS_THREAD_CURRENT_ID != getCoreThreadId() && "Cannot queue commands on the core thread for the core thread");
 
 
-		UINT32 commandId = -1;
+		if (!flags.isSet(CTQF_InternalQueue))
+			getQueue()->queueCommand(commandCallback);
+		else
 		{
 		{
-			Lock lock(mCommandQueueMutex);
+			bool blockUntilComplete = flags.isSet(CTQF_BlockUntilComplete);
 
 
-			if(blockUntilComplete)
+			UINT32 commandId = -1;
 			{
 			{
-				commandId = mMaxCommandNotifyId++;
-				mCommandQueue->queue(commandCallback, true, commandId);
+				Lock lock(mCommandQueueMutex);
+
+				if (blockUntilComplete)
+				{
+					commandId = mMaxCommandNotifyId++;
+					mCommandQueue->queue(commandCallback, true, commandId);
+				}
+				else
+					mCommandQueue->queue(commandCallback);
 			}
 			}
-			else
-				mCommandQueue->queue(commandCallback);
-		}
 
 
-		mCommandReadyCondition.notify_all();
+			mCommandReadyCondition.notify_all();
 
 
-		if(blockUntilComplete)
-			blockUntilCommandCompleted(commandId);
+			if (blockUntilComplete)
+				blockUntilCommandCompleted(commandId);
+		}
 	}
 	}
 
 
 	void CoreThread::update()
 	void CoreThread::update()
@@ -300,11 +306,6 @@ namespace bs
 		return CoreThread::instance();
 		return CoreThread::instance();
 	}
 	}
 
 
-	CoreThreadAccessor<CommandQueueNoSync>& gCoreAccessor()
-	{
-		return *CoreThread::instance().getAccessor();
-	}
-
 	void throwIfNotCoreThread()
 	void throwIfNotCoreThread()
 	{
 	{
 #if !BS_FORCE_SINGLETHREADED_RENDERING
 #if !BS_FORCE_SINGLETHREADED_RENDERING

+ 9 - 18
Source/BansheeCore/Source/BsCoreThreadAccessor.cpp → Source/BansheeCore/Source/BsCoreThreadQueue.cpp

@@ -1,51 +1,42 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsCoreThreadAccessor.h"
+#include "BsCoreThreadQueue.h"
 #include "BsCommandQueue.h"
 #include "BsCommandQueue.h"
-#include "BsRenderAPI.h"
-#include "BsBlendState.h"
-#include "BsRasterizerState.h"
-#include "BsDepthStencilState.h"
-#include "BsGpuResourceData.h"
-#include "BsIndexBuffer.h"
-#include "BsVertexBuffer.h"
-#include "BsVideoModeInfo.h"
-#include "BsGpuParams.h"
-#include "BsPass.h"
 #include "BsMaterial.h"
 #include "BsMaterial.h"
 #include "BsCoreThread.h"
 #include "BsCoreThread.h"
 
 
 namespace bs
 namespace bs
 {
 {
-	CoreThreadAccessorBase::CoreThreadAccessorBase(CommandQueueBase* commandQueue)
+	CoreThreadQueueBase::CoreThreadQueueBase(CommandQueueBase* commandQueue)
 		:mCommandQueue(commandQueue)
 		:mCommandQueue(commandQueue)
 	{
 	{
 
 
 	}
 	}
 
 
-	CoreThreadAccessorBase::~CoreThreadAccessorBase()
+	CoreThreadQueueBase::~CoreThreadQueueBase()
 	{
 	{
 		bs_delete(mCommandQueue);
 		bs_delete(mCommandQueue);
 	}
 	}
 
 
-	AsyncOp CoreThreadAccessorBase::queueReturnCommand(std::function<void(AsyncOp&)> commandCallback)
+	AsyncOp CoreThreadQueueBase::queueReturnCommand(std::function<void(AsyncOp&)> commandCallback)
 	{
 	{
 		return mCommandQueue->queueReturn(commandCallback);
 		return mCommandQueue->queueReturn(commandCallback);
 	}
 	}
 
 
-	void CoreThreadAccessorBase::queueCommand(std::function<void()> commandCallback)
+	void CoreThreadQueueBase::queueCommand(std::function<void()> commandCallback)
 	{
 	{
 		mCommandQueue->queue(commandCallback);
 		mCommandQueue->queue(commandCallback);
 	}
 	}
 
 
-	void CoreThreadAccessorBase::submitToCoreThread(bool blockUntilComplete)
+	void CoreThreadQueueBase::submitToCoreThread(bool blockUntilComplete)
 	{
 	{
 		Queue<QueuedCommand>* commands = mCommandQueue->flush();
 		Queue<QueuedCommand>* commands = mCommandQueue->flush();
 
 
-		gCoreThread().queueCommand(std::bind(&CommandQueueBase::playback, mCommandQueue, commands), blockUntilComplete);
+		gCoreThread().queueCommand(std::bind(&CommandQueueBase::playback, mCommandQueue, commands), 
+			CTQF_InternalQueue | CTQF_BlockUntilComplete);
 	}
 	}
 
 
-	void CoreThreadAccessorBase::cancelAll()
+	void CoreThreadQueueBase::cancelAll()
 	{
 	{
 		// Note that this won't free any Frame data allocated for all the canceled commands since
 		// Note that this won't free any Frame data allocated for all the canceled commands since
 		// frame data will only get cleared at frame start
 		// frame data will only get cleared at frame start

+ 19 - 19
Source/BansheeCore/Source/BsMesh.cpp

@@ -73,7 +73,7 @@ namespace bs
 		// buffer data upon buffer construction, instead of setting it in a second step like I do here
 		// buffer data upon buffer construction, instead of setting it in a second step like I do here
 		if (mTempInitialMeshData != nullptr)
 		if (mTempInitialMeshData != nullptr)
 		{
 		{
-			writeSubresource(0, *mTempInitialMeshData, isDynamic);
+			writeData(*mTempInitialMeshData, isDynamic);
 			mTempInitialMeshData = nullptr;
 			mTempInitialMeshData = nullptr;
 		}
 		}
 
 
@@ -101,8 +101,7 @@ namespace bs
 		return mVertexDesc;
 		return mVertexDesc;
 	}
 	}
 
 
-	void MeshCore::writeSubresource(UINT32 subresourceIdx, const MeshData& meshData, bool discardEntireBuffer, 
-		bool performUpdateBounds, UINT32 queueIdx)
+	void MeshCore::writeData(const MeshData& meshData, bool discardEntireBuffer, bool performUpdateBounds, UINT32 queueIdx)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
@@ -213,7 +212,7 @@ namespace bs
 			updateBounds(meshData);
 			updateBounds(meshData);
 	}
 	}
 
 
-	void MeshCore::readSubresource(UINT32 subresourceIdx, MeshData& meshData, UINT32 deviceIdx, UINT32 queueIdx)
+	void MeshCore::readData(MeshData& meshData, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
@@ -406,46 +405,47 @@ namespace bs
 		
 		
 	}
 	}
 
 
-	AsyncOp Mesh::writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const SPtr<MeshData>& data, bool discardEntireBuffer)
+	AsyncOp Mesh::writeData(const SPtr<MeshData>& data, bool discardEntireBuffer)
 	{
 	{
 		updateBounds(*data);
 		updateBounds(*data);
-		updateCPUBuffer(subresourceIdx, *data);
+		updateCPUBuffer(0, *data);
 
 
 		data->_lock();
 		data->_lock();
 
 
-		std::function<void(const SPtr<MeshCore>&, UINT32, const SPtr<MeshData>&, bool, AsyncOp&)> func =
-			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const SPtr<MeshData>& _meshData, bool _discardEntireBuffer, AsyncOp& asyncOp)
+		std::function<void(const SPtr<MeshCore>&, const SPtr<MeshData>&, bool, AsyncOp&)> func =
+			[&](const SPtr<MeshCore>& mesh, const SPtr<MeshData>& _meshData, bool _discardEntireBuffer, AsyncOp& asyncOp)
 		{
 		{
-			mesh->writeSubresource(_subresourceIdx, *_meshData, _discardEntireBuffer, false);
+			mesh->writeData(*_meshData, _discardEntireBuffer, false);
 			_meshData->_unlock();
 			_meshData->_unlock();
 			asyncOp._completeOperation();
 			asyncOp._completeOperation();
 
 
 		};
 		};
 
 
-		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+		return gCoreThread().queueReturnCommand(std::bind(func, getCore(),
 			 data, discardEntireBuffer, std::placeholders::_1));
 			 data, discardEntireBuffer, std::placeholders::_1));
 	}
 	}
 
 
-	AsyncOp Mesh::readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const SPtr<MeshData>& data)
+	AsyncOp Mesh::readData(const SPtr<MeshData>& data)
 	{
 	{
 		data->_lock();
 		data->_lock();
 
 
-		std::function<void(const SPtr<MeshCore>&, UINT32, const SPtr<MeshData>&, AsyncOp&)> func =
-			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const SPtr<MeshData>& _meshData, AsyncOp& asyncOp)
+		std::function<void(const SPtr<MeshCore>&, const SPtr<MeshData>&, AsyncOp&)> func =
+			[&](const SPtr<MeshCore>& mesh, const SPtr<MeshData>& _meshData, AsyncOp& asyncOp)
 		{
 		{
-			mesh->readSubresource(_subresourceIdx, *_meshData);
+			mesh->readData(*_meshData);
 			_meshData->_unlock();
 			_meshData->_unlock();
 			asyncOp._completeOperation();
 			asyncOp._completeOperation();
 
 
 		};
 		};
 
 
-		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+		return gCoreThread().queueReturnCommand(std::bind(func, getCore(),
 			data, std::placeholders::_1));
 			data, std::placeholders::_1));
 	}
 	}
 
 
-	SPtr<MeshData> Mesh::allocateSubresourceBuffer(UINT32 subresourceIdx) const
+	SPtr<MeshData> Mesh::allocBuffer() const
 	{
 	{
-		SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(mProperties.mNumVertices, mProperties.mNumIndices, mVertexDesc, mIndexType);
+		SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(mProperties.mNumVertices, mProperties.mNumIndices, 
+			mVertexDesc, mIndexType);
 
 
 		return meshData;
 		return meshData;
 	}
 	}
@@ -524,7 +524,7 @@ namespace bs
 		memcpy(dest, src, pixelData.getSize());
 		memcpy(dest, src, pixelData.getSize());
 	}
 	}
 
 
-	void Mesh::readData(MeshData& dest)
+	void Mesh::readCachedData(MeshData& dest)
 	{
 	{
 		if ((mUsage & MU_CPUCACHED) == 0)
 		if ((mUsage & MU_CPUCACHED) == 0)
 		{
 		{
@@ -552,7 +552,7 @@ namespace bs
 
 
 	void Mesh::createCPUBuffer()
 	void Mesh::createCPUBuffer()
 	{
 	{
-		mCPUData = allocateSubresourceBuffer(0);
+		mCPUData = allocBuffer();
 	}
 	}
 
 
 	HMesh Mesh::dummy()
 	HMesh Mesh::dummy()

+ 0 - 1
Source/BansheeCore/Source/BsMeshManager.cpp

@@ -1,7 +1,6 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsMeshManager.h"
 #include "BsMeshManager.h"
-#include "BsCoreThreadAccessor.h"
 #include "BsCoreApplication.h"
 #include "BsCoreApplication.h"
 #include "BsVector3.h"
 #include "BsVector3.h"
 #include "BsMesh.h"
 #include "BsMesh.h"

+ 44 - 42
Source/BansheeCore/Source/BsRenderAPI.cpp

@@ -17,25 +17,25 @@ using namespace std::placeholders;
 
 
 namespace bs 
 namespace bs 
 {
 {
-	void RenderAPI::setGpuParams(CoreAccessor& accessor, const SPtr<GpuParams>& gpuParams)
+	void RenderAPI::setGpuParams(const SPtr<GpuParams>& gpuParams)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setGpuParams, RenderAPICore::instancePtr(), gpuParams->getCore(), 
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::setGpuParams, RenderAPICore::instancePtr(), gpuParams->getCore(), 
 			nullptr));
 			nullptr));
 	}
 	}
 
 
-	void RenderAPI::setGraphicsPipeline(CoreAccessor& accessor, const SPtr<GraphicsPipelineState>& pipelineState)
+	void RenderAPI::setGraphicsPipeline(const SPtr<GraphicsPipelineState>& pipelineState)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setGraphicsPipeline, RenderAPICore::instancePtr(),
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::setGraphicsPipeline, RenderAPICore::instancePtr(),
 			pipelineState->getCore(), nullptr));
 			pipelineState->getCore(), nullptr));
 	}
 	}
 
 
-	void RenderAPI::setComputePipeline(CoreAccessor& accessor, const SPtr<ComputePipelineState>& pipelineState)
+	void RenderAPI::setComputePipeline(const SPtr<ComputePipelineState>& pipelineState)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setComputePipeline, RenderAPICore::instancePtr(),
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::setComputePipeline, RenderAPICore::instancePtr(),
 							  pipelineState->getCore(), nullptr));
 							  pipelineState->getCore(), nullptr));
 	}
 	}
 
 
-	void RenderAPI::setVertexBuffers(CoreAccessor& accessor, UINT32 index, const Vector<SPtr<VertexBuffer>>& buffers)
+	void RenderAPI::setVertexBuffers(UINT32 index, const Vector<SPtr<VertexBuffer>>& buffers)
 	{
 	{
 		Vector<SPtr<VertexBufferCore>> coreBuffers(buffers.size());
 		Vector<SPtr<VertexBufferCore>> coreBuffers(buffers.size());
 		for (UINT32 i = 0; i < (UINT32)buffers.size(); i++)
 		for (UINT32 i = 0; i < (UINT32)buffers.size(); i++)
@@ -47,95 +47,95 @@ namespace bs
 			rs->setVertexBuffers(idx, (SPtr<VertexBufferCore>*)_buffers.data(), (UINT32)_buffers.size());
 			rs->setVertexBuffers(idx, (SPtr<VertexBufferCore>*)_buffers.data(), (UINT32)_buffers.size());
 		};
 		};
 
 
-		accessor.queueCommand(std::bind(resizeFunc, RenderAPICore::instancePtr(), index, coreBuffers));
+		gCoreThread().queueCommand(std::bind(resizeFunc, RenderAPICore::instancePtr(), index, coreBuffers));
 	}
 	}
 
 
-	void RenderAPI::setIndexBuffer(CoreAccessor& accessor, const SPtr<IndexBuffer>& buffer)
+	void RenderAPI::setIndexBuffer(const SPtr<IndexBuffer>& buffer)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setIndexBuffer, RenderAPICore::instancePtr(), buffer->getCore(), 
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::setIndexBuffer, RenderAPICore::instancePtr(), buffer->getCore(), 
 			nullptr));
 			nullptr));
 	}
 	}
 
 
-	void RenderAPI::setVertexDeclaration(CoreAccessor& accessor, const SPtr<VertexDeclaration>& vertexDeclaration)
+	void RenderAPI::setVertexDeclaration(const SPtr<VertexDeclaration>& vertexDeclaration)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setVertexDeclaration, RenderAPICore::instancePtr(), 
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::setVertexDeclaration, RenderAPICore::instancePtr(), 
 			vertexDeclaration->getCore(), nullptr));
 			vertexDeclaration->getCore(), nullptr));
 	}
 	}
 
 
-	void RenderAPI::setViewport(CoreAccessor& accessor, const Rect2& vp)
+	void RenderAPI::setViewport(const Rect2& vp)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setViewport, RenderAPICore::instancePtr(), vp, nullptr));
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::setViewport, RenderAPICore::instancePtr(), vp, nullptr));
 	}
 	}
 
 
-	void RenderAPI::setStencilRef(CoreAccessor& accessor, UINT32 value)
+	void RenderAPI::setStencilRef(UINT32 value)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setStencilRef, RenderAPICore::instancePtr(), value, nullptr));
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::setStencilRef, RenderAPICore::instancePtr(), value, nullptr));
 	}
 	}
 
 
-	void RenderAPI::setDrawOperation(CoreAccessor& accessor, DrawOperationType op)
+	void RenderAPI::setDrawOperation(DrawOperationType op)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setDrawOperation, RenderAPICore::instancePtr(), op, 
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::setDrawOperation, RenderAPICore::instancePtr(), op, 
 			nullptr));
 			nullptr));
 	}
 	}
 
 
-	void RenderAPI::setScissorRect(CoreAccessor& accessor, UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
+	void RenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setScissorRect, RenderAPICore::instancePtr(), left, top, right, bottom, 
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::setScissorRect, RenderAPICore::instancePtr(), left, top, right, bottom, 
 			nullptr));
 			nullptr));
 	}
 	}
 
 
-	void RenderAPI::setRenderTarget(CoreAccessor& accessor, const SPtr<RenderTarget>& target, bool readOnlyDepthStencil,
+	void RenderAPI::setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil,
 									bool preserveContents)
 									bool preserveContents)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setRenderTarget, 
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::setRenderTarget, 
 			RenderAPICore::instancePtr(), target->getCore(), readOnlyDepthStencil, preserveContents, nullptr));
 			RenderAPICore::instancePtr(), target->getCore(), readOnlyDepthStencil, preserveContents, nullptr));
 	}
 	}
 
 
-	void RenderAPI::beginRender(CoreAccessor& accessor)
+	void RenderAPI::beginRender()
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::beginFrame, RenderAPICore::instancePtr(), nullptr));
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::beginFrame, RenderAPICore::instancePtr(), nullptr));
 	}
 	}
 
 
-	void RenderAPI::endRender(CoreAccessor& accessor)
+	void RenderAPI::endRender()
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::endFrame, RenderAPICore::instancePtr(), nullptr));
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::endFrame, RenderAPICore::instancePtr(), nullptr));
 	}
 	}
 
 
-	void RenderAPI::clearRenderTarget(CoreAccessor& accessor, UINT32 buffers, const Color& color, float depth, 
+	void RenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, 
 		UINT16 stencil, UINT8 targetMask)
 		UINT16 stencil, UINT8 targetMask)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::clearRenderTarget, RenderAPICore::instancePtr(), buffers, color,
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::clearRenderTarget, RenderAPICore::instancePtr(), buffers, color,
 			depth, stencil, targetMask, nullptr));
 			depth, stencil, targetMask, nullptr));
 	}
 	}
 
 
-	void RenderAPI::clearViewport(CoreAccessor& accessor, UINT32 buffers, const Color& color, float depth, UINT16 stencil, 
+	void RenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil, 
 		UINT8 targetMask)
 		UINT8 targetMask)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::clearViewport, RenderAPICore::instancePtr(), buffers, color, depth,
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::clearViewport, RenderAPICore::instancePtr(), buffers, color, depth,
 			stencil, targetMask, nullptr));
 			stencil, targetMask, nullptr));
 	}
 	}
 
 
-	void RenderAPI::swapBuffers(CoreAccessor& accessor, const SPtr<RenderTarget>& target)
+	void RenderAPI::swapBuffers(const SPtr<RenderTarget>& target)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::swapBuffers, RenderAPICore::instancePtr(), target->getCore(), 1));
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::swapBuffers, RenderAPICore::instancePtr(), target->getCore(), 1));
 	}
 	}
 
 
-	void RenderAPI::draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount)
+	void RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::draw, RenderAPICore::instancePtr(), vertexOffset, 
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::draw, RenderAPICore::instancePtr(), vertexOffset, 
 			vertexCount, instanceCount, nullptr));
 			vertexCount, instanceCount, nullptr));
 	}
 	}
 
 
-	void RenderAPI::drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, 
+	void RenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, 
 		UINT32 vertexCount, UINT32 instanceCount)
 		UINT32 vertexCount, UINT32 instanceCount)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::drawIndexed, RenderAPICore::instancePtr(), startIndex, indexCount, 
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::drawIndexed, RenderAPICore::instancePtr(), startIndex, indexCount, 
 			vertexOffset, vertexCount, instanceCount, nullptr));
 			vertexOffset, vertexCount, instanceCount, nullptr));
 	}
 	}
 
 
-	void RenderAPI::dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
+	void RenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::dispatchCompute, RenderAPICore::instancePtr(), numGroupsX, 
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::dispatchCompute, RenderAPICore::instancePtr(), numGroupsX, 
 			numGroupsY, numGroupsZ, nullptr));
 			numGroupsY, numGroupsZ, nullptr));
 	}
 	}
 
 
@@ -169,12 +169,14 @@ namespace bs
 
 
 	SPtr<RenderWindow> RenderAPICore::initialize(const RENDER_WINDOW_DESC& primaryWindowDesc)
 	SPtr<RenderWindow> RenderAPICore::initialize(const RENDER_WINDOW_DESC& primaryWindowDesc)
 	{
 	{
-		gCoreThread().queueCommand(std::bind((void(RenderAPICore::*)())&RenderAPICore::initialize, this), true);
+		gCoreThread().queueCommand(std::bind((void(RenderAPICore::*)())&RenderAPICore::initialize, this), 
+			CTQF_InternalQueue | CTQF_BlockUntilComplete);
 
 
 		RENDER_WINDOW_DESC windowDesc = primaryWindowDesc;
 		RENDER_WINDOW_DESC windowDesc = primaryWindowDesc;
 		SPtr<RenderWindow> renderWindow = RenderWindow::create(windowDesc, nullptr);
 		SPtr<RenderWindow> renderWindow = RenderWindow::create(windowDesc, nullptr);
 
 
-		gCoreThread().queueCommand(std::bind(&RenderAPICore::initializeWithWindow, this, renderWindow->getCore()), true);
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::initializeWithWindow, this, renderWindow->getCore()), 
+			CTQF_InternalQueue | CTQF_BlockUntilComplete);
 
 
 		return renderWindow;
 		return renderWindow;
 	}
 	}
@@ -191,8 +193,8 @@ namespace bs
 
 
 	void RenderAPICore::destroy()
 	void RenderAPICore::destroy()
 	{
 	{
-		gCoreAccessor().queueCommand(std::bind(&RenderAPICore::destroyCore, this));
-		gCoreThread().submitAccessors(true);
+		gCoreThread().queueCommand(std::bind(&RenderAPICore::destroyCore, this));
+		gCoreThread().submitAll(true);
 	}
 	}
 
 
 	void RenderAPICore::destroyCore()
 	void RenderAPICore::destroyCore()

+ 2 - 2
Source/BansheeCore/Source/BsRenderTarget.cpp

@@ -37,7 +37,7 @@ namespace bs
 		markCoreClean();
 		markCoreClean();
 	}
 	}
 
 
-	void RenderTarget::setPriority(CoreAccessor& accessor, INT32 priority)
+	void RenderTarget::setPriority(INT32 priority)
 	{
 	{
 		std::function<void(SPtr<RenderTargetCore>, INT32)> windowedFunc =
 		std::function<void(SPtr<RenderTargetCore>, INT32)> windowedFunc =
 			[](SPtr<RenderTargetCore> renderTarget, INT32 priority)
 			[](SPtr<RenderTargetCore> renderTarget, INT32 priority)
@@ -45,7 +45,7 @@ namespace bs
 			renderTarget->setPriority(priority);
 			renderTarget->setPriority(priority);
 		};
 		};
 
 
-		accessor.queueCommand(std::bind(windowedFunc, getCore(), priority));
+		gCoreThread().queueCommand(std::bind(windowedFunc, getCore(), priority));
 	}
 	}
 
 
 	SPtr<RenderTargetCore> RenderTarget::getCore() const
 	SPtr<RenderTargetCore> RenderTarget::getCore() const

+ 20 - 21
Source/BansheeCore/Source/BsRenderWindow.cpp

@@ -179,7 +179,7 @@ namespace bs
 
 
 	}
 	}
 
 
-	void RenderWindow::resize(CoreAccessor& accessor, UINT32 width, UINT32 height)
+	void RenderWindow::resize(UINT32 width, UINT32 height)
 	{
 	{
 		std::function<void(SPtr<RenderWindowCore>, UINT32, UINT32)> resizeFunc =
 		std::function<void(SPtr<RenderWindowCore>, UINT32, UINT32)> resizeFunc =
 			[](SPtr<RenderWindowCore> renderWindow, UINT32 width, UINT32 height)
 			[](SPtr<RenderWindowCore> renderWindow, UINT32 width, UINT32 height)
@@ -199,10 +199,10 @@ namespace bs
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
 		onResized();
 		onResized();
 
 
-		accessor.queueCommand(std::bind(resizeFunc, getCore(), width, height));
+		gCoreThread().queueCommand(std::bind(resizeFunc, getCore(), width, height));
 	}
 	}
 
 
-	void RenderWindow::move(CoreAccessor& accessor, INT32 left, INT32 top)
+	void RenderWindow::move(INT32 left, INT32 top)
 	{
 	{
 		std::function<void(SPtr<RenderWindowCore>, INT32, INT32)> moveFunc =
 		std::function<void(SPtr<RenderWindowCore>, INT32, INT32)> moveFunc =
 			[](SPtr<RenderWindowCore> renderWindow, INT32 left, INT32 top)
 			[](SPtr<RenderWindowCore> renderWindow, INT32 left, INT32 top)
@@ -220,10 +220,10 @@ namespace bs
 		}
 		}
 
 
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
-		accessor.queueCommand(std::bind(moveFunc, getCore(), left, top));
+		gCoreThread().queueCommand(std::bind(moveFunc, getCore(), left, top));
 	}
 	}
 
 
-	void RenderWindow::hide(CoreAccessor& accessor)
+	void RenderWindow::hide()
 	{
 	{
 		std::function<void(SPtr<RenderWindowCore>)> hideFunc =
 		std::function<void(SPtr<RenderWindowCore>)> hideFunc =
 			[](SPtr<RenderWindowCore> renderWindow)
 			[](SPtr<RenderWindowCore> renderWindow)
@@ -238,10 +238,10 @@ namespace bs
 		}
 		}
 
 
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
-		accessor.queueCommand(std::bind(hideFunc, getCore()));
+		gCoreThread().queueCommand(std::bind(hideFunc, getCore()));
 	}
 	}
 
 
-	void RenderWindow::show(CoreAccessor& accessor)
+	void RenderWindow::show()
 	{
 	{
 		std::function<void(SPtr<RenderWindowCore>)> showFunc =
 		std::function<void(SPtr<RenderWindowCore>)> showFunc =
 			[](SPtr<RenderWindowCore> renderWindow)
 			[](SPtr<RenderWindowCore> renderWindow)
@@ -256,10 +256,10 @@ namespace bs
 		}
 		}
 
 
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
-		accessor.queueCommand(std::bind(showFunc, getCore()));
+		gCoreThread().queueCommand(std::bind(showFunc, getCore()));
 	}
 	}
 
 
-	void RenderWindow::minimize(CoreAccessor& accessor)
+	void RenderWindow::minimize()
 	{
 	{
 		std::function<void(SPtr<RenderWindowCore>)> minimizeFunc =
 		std::function<void(SPtr<RenderWindowCore>)> minimizeFunc =
 			[](SPtr<RenderWindowCore> renderWindow)
 			[](SPtr<RenderWindowCore> renderWindow)
@@ -274,10 +274,10 @@ namespace bs
 		}
 		}
 
 
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
-		accessor.queueCommand(std::bind(minimizeFunc, getCore()));
+		gCoreThread().queueCommand(std::bind(minimizeFunc, getCore()));
 	}
 	}
 
 
-	void RenderWindow::maximize(CoreAccessor& accessor)
+	void RenderWindow::maximize()
 	{
 	{
 		std::function<void(SPtr<RenderWindowCore>)> maximizeFunc =
 		std::function<void(SPtr<RenderWindowCore>)> maximizeFunc =
 			[](SPtr<RenderWindowCore> renderWindow)
 			[](SPtr<RenderWindowCore> renderWindow)
@@ -292,10 +292,10 @@ namespace bs
 		}
 		}
 
 
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
-		accessor.queueCommand(std::bind(maximizeFunc, getCore()));
+		gCoreThread().queueCommand(std::bind(maximizeFunc, getCore()));
 	}
 	}
 
 
-	void RenderWindow::restore(CoreAccessor& accessor)
+	void RenderWindow::restore()
 	{
 	{
 		std::function<void(SPtr<RenderWindowCore>)> restoreFunc =
 		std::function<void(SPtr<RenderWindowCore>)> restoreFunc =
 			[](SPtr<RenderWindowCore> renderWindow)
 			[](SPtr<RenderWindowCore> renderWindow)
@@ -310,11 +310,10 @@ namespace bs
 		}
 		}
 
 
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
 		RenderWindowCoreManager::instance().notifySyncDataDirty(getCore().get());
-		accessor.queueCommand(std::bind(restoreFunc, getCore()));
+		gCoreThread().queueCommand(std::bind(restoreFunc, getCore()));
 	}
 	}
 
 
-	void RenderWindow::setFullscreen(CoreAccessor& accessor, UINT32 width, UINT32 height,
-		float refreshRate, UINT32 monitorIdx)
+	void RenderWindow::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
 	{
 	{
 		std::function<void(SPtr<RenderWindowCore>, UINT32, UINT32, float, UINT32)> fullscreenFunc =
 		std::function<void(SPtr<RenderWindowCore>, UINT32, UINT32, float, UINT32)> fullscreenFunc =
 			[](SPtr<RenderWindowCore> renderWindow, UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
 			[](SPtr<RenderWindowCore> renderWindow, UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
@@ -322,10 +321,10 @@ namespace bs
 			renderWindow->setFullscreen(width, height, refreshRate, monitorIdx);
 			renderWindow->setFullscreen(width, height, refreshRate, monitorIdx);
 		};
 		};
 
 
-		accessor.queueCommand(std::bind(fullscreenFunc, getCore(), width, height, refreshRate, monitorIdx));
+		gCoreThread().queueCommand(std::bind(fullscreenFunc, getCore(), width, height, refreshRate, monitorIdx));
 	}
 	}
 
 
-	void RenderWindow::setFullscreen(CoreAccessor& accessor, const VideoMode& mode)
+	void RenderWindow::setFullscreen(const VideoMode& mode)
 	{
 	{
 		std::function<void(SPtr<RenderWindowCore>, const VideoMode&)> fullscreenFunc =
 		std::function<void(SPtr<RenderWindowCore>, const VideoMode&)> fullscreenFunc =
 			[](SPtr<RenderWindowCore> renderWindow, const VideoMode& mode)
 			[](SPtr<RenderWindowCore> renderWindow, const VideoMode& mode)
@@ -333,10 +332,10 @@ namespace bs
 			renderWindow->setFullscreen(mode);
 			renderWindow->setFullscreen(mode);
 		};
 		};
 
 
-		accessor.queueCommand(std::bind(fullscreenFunc, getCore(), std::cref(mode)));
+		gCoreThread().queueCommand(std::bind(fullscreenFunc, getCore(), std::cref(mode)));
 	}
 	}
 
 
-	void RenderWindow::setWindowed(CoreAccessor& accessor, UINT32 width, UINT32 height)
+	void RenderWindow::setWindowed(UINT32 width, UINT32 height)
 	{
 	{
 		std::function<void(SPtr<RenderWindowCore>, UINT32, UINT32)> windowedFunc =
 		std::function<void(SPtr<RenderWindowCore>, UINT32, UINT32)> windowedFunc =
 			[](SPtr<RenderWindowCore> renderWindow, UINT32 width, UINT32 height)
 			[](SPtr<RenderWindowCore> renderWindow, UINT32 width, UINT32 height)
@@ -344,7 +343,7 @@ namespace bs
 			renderWindow->setWindowed(width, height);
 			renderWindow->setWindowed(width, height);
 		};
 		};
 
 
-		accessor.queueCommand(std::bind(windowedFunc, getCore(), width, height));
+		gCoreThread().queueCommand(std::bind(windowedFunc, getCore(), width, height));
 	}
 	}
 
 
 	SPtr<RenderWindowCore> RenderWindow::getCore() const
 	SPtr<RenderWindowCore> RenderWindow::getCore() const

+ 31 - 49
Source/BansheeCore/Source/BsTexture.cpp

@@ -46,19 +46,15 @@ namespace bs
 		return face * (getNumMipmaps() + 1) + mip;
 		return face * (getNumMipmaps() + 1) + mip;
 	}
 	}
 
 
-	SPtr<PixelData> TextureProperties::allocateSubresourceBuffer(UINT32 subresourceIdx) const
+	SPtr<PixelData> TextureProperties::allocBuffer(UINT32 face, UINT32 mipLevel) const
 	{
 	{
-		UINT32 face = 0;
-		UINT32 mip = 0;
-		mapFromSubresourceIdx(subresourceIdx, face, mip);
-
 		UINT32 width = getWidth();
 		UINT32 width = getWidth();
 		UINT32 height = getHeight();
 		UINT32 height = getHeight();
 		UINT32 depth = getDepth();
 		UINT32 depth = getDepth();
 
 
 		UINT32 totalSize = PixelUtil::getMemorySize(width, height, depth, getFormat());
 		UINT32 totalSize = PixelUtil::getMemorySize(width, height, depth, getFormat());
 
 
-		for (UINT32 j = 0; j < mip; j++)
+		for (UINT32 j = 0; j < mipLevel; j++)
 		{
 		{
 			totalSize = PixelUtil::getMemorySize(width, height, depth, getFormat());
 			totalSize = PixelUtil::getMemorySize(width, height, depth, getFormat());
 
 
@@ -86,13 +82,13 @@ namespace bs
 	{
 	{
 		if (mInitData != nullptr)
 		if (mInitData != nullptr)
 		{
 		{
-			writeSubresource(0, *mInitData, true);
+			writeData(*mInitData, 0, 0, true);
 			mInitData->_unlock();
 			mInitData->_unlock();
 			mInitData = nullptr;
 			mInitData = nullptr;
 		}
 		}
 	}
 	}
 
 
-	void TextureCore::writeSubresource(UINT32 subresourceIdx, const PixelData& pixelData, bool discardEntireBuffer, 
+	void TextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardEntireBuffer,
 		UINT32 queueIdx)
 		UINT32 queueIdx)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
@@ -106,14 +102,10 @@ namespace bs
 			}
 			}
 		}
 		}
 
 
-		UINT32 face = 0;
-		UINT32 mip = 0;
-		mProperties.mapFromSubresourceIdx(subresourceIdx, face, mip);
-
-		writeData(pixelData, mip, face, discardEntireBuffer, queueIdx);
+		writeDataImpl(src, face, mipLevel, discardEntireBuffer, queueIdx);
 	}
 	}
 
 
-	void TextureCore::readSubresource(UINT32 subresourceIdx, PixelData& data, UINT32 deviceIdx, UINT32 queueIdx)
+	void TextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
@@ -123,15 +115,11 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		UINT32 face = 0;
-		UINT32 mip = 0;
-		mProperties.mapFromSubresourceIdx(subresourceIdx, face, mip);
-
-		PixelData& pixelData = static_cast<PixelData&>(data);
+		PixelData& pixelData = static_cast<PixelData&>(dest);
 
 
 		UINT32 mipWidth, mipHeight, mipDepth;
 		UINT32 mipWidth, mipHeight, mipDepth;
 		PixelUtil::getSizeForMipLevel(mProperties.getWidth(), mProperties.getHeight(), mProperties.getDepth(),
 		PixelUtil::getSizeForMipLevel(mProperties.getWidth(), mProperties.getHeight(), mProperties.getDepth(),
-			mip, mipWidth, mipHeight, mipDepth);
+			mipLevel, mipWidth, mipHeight, mipDepth);
 
 
 		if (pixelData.getWidth() != mipWidth || pixelData.getHeight() != mipHeight ||
 		if (pixelData.getWidth() != mipWidth || pixelData.getHeight() != mipHeight ||
 			pixelData.getDepth() != mipDepth || pixelData.getFormat() != mProperties.getFormat())
 			pixelData.getDepth() != mipDepth || pixelData.getFormat() != mProperties.getFormat())
@@ -140,7 +128,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		readData(pixelData, mip, face, deviceIdx, queueIdx);
+		readDataImpl(pixelData, face, mipLevel , deviceIdx, queueIdx);
 	}
 	}
 
 
 	PixelData TextureCore::lock(GpuLockOptions options, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
 	PixelData TextureCore::lock(GpuLockOptions options, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
@@ -169,8 +157,8 @@ namespace bs
 		unlockImpl();
 		unlockImpl();
 	}
 	}
 
 
-	void TextureCore::copy(UINT32 srcSubresourceIdx, UINT32 destSubresourceIdx, const SPtr<TextureCore>& target,
-						   UINT32 queueIdx)
+	void TextureCore::copy(const SPtr<TextureCore>& target, UINT32 srcFace, UINT32 srcMipLevel, UINT32 dstFace,
+						   UINT32 dstMipLevel, UINT32 queueIdx)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
@@ -192,16 +180,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		UINT32 srcFace = 0;
-		UINT32 srcMipLevel = 0;
-
-		UINT32 destFace = 0;
-		UINT32 destMipLevel = 0;
-
-		mProperties.mapFromSubresourceIdx(srcSubresourceIdx, srcFace, srcMipLevel);
-		target->mProperties.mapFromSubresourceIdx(destSubresourceIdx, destFace, destMipLevel);
-
-		if (destFace >= mProperties.getNumFaces())
+		if (dstFace >= mProperties.getNumFaces())
 		{
 		{
 			LOGERR("Invalid destination face index");
 			LOGERR("Invalid destination face index");
 			return;
 			return;
@@ -219,7 +198,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		if (destMipLevel > target->mProperties.getNumMipmaps())
+		if (dstMipLevel > target->mProperties.getNumMipmaps())
 		{
 		{
 			LOGERR("Destination mip level out of range. Valid range is [0, " + toString(target->mProperties.getNumMipmaps()) + "]");
 			LOGERR("Destination mip level out of range. Valid range is [0, " + toString(target->mProperties.getNumMipmaps()) + "]");
 			return;
 			return;
@@ -229,9 +208,9 @@ namespace bs
 		UINT32 srcMipHeight = mProperties.getHeight() >> srcMipLevel;
 		UINT32 srcMipHeight = mProperties.getHeight() >> srcMipLevel;
 		UINT32 srcMipDepth = mProperties.getDepth() >> srcMipLevel;
 		UINT32 srcMipDepth = mProperties.getDepth() >> srcMipLevel;
 
 
-		UINT32 dstMipWidth = target->mProperties.getWidth() >> destMipLevel;
-		UINT32 dstMipHeight = target->mProperties.getHeight() >> destMipLevel;
-		UINT32 dstMipDepth = target->mProperties.getDepth() >> destMipLevel;
+		UINT32 dstMipWidth = target->mProperties.getWidth() >> dstMipLevel;
+		UINT32 dstMipHeight = target->mProperties.getHeight() >> dstMipLevel;
+		UINT32 dstMipDepth = target->mProperties.getDepth() >> dstMipLevel;
 
 
 		if (srcMipWidth != dstMipWidth || srcMipHeight != dstMipHeight || srcMipDepth != dstMipDepth)
 		if (srcMipWidth != dstMipWidth || srcMipHeight != dstMipHeight || srcMipDepth != dstMipDepth)
 		{
 		{
@@ -239,7 +218,7 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		copyImpl(srcFace, srcMipLevel, destFace, destMipLevel, target, queueIdx);
+		copyImpl(srcFace, srcMipLevel, dstFace, dstMipLevel, target, queueIdx);
 	}
 	}
 
 
 	/************************************************************************/
 	/************************************************************************/
@@ -390,39 +369,42 @@ namespace bs
 		return coreObj;
 		return coreObj;
 	}
 	}
 
 
-	AsyncOp Texture::writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const SPtr<PixelData>& data, bool discardEntireBuffer)
+	AsyncOp Texture::writeData(const SPtr<PixelData>& data, UINT32 face, UINT32 mipLevel, bool discardEntireBuffer)
 	{
 	{
+		UINT32 subresourceIdx = mProperties.mapToSubresourceIdx(face, mipLevel);
 		updateCPUBuffers(subresourceIdx, *data);
 		updateCPUBuffers(subresourceIdx, *data);
 
 
 		data->_lock();
 		data->_lock();
 
 
-		std::function<void(const SPtr<TextureCore>&, UINT32, const SPtr<PixelData>&, bool, AsyncOp&)> func =
-			[&](const SPtr<TextureCore>& texture, UINT32 _subresourceIdx, const SPtr<PixelData>& _pixData, bool _discardEntireBuffer, AsyncOp& asyncOp)
+		std::function<void(const SPtr<TextureCore>&, UINT32, UINT32, const SPtr<PixelData>&, bool, AsyncOp&)> func =
+			[&](const SPtr<TextureCore>& texture, UINT32 _face, UINT32 _mipLevel, const SPtr<PixelData>& _pixData, 
+				bool _discardEntireBuffer, AsyncOp& asyncOp)
 		{
 		{
-			texture->writeSubresource(_subresourceIdx, *_pixData, _discardEntireBuffer);
+			texture->writeData(*_pixData, _face, _mipLevel, _discardEntireBuffer);
 			_pixData->_unlock();
 			_pixData->_unlock();
 			asyncOp._completeOperation();
 			asyncOp._completeOperation();
 
 
 		};
 		};
 
 
-		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+		return gCoreThread().queueReturnCommand(std::bind(func, getCore(), face, mipLevel,
 			data, discardEntireBuffer, std::placeholders::_1));
 			data, discardEntireBuffer, std::placeholders::_1));
 	}
 	}
 
 
-	AsyncOp Texture::readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const SPtr<PixelData>& data)
+	AsyncOp Texture::readData(const SPtr<PixelData>& data, UINT32 face, UINT32 mipLevel)
 	{
 	{
 		data->_lock();
 		data->_lock();
 
 
-		std::function<void(const SPtr<TextureCore>&, UINT32, const SPtr<PixelData>&, AsyncOp&)> func =
-			[&](const SPtr<TextureCore>& texture, UINT32 _subresourceIdx, const SPtr<PixelData>& _pixData, AsyncOp& asyncOp)
+		std::function<void(const SPtr<TextureCore>&, UINT32, UINT32, const SPtr<PixelData>&, AsyncOp&)> func =
+			[&](const SPtr<TextureCore>& texture, UINT32 _face, UINT32 _mipLevel, const SPtr<PixelData>& _pixData, 
+				AsyncOp& asyncOp)
 		{
 		{
-			texture->readSubresource(_subresourceIdx, *_pixData);
+			texture->readData(*_pixData, _face, _mipLevel);
 			_pixData->_unlock();
 			_pixData->_unlock();
 			asyncOp._completeOperation();
 			asyncOp._completeOperation();
 
 
 		};
 		};
 
 
-		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+		return gCoreThread().queueReturnCommand(std::bind(func, getCore(), face, mipLevel,
 			data, std::placeholders::_1));
 			data, std::placeholders::_1));
 	}
 	}
 
 
@@ -467,7 +449,7 @@ namespace bs
 		memcpy(dest, src, pixelData.getSize());
 		memcpy(dest, src, pixelData.getSize());
 	}
 	}
 
 
-	void Texture::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
+	void Texture::readCachedData(PixelData& dest, UINT32 face, UINT32 mipLevel)
 	{
 	{
 		if ((mProperties.getUsage() & TU_CPUCACHED) == 0)
 		if ((mProperties.getUsage() & TU_CPUCACHED) == 0)
 		{
 		{

+ 1 - 1
Source/BansheeCore/Source/BsViewport.cpp

@@ -10,7 +10,7 @@
 
 
 namespace bs 
 namespace bs 
 {
 {
-	const Color ViewportBase::DEFAULT_CLEAR_COLOR = Color(83.0f / 255.0f, 83.0f / 255.0f, 83.0f / 255.0f);
+	const Color ViewportBase::DEFAULT_CLEAR_COLOR = Color(0.0f, 0.3685f, 0.7969f);
 
 
 	ViewportBase::ViewportBase(float x, float y, float width, float height)
 	ViewportBase::ViewportBase(float x, float y, float width, float height)
 		: mNormArea(x, y, width, height), mRequiresColorClear(true), mRequiresDepthClear(true)
 		: mNormArea(x, y, width, height), mRequiresColorClear(true), mRequiresDepthClear(true)

+ 2 - 1
Source/BansheeCore/Source/Win32/BsWin32BrowseDialogs.cpp

@@ -170,7 +170,8 @@ namespace bs
 		Vector<Path>& paths)
 		Vector<Path>& paths)
 	{
 	{
 		AsyncOp returnValue = gCoreThread().queueReturnCommand(std::bind(&openBrowseDialogCore, type, 
 		AsyncOp returnValue = gCoreThread().queueReturnCommand(std::bind(&openBrowseDialogCore, type, 
-			std::cref(defaultPath), std::cref(filterList), std::ref(paths), _1), true);
+			std::cref(defaultPath), std::cref(filterList), std::ref(paths), _1), 
+			CTQF_InternalQueue | CTQF_BlockUntilComplete);
 
 
 		return returnValue.getReturnValue<bool>();
 		return returnValue.getReturnValue<bool>();
 	}
 	}

+ 2 - 2
Source/BansheeD3D11RenderAPI/Include/BsD3D11Texture.h

@@ -52,11 +52,11 @@ namespace bs
 					  const SPtr<TextureCore>& target, UINT32 queueIdx = 0) override;
 					  const SPtr<TextureCore>& target, UINT32 queueIdx = 0) override;
 
 
 		/** @copydoc TextureCore::readData */
 		/** @copydoc TextureCore::readData */
-		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
+		void readDataImpl(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
 					  UINT32 queueIdx = 0) override;
 					  UINT32 queueIdx = 0) override;
 
 
 		/** @copydoc TextureCore::writeData */
 		/** @copydoc TextureCore::writeData */
-		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
+		void writeDataImpl(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
 					   UINT32 queueIdx = 0) override;
 					   UINT32 queueIdx = 0) override;
 
 
 		/**	Creates a blank DX11 1D texture object. */
 		/**	Creates a blank DX11 1D texture object. */

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

@@ -155,7 +155,7 @@ namespace bs
 		}
 		}
 	}
 	}
 
 
-	void D3D11TextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
+	void D3D11TextureCore::readDataImpl(PixelData& dest, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 	{
 		if (mProperties.getNumSamples() > 1)
 		if (mProperties.getNumSamples() > 1)
 		{
 		{
@@ -178,7 +178,7 @@ namespace bs
 		unlock();
 		unlock();
 	}
 	}
 
 
-	void D3D11TextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer,
+	void D3D11TextureCore::writeDataImpl(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer,
 									 UINT32 queueIdx)
 									 UINT32 queueIdx)
 	{
 	{
 		PixelFormat format = mProperties.getFormat();
 		PixelFormat format = mProperties.getFormat();

+ 3 - 3
Source/BansheeEditor/Source/BsDockManager.cpp

@@ -465,7 +465,7 @@ namespace bs
 		HMaterial dropOverlayMat = BuiltinEditorResources::instance().createDockDropOverlayMaterial();
 		HMaterial dropOverlayMat = BuiltinEditorResources::instance().createDockDropOverlayMaterial();
 
 
 		mCore.store(bs_new<DockOverlayRenderer>(), std::memory_order_release);
 		mCore.store(bs_new<DockOverlayRenderer>(), std::memory_order_release);
-		gCoreAccessor().queueCommand(std::bind(&DockManager::initializeOverlayRenderer, 
+		gCoreThread().queueCommand(std::bind(&DockManager::initializeOverlayRenderer, 
 			this, dropOverlayMat->getCore()));
 			this, dropOverlayMat->getCore()));
 	}
 	}
 
 
@@ -476,7 +476,7 @@ namespace bs
 		bs_deleteN(mLeftDropPolygon, 4);
 		bs_deleteN(mLeftDropPolygon, 4);
 		bs_deleteN(mRightDropPolygon, 4);
 		bs_deleteN(mRightDropPolygon, 4);
 
 
-		gCoreAccessor().queueCommand(std::bind(&DockManager::destroyOverlayRenderer,
+		gCoreThread().queueCommand(std::bind(&DockManager::destroyOverlayRenderer,
 			this, mCore.load(std::memory_order_relaxed)));
 			this, mCore.load(std::memory_order_relaxed)));
 	}
 	}
 
 
@@ -508,7 +508,7 @@ namespace bs
 		HCamera camera = mParentWindow->getGUICamera();
 		HCamera camera = mParentWindow->getGUICamera();
 
 
 		DockOverlayRenderer* core = mCore.load(std::memory_order_relaxed);
 		DockOverlayRenderer* core = mCore.load(std::memory_order_relaxed);
-		gCoreAccessor().queueCommand(std::bind(&DockOverlayRenderer::updateData, core, camera->_getCamera()->getCore(),
+		gCoreThread().queueCommand(std::bind(&DockOverlayRenderer::updateData, core, camera->_getCamera()->getCore(),
 			mDropOverlayMesh->getCore(), mShowOverlay, mHighlightedDropLoc));
 			mDropOverlayMesh->getCore(), mShowOverlay, mHighlightedDropLoc));
 	}
 	}
 
 

+ 1 - 1
Source/BansheeEditor/Source/BsEditorWidgetManager.cpp

@@ -290,7 +290,7 @@ namespace bs
 		}
 		}
 
 
 		if (layout->getIsMainWindowMaximized())
 		if (layout->getIsMainWindowMaximized())
-			mainWindow->getRenderWindow()->maximize(gCoreAccessor());
+			mainWindow->getRenderWindow()->maximize();
 	}
 	}
 
 
 	void EditorWidgetManager::onFocusGained(const RenderWindow& window)
 	void EditorWidgetManager::onFocusGained(const RenderWindow& window)

+ 2 - 2
Source/BansheeEditor/Source/BsEditorWindow.cpp

@@ -77,9 +77,9 @@ namespace bs
 	void EditorWindow::maximizeClicked()
 	void EditorWindow::maximizeClicked()
 	{
 	{
 		if (mRenderWindow->getProperties().isMaximized())
 		if (mRenderWindow->getProperties().isMaximized())
-			mRenderWindow->restore(gCoreAccessor());
+			mRenderWindow->restore();
 		else
 		else
-			mRenderWindow->maximize(gCoreAccessor());
+			mRenderWindow->maximize();
 	}
 	}
 
 
 	void EditorWindow::closeWindowDelayed()
 	void EditorWindow::closeWindowDelayed()

+ 3 - 3
Source/BansheeEditor/Source/BsEditorWindowBase.cpp

@@ -76,7 +76,7 @@ namespace bs
 
 
 	void EditorWindowBase::hide()
 	void EditorWindowBase::hide()
 	{
 	{
-		mRenderWindow->hide(gCoreAccessor());
+		mRenderWindow->hide();
 	}
 	}
 
 
 	void EditorWindowBase::construct(const SPtr<RenderWindow>& renderWindow)
 	void EditorWindowBase::construct(const SPtr<RenderWindow>& renderWindow)
@@ -103,12 +103,12 @@ namespace bs
 
 
 	void EditorWindowBase::setPosition(INT32 x, INT32 y)
 	void EditorWindowBase::setPosition(INT32 x, INT32 y)
 	{
 	{
-		mRenderWindow->move(gCoreAccessor(), x, y);
+		mRenderWindow->move(x, y);
 	}
 	}
 
 
 	void EditorWindowBase::setSize(UINT32 width, UINT32 height)
 	void EditorWindowBase::setSize(UINT32 width, UINT32 height)
 	{
 	{
-		mRenderWindow->resize(gCoreAccessor(), width, height);
+		mRenderWindow->resize(width, height);
 	}
 	}
 
 
 	INT32 EditorWindowBase::getLeft() const
 	INT32 EditorWindowBase::getLeft() const

+ 3 - 3
Source/BansheeEditor/Source/BsGUIMenuBar.cpp

@@ -525,15 +525,15 @@ namespace bs
 
 
 	void GUIMenuBar::onMinimizeClicked()
 	void GUIMenuBar::onMinimizeClicked()
 	{
 	{
-		mParentWindow->minimize(gCoreAccessor());
+		mParentWindow->minimize();
 	}
 	}
 
 
 	void GUIMenuBar::onMaximizeClicked()
 	void GUIMenuBar::onMaximizeClicked()
 	{
 	{
 		if(mParentWindow->getProperties().isMaximized())
 		if(mParentWindow->getProperties().isMaximized())
-			mParentWindow->restore(gCoreAccessor());
+			mParentWindow->restore();
 		else
 		else
-			mParentWindow->maximize(gCoreAccessor());
+			mParentWindow->maximize();
 	}
 	}
 
 
 	void GUIMenuBar::onCloseClicked()
 	void GUIMenuBar::onCloseClicked()

+ 7 - 7
Source/BansheeEditor/Source/BsGizmoManager.cpp

@@ -70,7 +70,7 @@ namespace bs
 
 
 		mCore.store(bs_new<GizmoManagerCore>(GizmoManagerCore::PrivatelyConstuct()), std::memory_order_release);
 		mCore.store(bs_new<GizmoManagerCore>(GizmoManagerCore::PrivatelyConstuct()), std::memory_order_release);
 
 
-		gCoreAccessor().queueCommand(std::bind(&GizmoManager::initializeCore, this, initData));
+		gCoreThread().queueCommand(std::bind(&GizmoManager::initializeCore, this, initData));
 	}
 	}
 
 
 	GizmoManager::~GizmoManager()
 	GizmoManager::~GizmoManager()
@@ -84,7 +84,7 @@ namespace bs
 		bs_delete(mDrawHelper);
 		bs_delete(mDrawHelper);
 		bs_delete(mPickingDrawHelper);
 		bs_delete(mPickingDrawHelper);
 
 
-		gCoreAccessor().queueCommand(std::bind(&GizmoManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
+		gCoreThread().queueCommand(std::bind(&GizmoManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
 	}
 	}
 
 
 	void GizmoManager::initializeCore(const CoreInitData& initData)
 	void GizmoManager::initializeCore(const CoreInitData& initData)
@@ -471,7 +471,7 @@ namespace bs
 
 
 		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
 		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
 
 
-		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, core, camera->getCore(),
+		gCoreThread().queueCommand(std::bind(&GizmoManagerCore::updateData, core, camera->getCore(),
 			proxyData, iconMesh, iconRenderData));
 			proxyData, iconMesh, iconRenderData));
 	}
 	}
 
 
@@ -659,19 +659,19 @@ namespace bs
 
 
 			if(meshData.type == DrawHelper::MeshType::Text)
 			if(meshData.type == DrawHelper::MeshType::Text)
 			{
 			{
-				gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos, core, viewMat, projMat,
+				gCoreThread().queueCommand(std::bind(&GizmoManagerCore::renderGizmos, core, viewMat, projMat,
 					camera->getForward(), meshData.mesh->getCore(), tex, GizmoMaterial::PickingAlpha));
 					camera->getForward(), meshData.mesh->getCore(), tex, GizmoMaterial::PickingAlpha));
 			}
 			}
 			else
 			else
 			{
 			{
-				gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos, core, viewMat, projMat,
+				gCoreThread().queueCommand(std::bind(&GizmoManagerCore::renderGizmos, core, viewMat, projMat,
 					camera->getForward(), meshData.mesh->getCore(), tex, GizmoMaterial::Picking));
 					camera->getForward(), meshData.mesh->getCore(), tex, GizmoMaterial::Picking));
 			}
 			}
 		}
 		}
 
 
 		Rect2I screenArea = camera->getViewport()->getArea();
 		Rect2I screenArea = camera->getViewport()->getArea();
 
 
-		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderIconGizmos,
+		gCoreThread().queueCommand(std::bind(&GizmoManagerCore::renderIconGizmos,
 			core, screenArea, iconMesh->getCore(), iconRenderData, true));
 			core, screenArea, iconMesh->getCore(), iconRenderData, true));
 
 
 		mPickingDrawHelper->clearMeshes(meshes);
 		mPickingDrawHelper->clearMeshes(meshes);
@@ -714,7 +714,7 @@ namespace bs
 		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
 		GizmoManagerCore* core = mCore.load(std::memory_order_relaxed);
 		IconRenderDataVecPtr iconRenderData = bs_shared_ptr_new<IconRenderDataVec>();
 		IconRenderDataVecPtr iconRenderData = bs_shared_ptr_new<IconRenderDataVec>();
 		
 		
-		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, core, 
+		gCoreThread().queueCommand(std::bind(&GizmoManagerCore::updateData, core,
 			nullptr, Vector<GizmoManagerCore::MeshData>(), nullptr, iconRenderData));
 			nullptr, Vector<GizmoManagerCore::MeshData>(), nullptr, iconRenderData));
 	}
 	}
 
 

+ 4 - 4
Source/BansheeEditor/Source/BsHandleDrawManager.cpp

@@ -41,7 +41,7 @@ namespace bs
 
 
 		mCore.store(bs_new<HandleDrawManagerCore>(HandleDrawManagerCore::PrivatelyConstruct()), std::memory_order_release);
 		mCore.store(bs_new<HandleDrawManagerCore>(HandleDrawManagerCore::PrivatelyConstruct()), std::memory_order_release);
 
 
-		gCoreAccessor().queueCommand(std::bind(&HandleDrawManager::initializeCore, this, 
+		gCoreThread().queueCommand(std::bind(&HandleDrawManager::initializeCore, this,
 			lineMaterialProxy, solidMaterialProxy, textMaterialProxy, clearMaterialProxy));
 			lineMaterialProxy, solidMaterialProxy, textMaterialProxy, clearMaterialProxy));
 	}
 	}
 
 
@@ -50,7 +50,7 @@ namespace bs
 		clearMeshes();
 		clearMeshes();
 		bs_delete(mDrawHelper);
 		bs_delete(mDrawHelper);
 
 
-		gCoreAccessor().queueCommand(std::bind(&HandleDrawManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
+		gCoreThread().queueCommand(std::bind(&HandleDrawManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
 	}
 	}
 
 
 	void HandleDrawManager::initializeCore(const SPtr<MaterialCore>& lineMat, const SPtr<MaterialCore>& solidMat, 
 	void HandleDrawManager::initializeCore(const SPtr<MaterialCore>& lineMat, const SPtr<MaterialCore>& solidMat, 
@@ -191,7 +191,7 @@ namespace bs
 		UINT64 frameIdx = gTime().getFrameIdx();
 		UINT64 frameIdx = gTime().getFrameIdx();
 		if(frameIdx != mLastFrameIdx)
 		if(frameIdx != mLastFrameIdx)
 		{
 		{
-			gCoreAccessor().queueCommand(std::bind(&HandleDrawManagerCore::clearQueued, core));
+			gCoreThread().queueCommand(std::bind(&HandleDrawManagerCore::clearQueued, core));
 
 
 			clearMeshes();
 			clearMeshes();
 			mLastFrameIdx = frameIdx;
 			mLastFrameIdx = frameIdx;
@@ -226,7 +226,7 @@ namespace bs
 			}
 			}
 		}
 		}
 
 
-		gCoreAccessor().queueCommand(std::bind(&HandleDrawManagerCore::queueForDraw, core, camera->getCore(), proxyData));
+		gCoreThread().queueCommand(std::bind(&HandleDrawManagerCore::queueForDraw, core, camera->getCore(), proxyData));
 	}
 	}
 
 
 	void HandleDrawManager::clear()
 	void HandleDrawManager::clear()

+ 1 - 1
Source/BansheeEditor/Source/BsMainEditorWindow.cpp

@@ -40,7 +40,7 @@ namespace bs
 		ExceptionTestOutput testOutput;
 		ExceptionTestOutput testOutput;
 		testSuite->run(testOutput);
 		testSuite->run(testOutput);
 
 
-		mRenderWindow->maximize(gCoreAccessor());
+		mRenderWindow->maximize();
 	}
 	}
 
 
 	MainEditorWindow::~MainEditorWindow()
 	MainEditorWindow::~MainEditorWindow()

+ 3 - 3
Source/BansheeEditor/Source/BsSceneGrid.cpp

@@ -34,14 +34,14 @@ namespace bs
 
 
 		HMaterial gridMaterial = BuiltinEditorResources::instance().createSceneGridMaterial();
 		HMaterial gridMaterial = BuiltinEditorResources::instance().createSceneGridMaterial();
 		SPtr<MaterialCore> materialCore = gridMaterial->getCore();
 		SPtr<MaterialCore> materialCore = gridMaterial->getCore();
-		gCoreAccessor().queueCommand(std::bind(&SceneGrid::initializeCore, this, camera->getCore(), materialCore));
+		gCoreThread().queueCommand(std::bind(&SceneGrid::initializeCore, this, camera->getCore(), materialCore));
 
 
 		updateGridMesh();
 		updateGridMesh();
 	}
 	}
 
 
 	SceneGrid::~SceneGrid()
 	SceneGrid::~SceneGrid()
 	{
 	{
-		gCoreAccessor().queueCommand(std::bind(&SceneGrid::destroyCore, this, mCore.load(std::memory_order_relaxed)));
+		gCoreThread().queueCommand(std::bind(&SceneGrid::destroyCore, this, mCore.load(std::memory_order_relaxed)));
 	}
 	}
 
 
 	void SceneGrid::initializeCore(const SPtr<CameraCore>& camera, const SPtr<MaterialCore>& material)
 	void SceneGrid::initializeCore(const SPtr<CameraCore>& camera, const SPtr<MaterialCore>& material)
@@ -115,7 +115,7 @@ namespace bs
 			}
 			}
 
 
 			SceneGridCore* core = mCore.load(std::memory_order_relaxed);
 			SceneGridCore* core = mCore.load(std::memory_order_relaxed);
-			gCoreAccessor().queueCommand(
+			gCoreThread().queueCommand(
 				std::bind(&SceneGridCore::updateData, core, mGridMesh->getCore(), mSpacing, 
 				std::bind(&SceneGridCore::updateData, core, mGridMesh->getCore(), mSpacing, 
 				mMode == GridMode::Perspective, gridPlaneNormal));
 				mMode == GridMode::Perspective, gridPlaneNormal));
 
 

+ 11 - 11
Source/BansheeEditor/Source/BsScenePicking.cpp

@@ -45,12 +45,12 @@ namespace bs
 			mCore->mMaterialData[i].mMatPickingAlphaCore = matPickingAlpha->getCore();
 			mCore->mMaterialData[i].mMatPickingAlphaCore = matPickingAlpha->getCore();
 		}
 		}
 
 
-		gCoreAccessor().queueCommand(std::bind(&ScenePickingCore::initialize, mCore));
+		gCoreThread().queueCommand(std::bind(&ScenePickingCore::initialize, mCore));
 	}
 	}
 
 
 	ScenePicking::~ScenePicking()
 	ScenePicking::~ScenePicking()
 	{
 	{
-		gCoreAccessor().queueCommand(std::bind(&ScenePickingCore::destroy, mCore));
+		gCoreThread().queueCommand(std::bind(&ScenePickingCore::destroy, mCore));
 	}
 	}
 
 
 	HSceneObject ScenePicking::pickClosestObject(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, 
 	HSceneObject ScenePicking::pickClosestObject(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, 
@@ -179,14 +179,14 @@ namespace bs
 		UINT32 firstGizmoIdx = (UINT32)pickData.size();
 		UINT32 firstGizmoIdx = (UINT32)pickData.size();
 
 
 		SPtr<RenderTargetCore> target = cam->getViewport()->getTarget()->getCore();
 		SPtr<RenderTargetCore> target = cam->getViewport()->getTarget()->getCore();
-		gCoreAccessor().queueCommand(std::bind(&ScenePickingCore::corePickingBegin, mCore, target,
+		gCoreThread().queueCommand(std::bind(&ScenePickingCore::corePickingBegin, mCore, target,
 			cam->getViewport()->getNormArea(), std::cref(pickData), position, area));
 			cam->getViewport()->getNormArea(), std::cref(pickData), position, area));
 
 
 		GizmoManager::instance().renderForPicking(cam, [&](UINT32 inputIdx) { return encodeIndex(firstGizmoIdx + inputIdx); });
 		GizmoManager::instance().renderForPicking(cam, [&](UINT32 inputIdx) { return encodeIndex(firstGizmoIdx + inputIdx); });
 
 
-		AsyncOp op = gCoreAccessor().queueReturnCommand(std::bind(&ScenePickingCore::corePickingEnd, mCore, target, 
+		AsyncOp op = gCoreThread().queueReturnCommand(std::bind(&ScenePickingCore::corePickingEnd, mCore, target,
 			cam->getViewport()->getNormArea(), position, area, data != nullptr, _1));
 			cam->getViewport()->getNormArea(), position, area, data != nullptr, _1));
-		gCoreAccessor().submitToCoreThread(true);
+		gCoreThread().submit(true);
 
 
 		assert(op.hasCompleted());
 		assert(op.hasCompleted());
 
 
@@ -388,16 +388,16 @@ namespace bs
 			return;
 			return;
 		}
 		}
 
 
-		SPtr<PixelData> outputPixelData = outputTexture->getProperties().allocateSubresourceBuffer(0);
+		SPtr<PixelData> outputPixelData = outputTexture->getProperties().allocBuffer(0, 0);
 		SPtr<PixelData> normalsPixelData;
 		SPtr<PixelData> normalsPixelData;
 		SPtr<PixelData> depthPixelData;
 		SPtr<PixelData> depthPixelData;
 		if (gatherSnapData)
 		if (gatherSnapData)
 		{
 		{
-			normalsPixelData = normalsTexture->getProperties().allocateSubresourceBuffer(0);
-			depthPixelData = depthTexture->getProperties().allocateSubresourceBuffer(0);
+			normalsPixelData = normalsTexture->getProperties().allocBuffer(0, 0);
+			depthPixelData = depthTexture->getProperties().allocBuffer(0, 0);
 		}
 		}
 
 
-		outputTexture->readSubresource(0, *outputPixelData);
+		outputTexture->readData(*outputPixelData);
 
 
 		Map<UINT32, UINT32> selectionScores;
 		Map<UINT32, UINT32> selectionScores;
 		UINT32 maxWidth = std::min((UINT32)(position.x + area.x), outputPixelData->getWidth());
 		UINT32 maxWidth = std::min((UINT32)(position.x + area.x), outputPixelData->getWidth());
@@ -469,8 +469,8 @@ namespace bs
 		PickResults result;
 		PickResults result;
 		if (gatherSnapData)
 		if (gatherSnapData)
 		{
 		{
-			depthTexture->readSubresource(0, *depthPixelData);
-			normalsTexture->readSubresource(0, *normalsPixelData);
+			depthTexture->readData(*depthPixelData);
+			normalsTexture->readData(*normalsPixelData);
 
 
 			Vector2I samplePixel = position;
 			Vector2I samplePixel = position;
 			if (rtProps.requiresTextureFlipping())
 			if (rtProps.requiresTextureFlipping())

+ 3 - 3
Source/BansheeEditor/Source/BsSelectionRenderer.cpp

@@ -35,12 +35,12 @@ namespace bs
 			
 			
 		mCore.store(bs_new<SelectionRendererCore>(SelectionRendererCore::PrivatelyConstuct()), std::memory_order_release);
 		mCore.store(bs_new<SelectionRendererCore>(SelectionRendererCore::PrivatelyConstuct()), std::memory_order_release);
 
 
-		gCoreAccessor().queueCommand(std::bind(&SelectionRenderer::initializeCore, this, selectionMat->getCore()));
+		gCoreThread().queueCommand(std::bind(&SelectionRenderer::initializeCore, this, selectionMat->getCore()));
 	}
 	}
 
 
 	SelectionRenderer::~SelectionRenderer()
 	SelectionRenderer::~SelectionRenderer()
 	{
 	{
-		gCoreAccessor().queueCommand(std::bind(&SelectionRenderer::destroyCore, this, mCore.load(std::memory_order_relaxed)));
+		gCoreThread().queueCommand(std::bind(&SelectionRenderer::destroyCore, this, mCore.load(std::memory_order_relaxed)));
 	}
 	}
 
 
 	void SelectionRenderer::initializeCore(const SPtr<MaterialCore>& initData)
 	void SelectionRenderer::initializeCore(const SPtr<MaterialCore>& initData)
@@ -76,7 +76,7 @@ namespace bs
 		}
 		}
 
 
 		SelectionRendererCore* core = mCore.load(std::memory_order_relaxed);
 		SelectionRendererCore* core = mCore.load(std::memory_order_relaxed);
-		gCoreAccessor().queueCommand(std::bind(&SelectionRendererCore::updateData, core, camera->getCore(), objects));
+		gCoreThread().queueCommand(std::bind(&SelectionRendererCore::updateData, core, camera->getCore(), objects));
 	}
 	}
 
 
 	const Color SelectionRendererCore::SELECTION_COLOR = Color(1.0f, 1.0f, 1.0f, 0.3f);
 	const Color SelectionRendererCore::SELECTION_COLOR = Color(1.0f, 1.0f, 1.0f, 0.3f);

+ 2 - 2
Source/BansheeEngine/Source/BsApplication.cpp

@@ -32,9 +32,9 @@ namespace bs
 	Application::~Application()
 	Application::~Application()
 	{
 	{
 		// Cleanup any new objects queued for destruction by unloaded scripts
 		// Cleanup any new objects queued for destruction by unloaded scripts
-		CoreObjectManager::instance().syncToCore(gCoreAccessor());
+		CoreObjectManager::instance().syncToCore();
 		gCoreThread().update();
 		gCoreThread().update();
-		gCoreThread().submitAccessors(true);
+		gCoreThread().submitAll(true);
 
 
 		Cursor::shutDown();
 		Cursor::shutDown();
 
 

+ 25 - 25
Source/BansheeEngine/Source/BsBuiltinResources.cpp

@@ -287,35 +287,35 @@ namespace bs
 		HTexture cursorSizeNWSETex = getCursorTexture(CursorSizeNWSETex);
 		HTexture cursorSizeNWSETex = getCursorTexture(CursorSizeNWSETex);
 		HTexture cursorSizeWETex = getCursorTexture(CursorSizeWETex);
 		HTexture cursorSizeWETex = getCursorTexture(CursorSizeWETex);
 
 
-		mCursorArrow = cursorArrowTex->getProperties().allocateSubresourceBuffer(0);
-		cursorArrowTex->readSubresource(gCoreAccessor(), 0, mCursorArrow);
+		mCursorArrow = cursorArrowTex->getProperties().allocBuffer(0, 0);
+		cursorArrowTex->readData(mCursorArrow);
 
 
-		mCursorArrowDrag = cursorArrowDragTex->getProperties().allocateSubresourceBuffer(0);
-		cursorArrowDragTex->readSubresource(gCoreAccessor(), 0, mCursorArrowDrag);
+		mCursorArrowDrag = cursorArrowDragTex->getProperties().allocBuffer(0, 0);
+		cursorArrowDragTex->readData(mCursorArrowDrag);
 
 
-		mCursorArrowLeftRight = cursorArrowLeftRightTex->getProperties().allocateSubresourceBuffer(0);
-		cursorArrowLeftRightTex->readSubresource(gCoreAccessor(), 0, mCursorArrowLeftRight);
+		mCursorArrowLeftRight = cursorArrowLeftRightTex->getProperties().allocBuffer(0, 0);
+		cursorArrowLeftRightTex->readData(mCursorArrowLeftRight);
 
 
-		mCursorIBeam = cursorIBeamTex->getProperties().allocateSubresourceBuffer(0);
-		cursorIBeamTex->readSubresource(gCoreAccessor(), 0, mCursorIBeam);
+		mCursorIBeam = cursorIBeamTex->getProperties().allocBuffer(0, 0);
+		cursorIBeamTex->readData(mCursorIBeam);
 
 
-		mCursorDeny = cursorDenyTex->getProperties().allocateSubresourceBuffer(0);
-		cursorDenyTex->readSubresource(gCoreAccessor(), 0, mCursorDeny);
+		mCursorDeny = cursorDenyTex->getProperties().allocBuffer(0, 0);
+		cursorDenyTex->readData(mCursorDeny);
 
 
-		mCursorWait = cursorWaitTex->getProperties().allocateSubresourceBuffer(0);
-		cursorWaitTex->readSubresource(gCoreAccessor(), 0, mCursorWait);
+		mCursorWait = cursorWaitTex->getProperties().allocBuffer(0, 0);
+		cursorWaitTex->readData(mCursorWait);
 
 
-		mCursorSizeNESW = cursorSizeNESWTex->getProperties().allocateSubresourceBuffer(0);
-		cursorSizeNESWTex->readSubresource(gCoreAccessor(), 0, mCursorSizeNESW);
+		mCursorSizeNESW = cursorSizeNESWTex->getProperties().allocBuffer(0, 0);
+		cursorSizeNESWTex->readData(mCursorSizeNESW);
 
 
-		mCursorSizeNS = cursorSizeNSTex->getProperties().allocateSubresourceBuffer(0);
-		cursorSizeNSTex->readSubresource(gCoreAccessor(), 0, mCursorSizeNS);
+		mCursorSizeNS = cursorSizeNSTex->getProperties().allocBuffer(0, 0);
+		cursorSizeNSTex->readData(mCursorSizeNS);
 
 
-		mCursorSizeNWSE = cursorSizeNWSETex->getProperties().allocateSubresourceBuffer(0);
-		cursorSizeNWSETex->readSubresource(gCoreAccessor(), 0, mCursorSizeNWSE);
+		mCursorSizeNWSE = cursorSizeNWSETex->getProperties().allocBuffer(0, 0);
+		cursorSizeNWSETex->readData(mCursorSizeNWSE);
 
 
-		mCursorSizeWE = cursorSizeWETex->getProperties().allocateSubresourceBuffer(0);
-		cursorSizeWETex->readSubresource(gCoreAccessor(), 0, mCursorSizeWE);
+		mCursorSizeWE = cursorSizeWETex->getProperties().allocBuffer(0, 0);
+		cursorSizeWETex->readData(mCursorSizeWE);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								ICON		                     		*/
 		/* 								ICON		                     		*/
@@ -326,10 +326,10 @@ namespace bs
 
 
 		HTexture iconTex = gResources().load<Texture>(iconPath);
 		HTexture iconTex = gResources().load<Texture>(iconPath);
 
 
-		mBansheeIcon = iconTex->getProperties().allocateSubresourceBuffer(0);
-		iconTex->readSubresource(gCoreAccessor(), 0, mBansheeIcon);
+		mBansheeIcon = iconTex->getProperties().allocBuffer(0, 0);
+		iconTex->readData(mBansheeIcon);
 
 
-		gCoreAccessor().submitToCoreThread(true);
+		gCoreThread().submit(true);
 	}
 	}
 
 
 	void BuiltinResources::preprocess()
 	void BuiltinResources::preprocess()
@@ -380,8 +380,8 @@ namespace bs
 			textureIO->setGenerateMipmaps(false);
 			textureIO->setGenerateMipmaps(false);
 			HTexture splashTexture = gImporter().import<Texture>(inputPath, textureIO);
 			HTexture splashTexture = gImporter().import<Texture>(inputPath, textureIO);
 
 
-			SPtr<PixelData> splashPixelData = splashTexture->getProperties().allocateSubresourceBuffer(0);
-			splashTexture->readData(*splashPixelData);
+			SPtr<PixelData> splashPixelData = splashTexture->getProperties().allocBuffer(0, 0);
+			splashTexture->readCachedData(*splashPixelData);
 
 
 			FileEncoder fe(outputPath);
 			FileEncoder fe(outputPath);
 			fe.encode(splashPixelData.get());
 			fe.encode(splashPixelData.get());

+ 3 - 3
Source/BansheeEngine/Source/BsBuiltinResourcesHelper.cpp

@@ -212,11 +212,11 @@ namespace bs
 		{
 		{
 			IconData& data = iconsToGenerate[i];
 			IconData& data = iconsToGenerate[i];
 
 
-			data.srcData = data.source->getProperties().allocateSubresourceBuffer(0);
-			data.source->readSubresource(gCoreAccessor(), 0, data.srcData);
+			data.srcData = data.source->getProperties().allocBuffer(0, 0);
+			data.source->readData(data.srcData);
 		}
 		}
 
 
-		gCoreAccessor().submitToCoreThread(true);
+		gCoreThread().submit(true);
 
 
 		auto saveTexture = [&](auto& pixelData, auto& path, auto& UUID)
 		auto saveTexture = [&](auto& pixelData, auto& path, auto& UUID)
 		{
 		{

+ 7 - 10
Source/BansheeEngine/Source/BsGUIManager.cpp

@@ -121,7 +121,7 @@ namespace bs
 		GUIManagerCore* core = bs_new<GUIManagerCore>();
 		GUIManagerCore* core = bs_new<GUIManagerCore>();
 		mCore.store(core, std::memory_order_release);
 		mCore.store(core, std::memory_order_release);
 
 
-		gCoreAccessor().queueCommand(std::bind(&GUIManagerCore::initialize, core));
+		gCoreThread().queueCommand(std::bind(&GUIManagerCore::initialize, core));
 	}
 	}
 
 
 	GUIManager::~GUIManager()
 	GUIManager::~GUIManager()
@@ -158,7 +158,7 @@ namespace bs
 		bs_delete(mInputCaret);
 		bs_delete(mInputCaret);
 		bs_delete(mInputSelection);
 		bs_delete(mInputSelection);
 
 
-		gCoreAccessor().queueCommand(std::bind(&GUIManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
+		gCoreThread().queueCommand(std::bind(&GUIManager::destroyCore, this, mCore.load(std::memory_order_relaxed)));
 
 
 		assert(mCachedGUIData.size() == 0);
 		assert(mCachedGUIData.size() == 0);
 	}
 	}
@@ -423,7 +423,7 @@ namespace bs
 			}
 			}
 
 
 			GUIManagerCore* core = mCore.load(std::memory_order_relaxed);
 			GUIManagerCore* core = mCore.load(std::memory_order_relaxed);
-			gCoreAccessor().queueCommand(std::bind(&GUIManagerCore::updateData, core, corePerCameraData));
+			gCoreThread().queueCommand(std::bind(&GUIManagerCore::updateData, core, corePerCameraData));
 
 
 			mCoreDirty = false;
 			mCoreDirty = false;
 		}
 		}
@@ -710,11 +710,10 @@ namespace bs
 		}
 		}
 
 
 		const HTexture& tex = mCaretTexture->getTexture();
 		const HTexture& tex = mCaretTexture->getTexture();
-		UINT32 subresourceIdx = tex->getProperties().mapToSubresourceIdx(0, 0);
-		SPtr<PixelData> data = tex->getProperties().allocateSubresourceBuffer(subresourceIdx);
+		SPtr<PixelData> data = tex->getProperties().allocBuffer(0, 0);
 
 
 		data->setColorAt(mCaretColor, 0, 0);
 		data->setColorAt(mCaretColor, 0, 0);
-		tex->writeSubresource(gCoreAccessor(), subresourceIdx, data, false);
+		tex->writeData(data);
 	}
 	}
 
 
 	void GUIManager::updateTextSelectionTexture()
 	void GUIManager::updateTextSelectionTexture()
@@ -728,12 +727,10 @@ namespace bs
 		}
 		}
 
 
 		const HTexture& tex = mTextSelectionTexture->getTexture();
 		const HTexture& tex = mTextSelectionTexture->getTexture();
-		UINT32 subresourceIdx = tex->getProperties().mapToSubresourceIdx(0, 0);
-		SPtr<PixelData> data = tex->getProperties().allocateSubresourceBuffer(subresourceIdx);
+		SPtr<PixelData> data = tex->getProperties().allocBuffer(0, 0);
 
 
 		data->setColorAt(mTextSelectionColor, 0, 0);
 		data->setColorAt(mTextSelectionColor, 0, 0);
-
-		tex->writeSubresource(gCoreAccessor(), subresourceIdx, data, false);
+		tex->writeData(data);
 	}
 	}
 
 
 	void GUIManager::onMouseDragEnded(const PointerEvent& event, DragCallbackInfo& dragInfo)
 	void GUIManager::onMouseDragEnded(const PointerEvent& event, DragCallbackInfo& dragInfo)

+ 0 - 1
Source/BansheeEngine/Source/BsGUIWidget.cpp

@@ -5,7 +5,6 @@
 #include "BsGUISkin.h"
 #include "BsGUISkin.h"
 #include "BsGUILabel.h"
 #include "BsGUILabel.h"
 #include "BsGUIPanel.h"
 #include "BsGUIPanel.h"
-#include "BsCoreThreadAccessor.h"
 #include "BsVector2I.h"
 #include "BsVector2I.h"
 #include "BsCCamera.h"
 #include "BsCCamera.h"
 #include "BsViewport.h"
 #include "BsViewport.h"

+ 2 - 2
Source/BansheeEngine/Source/BsRendererMaterialManager.cpp

@@ -22,12 +22,12 @@ namespace bs
 				shaders.push_back(nullptr);
 				shaders.push_back(nullptr);
 		}
 		}
 
 
-		gCoreThread().queueCommand(std::bind(&RendererMaterialManager::initOnCore, shaders));
+		gCoreThread().queueCommand(std::bind(&RendererMaterialManager::initOnCore, shaders), CTQF_InternalQueue);
 	}
 	}
 
 
 	RendererMaterialManager::~RendererMaterialManager()
 	RendererMaterialManager::~RendererMaterialManager()
 	{
 	{
-		gCoreAccessor().queueCommand(std::bind(&RendererMaterialManager::destroyOnCore));
+		gCoreThread().queueCommand(std::bind(&RendererMaterialManager::destroyOnCore));
 	}
 	}
 
 
 	void RendererMaterialManager::_registerMaterial(RendererMaterialMetaData* metaData, const Path& shaderPath)
 	void RendererMaterialManager::_registerMaterial(RendererMaterialMetaData* metaData, const Path& shaderPath)

+ 1 - 1
Source/BansheeEngine/Source/BsRendererUtility.cpp

@@ -316,7 +316,7 @@ namespace bs
 		indices[4] = 3;
 		indices[4] = 3;
 		indices[5] = 2;
 		indices[5] = 2;
 
 
-		mFullScreenQuadMesh->writeSubresource(0, *meshData, true, false);
+		mFullScreenQuadMesh->writeData(*meshData, true, false);
 		draw(mFullScreenQuadMesh, mFullScreenQuadMesh->getProperties().getSubMesh(), numInstances);
 		draw(mFullScreenQuadMesh, mFullScreenQuadMesh->getProperties().getSubMesh(), numInstances);
 	}
 	}
 
 

+ 2 - 2
Source/BansheeEngine/Source/BsSplashScreen.cpp

@@ -23,12 +23,12 @@ namespace bs
 
 
 	void SplashScreen::show()
 	void SplashScreen::show()
 	{
 	{
-		gCoreThread().queueCommand(&SplashScreen::create);
+		gCoreThread().queueCommand(&SplashScreen::create, CTQF_InternalQueue);
 	}
 	}
 
 
 	void SplashScreen::hide()
 	void SplashScreen::hide()
 	{
 	{
-		gCoreThread().queueCommand(&SplashScreen::destroy);
+		gCoreThread().queueCommand(&SplashScreen::destroy, CTQF_InternalQueue);
 	}
 	}
 
 
 	void SplashScreen::create()
 	void SplashScreen::create()

+ 2 - 2
Source/BansheeEngine/Source/BsSpriteMaterial.cpp

@@ -16,12 +16,12 @@ namespace bs
 		mMaterial = material->getCore();
 		mMaterial = material->getCore();
 		mMaterialStored.store(true, std::memory_order_release);
 		mMaterialStored.store(true, std::memory_order_release);
 
 
-		gCoreAccessor().queueCommand(std::bind(&SpriteMaterial::initialize, this));
+		gCoreThread().queueCommand(std::bind(&SpriteMaterial::initialize, this));
 	}
 	}
 
 
 	SpriteMaterial::~SpriteMaterial()
 	SpriteMaterial::~SpriteMaterial()
 	{
 	{
-		gCoreAccessor().queueCommand(std::bind(&SpriteMaterial::destroy, mMaterial, mParams));
+		gCoreThread().queueCommand(std::bind(&SpriteMaterial::destroy, mMaterial, mParams));
 	}
 	}
 
 
 	void SpriteMaterial::initialize()
 	void SpriteMaterial::initialize()

+ 3 - 5
Source/BansheeFontImporter/Source/BsFontImporter.cpp

@@ -9,7 +9,6 @@
 #include "BsTexAtlasGenerator.h"
 #include "BsTexAtlasGenerator.h"
 #include "BsCoreApplication.h"
 #include "BsCoreApplication.h"
 #include "BsCoreThread.h"
 #include "BsCoreThread.h"
-#include "BsCoreThreadAccessor.h"
 
 
 #include <ft2build.h>
 #include <ft2build.h>
 #include <freetype/freetype.h>
 #include <freetype/freetype.h>
@@ -329,19 +328,18 @@ namespace bs
 				texDesc.format = PF_R8G8;
 				texDesc.format = PF_R8G8;
 
 
 				HTexture newTex = Texture::create(texDesc);
 				HTexture newTex = Texture::create(texDesc);
-				UINT32 subresourceIdx = newTex->getProperties().mapToSubresourceIdx(0, 0);
 
 
 				// It's possible the formats no longer match
 				// It's possible the formats no longer match
 				if (newTex->getProperties().getFormat() != pixelData->getFormat())
 				if (newTex->getProperties().getFormat() != pixelData->getFormat())
 				{
 				{
-					SPtr<PixelData> temp = newTex->getProperties().allocateSubresourceBuffer(subresourceIdx);
+					SPtr<PixelData> temp = newTex->getProperties().allocBuffer(0, 0);
 					PixelUtil::bulkPixelConversion(*pixelData, *temp);
 					PixelUtil::bulkPixelConversion(*pixelData, *temp);
 
 
-					newTex->writeSubresource(gCoreAccessor(), subresourceIdx, temp, false);
+					newTex->writeData(temp);
 				}
 				}
 				else
 				else
 				{
 				{
-					newTex->writeSubresource(gCoreAccessor(), subresourceIdx, pixelData, false);
+					newTex->writeData(pixelData);
 				}
 				}
 
 
 				newTex->setName(L"FontPage" + toWString((UINT32)fontData->texturePages.size()));
 				newTex->setName(L"FontPage" + toWString((UINT32)fontData->texturePages.size()));

+ 2 - 5
Source/BansheeFreeImgImporter/Source/BsFreeImgImporter.cpp

@@ -10,7 +10,6 @@
 #include "BsFileSystem.h"
 #include "BsFileSystem.h"
 #include "BsCoreApplication.h"
 #include "BsCoreApplication.h"
 #include "BsCoreThread.h"
 #include "BsCoreThread.h"
-#include "BsCoreThreadAccessor.h"
 
 
 #include "FreeImage.h"
 #include "FreeImage.h"
 
 
@@ -178,12 +177,10 @@ namespace bs
 
 
 		for (UINT32 mip = 0; mip < (UINT32)mipLevels.size(); ++mip)
 		for (UINT32 mip = 0; mip < (UINT32)mipLevels.size(); ++mip)
 		{
 		{
-			UINT32 subresourceIdx = newTexture->getProperties().mapToSubresourceIdx(0, mip);
-			SPtr<PixelData> dst = newTexture->getProperties().allocateSubresourceBuffer(subresourceIdx);
+			SPtr<PixelData> dst = newTexture->getProperties().allocBuffer(0, mip);
 
 
 			PixelUtil::bulkPixelConversion(*mipLevels[mip], *dst);
 			PixelUtil::bulkPixelConversion(*mipLevels[mip], *dst);
-
-			newTexture->writeSubresource(gCoreAccessor(), subresourceIdx, dst, false);
+			newTexture->writeData(dst, 0, mip);
 		}
 		}
 
 
 		fileData->close();
 		fileData->close();

+ 2 - 2
Source/BansheeGLRenderAPI/Include/BsGLTexture.h

@@ -59,11 +59,11 @@ namespace bs
 					  const SPtr<TextureCore>& target, UINT32 queueIdx = 0) override;
 					  const SPtr<TextureCore>& target, UINT32 queueIdx = 0) override;
 
 
 		/** @copydoc TextureCore::readData */
 		/** @copydoc TextureCore::readData */
-		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
+		void readDataImpl(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
 					  UINT32 queueIdx = 0) override;
 					  UINT32 queueIdx = 0) override;
 
 
 		/** @copydoc TextureCore::writeData */
 		/** @copydoc TextureCore::writeData */
-		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
+		void writeDataImpl(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
 					   UINT32 queueIdx = 0) override;
 					   UINT32 queueIdx = 0) override;
 
 
 		/** Creates pixel buffers for each face and mip level. Texture must have been created previously. */
 		/** Creates pixel buffers for each face and mip level. Texture must have been created previously. */

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

@@ -239,7 +239,7 @@ namespace bs
 		mLockedBuffer = nullptr;
 		mLockedBuffer = nullptr;
 	}
 	}
 
 
-	void GLTextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
+	void GLTextureCore::readDataImpl(PixelData& dest, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 	{
 		if (mProperties.getNumSamples() > 1)
 		if (mProperties.getNumSamples() > 1)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
@@ -247,7 +247,7 @@ namespace bs
 		getBuffer(face, mipLevel)->download(dest);
 		getBuffer(face, mipLevel)->download(dest);
 	}
 	}
 
 
-	void GLTextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer,
+	void GLTextureCore::writeDataImpl(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer,
 								  UINT32 queueIdx)
 								  UINT32 queueIdx)
 	{
 	{
 		if (mProperties.getNumSamples() > 1)
 		if (mProperties.getNumSamples() > 1)

+ 2 - 2
Source/BansheeVulkanRenderAPI/Include/BsVulkanTexture.h

@@ -99,11 +99,11 @@ namespace bs
 					  const SPtr<TextureCore>& target, UINT32 queueIdx = 0) override;
 					  const SPtr<TextureCore>& target, UINT32 queueIdx = 0) override;
 
 
 		/** @copydoc TextureCore::readData */
 		/** @copydoc TextureCore::readData */
-		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
+		void readDataImpl(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
 					  UINT32 queueIdx = 0) override;
 					  UINT32 queueIdx = 0) override;
 
 
 		/** @copydoc TextureCore::writeData */
 		/** @copydoc TextureCore::writeData */
-		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
+		void writeDataImpl(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
 					   UINT32 queueIdx = 0) override;
 					   UINT32 queueIdx = 0) override;
 
 
 	private:
 	private:

+ 2 - 2
Source/BansheeVulkanRenderAPI/Source/BsVulkanTexture.cpp

@@ -287,7 +287,7 @@ namespace bs
 		
 		
 	}
 	}
 
 
-	void VulkanTextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
+	void VulkanTextureCore::readDataImpl(PixelData& dest, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 	{
 		if (mProperties.getNumSamples() > 1)
 		if (mProperties.getNumSamples() > 1)
 		{
 		{
@@ -312,7 +312,7 @@ namespace bs
 		BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_Texture);
 		BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_Texture);
 	}
 	}
 
 
-	void VulkanTextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer,
+	void VulkanTextureCore::writeDataImpl(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer,
 									  UINT32 queueIdx)
 									  UINT32 queueIdx)
 	{
 	{
 		if (mProperties.getNumSamples() > 1)
 		if (mProperties.getNumSamples() > 1)

+ 3 - 17
Source/ExampleProject/Source/Main.cpp

@@ -463,24 +463,10 @@ namespace bs
 	{
 	{
 		SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
 		SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
 
 
-		// In order to toggle between full-screen and windowed mode we need to use a CoreAccessor.
-		// Banshee is a multi-threaded engine and when you need to communicate between simulation and
-		// core thread you will use a CoreAccessor. Calling a core accessor method will essentially
-		// queue the method to be executed later. Since RenderWindow is a core object you need to use
-		// CoreAccessor to modify and access it from simulation thread, except where noted otherwise.
-
-		// Classes where it is not clear if they are to be used on the core or simulation thread have
-		// it noted in their documentation. e.g. RenderWindow::setWindowed method is marked as "Core only".
-		// Additional asserts are normally in place for debug builds which make it harder for you to accidentally
-		// call something from the wrong thread.
 		if (fullscreen)
 		if (fullscreen)
-		{
-			window->setWindowed(gCoreAccessor(), windowResWidth, windowResHeight);
-		}
+			window->setWindowed(windowResWidth, windowResHeight);
 		else
 		else
-		{
-			window->setFullscreen(gCoreAccessor(), *selectedVideoMode);
-		}
+			window->setFullscreen(*selectedVideoMode);
 
 
 		fullscreen = !fullscreen;
 		fullscreen = !fullscreen;
 	}
 	}
@@ -511,7 +497,7 @@ namespace bs
 		if (fullscreen)
 		if (fullscreen)
 		{
 		{
 			SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
 			SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
-			window->setFullscreen(gCoreAccessor(), *selectedVideoMode);
+			window->setFullscreen(*selectedVideoMode);
 		}
 		}
 	}
 	}
 
 

+ 3 - 3
Source/Game/Source/Main.cpp

@@ -99,7 +99,7 @@ void runApplication()
 			const VideoMode& selectedVideoMode = primaryMonitorInfo.getDesktopVideoMode();
 			const VideoMode& selectedVideoMode = primaryMonitorInfo.getDesktopVideoMode();
 
 
 			SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
 			SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
-			window->setFullscreen(gCoreAccessor(), selectedVideoMode);
+			window->setFullscreen(selectedVideoMode);
 
 
 			resolutionWidth = selectedVideoMode.getWidth();
 			resolutionWidth = selectedVideoMode.getWidth();
 			resolutionHeight = selectedVideoMode.getHeight();
 			resolutionHeight = selectedVideoMode.getHeight();
@@ -112,8 +112,8 @@ void runApplication()
 			VideoMode videoMode(resolutionWidth, resolutionHeight);
 			VideoMode videoMode(resolutionWidth, resolutionHeight);
 
 
 			SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
 			SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
-			window->show(gCoreAccessor());
-			window->setFullscreen(gCoreAccessor(), videoMode);
+			window->show();
+			window->setFullscreen(videoMode);
 		}
 		}
 	}
 	}
 
 

+ 1 - 1
Source/MBansheeEditor/Windows/Scene/SceneWindow.cs

@@ -25,7 +25,7 @@ namespace BansheeEditor
 
 
         private const int HeaderHeight = 20;
         private const int HeaderHeight = 20;
         private const float DefaultPlacementDepth = 5.0f;
         private const float DefaultPlacementDepth = 5.0f;
-        private static readonly Color ClearColor = new Color(83.0f/255.0f, 83.0f/255.0f, 83.0f/255.0f);
+        private static readonly Color ClearColor = new Color(0.0f, 0.3685f, 0.7969f);
         private const string ProfilerOverlayActiveKey = "_Internal_ProfilerOverlayActive";
         private const string ProfilerOverlayActiveKey = "_Internal_ProfilerOverlayActive";
         private const int HandleAxesGUISize = 50;
         private const int HandleAxesGUISize = 50;
         private const int HandleAxesGUIPaddingX = 10;
         private const int HandleAxesGUIPaddingX = 10;

+ 6 - 6
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -54,15 +54,15 @@ namespace bs
 	{
 	{
 		CoreRenderer::initialize();
 		CoreRenderer::initialize();
 
 
-		CoreThread::instance().queueCommand(std::bind(&RenderBeast::initializeCore, this));
+		gCoreThread().queueCommand(std::bind(&RenderBeast::initializeCore, this), CTQF_InternalQueue);
 	}
 	}
 
 
 	void RenderBeast::destroy()
 	void RenderBeast::destroy()
 	{
 	{
 		CoreRenderer::destroy();
 		CoreRenderer::destroy();
 
 
-		gCoreAccessor().queueCommand(std::bind(&RenderBeast::destroyCore, this));
-		gCoreAccessor().submitToCoreThread(true);
+		gCoreThread().queueCommand(std::bind(&RenderBeast::destroyCore, this));
+		gCoreThread().submit(true);
 	}
 	}
 
 
 	void RenderBeast::initializeCore()
 	void RenderBeast::initializeCore()
@@ -533,15 +533,15 @@ namespace bs
 	void RenderBeast::renderAll() 
 	void RenderBeast::renderAll() 
 	{
 	{
 		// Sync all dirty sim thread CoreObject data to core thread
 		// Sync all dirty sim thread CoreObject data to core thread
-		CoreObjectManager::instance().syncToCore(gCoreAccessor());
+		CoreObjectManager::instance().syncToCore();
 
 
 		if (mOptionsDirty)
 		if (mOptionsDirty)
 		{
 		{
-			gCoreAccessor().queueCommand(std::bind(&RenderBeast::syncOptions, this, *mOptions));
+			gCoreThread().queueCommand(std::bind(&RenderBeast::syncOptions, this, *mOptions));
 			mOptionsDirty = false;
 			mOptionsDirty = false;
 		}
 		}
 
 
-		gCoreAccessor().queueCommand(std::bind(&RenderBeast::renderAllCore, this, gTime().getTime(), gTime().getFrameDelta()));
+		gCoreThread().queueCommand(std::bind(&RenderBeast::renderAllCore, this, gTime().getTime(), gTime().getFrameDelta()));
 	}
 	}
 
 
 	void RenderBeast::renderAllCore(float time, float delta)
 	void RenderBeast::renderAllCore(float time, float delta)

+ 3 - 3
Source/SBansheeEditor/Source/BsScriptBuildManager.cpp

@@ -202,9 +202,9 @@ namespace bs
 			{
 			{
 				auto& texProps = icon->getProperties();
 				auto& texProps = icon->getProperties();
 
 
-				SPtr<PixelData> pixels = texProps.allocateSubresourceBuffer(0);
-				icon->readSubresource(gCoreAccessor(), 0, pixels);
-				gCoreAccessor().submitToCoreThread(true);
+				SPtr<PixelData> pixels = texProps.allocBuffer(0, 0);
+				icon->readData(pixels);
+				gCoreThread().submit(true);
 
 
 				for (auto& entry : textures)
 				for (auto& entry : textures)
 				{
 				{

+ 1 - 3
Source/SBansheeEngine/Source/BsScriptAsyncOp.cpp

@@ -62,9 +62,7 @@ namespace bs
 	{
 	{
 		if (!thisPtr->mAsyncOp.hasCompleted())
 		if (!thisPtr->mAsyncOp.hasCompleted())
 		{
 		{
-			// Note: Assuming the AsyncOp was queued via accessor. This will deadlock
-			// if it wasn't.
-			gCoreThread().getAccessor()->submitToCoreThread();
+			gCoreThread().submit();
 			thisPtr->mAsyncOp.blockUntilComplete();
 			thisPtr->mAsyncOp.blockUntilComplete();
 		}
 		}
 	}
 	}

+ 3 - 3
Source/SBansheeEngine/Source/BsScriptMesh.cpp

@@ -152,8 +152,8 @@ namespace bs
 	{
 	{
 		HMesh mesh = thisPtr->getHandle();
 		HMesh mesh = thisPtr->getHandle();
 
 
-		SPtr<MeshData> meshData = mesh->allocateSubresourceBuffer(0);
-		mesh->readData(*meshData);
+		SPtr<MeshData> meshData = mesh->allocBuffer();
+		mesh->readCachedData(*meshData);
 
 
 		return ScriptMeshData::create(meshData);
 		return ScriptMeshData::create(meshData);
 	}
 	}
@@ -164,7 +164,7 @@ namespace bs
 		if (value != nullptr)
 		if (value != nullptr)
 		{
 		{
 			SPtr<MeshData> meshData = value->getInternalValue()->getData();
 			SPtr<MeshData> meshData = value->getInternalValue()->getData();
-			mesh->writeSubresource(gCoreAccessor(), 0, meshData, true);
+			mesh->writeData(meshData, true);
 		}
 		}
 	}
 	}
 
 

+ 1 - 1
Source/SBansheeEngine/Source/BsScriptRenderTarget.cpp

@@ -59,6 +59,6 @@ namespace bs
 	void ScriptRenderTarget::internal_setPriority(ScriptRenderTarget* thisPtr, int value)
 	void ScriptRenderTarget::internal_setPriority(ScriptRenderTarget* thisPtr, int value)
 	{
 	{
 		SPtr<RenderTarget> rt = thisPtr->getNativeValue();
 		SPtr<RenderTarget> rt = thisPtr->getNativeValue();
-		rt->setPriority(gCoreAccessor(), value);
+		rt->setPriority(value);
 	}
 	}
 }
 }

+ 6 - 13
Source/SBansheeEngine/Source/BsScriptTexture2D.cpp

@@ -58,11 +58,9 @@ namespace bs
 	MonoObject* ScriptTexture2D::internal_getPixels(ScriptTexture2D* thisPtr, UINT32 mipLevel)
 	MonoObject* ScriptTexture2D::internal_getPixels(ScriptTexture2D* thisPtr, UINT32 mipLevel)
 	{
 	{
 		HTexture texture = thisPtr->getHandle();
 		HTexture texture = thisPtr->getHandle();
-		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
 
 
-		SPtr<PixelData> pixelData = texture->getProperties().allocateSubresourceBuffer(subresourceIdx);
-
-		texture->readData(*pixelData, mipLevel);
+		SPtr<PixelData> pixelData = texture->getProperties().allocBuffer(0, mipLevel);
+		texture->readCachedData(*pixelData, 0, mipLevel);
 
 
 		return ScriptPixelData::create(pixelData);
 		return ScriptPixelData::create(pixelData);
 	}
 	}
@@ -70,11 +68,9 @@ namespace bs
 	MonoObject* ScriptTexture2D::internal_getGPUPixels(ScriptTexture2D* thisPtr, UINT32 mipLevel)
 	MonoObject* ScriptTexture2D::internal_getGPUPixels(ScriptTexture2D* thisPtr, UINT32 mipLevel)
 	{
 	{
 		HTexture texture = thisPtr->getHandle();
 		HTexture texture = thisPtr->getHandle();
-		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
-
-		SPtr<PixelData> readData = texture->getProperties().allocateSubresourceBuffer(subresourceIdx);
+		SPtr<PixelData> readData = texture->getProperties().allocBuffer(0, mipLevel);
 
 
-		AsyncOp asyncOp = texture->readSubresource(gCoreAccessor(), subresourceIdx, readData);
+		AsyncOp asyncOp = texture->readData(readData, 0, mipLevel);
 
 
 		std::function<MonoObject*(const AsyncOp&, const SPtr<PixelData>&)> asyncOpToMono =
 		std::function<MonoObject*(const AsyncOp&, const SPtr<PixelData>&)> asyncOpToMono =
 			[&](const AsyncOp& op, const SPtr<PixelData>& returnValue)
 			[&](const AsyncOp& op, const SPtr<PixelData>& returnValue)
@@ -92,9 +88,7 @@ namespace bs
 		if (scriptPixelData != nullptr)
 		if (scriptPixelData != nullptr)
 		{
 		{
 			HTexture texture = thisPtr->getHandle();
 			HTexture texture = thisPtr->getHandle();
-			UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
-
-			texture->writeSubresource(gCoreAccessor(), subresourceIdx, scriptPixelData->getInternalValue(), false);
+			texture->writeData(scriptPixelData->getInternalValue(), 0, mipLevel, false);
 		}
 		}
 	}
 	}
 
 
@@ -112,8 +106,7 @@ namespace bs
 		pixelData->allocateInternalBuffer();
 		pixelData->allocateInternalBuffer();
 		pixelData->setColors(colorsRaw, numElements);
 		pixelData->setColors(colorsRaw, numElements);
 
 
-		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
-		texture->writeSubresource(gCoreAccessor(), subresourceIdx, pixelData, false);
+		texture->writeData(pixelData, 0, mipLevel, false);
 	}
 	}
 
 
 	MonoObject* ScriptTexture2D::createInstance()
 	MonoObject* ScriptTexture2D::createInstance()

+ 5 - 10
Source/SBansheeEngine/Source/BsScriptTexture3D.cpp

@@ -57,11 +57,9 @@ namespace bs
 	MonoObject* ScriptTexture3D::internal_getPixels(ScriptTexture3D* thisPtr, UINT32 mipLevel)
 	MonoObject* ScriptTexture3D::internal_getPixels(ScriptTexture3D* thisPtr, UINT32 mipLevel)
 	{
 	{
 		HTexture texture = thisPtr->getHandle();
 		HTexture texture = thisPtr->getHandle();
-		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
 
 
-		SPtr<PixelData> pixelData = texture->getProperties().allocateSubresourceBuffer(subresourceIdx);
-
-		texture->readData(*pixelData, mipLevel);
+		SPtr<PixelData> pixelData = texture->getProperties().allocBuffer(0, mipLevel);
+		texture->readCachedData(*pixelData, 0, mipLevel);
 
 
 		return ScriptPixelData::create(pixelData);
 		return ScriptPixelData::create(pixelData);
 	}
 	}
@@ -69,11 +67,9 @@ namespace bs
 	MonoObject* ScriptTexture3D::internal_getGPUPixels(ScriptTexture3D* thisPtr, UINT32 mipLevel)
 	MonoObject* ScriptTexture3D::internal_getGPUPixels(ScriptTexture3D* thisPtr, UINT32 mipLevel)
 	{
 	{
 		HTexture texture = thisPtr->getHandle();
 		HTexture texture = thisPtr->getHandle();
-		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
-
-		SPtr<PixelData> readData = texture->getProperties().allocateSubresourceBuffer(subresourceIdx);
+		SPtr<PixelData> readData = texture->getProperties().allocBuffer(0, mipLevel);
 
 
-		AsyncOp asyncOp = texture->readSubresource(gCoreAccessor(), subresourceIdx, readData);
+		AsyncOp asyncOp = texture->readData(readData, 0, mipLevel);
 
 
 		std::function<MonoObject*(const AsyncOp&, const SPtr<PixelData>&)> asyncOpToMono =
 		std::function<MonoObject*(const AsyncOp&, const SPtr<PixelData>&)> asyncOpToMono =
 			[&](const AsyncOp& op, const SPtr<PixelData>& returnValue)
 			[&](const AsyncOp& op, const SPtr<PixelData>& returnValue)
@@ -91,9 +87,8 @@ namespace bs
 		if (scriptPixelData != nullptr)
 		if (scriptPixelData != nullptr)
 		{
 		{
 			HTexture texture = thisPtr->getHandle();
 			HTexture texture = thisPtr->getHandle();
-			UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
 
 
-			texture->writeSubresource(gCoreAccessor(), subresourceIdx, scriptPixelData->getInternalValue(), false);
+			texture->writeData(scriptPixelData->getInternalValue(), 0, mipLevel, false);
 		}
 		}
 	}
 	}
 
 

+ 5 - 10
Source/SBansheeEngine/Source/BsScriptTextureCube.cpp

@@ -57,11 +57,9 @@ namespace bs
 	MonoObject* ScriptTextureCube::internal_getPixels(ScriptTextureCube* thisPtr, UINT32 face, UINT32 mipLevel)
 	MonoObject* ScriptTextureCube::internal_getPixels(ScriptTextureCube* thisPtr, UINT32 face, UINT32 mipLevel)
 	{
 	{
 		HTexture texture = thisPtr->getHandle();
 		HTexture texture = thisPtr->getHandle();
-		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(face, mipLevel);
 
 
-		SPtr<PixelData> pixelData = texture->getProperties().allocateSubresourceBuffer(subresourceIdx);
-
-		texture->readData(*pixelData, mipLevel, face);
+		SPtr<PixelData> pixelData = texture->getProperties().allocBuffer(face, mipLevel);
+		texture->readCachedData(*pixelData, face, mipLevel);
 
 
 		return ScriptPixelData::create(pixelData);
 		return ScriptPixelData::create(pixelData);
 	}
 	}
@@ -69,10 +67,9 @@ namespace bs
 	MonoObject* ScriptTextureCube::internal_getGPUPixels(ScriptTextureCube* thisPtr, UINT32 face, UINT32 mipLevel)
 	MonoObject* ScriptTextureCube::internal_getGPUPixels(ScriptTextureCube* thisPtr, UINT32 face, UINT32 mipLevel)
 	{
 	{
 		HTexture texture = thisPtr->getHandle();
 		HTexture texture = thisPtr->getHandle();
-		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(face, mipLevel);
+		SPtr<PixelData> readData = texture->getProperties().allocBuffer(face, mipLevel);
 
 
-		SPtr<PixelData> readData = texture->getProperties().allocateSubresourceBuffer(subresourceIdx);
-		AsyncOp asyncOp = texture->readSubresource(gCoreAccessor(), subresourceIdx, readData);
+		AsyncOp asyncOp = texture->readData(readData, face, mipLevel);
 
 
 		std::function<MonoObject*(const AsyncOp&, const SPtr<PixelData>&)> asyncOpToMono =
 		std::function<MonoObject*(const AsyncOp&, const SPtr<PixelData>&)> asyncOpToMono =
 			[&](const AsyncOp& op, const SPtr<PixelData>& returnValue)
 			[&](const AsyncOp& op, const SPtr<PixelData>& returnValue)
@@ -90,9 +87,7 @@ namespace bs
 		if (scriptPixelData != nullptr)
 		if (scriptPixelData != nullptr)
 		{
 		{
 			HTexture texture = thisPtr->getHandle();
 			HTexture texture = thisPtr->getHandle();
-			UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(face, mipLevel);
-
-			texture->writeSubresource(gCoreAccessor(), subresourceIdx, scriptPixelData->getInternalValue(), false);
+			texture->writeData(scriptPixelData->getInternalValue(), face, mipLevel, false);
 		}
 		}
 	}
 	}