diff --git a/source/SkyXEngine.h b/source/SkyXEngine.h
index 33a90bd6224f2d95007c27ca4e0dde76f0423a3c..cd3cb60f7bbd1c8c360b6ff1ed1f5381b891333c 100644
--- a/source/SkyXEngine.h
+++ b/source/SkyXEngine.h
@@ -292,7 +292,7 @@ QT стиль документирования (!) и QT_AUTOBRIEF - корот
 #ifndef __SKYXENGINE_H
 #define __SKYXENGINE_H
 
-#define SKYXENGINE_VERSION "X.7.0-dev"
+#define SKYXENGINE_VERSION "X.7.0"
 
 #define SKYXENGINE_VERSION4EDITORS "SkyXEngine version " ## SKYXENGINE_VERSION
 
diff --git a/source/anim/DynamicModelProvider.cpp b/source/anim/DynamicModelProvider.cpp
index a535262fb278981a478d1938de8cfb7a5e3a4d14..7e85e07760c6fd57f1913dd9b0efec8803d830c0 100644
--- a/source/anim/DynamicModelProvider.cpp
+++ b/source/anim/DynamicModelProvider.cpp
@@ -87,6 +87,67 @@ protected:
 };
 */
 
+class CVisUpdate: public IParallelForBody
+{
+public:
+	CVisUpdate(const IFrustum *pFrustum, CRenderableVisibility *pVisibility, CRenderableVisibility *pReference, Array<CDynamicModel*> &m_apModels):
+		m_pFrustum(pFrustum),
+		m_pVisibility(pVisibility),
+		m_pReference(pReference),
+		m_apModels(m_apModels)
+	{
+	}
+
+	void forLoop(int iStart, int iEnd) const
+	{
+		CDynamicModel *pMdl;
+		for(int i = iStart; i < iEnd; ++i)
+		{
+			pMdl = m_apModels[i];
+			auto *pItem = m_pVisibility->getItemDynamic(i);
+			if(pMdl->isEnabled())
+			{
+				float3 vDelta = pMdl->getPosition();
+				pItem->isVisible = (m_pReference ? m_pReference->getItemDynamic(i)->isVisible : true)
+					&& m_pFrustum->boxInFrustum(&float3(pMdl->getLocalBoundMin() + vDelta), &float3(pMdl->getLocalBoundMax() + vDelta));
+
+				if(pItem->isVisible)
+				{
+					pItem->isTransparent = pMdl->hasTransparentSubsets(pItem->uLod);
+					if(pItem->isTransparent)
+					{
+						IXMaterial *pMaterial = pMdl->getTransparentMaterial(pItem->uLod);
+						UINT uPSPcount = pMdl->getPSPcount(pItem->uLod);
+						{
+							ScopedLock lock(m_transparency);
+							if(uPSPcount)
+							{
+								m_pVisibility->addItemTransparentDynamic({pMdl, true, pMdl->getPSP(pItem->uLod, 0), 0, pMaterial});
+							}
+							else
+							{
+								m_pVisibility->addItemTransparentDynamic({pMdl, false, SMPLANE(), 0, pMaterial});
+							}
+						}
+						mem_release(pMaterial);
+					}
+				}
+			}
+			else
+			{
+				pItem->isVisible = false;
+			}
+		}
+	};
+
+protected:
+	const IFrustum *m_pFrustum;
+	CRenderableVisibility *m_pVisibility;
+	CRenderableVisibility *m_pReference;
+	Array<CDynamicModel*> &m_apModels;
+	mutable mutex m_transparency;
+};
+
 //##########################################################################
 
 CDynamicModelProvider::CDynamicModelProvider(IXCore *pCore):
@@ -290,7 +351,11 @@ void CDynamicModelProvider::computeVisibility(const IFrustum *pFrustum, CRendera
 {
 	pVisibility->setItemCountDynamic(m_apModels.size());
 	pVisibility->resetItemTransparentDynamic();
-
+#if 1
+	CVisUpdate cycle(pFrustum, pVisibility, pReference, m_apModels);
+	ID id = m_pCore->getAsyncTaskRunner()->forLoop(0, m_apModels.size(), &cycle, 500);
+	m_pCore->getAsyncTaskRunner()->waitForLoop(id);
+#else
 	CDynamicModel *pMdl;
 	for(UINT i = 0, l = m_apModels.size(); i < l; ++i)
 	{
@@ -305,9 +370,9 @@ void CDynamicModelProvider::computeVisibility(const IFrustum *pFrustum, CRendera
 			if(pItem->isVisible)
 			{
 				pItem->isTransparent = pMdl->hasTransparentSubsets(pItem->uLod);
-				IXMaterial *pMaterial = pMdl->getTransparentMaterial(pItem->uLod);
 				if(pItem->isTransparent)
 				{
+					IXMaterial *pMaterial = pMdl->getTransparentMaterial(pItem->uLod);
 					UINT uPSPcount = pMdl->getPSPcount(pItem->uLod);
 					if(uPSPcount)
 					{
@@ -317,8 +382,8 @@ void CDynamicModelProvider::computeVisibility(const IFrustum *pFrustum, CRendera
 					{
 						pVisibility->addItemTransparentDynamic({pMdl, false, SMPLANE(), 0, pMaterial});
 					}
+					mem_release(pMaterial);
 				}
-				mem_release(pMaterial);
 			}
 		}
 		else
@@ -326,6 +391,7 @@ void CDynamicModelProvider::computeVisibility(const IFrustum *pFrustum, CRendera
 			pItem->isVisible = false;
 		}
 	}
+#endif
 }
 
 void CDynamicModelProvider::getLevelSize(const XEventLevelSize *pData)
diff --git a/source/core/AsyncTaskRunner.cpp b/source/core/AsyncTaskRunner.cpp
index 56d116c4464d3d73381b808ae38e2f3adaf8afa0..8c407ce60a3d413093b379795eb7fc3c8df83504 100644
--- a/source/core/AsyncTaskRunner.cpp
+++ b/source/core/AsyncTaskRunner.cpp
@@ -154,3 +154,12 @@ void XMETHODCALLTYPE CAsyncTaskRunner::runCallbacks()
 		g_pTaskManager->addTask(m_vpQueue[0]);
 	}
 }
+
+ID XMETHODCALLTYPE CAsyncTaskRunner::forLoop(int iStart, int iEnd, const IParallelForBody *pBody, int iMaxChunkSize)
+{
+	return(g_pTaskManager->forLoop(iStart, iEnd, pBody, iMaxChunkSize));
+}
+void XMETHODCALLTYPE CAsyncTaskRunner::waitForLoop(ID id)
+{
+	g_pTaskManager->waitFor(id);
+}
diff --git a/source/core/AsyncTaskRunner.h b/source/core/AsyncTaskRunner.h
index 8b5275246f7894d893ab46339a67c5890d0d8e81..9d2a2ea298df20f106ca82bda1ac282be2218486 100644
--- a/source/core/AsyncTaskRunner.h
+++ b/source/core/AsyncTaskRunner.h
@@ -15,6 +15,9 @@ public:
 	void XMETHODCALLTYPE runTask(IAsyncTask *pTask) override;
 	void XMETHODCALLTYPE runCallbacks() override;
 
+	ID XMETHODCALLTYPE forLoop(int iStart, int iEnd, const IParallelForBody *pBody, int iMaxChunkSize = 0) override;
+	void XMETHODCALLTYPE waitForLoop(ID id) override;
+
 protected:
 	IXCore *m_pCore;
 
diff --git a/source/core/TaskManager.cpp b/source/core/TaskManager.cpp
index db6ada934593dcf3c0221b0a744309038af0c598..0ecc383bcf207ccd21625a8c258c9417cf12c4e6 100644
--- a/source/core/TaskManager.cpp
+++ b/source/core/TaskManager.cpp
@@ -225,7 +225,7 @@ void CTaskManager::synchronize()
 	{
 		execute(m_OnSyncTasks.pop());
 	}
-
+	g_pPerfMon->syncBegin();
 	/*std::unique_lock<std::mutex> lock(m_mutexSync);
 
 	while(m_iNumTasksToWaitFor > 0)
diff --git a/source/core/sxcore.h b/source/core/sxcore.h
index c9a84844274bdc2a7f83ee82d42e258775a2b8d8..bf665fe3825f52960da96633f1ac9aa9d9230d15 100644
--- a/source/core/sxcore.h
+++ b/source/core/sxcore.h
@@ -141,7 +141,7 @@ SX_LIB_API ID Core_MGetThreadID();
 //! получить количество потоков
 SX_LIB_API int Core_MGetThreadCount();
 
-
+#if 0
 class IParallelForBody
 {
 public:
@@ -149,6 +149,7 @@ public:
 
 	virtual void forLoop(int iStart, int iEnd) const = 0;
 };
+#endif
 
 //! запускает в параллельную обработку pBody
 SX_LIB_API ID Core_MForLoop(int iStart, int iEnd, const IParallelForBody *pBody, int iMaxChunkSize = 0);
@@ -184,9 +185,9 @@ enum PERF_SECTION
 	PERF_SECTION_AMBIENT_SND_UPDATE, // 8
 	PERF_SECTION_MATSORT_UPDATE, // 9
 	PERF_SECTION_OC_REPROJECTION, // A
-	PERF_SECTION_VIS_CAMERA, // B
+	PERF_SECTION_VIS_ALL, // B
 	PERF_SECTION_RENDER, // C
-	PERF_SECTION_SML_UPDATE, // D
+	PERF_SECTION_CORE_UPDATE, // D
 	PERF_SECTION_SHADOW_UPDATE, // E
 	PERF_SECTION_MRT, // F
 	PERF_SECTION_LIGHTING, // G
@@ -226,9 +227,9 @@ static const char *g_szPerfSectionName[] = {
 	"Ambient sound update",
 	"Matsort update",
 	"OC reprojection",
-	"Vis camera",
+	"Vis all",
 	"Render overall",
-	"SML update",
+	"Core update",
 	"Shadow update",
 	"Render MRT",
 	"Render lighting",
diff --git a/source/xEngine/Engine.cpp b/source/xEngine/Engine.cpp
index 9b85b4f9ddc3610b5c916d30a971f8972e8883b8..8ac1a687d138d033f58330c8adafddf2f67642af 100644
--- a/source/xEngine/Engine.cpp
+++ b/source/xEngine/Engine.cpp
@@ -238,7 +238,7 @@ bool CEngine::runFrame()
 	Core_0ConsoleUpdate();
 
 	SSInput_Update();
-
+	
 	
 	// draw frame
 	{
@@ -250,19 +250,31 @@ bool CEngine::runFrame()
 
 		//#############################################################################
 
+		Core_PStartSection(PERF_SECTION_GAME_UPDATE);
 		SGame_Update();
+		Core_PEndSection(PERF_SECTION_GAME_UPDATE);
 
+		Core_PStartSection(PERF_SECTION_PHYS_UPDATE);
 		SPhysics_Update();
+		Core_PEndSection(PERF_SECTION_PHYS_UPDATE);
 
 		//#############################################################################
 
+		Core_PStartSection(PERF_SECTION_PHYS_SYNC);
 		SPhysics_Sync();
+		Core_PEndSection(PERF_SECTION_PHYS_SYNC);
 
+		Core_PStartSection(PERF_SECTION_GAME_SYNC);
 		SGame_Sync();
+		Core_PEndSection(PERF_SECTION_GAME_SYNC);
 
+		Core_PStartSection(PERF_SECTION_MATSORT_UPDATE);
 		SMtrl_Update(0);
+		Core_PEndSection(PERF_SECTION_MATSORT_UPDATE);
 
+		Core_PStartSection(PERF_SECTION_CORE_UPDATE);
 		m_pCore->runUpdate();
+		Core_PEndSection(PERF_SECTION_CORE_UPDATE);
 		
 		//#############################################################################
 
@@ -275,12 +287,19 @@ bool CEngine::runFrame()
 			IXRenderPipeline *pRenderPipeline;
 			m_pCore->getRenderPipeline(&pRenderPipeline);
 
+			Core_PStartSection(PERF_SECTION_VIS_ALL);
 			pRenderPipeline->updateVisibility();
+			Core_PEndSection(PERF_SECTION_VIS_ALL);
+
+			Core_PStartSection(PERF_SECTION_RENDER_PRESENT);
 			pRenderPipeline->endFrame();
+			Core_PEndSection(PERF_SECTION_RENDER_PRESENT);
 
+			Core_PStartSection(PERF_SECTION_RENDER);
 			pRenderContext->getThreadContext()->beginFrame();
 			pRenderPipeline->renderFrame();
 			pRenderContext->getThreadContext()->endFrame();
+			Core_PEndSection(PERF_SECTION_RENDER);
 
 			mem_release(pRenderPipeline);
 		}
diff --git a/source/xcommon/IAsyncTaskRunner.h b/source/xcommon/IAsyncTaskRunner.h
index b4027a09ebd44a48a809712aedc177a4950d6f86..b98b32220eb5cff5300cfb51cd7c82f33a226b89 100644
--- a/source/xcommon/IAsyncTaskRunner.h
+++ b/source/xcommon/IAsyncTaskRunner.h
@@ -3,6 +3,15 @@
 
 #include <gdefines.h>
 
+
+class IParallelForBody
+{
+public:
+	virtual ~IParallelForBody() = default;
+
+	virtual void forLoop(int iStart, int iEnd) const = 0;
+};
+
 class IAsyncTask: public IXUnknown
 {
 public:
@@ -25,6 +34,9 @@ class IAsyncTaskRunner: public IXUnknown
 public:
 	virtual void XMETHODCALLTYPE runTask(IAsyncTask *pTask) = 0;
 	virtual void XMETHODCALLTYPE runCallbacks() = 0;
+
+	virtual ID XMETHODCALLTYPE forLoop(int iStart, int iEnd, const IParallelForBody *pBody, int iMaxChunkSize = 0) = 0;
+	virtual void XMETHODCALLTYPE waitForLoop(ID id) = 0;
 };
 
 #endif