| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- #include "CmRenderSystemContext.h"
- #include "CmException.h"
- #include "CmRenderSystemManager.h"
- #include "CmRenderSystem.h"
- #include "CmDebug.h"
- namespace CamelotEngine
- {
- RenderSystemContext::RenderSystemContext(CM_THREAD_ID_TYPE threadId)
- :mMyThreadId(threadId), mIsExecuting(false)
- , waitForVerticalBlank(true)
- , cullingMode(CULL_CLOCKWISE)
- , vertexProgramBound(false)
- , geometryProgramBound(false)
- , fragmentProgramBound(false)
- , invertVertexWinding(false)
- {
- mCommands = new vector<RenderSystemCommand>::type();
- }
- /************************************************************************/
- /* FRAME CONTEXT */
- /************************************************************************/
- RenderSystemFrameContext::RenderSystemFrameContext(CM_THREAD_ID_TYPE threadId)
- :RenderSystemContext(threadId), mReadyCommands(nullptr)
- {
- }
- AsyncOp RenderSystemFrameContext::queueReturnCommand(boost::function<void(AsyncOp&)> commandCallback, UINT32 _callbackId)
- {
- #if CM_DEBUG_MODE
- #if CM_THREAD_SUPPORT != 0
- if(CM_THREAD_CURRENT_ID != mMyThreadId)
- {
- CM_EXCEPT(InternalErrorException, "Render system context accessed from an invalid thread.");
- }
- #endif
- #endif
- RenderSystemCommand newCommand(commandCallback, _callbackId);
- mCommands->push_back(newCommand);
- return newCommand.asyncOp;
- }
- void RenderSystemFrameContext::queueCommand(boost::function<void()> commandCallback, UINT32 _callbackId)
- {
- #if CM_DEBUG_MODE
- #if CM_THREAD_SUPPORT != 0
- if(CM_THREAD_CURRENT_ID != mMyThreadId)
- {
- CM_EXCEPT(InternalErrorException, "Render system context accessed from an invalid thread.");
- }
- #endif
- #endif
- RenderSystemCommand newCommand(commandCallback, _callbackId);
- mCommands->push_back(newCommand);
- }
- void RenderSystemFrameContext::submitToGpu()
- {
- {
- CM_LOCK_MUTEX(mCommandBufferMutex);
- if(mReadyCommands != nullptr)
- {
- delete mReadyCommands;
- mReadyCommands = nullptr;
- }
- mReadyCommands = mCommands;
- mCommands = new vector<RenderSystemCommand>::type();
- }
- }
- void RenderSystemFrameContext::playbackCommands()
- {
- #if CM_DEBUG_MODE
- RenderSystem* rs = RenderSystemManager::getActive();
- if(rs->getRenderThreadId() != CM_THREAD_CURRENT_ID)
- CM_EXCEPT(InternalErrorException, "This method should only be called from the render thread.");
- #endif
- vector<RenderSystemCommand>::type* currentCommands = nullptr;
- {
- CM_LOCK_MUTEX(mCommandBufferMutex)
- currentCommands = mReadyCommands;
- mReadyCommands = nullptr;
- mIsExecuting = true;
- }
- if(currentCommands == nullptr)
- {
- {
- CM_LOCK_MUTEX(mCommandBufferMutex);
- mIsExecuting = false;
- }
- CM_THREAD_NOTIFY_ALL(mContextPlaybackDoneCondition)
- return;
- }
- for(auto iter = currentCommands->begin(); iter != currentCommands->end(); ++iter)
- {
- RenderSystemCommand command = (*iter);
- if(command.returnsValue)
- {
- command.callbackWithReturnValue(command.asyncOp);
- if(!command.asyncOp.hasCompleted())
- {
- LOGDBG("Async operation return value wasn't resolved properly. Resolving automatically to nullptr. " \
- "Make sure to complete the operation before returning from the command callback method.");
- command.asyncOp.completeOperation(nullptr);
- }
- }
- else
- {
- command.callback();
- }
- }
- delete currentCommands;
- {
- CM_LOCK_MUTEX(mCommandBufferMutex);
- mIsExecuting = false;
- }
- CM_THREAD_NOTIFY_ALL(mContextPlaybackDoneCondition)
- }
- bool RenderSystemFrameContext::hasReadyCommands()
- {
- CM_LOCK_MUTEX(mCommandBufferMutex);
- if(mReadyCommands != nullptr && mReadyCommands->size() > 0)
- return true;
- return false;
- }
- void RenderSystemFrameContext::blockUntilExecuted()
- {
- #if CM_DEBUG_MODE
- RenderSystem* rs = RenderSystemManager::getActive();
- if(rs->getRenderThreadId() == CM_THREAD_CURRENT_ID)
- CM_EXCEPT(InternalErrorException, "This method should never be called from the render thread as it will cause a deadlock.");
- #endif
- {
- CM_LOCK_MUTEX_NAMED(mCommandBufferMutex, lock);
- while (mReadyCommands != nullptr && mReadyCommands->size() > 0 || mIsExecuting)
- {
- CM_THREAD_WAIT(mContextPlaybackDoneCondition, mCommandBufferMutex, lock)
- }
- }
- }
- /************************************************************************/
- /* IMMEDIATE CONTEXT */
- /************************************************************************/
- RenderSystemImmediateContext::RenderSystemImmediateContext(CM_THREAD_ID_TYPE threadId)
- :RenderSystemContext(threadId)
- {
- }
- AsyncOp RenderSystemImmediateContext::queueReturnCommand(boost::function<void(AsyncOp&)> commandCallback, UINT32 _callbackId)
- {
- CM_LOCK_MUTEX(mCommandBufferMutex)
- RenderSystemCommand newCommand(commandCallback, _callbackId);
- mCommands->push_back(newCommand);
- return newCommand.asyncOp;
- }
- void RenderSystemImmediateContext::queueCommand(boost::function<void()> commandCallback, UINT32 _callbackId)
- {
- CM_LOCK_MUTEX(mCommandBufferMutex)
- RenderSystemCommand newCommand(commandCallback, _callbackId);
- mCommands->push_back(newCommand);
- }
- void RenderSystemImmediateContext::submitToGpu()
- {
- // Do nothing
- }
- void RenderSystemImmediateContext::playbackCommands()
- {
- #if CM_DEBUG_MODE
- RenderSystem* rs = RenderSystemManager::getActive();
- if(rs->getRenderThreadId() != CM_THREAD_CURRENT_ID)
- CM_EXCEPT(InternalErrorException, "This method should only be called from the render thread.");
- #endif
- vector<RenderSystemCommand>::type* currentCommands = nullptr;
- {
- CM_LOCK_MUTEX(mCommandBufferMutex)
- currentCommands = mCommands;
- mCommands = new vector<RenderSystemCommand>::type();
- mIsExecuting = true;
- }
- if(currentCommands == nullptr)
- {
- {
- CM_LOCK_MUTEX(mCommandBufferMutex);
- mIsExecuting = false;
- }
- CM_THREAD_NOTIFY_ALL(mContextPlaybackDoneCondition)
- return;
- }
- for(auto iter = currentCommands->begin(); iter != currentCommands->end(); ++iter)
- {
- RenderSystemCommand command = (*iter);
- if(command.returnsValue)
- {
- command.callbackWithReturnValue(command.asyncOp);
- if(!command.asyncOp.hasCompleted())
- {
- LOGDBG("Async operation return value wasn't resolved properly. Resolving automatically to nullptr. " \
- "Make sure to complete the operation before returning from the command callback method.");
- command.asyncOp.completeOperation(nullptr);
- }
- }
- else
- {
- command.callback();
- }
- }
- delete currentCommands;
- {
- CM_LOCK_MUTEX(mCommandBufferMutex);
- mIsExecuting = false;
- }
- CM_THREAD_NOTIFY_ALL(mContextPlaybackDoneCondition)
- }
- bool RenderSystemImmediateContext::hasReadyCommands()
- {
- CM_LOCK_MUTEX(mCommandBufferMutex);
- if(mCommands != nullptr && mCommands->size() > 0)
- return true;
- return false;
- }
- void RenderSystemImmediateContext::blockUntilExecuted()
- {
- #if CM_DEBUG_MODE
- RenderSystem* rs = RenderSystemManager::getActive();
- if(rs->getRenderThreadId() == CM_THREAD_CURRENT_ID)
- CM_EXCEPT(InternalErrorException, "This method should never be called from the render thread as it will cause a deadlock.");
- #endif
- {
- CM_LOCK_MUTEX_NAMED(mCommandBufferMutex, lock);
- while (mCommands != nullptr && mCommands->size() > 0 || mIsExecuting)
- {
- CM_THREAD_WAIT(mContextPlaybackDoneCondition, mCommandBufferMutex, lock)
- }
- }
- }
- }
|