Browse Source

Updating documentation to reflect the core accessor changes

BearishSun 9 years ago
parent
commit
01cf5c56f4

+ 17 - 20
Documentation/Manuals/Native/coreThread.md

@@ -22,37 +22,34 @@ Here are some examples of when the simulation thread needs to interact with the
 As you can see the communication is one directional. Simulation thread calls into the core thread when it needs to notify it of a certain event. In rare cases the core thread needs to notify the simulation thread (e.g. when the user moves/resizes the window the simulation thread needs to be aware of the new position/size), but this is handled on a per-case basis using normal thread synchronization primitives, and we won't touch on it further.
 
 # Command queue {#coreThread_a}
-All the operations listed above happen with the help of a @ref bs::CommandQueue<SyncPolicy> "CommandQueue". When simulation thread needs to notify the core thread about something it queues a command in the queue using @ref bs::CommandQueue<SyncPolicy>::queue "CommandQueue::queue", which accepts a function to be executed. The core thread continually reads from the command queue and executes commands in the order of they are submitted.
+All the operations listed above happen with the help of a command queue. When simulation thread needs to notify the core thread about something it queues a command, which is then eventually received and processed by the core thread.
 
-The main command queue can be accessed using @ref bs::CoreThread::queueCommand "CoreThread::queueCommand", which is just a wrapper for the @ref bs::CommandQueue<SyncPolicy>::queue "CommandQueue::queue" method mentioned above.
+@ref bs::CoreThread "CoreThread" managed the command queues. Use @ref bs::CoreThread::queueCommand "CoreThread::queueCommand" to queue a new command.
 
-## Returning values {#coreThread_a_a}
-Sometimes a queued command needs to return a value to the simulation thread (for example, when reading pixels from a texture). This can be performed by calling @ref bs::CoreThread::queueReturnCommand "CoreThread::queueReturnCommand", which internally calls @ref bs::CommandQueue<SyncPolicy>::queueReturn "CommandQueue::queueReturn". 
+Each thread has its own command queue, so calling this method from multiple threads will fill up different command queues.
 
-Since the command was queued and we don't know when will the core thread execute, we have no guarantees when its return value will be available. Therefore this method will return an @ref bs::AsyncOp "AsyncOp" object. This object can be used for checking if the return value is available by calling @ref bs::AsyncOp::hasCompleted "AsyncOp::hasCompleted". If the return value is available you can retrieve it via @ref bs::AsyncOp::getReturnValue<T> "AsyncOp::getReturnValue<T>".
-
-## Blocking {#coreThread_a_b}
-In certain cases you need to see the results of an operation right away. In such cases you can tell the simulation thread to wait until a certain command is done executing on the core thread. You can do this by setting the `blockUntilComplete` parameter of @ref bs::CoreThread::queueCommand "CoreThread::queueCommand" and @ref bs::CoreThread::queueReturnCommand "CoreThread::queueReturnCommand" to true.
+## Submitting commands {#coreThread_a_a}
+Commands that are queued aren't yet visible to the core thread. In order to make the command visible you must call @ref bs::CoreThread::submit "CoreThread::submit", which will submit all the commands for the current thread's command queue. You may also call @ref bs::CoreThread::submitAll "CoreThread::submitAll" to submit queues for all threads.
 
-You can also block by calling @ref bs::AsyncOp::blockUntilComplete "AsyncOp::blockUntilComplete". This is similar to blocking directly on the @ref bs::CoreThread::queueReturnCommand "CoreThread::queueReturnCommand" call, but can be more useful if you're not sure immediately if you need to wait for the result or not.
+By default commands are also submitted at the end of every frame, just before rendering. Therefore normally you do not need to submit commands manually.
 
-You should be very careful about blocking as it wastes CPU cycles since one thread is just sitting there doing nothing until the core thread reaches the command (which could be as long as a few dozen milliseconds).
+The most common case for submitting commands manually is when you need the results of the command right away. In such a case you can call @ref bs::CoreThread::submit "CoreThread::submit" or @ref bs::CoreThread::submitAll "CoreThread::submitAll" with the parameter @p blockUntilComplete set to true. This will block the calling thread until the command finishes executing. Not that this is expensive and shouldn't be done in performance critical code.
 
-## Core accessors {#coreThread_a_c}
-Core accessors can be considered as light-weight command queues. They perform the same operations as @ref bs::CoreThread::queueCommand "CoreThread::queueCommand" and @ref bs::CoreThread::queueReturnCommand "CoreThread::queueReturnCommand". However core accessors can only be accessed from a single thread, while the methods just listed can be accessed from any thread. Accessors also don't submit their commands to the core thread immediately, instead they are submitted all together using a separate method.
+## Internal queue {#coreThread_a_b}
+Internal command queue is different from the per-thread command queues because that's the only command queue that the core thread actually sees. For example, when you call @ref bs::CoreThread::submit "CoreThread::submit" the system takes all the commands from the per-thread command queue and moves them in the internal command queue, making them visible to the core thread.
 
-Because of these two reasons core accessors are much faster than the primary command queue, and you should always prefer to use them instead of directly queuing commands on the primary queue.
+Optionally you may directly queue commands on the internal command queue by calling @ref bs::CoreThread::queueCommand "CoreThread::queueCommand" with the @ref bs::CTQF_InternalQueue "CTQF_InternalQueue" flag. When such a command is submitted it is immediately visible to the core thread. You may also optionally provide the @ref bs::CTQF_BlockUntilComplete "CTQF_BlockUntilComplete" if you wish to block the calling thread until the command finishes executing.
 
-Accessor for the current thread can be retrieved with @ref bs::CoreThread::getAccessor "CoreThread::getAccessor". You queue the commands in the accessor by calling @ref bs::CoreThreadAccessorBase::queueCommand "CoreThreadAccessor::queueCommand" and @ref bs::CoreThreadAccessorBase::queueReturnCommand "CoreThreadAccessor::queueReturnCommand". Once you are done queuing commands you can submit them to the core thread by calling @ref bs::CoreThread::submitAccessors "CoreThread::submitAccessors".
+There is only one internal command queue, so different threads can write to it in an interleaved manner, unlike with normal threads. Note that internal command queue is slower than per-thread queues and you should prefer to use them instead.
 
-Internally @ref bs::CoreThread::submitAccessors "CoreThread::submitAccessors" uses the primary queue to submit a command that reads all the commands from the accessor and executes them in order. So esentially they are just built on top of the primary command queue, and in fact most of the threading functionality is.
+Also note that since command queued on the internal command queue are seen by the core thread immediately, they will execute before commands previously queued on normal per-thread queues, unless they were submitted.
 
-### Core accessor APIs {#coreThread_a_c_a}
-Although you can queue your own commands to the core accessor, many systems provide methods that automatically queue commands on the core accessor. For example take a look at @ref bs::RenderAPI "RenderAPI" which allows you to interact directly with the render API from the simulation thread (something that is normally reserved for the core thread). Most of the methods accept a @ref bs::CoreThreadAccessor<CommandQueueSyncPolicy> "CoreThreadAccessor", and internally just queue commands on it. This allows you to perform low level rendering operations from the simulation thread.
+## Returning values {#coreThread_a_c}
+Sometimes a queued command needs to return a value to the simulation thread (for example, when reading pixels from a texture). This can be performed by calling @ref bs::CoreThread::queueReturnCommand "CoreThread::queueReturnCommand". Aside from the return value it operates in the same manner as @ref bs::CoreThread::queueCommand "CoreThread::queueCommand".
 
-@ref bs::Mesh "Mesh", @ref bs::Texture "Texture" and @ref bs::RenderTarget "RenderTarget" also provide several methods for performing core thread operations from the simulation thread via the core accessors.
+Since the command was queued and we don't know when will the core thread execute, we have no guarantees when its return value will be available. Therefore this method will return an @ref bs::AsyncOp "AsyncOp" object. This object can be used for checking if the return value is available by calling @ref bs::AsyncOp::hasCompleted "AsyncOp::hasCompleted". If the return value is available you can retrieve it via @ref bs::AsyncOp::getReturnValue<T> "AsyncOp::getReturnValue<T>".
 
-It's important to remember these methods are just a convenience, and internally they use the same command queuing methods we described in the previous section.
+@ref bs::AsyncOp "AsyncOp" also allow you to block the calling thread by calling @ref bs::AsyncOp::blockUntilComplete "AsyncOp::blockUntilComplete". This is similar to blocking directly on the @ref bs::CoreThread::submit "CoreThread::submit" or @ref bs::CoreThread::queueReturnCommand "CoreThread::queueReturnCommand" call, but can be more useful if you're not sure immediately if you need to wait for the result or not.
 
 # Core objects {#coreThread_b}
 Core objects are objects that need to exist on both simulation and core threads. Although you could technically handle such cases manually by using the command queue, it is useful to provide an interface that allows the user to work normally with an object without needing to know about the threading internals, and this is where core objects come in.
@@ -128,7 +125,7 @@ void MyCoreObjectCore::syncToCore(const CoreSyncData& data)
 }
 ~~~~~~~~~~~~~
 
-Whenever you need to trigger synchronization you must call @ref bs::CoreObject::markCoreDirty "CoreObject::markCoreDirty" which notifies the system that synchronization is required. This will in turn trigger a call to @ref bs::CoreObject::syncToCore(FrameAlloc*) "CoreObject::syncToCore" method you implemented earlier. Synchronization happens automatically for all dirty core objects once per frame. Optionally you may call @ref bs::CoreObject::syncToCore(CoreAccessor&) "CoreObject::syncToCore" to manually queue the synchronization.
+Whenever you need to trigger synchronization you must call @ref bs::CoreObject::markCoreDirty "CoreObject::markCoreDirty" which notifies the system that synchronization is required. This will in turn trigger a call to @ref bs::CoreObject::syncToCore(FrameAlloc*) "CoreObject::syncToCore" method you implemented earlier. Synchronization happens automatically for all dirty core objects once per frame. Optionally you may call @ref bs::CoreObject::syncToCore() "CoreObject::syncToCore" to manually queue the synchronization.
 
 See implementation of @ref bs::Light "Light" and @ref bs::LightCore "LightCore" in "BsLight.cpp" for a simple example of synchronization.
 

+ 6 - 6
Documentation/Manuals/Native/meshes.md

@@ -33,11 +33,11 @@ You can also create a non-empty mesh by creating it with a populated @ref bs::Me
 You can access various mesh properties by calling @ref bs::Mesh::getProperties() "Mesh::getProperties()" which will return an instance of @ref bs::MeshProperties "MeshProperties" which contains information such as mesh bounds, number of indices/vertices and sub-meshes. 
  
 # Reading/writing {#meshes_c}
-To read and write from/to the mesh use the @ref bs::Mesh::readSubresource "Mesh::readSubresource" and @ref bs::Mesh::writeSubresource "Mesh::writeSubresource" methods. These expect an index of a sub-resource to read/write to, and a @ref bs::MeshData "MeshData" object.
+To read and write from/to the mesh use the @ref bs::Mesh::readData "Mesh::readData" and @ref bs::Mesh::writeData "Mesh::writeData" methods. These expect a @ref bs::MeshData "MeshData" object as input.
 
-The sub-resource index for a mesh is currently ignored and should be always left as zero.
+@ref bs::MeshData "MeshData" object is just a container for a set of vertices and indices. You can create one manually or use @ref bs::Mesh::allocBuffer "Mesh::allocBuffer" to create the object of valid size and format for the specified mesh. When reading from the mesh the buffer will be filled with vertices/indices from the mesh, and when writing you are expected to populate the object.
 
-@ref bs::MeshData "MeshData" object is just a container for a set of vertices and indices. You can create one manually or use @ref bs::Mesh::allocateSubresourceBuffer "Mesh::allocateSubresourceBuffer" to create the object of valid size and format for the specified mesh. When reading from the mesh the buffer will be filled with vertices/indices from the mesh, and when writing you are expected to populate the object.
+Be aware that read and write operations are asynchronous and you must follow the rules for @ref asyncMethod "asynchronous methods".
 
 ## MeshData {#meshes_c_a}
 You can create @ref bs::MeshData "MeshData" manually by calling @ref bs::MeshData::create "MeshData::create" and providing it with vertex description, index type and number of vertices and indices. You must ensure that the formats and sizes matches the mesh this will be used on.
@@ -118,9 +118,9 @@ indices[5] = 3;
 ~~~~~~~~~~~~~
 
 ## Cached CPU data {#meshes_c_b}
-When you read from a mesh using the @ref bs::Mesh::readSubresource "Mesh::readSubresource" method the read will be performed from the GPU. This is useful if the GPU has in some way modified the mesh, but will also incur a potentially large performance penalty because it will introduce a CPU-GPU synchronization point. In a lot of cases you might just want to read mesh data from a mesh that was imported or created on the CPU in some other way.
+When you read from a mesh using the @ref bs::Mesh::readData "Mesh::readData" method the read will be performed from the GPU. This is useful if the GPU has in some way modified the mesh, but will also incur a potentially large performance penalty because it will introduce a CPU-GPU synchronization point. In a lot of cases you might just want to read mesh data from a mesh that was imported or created on the CPU in some other way.
 
-For this reason @ref bs::Mesh::readData "Mesh::readData" exists. It will read data quickly with little performance impact. However you must create the mesh using the @ref bs::MU_CPUCACHED "MU_CPUCACHED" usage. This also means that the mesh will keep a copy of its data in system memory, so use it sparingly. If the mesh is modified from the GPU this method will not reflect such changes.
+For this reason @ref bs::Mesh::readCachedData "Mesh::readCachedData" exists. It will read data quickly with little performance impact. However you must create the mesh using the @ref bs::MU_CPUCACHED "MU_CPUCACHED" usage. This also means that the mesh will keep a copy of its data in system memory, so use it sparingly. If the mesh is modified from the GPU this method will not reflect such changes.
 
 # Rendering using the mesh {#meshes_d}
 To use a mesh for rendering you need to bind its vertex buffer(s), index buffer, vertex declaration and draw operation using the @ref bs::RenderAPI "RenderAPI". Relevant methods are @ref bs::RenderAPI::setVertexBuffers "RenderAPI::setVertexBuffers", @ref bs::RenderAPI::setIndexBuffer "RenderAPI::setIndexBuffer", @ref bs::RenderAPI::setVertexDeclaration "RenderAPI::setVertexDeclaration" and @ref bs::RenderAPI::setDrawOperation "RenderAPI::setDrawOperation". See below for information about how to retrieve this information from a mesh.
@@ -133,7 +133,7 @@ If working on the core thread you can use the helper @ref bs::RendererUtility::d
 A mesh is a @ref bs::Resource "Resource" and can be saved/loaded like any other. See the [resource](@ref resources) manual.
 
 # Core thread meshes {#meshes_f}
-So far we have only talked about the simulation thread @ref bs::Mesh "Mesh" but have ignored the core thread @ref bs::MeshCore "MeshCore". The functionality between the two is mostly the same, with the major difference being that the core thread version doesn't require a @ref bs::CoreThreadAccessor "CoreAccessor" for access, and you can instead perform operations on it directly.
+So far we have only talked about the simulation thread @ref bs::Mesh "Mesh" but have ignored the core thread @ref bs::MeshCore "MeshCore". The functionality between the two is mostly the same, with the major difference being that the core thread version doesn't have asychronous write/read methods, and those operations are instead performed immediately.
 
 You can also use the core thread version to access and manipulate vertex and index buffers directly (including binding them to the pipeline as described earlier). Use @ref bs::MeshCore::getVertexData "MeshCore::getVertexData" to retrieve information about all @ref bs::VertexBufferCore "vertex buffers", @ref bs::MeshCore::getIndexBuffer "MeshCore::getIndexBuffer" to retrieve the @ref bs::IndexBufferCore "index buffer" and @ref bs::MeshCore::getVertexDesc "MeshCore::getVertexDesc" to retrieve the @ref bs::VertexDataDesc "vertex description".
 

+ 6 - 6
Documentation/Manuals/Native/textures.md

@@ -33,11 +33,11 @@ You can also create a non-empty texture by creating it with a populated @ref bs:
 You can access all relevant information about a texture (e.g. width, height) by calling @ref bs::Texture::getProperties() "Texture::getProperties()" which will return an instance of @ref bs::TextureProperties "TextureProperties". 
  
 # Reading/writing {#textures_c}
-To read and write from/to the texture use the @ref bs::Texture::readSubresource "Texture::readSubresource" and @ref bs::Texture::writeSubresource "Texture::writeSubresource" methods. These expect an index of a sub-resource to read/write to, and a @ref bs::PixelData "PixelData" object.
+To read and write from/to the texture use the @ref bs::Texture::readData "Texture::readData" and @ref bs::Texture::writeData "Texture::writeData" methods. These expect a face and mipmap index to read/write to, and a @ref bs::PixelData "PixelData" object.
 
-The sub-resource index is simply a sequential index of the surface you want to access. If the texture has only one surface this will always be zero. But if the texture has multiple mipmaps or multiple faces (like for cube textures or texture arrays) you can use @ref bs::TextureProperties::mapToSubresourceIdx "TextureProperties::mapToSubresourceIdx" to convert mip/face combination into an subresource index, and @ref bs::TextureProperties::mapFromSubresourceIdx "TextureProperties::mapFromSubresourceIdx" for the other way around.
+@ref bs::PixelData "PixelData" object is just a container for a set of pixels. You can create one manually or use @ref bs::TextureProperties::allocBuffer "TextureProperties::allocBuffer" to create the object of valid size and format for the specified sub-resource index. When reading from the texture the buffer will be filled with pixels from the texture, and when writing you are expected to populate the object.
 
-@ref bs::PixelData "PixelData" object is just a container for a set of pixels. You can create one manually or use @ref bs::TextureProperties::allocateSubresourceBuffer "TextureProperties::allocateSubresourceBuffer" to create the object of valid size and format for the specified sub-resource index. When reading from the texture the buffer will be filled with pixels from the texture, and when writing you are expected to populate the object.
+Be aware that read and write operations are asynchronous and you must follow the rules for @ref asyncMethod "asynchronous methods".
 
 ## PixelData {#textures_c_a}
 You can create @ref bs::PixelData "PixelData" manually by calling @ref bs::PixelData::create "PixelData::create" and providing it with dimensions and pixel format. When working with textures you must ensure that the dimensions and the format matches the texture sub-resource.
@@ -47,9 +47,9 @@ Once created you can use @ref bs::PixelData::getColorAt "PixelData::getColorAt",
 You can also use @ref bs::PixelUtil "PixelUtil" to perform various operations on the pixels. This includes generating mip maps, converting to different pixel formats, compressing, scaling and other.
 
 ## Cached CPU data {#textures_c_b}
-When you read from a texture using the @ref bs::Texture::readSubresource "Texture::readSubresource" method the read will be performed from the GPU. This is useful if the GPU has in some way modified the texture, but will also incur a potentially large performance penalty because it will introduce a CPU-GPU synchronization point. In a lot of cases you might just want to read pixels from a texture that was imported or created on the CPU in some other way.
+When you read from a texture using the @ref bs::Texture::readData "Texture::readData" method the read will be performed from the GPU. This is useful if the GPU has in some way modified the texture, but will also incur a potentially large performance penalty because it will introduce a CPU-GPU synchronization point. In a lot of cases you might just want to read pixels from a texture that was imported or created on the CPU in some other way.
 
-For this reason @ref bs::Texture::readData "Texture::readData" exists. It will read data quickly with little performance impact. However you must create the texture using the @ref bs::TU_CPUCACHED "TU_CPUCACHED" usage. This also means that the texture will keep a copy of its pixels in system memory, so use it sparingly. If the texture is modified from the GPU this method will not reflect such changes.
+For this reason @ref bs::Texture::readCachedData "Texture::readCachedData" exists. It will read data quickly with little performance impact. However you must create the texture using the @ref bs::TU_CPUCACHED "TU_CPUCACHED" usage. This also means that the texture will keep a copy of its pixels in system memory, so use it sparingly. If the texture is modified from the GPU this method will not reflect such changes.
 
 # Rendering using the texture {#textures_d}
 To use a texture for rendering you need to either:
@@ -60,7 +60,7 @@ To use a texture for rendering you need to either:
 A texture is a @ref bs::Resource "Resource" and can be saved/loaded like any other. See the [resource](@ref resources) manual.
 
 # Core thread textures {#textures_f}
-So far we have only talked about the simulation thread @ref bs::Texture "Texture" but have ignored the core thread @ref bs::TextureCore "TextureCore". The functionality between the two is mostly the same, with the major difference being that the core thread version doesn't require a @ref bs::CoreThreadAccessor "CoreAccessor" for access, and you can instead perform operations on it directly.
+So far we have only talked about the simulation thread @ref bs::Texture "Texture" but have ignored the core thread @ref bs::TextureCore "TextureCore". The functionality between the two is mostly the same, with the major difference being that the core thread version doesn't have asychronous write/read methods, and those operations are instead performed immediately.
 
 You can also use @ref bs::TextureCore::lock "TextureCore::lock" and @ref bs::TextureCore::unlock "TextureCore::unlock" to get access to the texture buffer, which allows you to only read/write from/to portions of it, instead of always writing to the entire buffer.
 

+ 1 - 1
Source/BansheeCore/Include/BsTexture.h

@@ -447,7 +447,7 @@ namespace bs
 		virtual void unlockImpl() = 0;
 
 		/** @copydoc copy */
-		virtual void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, 
+		virtual void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 dstFace, UINT32 dstMipLevel, 
 			const SPtr<TextureCore>& target, UINT32 queueIdx = 0) = 0;
 
 		/** @copydoc readData */

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

@@ -48,7 +48,7 @@ namespace bs
 		void unlockImpl() override;
 
 		/** @copydoc TextureCore::copyImpl */
-		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel,
+		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 dstFace, UINT32 dstMipLevel,
 					  const SPtr<TextureCore>& target, UINT32 queueIdx = 0) override;
 
 		/** @copydoc TextureCore::readData */

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

@@ -55,7 +55,7 @@ namespace bs
 		void unlockImpl() override;
 
 		/** @copydoc TextureCore::copyImpl */
-		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel,
+		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 dstFace, UINT32 dstMipLevel,
 					  const SPtr<TextureCore>& target, UINT32 queueIdx = 0) override;
 
 		/** @copydoc TextureCore::readData */