Просмотр исходного кода

write/readSubresource now accept GpuResourceData shared pointer which means the method no longer needs to be blocking
Rewrote Mesh::getSubMeshData because mesh data was being accessed from sim thread, yet it was written on core thread
And a couple of another smaller potential issues

Marko Pintera 12 лет назад
Родитель
Сommit
453fc2fe21
39 измененных файлов с 163 добавлено и 182 удалено
  1. 6 10
      BansheeEngine/Source/BsDrawHelper2D.cpp
  2. 5 10
      BansheeEngine/Source/BsDrawHelper3D.cpp
  3. 3 3
      BansheeEngine/Source/BsDrawHelperTemplate.cpp
  4. 10 7
      BansheeEngine/Source/BsGUIManager.cpp
  5. 1 1
      BansheeEngine/Source/BsImageSprite.cpp
  6. 1 1
      BansheeEngine/Source/BsRenderable.cpp
  7. 1 1
      BansheeEngine/Source/BsTextSprite.cpp
  8. 1 1
      BansheeForwardRenderer/Source/BsForwardRenderer.cpp
  9. 2 2
      CamelotClient/CamelotClient.cpp
  10. 2 3
      CamelotClient/Source/BsDockManager.cpp
  11. 1 1
      CamelotCore/CamelotCore.vcxproj
  12. 3 3
      CamelotCore/CamelotCore.vcxproj.filters
  13. 0 4
      CamelotCore/Include/CmCPUProfiler.h
  14. 8 8
      CamelotCore/Include/CmCoreThreadAccessor.h
  15. 16 0
      CamelotCore/Include/CmDrawOps.h
  16. 1 1
      CamelotCore/Include/CmGpuProgram.h
  17. 1 1
      CamelotCore/Include/CmGpuProgramParams.h
  18. 14 6
      CamelotCore/Include/CmMesh.h
  19. 1 1
      CamelotCore/Include/CmMeshData.h
  20. 0 32
      CamelotCore/Include/CmRenderOpMesh.h
  21. 3 2
      CamelotCore/Include/CmRenderOperation.h
  22. 1 1
      CamelotCore/Include/CmRenderQueue.h
  23. 5 4
      CamelotCore/Include/CmRenderSystem.h
  24. 2 4
      CamelotCore/Include/CmTextureRTTI.h
  25. 2 1
      CamelotCore/Source/CmApplication.cpp
  26. 19 22
      CamelotCore/Source/CmMesh.cpp
  27. 1 2
      CamelotCore/Source/CmMeshManager.cpp
  28. 2 3
      CamelotCore/Source/CmMeshRTTI.h
  29. 3 2
      CamelotCore/Source/CmRenderQueue.cpp
  30. 18 15
      CamelotCore/Source/CmRenderSystem.cpp
  31. 1 1
      CamelotCore/Source/CmTextureManager.cpp
  32. 1 1
      CamelotD3D11RenderSystem/Include/CmD3D11Mappings.h
  33. 1 2
      CamelotFBXImporter/Source/CmFBXImporter.cpp
  34. 3 4
      CamelotFontImporter/Source/CmFontImporter.cpp
  35. 1 1
      CamelotFreeImgImporter/Include/CmTextureData.h
  36. 1 2
      CamelotFreeImgImporter/Source/CmFreeImgImporter.cpp
  37. 6 3
      CamelotFreeImgImporter/Source/CmTextureData.cpp
  38. 2 0
      CamelotUtility/Include/CmFwdDeclUtil.h
  39. 14 16
      TODO.txt

+ 6 - 10
BansheeEngine/Source/BsDrawHelper2D.cpp

@@ -8,6 +8,7 @@
 #include "CmApplication.h"
 #include "CmApplication.h"
 #include "CmRenderQueue.h"
 #include "CmRenderQueue.h"
 #include "BsCamera.h"
 #include "BsCamera.h"
+#include "CmCoreThreadAccessor.h"
 #include "BsBuiltinMaterialManager.h"
 #include "BsBuiltinMaterialManager.h"
 
 
 using namespace CamelotFramework;
 using namespace CamelotFramework;
@@ -102,8 +103,7 @@ namespace BansheeEngine
 		(*colors) = color.getAsRGBA();
 		(*colors) = color.getAsRGBA();
 
 
 		HMesh mesh = Mesh::create();
 		HMesh mesh = Mesh::create();
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true);
+		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
 
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.mesh = mesh;
 		dbgCmd.worldCenter = Vector3::ZERO;
 		dbgCmd.worldCenter = Vector3::ZERO;
@@ -152,8 +152,7 @@ namespace BansheeEngine
 
 
 		HMesh mesh = Mesh::create();
 		HMesh mesh = Mesh::create();
 
 
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true);
+		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
 
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.mesh = mesh;
 		dbgCmd.worldCenter = Vector3::ZERO;
 		dbgCmd.worldCenter = Vector3::ZERO;
@@ -202,8 +201,7 @@ namespace BansheeEngine
 
 
 		HMesh mesh = Mesh::create();
 		HMesh mesh = Mesh::create();
 
 
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true);
+		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
 
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.mesh = mesh;
 		dbgCmd.worldCenter = Vector3::ZERO;
 		dbgCmd.worldCenter = Vector3::ZERO;
@@ -257,8 +255,7 @@ namespace BansheeEngine
 
 
 		HMesh mesh = Mesh::create();
 		HMesh mesh = Mesh::create();
 
 
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true);
+		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
 
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.mesh = mesh;
 		dbgCmd.worldCenter = Vector3::ZERO;
 		dbgCmd.worldCenter = Vector3::ZERO;
@@ -312,8 +309,7 @@ namespace BansheeEngine
 
 
 		HMesh mesh = Mesh::create();
 		HMesh mesh = Mesh::create();
 
 
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true);
+		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
 
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.mesh = mesh;
 		dbgCmd.worldCenter = Vector3::ZERO;
 		dbgCmd.worldCenter = Vector3::ZERO;

+ 5 - 10
BansheeEngine/Source/BsDrawHelper3D.cpp

@@ -77,8 +77,7 @@ namespace BansheeEngine
 
 
 		HMesh mesh = Mesh::create();
 		HMesh mesh = Mesh::create();
 
 
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true);
+		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
 
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.mesh = mesh;
 		dbgCmd.type = DebugDrawType::WorldSpace;
 		dbgCmd.type = DebugDrawType::WorldSpace;
@@ -112,8 +111,7 @@ namespace BansheeEngine
 
 
 		HMesh mesh = Mesh::create();
 		HMesh mesh = Mesh::create();
 
 
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true);
+		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
 
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.mesh = mesh;
 		dbgCmd.type = DebugDrawType::WorldSpace;
 		dbgCmd.type = DebugDrawType::WorldSpace;
@@ -147,8 +145,7 @@ namespace BansheeEngine
 
 
 		HMesh mesh = Mesh::create();
 		HMesh mesh = Mesh::create();
 
 
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true);
+		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
 
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.mesh = mesh;
 		dbgCmd.type = DebugDrawType::WorldSpace;
 		dbgCmd.type = DebugDrawType::WorldSpace;
@@ -183,8 +180,7 @@ namespace BansheeEngine
 
 
 		HMesh mesh = Mesh::create();
 		HMesh mesh = Mesh::create();
 
 
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true);
+		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
 
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.mesh = mesh;
 		dbgCmd.type = DebugDrawType::WorldSpace;
 		dbgCmd.type = DebugDrawType::WorldSpace;
@@ -229,8 +225,7 @@ namespace BansheeEngine
 
 
 		HMesh mesh = Mesh::create();
 		HMesh mesh = Mesh::create();
 
 
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true);
+		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
 
 
 		dbgCmd.mesh = mesh;
 		dbgCmd.mesh = mesh;
 		dbgCmd.type = DebugDrawType::WorldSpace;
 		dbgCmd.type = DebugDrawType::WorldSpace;

+ 3 - 3
BansheeEngine/Source/BsDrawHelperTemplate.cpp

@@ -36,20 +36,20 @@ namespace BansheeEngine
 
 
 			if(cmd.type == DebugDrawType::ClipSpace)
 			if(cmd.type == DebugDrawType::ClipSpace)
 			{
 			{
-				renderQueue.add(cmd.material, cmd.mesh->getSubMeshData(), cmd.worldCenter);
+				renderQueue.add(cmd.material, cmd.mesh, 0, cmd.worldCenter);
 			}
 			}
 			else if(cmd.type == DebugDrawType::ScreenSpace)
 			else if(cmd.type == DebugDrawType::ScreenSpace)
 			{
 			{
 				cmd.material->setFloat("invViewportWidth", invViewportWidth);
 				cmd.material->setFloat("invViewportWidth", invViewportWidth);
 				cmd.material->setFloat("invViewportHeight", invViewportHeight);
 				cmd.material->setFloat("invViewportHeight", invViewportHeight);
 
 
-				renderQueue.add(cmd.material, cmd.mesh->getSubMeshData(), cmd.worldCenter);
+				renderQueue.add(cmd.material, cmd.mesh, 0, cmd.worldCenter);
 			}
 			}
 			else if(cmd.type == DebugDrawType::WorldSpace)
 			else if(cmd.type == DebugDrawType::WorldSpace)
 			{
 			{
 				cmd.material->setMat4("matViewProj", viewProjMatrix);
 				cmd.material->setMat4("matViewProj", viewProjMatrix);
 
 
-				renderQueue.add(cmd.material, cmd.mesh->getSubMeshData(), cmd.worldCenter);
+				renderQueue.add(cmd.material, cmd.mesh, 0, cmd.worldCenter);
 			}
 			}
 		}
 		}
 
 

+ 10 - 7
BansheeEngine/Source/BsGUIManager.cpp

@@ -248,16 +248,22 @@ namespace BansheeEngine
 				GUIWidget* widget = renderData.cachedWidgetsPerMesh[meshIdx];
 				GUIWidget* widget = renderData.cachedWidgetsPerMesh[meshIdx];
 
 
 				if(material == nullptr || !material.isLoaded())
 				if(material == nullptr || !material.isLoaded())
+				{
+					meshIdx++;
 					continue;
 					continue;
+				}
 
 
 				if(mesh == nullptr || !mesh.isLoaded())
 				if(mesh == nullptr || !mesh.isLoaded())
+				{
+					meshIdx++;
 					continue;
 					continue;
+				}
 
 
 				material->setFloat("invViewportWidth", invViewportWidth);
 				material->setFloat("invViewportWidth", invViewportWidth);
 				material->setFloat("invViewportHeight", invViewportHeight);
 				material->setFloat("invViewportHeight", invViewportHeight);
 				material->setMat4("worldTransform", widget->SO()->getWorldTfrm());
 				material->setMat4("worldTransform", widget->SO()->getWorldTfrm());
 
 
-				renderQueue.add(material, mesh->getSubMeshData(), Vector3::ZERO);
+				renderQueue.add(material, mesh, 0, Vector3::ZERO);
 
 
 				meshIdx++;
 				meshIdx++;
 			}
 			}
@@ -501,8 +507,7 @@ namespace BansheeEngine
 					renderData.cachedMeshes.push_back(Mesh::create());
 					renderData.cachedMeshes.push_back(Mesh::create());
 				}
 				}
 
 
-				gMainSyncedCA().writeSubresource(renderData.cachedMeshes[groupIdx].getInternalPtr(), 0, *meshData);
-				gMainSyncedCA().submitToCoreThread(true); // TODO - Remove this once I make writeSubresource accept a shared_ptr for MeshData
+				gMainSyncedCA().writeSubresource(renderData.cachedMeshes[groupIdx].getInternalPtr(), 0, meshData);
 
 
 				groupIdx++;
 				groupIdx++;
 			}
 			}
@@ -523,8 +528,7 @@ namespace BansheeEngine
 
 
 		data->setColorAt(mCaretColor, 0, 0);
 		data->setColorAt(mCaretColor, 0, 0);
 
 
-		gMainSyncedCA().writeSubresource(tex.getInternalPtr(), tex->mapToSubresourceIdx(0, 0), *data);
-		gMainSyncedCA().submitToCoreThread(true); // TODO - Remove this once I make writeSubresource accept a shared_ptr for MeshData
+		gMainSyncedCA().writeSubresource(tex.getInternalPtr(), tex->mapToSubresourceIdx(0, 0), data);
 	}
 	}
 
 
 	void GUIManager::updateTextSelectionTexture()
 	void GUIManager::updateTextSelectionTexture()
@@ -541,8 +545,7 @@ namespace BansheeEngine
 
 
 		data->setColorAt(mTextSelectionColor, 0, 0);
 		data->setColorAt(mTextSelectionColor, 0, 0);
 
 
-		gMainSyncedCA().writeSubresource(tex.getInternalPtr(), tex->mapToSubresourceIdx(0, 0), *data);
-		gMainSyncedCA().submitToCoreThread(true); // TODO - Remove this once I make writeSubresource accept a shared_ptr for MeshData
+		gMainSyncedCA().writeSubresource(tex.getInternalPtr(), tex->mapToSubresourceIdx(0, 0), data);
 	}
 	}
 
 
 	bool GUIManager::onMouseDragEnded(const CM::PositionalInputEvent& event)
 	bool GUIManager::onMouseDragEnded(const CM::PositionalInputEvent& event)

+ 1 - 1
BansheeEngine/Source/BsImageSprite.cpp

@@ -54,7 +54,7 @@ namespace BansheeEngine
 
 
 			HMaterial newMaterial = GUIMaterialManager::instance().requestImageMaterial(desc.texture->getTexture());
 			HMaterial newMaterial = GUIMaterialManager::instance().requestImageMaterial(desc.texture->getTexture());
 			if(renderElem.material != nullptr)
 			if(renderElem.material != nullptr)
-				GUIMaterialManager::instance().releaseMaterial(newMaterial);
+				GUIMaterialManager::instance().releaseMaterial(renderElem.material);
 
 
 			renderElem.material = newMaterial;
 			renderElem.material = newMaterial;
 
 

+ 1 - 1
BansheeEngine/Source/BsRenderable.cpp

@@ -62,7 +62,7 @@ namespace BansheeEngine
 					}
 					}
 				}
 				}
 
 
-				renderQueue.add(mat, mMesh->getSubMeshData(i), mWorldBounds[i].getCenter());
+				renderQueue.add(mat, mMesh, i, mWorldBounds[i].getCenter());
 			}
 			}
 
 
 		}
 		}

+ 1 - 1
BansheeEngine/Source/BsTextSprite.cpp

@@ -75,7 +75,7 @@ namespace BansheeEngine
 
 
 			HMaterial newMaterial = GUIMaterialManager::instance().requestTextMaterial(texturePages[texPage]);
 			HMaterial newMaterial = GUIMaterialManager::instance().requestTextMaterial(texturePages[texPage]);
 			if(cachedElem.material != nullptr)
 			if(cachedElem.material != nullptr)
-				GUIMaterialManager::instance().releaseMaterial(newMaterial);
+				GUIMaterialManager::instance().releaseMaterial(cachedElem.material);
 
 
 			cachedElem.material = newMaterial;
 			cachedElem.material = newMaterial;
 
 

+ 1 - 1
BansheeForwardRenderer/Source/BsForwardRenderer.cpp

@@ -182,7 +182,7 @@ namespace BansheeEngine
 			PassParametersPtr paramsPtr = material->getPassParameters(iter->passIdx);
 			PassParametersPtr paramsPtr = material->getPassParameters(iter->passIdx);
 			pass->bindParameters(coreAccessor, paramsPtr);
 			pass->bindParameters(coreAccessor, paramsPtr);
 
 
-			coreAccessor.render(renderOp.meshData);
+			coreAccessor.render(renderOp.mesh.getInternalPtr(), renderOp.submeshIdx);
 		}
 		}
 	}
 	}
 }
 }

+ 2 - 2
CamelotClient/CamelotClient.cpp

@@ -45,7 +45,7 @@ using namespace BansheeEngine;
 
 
 void editorUpdate()
 void editorUpdate()
 {
 {
-	EditorWindowManager::instance().update();
+	EditorWindowManager::instance().update();	
 }
 }
 
 
 int CALLBACK WinMain(
 int CALLBACK WinMain(
@@ -267,7 +267,7 @@ int CALLBACK WinMain(
 	HTexture dbgCursor = static_resource_cast<Texture>(Importer::instance().import("C:\\CursorDbg.psd"));
 	HTexture dbgCursor = static_resource_cast<Texture>(Importer::instance().import("C:\\CursorDbg.psd"));
 	PixelDataPtr cursorPixelData = dbgCursor->allocateSubresourceBuffer(0);
 	PixelDataPtr cursorPixelData = dbgCursor->allocateSubresourceBuffer(0);
 
 
-	gMainSyncedCA().readSubresource(dbgCursor.getInternalPtr(), 0, *cursorPixelData);
+	gMainSyncedCA().readSubresource(dbgCursor.getInternalPtr(), 0, cursorPixelData);
 	gMainSyncedCA().submitToCoreThread(true);
 	gMainSyncedCA().submitToCoreThread(true);
 
 
 	//Cursor::setCustomCursor(*cursorPixelData, Int2(0, 0));
 	//Cursor::setCustomCursor(*cursorPixelData, Int2(0, 0));

+ 2 - 3
CamelotClient/Source/BsDockManager.cpp

@@ -246,7 +246,7 @@ namespace BansheeEditor
 
 
 		mDropOverlayMat->setColor("highlightActive", highlightColor);
 		mDropOverlayMat->setColor("highlightActive", highlightColor);
 
 
-		renderQueue.add(mDropOverlayMat, mDropOverlayMesh->getSubMeshData(), Vector3::ZERO);
+		renderQueue.add(mDropOverlayMat, mDropOverlayMesh, 0, Vector3::ZERO);
 	}
 	}
 
 
 	void DockManager::insert(EditorWidgetContainer* relativeTo, EditorWidget* widgetToInsert, DockLocation location)
 	void DockManager::insert(EditorWidgetContainer* relativeTo, EditorWidget* widgetToInsert, DockLocation location)
@@ -444,8 +444,7 @@ namespace BansheeEditor
 
 
 		mDropOverlayMesh = Mesh::create();
 		mDropOverlayMesh = Mesh::create();
 
 
-		gMainSyncedCA().writeSubresource(mDropOverlayMesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true);
+		gMainSyncedCA().writeSubresource(mDropOverlayMesh.getInternalPtr(), 0, meshData);
 	}
 	}
 
 
 	void DockManager::onGUIMouseEvent(GUIWidget* widget, GUIElement* element, const GUIMouseEvent& event)
 	void DockManager::onGUIMouseEvent(GUIWidget* widget, GUIElement* element, const GUIMouseEvent& event)

+ 1 - 1
CamelotCore/CamelotCore.vcxproj

@@ -276,6 +276,7 @@
     <ClInclude Include="Include\CmCPUProfiler.h" />
     <ClInclude Include="Include\CmCPUProfiler.h" />
     <ClInclude Include="Include\CmDefaultRenderQueue.h" />
     <ClInclude Include="Include\CmDefaultRenderQueue.h" />
     <ClInclude Include="Include\CmDeferredCallManager.h" />
     <ClInclude Include="Include\CmDeferredCallManager.h" />
+    <ClInclude Include="Include\CmDrawOps.h" />
     <ClInclude Include="Include\CmGameObjectHandle.h" />
     <ClInclude Include="Include\CmGameObjectHandle.h" />
     <ClInclude Include="Include\CmGameObject.h" />
     <ClInclude Include="Include\CmGameObject.h" />
     <ClInclude Include="Include\CmGameObjectRTTI.h" />
     <ClInclude Include="Include\CmGameObjectRTTI.h" />
@@ -360,7 +361,6 @@
     <ClInclude Include="Include\CmRenderer.h" />
     <ClInclude Include="Include\CmRenderer.h" />
     <ClInclude Include="Include\CmRendererFactory.h" />
     <ClInclude Include="Include\CmRendererFactory.h" />
     <ClInclude Include="Include\CmRendererManager.h" />
     <ClInclude Include="Include\CmRendererManager.h" />
-    <ClInclude Include="Include\CmRenderOpMesh.h" />
     <ClInclude Include="Include\CmRenderStateManager.h" />
     <ClInclude Include="Include\CmRenderStateManager.h" />
     <ClInclude Include="Include\CmRenderSystem.h" />
     <ClInclude Include="Include\CmRenderSystem.h" />
     <ClInclude Include="Include\CmRenderSystemCapabilities.h" />
     <ClInclude Include="Include\CmRenderSystemCapabilities.h" />

+ 3 - 3
CamelotCore/CamelotCore.vcxproj.filters

@@ -450,9 +450,6 @@
     <ClInclude Include="Include\CmDeferredCallManager.h">
     <ClInclude Include="Include\CmDeferredCallManager.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="Include\CmRenderOpMesh.h">
-      <Filter>Header Files\RenderSystem</Filter>
-    </ClInclude>
     <ClInclude Include="Include\CmDefaultRenderQueue.h">
     <ClInclude Include="Include\CmDefaultRenderQueue.h">
       <Filter>Header Files\Renderer</Filter>
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
     </ClInclude>
@@ -483,6 +480,9 @@
     <ClInclude Include="Include\Win32\CmWin32DropTarget.h">
     <ClInclude Include="Include\Win32\CmWin32DropTarget.h">
       <Filter>Header Files\Platform</Filter>
       <Filter>Header Files\Platform</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\CmDrawOps.h">
+      <Filter>Header Files\RenderSystem</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmApplication.cpp">
     <ClCompile Include="Source\CmApplication.cpp">

+ 0 - 4
CamelotCore/Include/CmCPUProfiler.h

@@ -6,8 +6,6 @@ namespace CamelotFramework
 {
 {
 	class CPUProfilerReport;
 	class CPUProfilerReport;
 
 
-	// TODO: Add #defines for all profiler methods so we can easily remove them from final version
-
 	/**
 	/**
 	 * @brief	Provides various performance measuring methods
 	 * @brief	Provides various performance measuring methods
 	 * 			
 	 * 			
@@ -78,8 +76,6 @@ namespace CamelotFramework
 
 
 		struct PreciseProfileData
 		struct PreciseProfileData
 		{
 		{
-			// TODO - Add cache misses, branch mispredictions, retired instructions vs. optimal number of cycles (RDPMC instruction on Intel)
-
 			Vector<PreciseProfileSample>::type samples;
 			Vector<PreciseProfileSample>::type samples;
 			TimerPrecise timer;
 			TimerPrecise timer;
 
 

+ 8 - 8
CamelotCore/Include/CmCoreThreadAccessor.h

@@ -197,9 +197,9 @@ namespace CamelotFramework
 
 
 
 
 		/** @copydoc RenderSystem::render() */
 		/** @copydoc RenderSystem::render() */
-		void render(const RenderOpMesh& op)
+		void render(const MeshPtr& mesh, UINT32 submeshIdx)
 		{
 		{
-			mCommandQueue->queue(boost::bind(&RenderSystem::render, RenderSystem::instancePtr(), op));
+			mCommandQueue->queue(boost::bind(&RenderSystem::render, RenderSystem::instancePtr(), mesh, submeshIdx));
 		}
 		}
 
 
 		/** @copydoc RenderSystem::draw() */
 		/** @copydoc RenderSystem::draw() */
@@ -221,11 +221,11 @@ namespace CamelotFramework
 		 * 		 Until the async operation completes "data" is owned by the core thread and you won't
 		 * 		 Until the async operation completes "data" is owned by the core thread and you won't
 		 * 		 be able to access it. 
 		 * 		 be able to access it. 
 		 */
 		 */
-		AsyncOp writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceData& data)
+		AsyncOp writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceDataPtr& data)
 		{
 		{
-			data.lock();
+			data->lock();
 
 
-			return mCommandQueue->queueReturn(boost::bind(&RenderSystem::writeSubresource, RenderSystem::instancePtr(), resource, subresourceIdx, boost::cref(data), _1));
+			return mCommandQueue->queueReturn(boost::bind(&RenderSystem::writeSubresource, RenderSystem::instancePtr(), resource, subresourceIdx, data, _1));
 		}
 		}
 
 
 		/**
 		/**
@@ -235,11 +235,11 @@ namespace CamelotFramework
 		 * 		 Until the async operation completes "data" is owned by the core thread and you won't
 		 * 		 Until the async operation completes "data" is owned by the core thread and you won't
 		 * 		 be able to access it.
 		 * 		 be able to access it.
 		 */
 		 */
-		AsyncOp readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceData& data)
+		AsyncOp readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceDataPtr& data)
 		{
 		{
-			data.lock();
+			data->lock();
 
 
-			return mCommandQueue->queueReturn(boost::bind(&RenderSystem::readSubresource, RenderSystem::instancePtr(), resource, subresourceIdx, boost::ref(data), _1));
+			return mCommandQueue->queueReturn(boost::bind(&RenderSystem::readSubresource, RenderSystem::instancePtr(), resource, subresourceIdx, data, _1));
 		}
 		}
 
 
 		void resizeWindow(RenderWindowPtr& renderWindow, UINT32 width, UINT32 height)
 		void resizeWindow(RenderWindowPtr& renderWindow, UINT32 width, UINT32 height)

+ 16 - 0
CamelotCore/Include/CmDrawOps.h

@@ -0,0 +1,16 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+
+namespace CamelotFramework
+{
+	enum DrawOperationType 
+	{
+		DOT_POINT_LIST = 1,
+		DOT_LINE_LIST = 2,
+		DOT_LINE_STRIP = 3,
+		DOT_TRIANGLE_LIST = 4,
+		DOT_TRIANGLE_STRIP = 5,
+		DOT_TRIANGLE_FAN = 6
+	};
+}

+ 1 - 1
CamelotCore/Include/CmGpuProgram.h

@@ -30,7 +30,7 @@ THE SOFTWARE.
 
 
 // Precompiler options
 // Precompiler options
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
-#include "CmRenderOpMesh.h"
+#include "CmDrawOps.h"
 #include "CmGpuProgramParams.h"
 #include "CmGpuProgramParams.h"
 #include "CmResource.h"
 #include "CmResource.h"
 #include "CmGpuParamDesc.h"
 #include "CmGpuParamDesc.h"

+ 1 - 1
CamelotCore/Include/CmGpuProgramParams.h

@@ -30,7 +30,7 @@ THE SOFTWARE.
 
 
 // Precompiler options
 // Precompiler options
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
-#include "CmRenderOpMesh.h"
+#include "CmDrawOps.h"
 #include "CmSamplerState.h"
 #include "CmSamplerState.h"
 
 
 namespace CamelotFramework {
 namespace CamelotFramework {

+ 14 - 6
CamelotCore/Include/CmMesh.h

@@ -5,23 +5,31 @@
 #include "CmMeshData.h"
 #include "CmMeshData.h"
 #include "CmVertexData.h"
 #include "CmVertexData.h"
 #include "CmIndexData.h"
 #include "CmIndexData.h"
-#include "CmRenderOpMesh.h"
+#include "CmDrawOps.h"
 
 
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {
 	struct CM_EXPORT SubMesh
 	struct CM_EXPORT SubMesh
 	{
 	{
-		SubMesh():
-			indexOffset(0), indexCount(0), drawOp(DOT_TRIANGLE_LIST)
+		SubMesh()
+			: indexOffset(0), indexCount(0), drawOp(DOT_TRIANGLE_LIST), 
+			vertexData(nullptr), indexData(nullptr), useIndexes(true)
 		{ }
 		{ }
 
 
-		SubMesh(UINT32 indexOffset, UINT32 indexCount, DrawOperationType drawOp):
-			indexOffset(indexOffset), indexCount(indexCount), drawOp(drawOp)
+		SubMesh(UINT32 indexOffset, UINT32 indexCount, DrawOperationType drawOp, 
+			std::shared_ptr<VertexData> vertexData, std::shared_ptr<IndexData> indexData, bool useIndexes):
+			indexOffset(indexOffset), indexCount(indexCount), drawOp(drawOp),
+			vertexData(vertexData), indexData(indexData), useIndexes(useIndexes)
 		{ }
 		{ }
 
 
 		UINT32 indexOffset;
 		UINT32 indexOffset;
 		UINT32 indexCount;
 		UINT32 indexCount;
 		DrawOperationType drawOp;
 		DrawOperationType drawOp;
+
+		std::shared_ptr<VertexData> vertexData;
+		std::shared_ptr<IndexData> indexData;
+
+		bool useIndexes;
 	};
 	};
 
 
 	class CM_EXPORT Mesh : public GpuResource
 	class CM_EXPORT Mesh : public GpuResource
@@ -59,7 +67,7 @@ namespace CamelotFramework
 		 */
 		 */
 		UINT32 mapToSubresourceIdx() const { return 0; }
 		UINT32 mapToSubresourceIdx() const { return 0; }
 
 
-		RenderOpMesh getSubMeshData(UINT32 subMeshIdx = 0) const;
+		const SubMesh& getSubMesh(UINT32 subMeshIdx = 0) const;
 		UINT32 getNumSubMeshes() const { return (UINT32)mSubMeshes.size(); }
 		UINT32 getNumSubMeshes() const { return (UINT32)mSubMeshes.size(); }
 
 
 		const AABox& getBounds() const;
 		const AABox& getBounds() const;

+ 1 - 1
CamelotCore/Include/CmMeshData.h

@@ -5,7 +5,7 @@
 #include "CmVertexBuffer.h"
 #include "CmVertexBuffer.h"
 #include "CmIndexBuffer.h"
 #include "CmIndexBuffer.h"
 #include "CmVertexDeclaration.h"
 #include "CmVertexDeclaration.h"
-#include "CmRenderOpMesh.h"
+#include "CmDrawOps.h"
 
 
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {

+ 0 - 32
CamelotCore/Include/CmRenderOpMesh.h

@@ -1,32 +0,0 @@
-#pragma once
-
-#include "CmPrerequisites.h"
-#include "CmVertexDeclaration.h"
-#include "CmVertexData.h"
-#include "CmIndexData.h"
-
-namespace CamelotFramework 
-{
-	enum DrawOperationType {
-		DOT_POINT_LIST = 1,
-		DOT_LINE_LIST = 2,
-		DOT_LINE_STRIP = 3,
-		DOT_TRIANGLE_LIST = 4,
-		DOT_TRIANGLE_STRIP = 5,
-		DOT_TRIANGLE_FAN = 6
-	};
-
-	struct RenderOpMesh
-	{
-		RenderOpMesh() 
-			:vertexData(nullptr), operationType(DOT_TRIANGLE_LIST), useIndexes(true),
-			indexData(nullptr) 
-		{ }
-
-		std::shared_ptr<VertexData> vertexData;
-		std::shared_ptr<IndexData> indexData;
-
-		DrawOperationType operationType;
-		bool useIndexes;
-	};
-}

+ 3 - 2
CamelotCore/Include/CmRenderOperation.h

@@ -1,7 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
-#include "CmRenderOpMesh.h"
+#include "CmDrawOps.h"
 #include "CmVector3.h"
 #include "CmVector3.h"
 
 
 namespace CamelotFramework 
 namespace CamelotFramework 
@@ -12,7 +12,8 @@ namespace CamelotFramework
 		{ }
 		{ }
 
 
 		HMaterial material;
 		HMaterial material;
-		RenderOpMesh meshData;
+		HMesh mesh;
+		UINT32 submeshIdx;
 		Vector3 worldPosition;
 		Vector3 worldPosition;
 	};
 	};
 }
 }

+ 1 - 1
CamelotCore/Include/CmRenderQueue.h

@@ -19,7 +19,7 @@ namespace CamelotFramework
 	public:
 	public:
 		RenderQueue();
 		RenderQueue();
 
 
-		void add(const HMaterial& material, const RenderOpMesh& mesh, const Vector3& worldPosForSort);
+		void add(const HMaterial& material, const HMesh& mesh, UINT32 submeshIdx, const Vector3& worldPosForSort);
 		void clear();
 		void clear();
 		
 		
 		virtual void sort() = 0;
 		virtual void sort() = 0;

+ 5 - 4
CamelotCore/Include/CmRenderSystem.h

@@ -39,12 +39,13 @@ THE SOFTWARE.
 #include "CmCommonEnums.h"
 #include "CmCommonEnums.h"
 
 
 #include "CmCommandQueue.h"
 #include "CmCommandQueue.h"
-#include "CmRenderOpMesh.h"
+#include "CmDrawOps.h"
 #include "CmRenderSystemCapabilities.h"
 #include "CmRenderSystemCapabilities.h"
 #include "CmRenderTarget.h"
 #include "CmRenderTarget.h"
 #include "CmRenderTexture.h"
 #include "CmRenderTexture.h"
 #include "CmRenderWindow.h"
 #include "CmRenderWindow.h"
 #include "CmGpuProgram.h"
 #include "CmGpuProgram.h"
+#include "CmVertexDeclaration.h"
 #include "CmPlane.h"
 #include "CmPlane.h"
 #include "CmModule.h"
 #include "CmModule.h"
 
 
@@ -184,7 +185,7 @@ namespace CamelotFramework
 		 * 			It will automatically set up vertex declaration, draw operation, 
 		 * 			It will automatically set up vertex declaration, draw operation, 
 		 * 			vertex and index buffers and draw them.
 		 * 			vertex and index buffers and draw them.
 		 */
 		 */
-		virtual void render(const RenderOpMesh& op);
+		virtual void render(const MeshPtr& mesh, UINT32 submeshIdx);
 
 
 		/**
 		/**
 		 * @brief	Draw an object based on currently set
 		 * @brief	Draw an object based on currently set
@@ -291,12 +292,12 @@ namespace CamelotFramework
 		/**
 		/**
 		 * @brief	Updates the resource with the specified data.
 		 * @brief	Updates the resource with the specified data.
 		 */
 		 */
-		void writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceData& data, AsyncOp& asyncOp);
+		void writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceDataPtr& data, AsyncOp& asyncOp);
 
 
 		/**
 		/**
 		 * @brief	Reads data from a resource into a pre-allocated GpuResourceData instance.
 		 * @brief	Reads data from a resource into a pre-allocated GpuResourceData instance.
 		 */
 		 */
-		void readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceData& data, AsyncOp& asyncOp);
+		void readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceDataPtr& data, AsyncOp& asyncOp);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								UTILITY METHODS                    		*/
 		/* 								UTILITY METHODS                    		*/

+ 2 - 4
CamelotCore/Include/CmTextureRTTI.h

@@ -39,7 +39,7 @@ namespace CamelotFramework
 
 
 			GpuResourcePtr sharedTexPtr = std::static_pointer_cast<GpuResource>(obj->getThisPtr());
 			GpuResourcePtr sharedTexPtr = std::static_pointer_cast<GpuResource>(obj->getThisPtr());
 
 
-			gMainSyncedCA().readSubresource(sharedTexPtr, subresourceIdx, *pixelData);
+			gMainSyncedCA().readSubresource(sharedTexPtr, subresourceIdx, pixelData);
 			gMainSyncedCA().submitToCoreThread(true); // We need the data right away, so execute the context and wait until we get it
 			gMainSyncedCA().submitToCoreThread(true); // We need the data right away, so execute the context and wait until we get it
 
 
 			return pixelData;
 			return pixelData;
@@ -113,11 +113,9 @@ namespace CamelotFramework
 				UINT32 subresourceIdx = texture->mapToSubresourceIdx(face, mipmap);
 				UINT32 subresourceIdx = texture->mapToSubresourceIdx(face, mipmap);
 
 
 				GpuResourcePtr sharedTexPtr = std::static_pointer_cast<GpuResource>(texture->getThisPtr());
 				GpuResourcePtr sharedTexPtr = std::static_pointer_cast<GpuResource>(texture->getThisPtr());
-				gMainSyncedCA().writeSubresource(sharedTexPtr, subresourceIdx, *pixelData->at(i));
+				gMainSyncedCA().writeSubresource(sharedTexPtr, subresourceIdx, pixelData->at(i));
 			}
 			}
 
 
-			gMainSyncedCA().submitToCoreThread(true); // TODO - Possibly we can avoid this. I don't see a reason we need to wait for the update to complete.
-
 			cm_delete<PoolAlloc>(pixelData);
 			cm_delete<PoolAlloc>(pixelData);
 			texture->mRTTIData = nullptr;	
 			texture->mRTTIData = nullptr;	
 		}
 		}

+ 2 - 1
CamelotCore/Source/CmApplication.cpp

@@ -123,8 +123,9 @@ namespace CamelotFramework
 			}
 			}
 
 
 			gCoreThread().queueCommand(&Platform::coreUpdate);
 			gCoreThread().queueCommand(&Platform::coreUpdate);
-			gCoreThread().queueCommand(boost::bind(&Application::endCoreProfiling, this));
 			PROFILE_CALL(mPrimaryCoreAccessor->submitToCoreThread(), "CommandSubmit");
 			PROFILE_CALL(mPrimaryCoreAccessor->submitToCoreThread(), "CommandSubmit");
+			PROFILE_CALL(mPrimarySyncedCoreAccessor->submitToCoreThread(), "SyncCommandSubmit");
+			gCoreThread().queueCommand(boost::bind(&Application::endCoreProfiling, this));
 			gCoreThread().queueCommand(boost::bind(&Application::frameRenderingFinishedCallback, this));
 			gCoreThread().queueCommand(boost::bind(&Application::frameRenderingFinishedCallback, this));
 
 
 			gTime().update();
 			gTime().update();

+ 19 - 22
CamelotCore/Source/CmMesh.cpp

@@ -31,19 +31,6 @@ namespace CamelotFramework
 
 
 		const MeshData& meshData = static_cast<const MeshData&>(data);
 		const MeshData& meshData = static_cast<const MeshData&>(data);
 
 
-		mSubMeshes.clear();
-
-		// Submeshes
-		for(UINT32 i = 0; i < meshData.getNumSubmeshes(); i++)
-		{
-			UINT32 numIndices = meshData.getNumIndices(i);
-
-			if(numIndices > 0)
-			{
-				mSubMeshes.push_back(SubMesh(meshData.getIndexBufferOffset(i), numIndices, meshData.getDrawOp(i)));
-			}
-		}
-
 		// Indices
 		// Indices
 		mIndexData = std::shared_ptr<IndexData>(cm_new<IndexData, PoolAlloc>());
 		mIndexData = std::shared_ptr<IndexData>(cm_new<IndexData, PoolAlloc>());
 
 
@@ -112,6 +99,19 @@ namespace CamelotFramework
 
 
 			vertexBuffer->unlock();
 			vertexBuffer->unlock();
 		}
 		}
+
+		// Submeshes
+		mSubMeshes.clear();
+
+		for(UINT32 i = 0; i < meshData.getNumSubmeshes(); i++)
+		{
+			UINT32 numIndices = meshData.getNumIndices(i);
+
+			if(numIndices > 0)
+			{
+				mSubMeshes.push_back(SubMesh(meshData.getIndexBufferOffset(i), numIndices, meshData.getDrawOp(i), mVertexData, mIndexData, true));
+			}
+		}
 	}
 	}
 
 
 	void Mesh::readSubresource(UINT32 subresourceIdx, GpuResourceData& data)
 	void Mesh::readSubresource(UINT32 subresourceIdx, GpuResourceData& data)
@@ -214,23 +214,20 @@ namespace CamelotFramework
 		return meshData;
 		return meshData;
 	}
 	}
 
 
-	RenderOpMesh Mesh::getSubMeshData(UINT32 subMeshIdx) const
+	const SubMesh& Mesh::getSubMesh(UINT32 subMeshIdx) const
 	{
 	{
+		THROW_IF_NOT_CORE_THREAD;
+
 		if(subMeshIdx < 0 || subMeshIdx >= mSubMeshes.size())
 		if(subMeshIdx < 0 || subMeshIdx >= mSubMeshes.size())
 		{
 		{
 			CM_EXCEPT(InvalidParametersException, "Invalid sub-mesh index (" 
 			CM_EXCEPT(InvalidParametersException, "Invalid sub-mesh index (" 
 				+ toString(subMeshIdx) + "). Number of sub-meshes available: " + toString((int)mSubMeshes.size()));
 				+ toString(subMeshIdx) + "). Number of sub-meshes available: " + toString((int)mSubMeshes.size()));
 		}
 		}
 
 
-		// TODO - BIG TODO - Completely ignores subMeshIdx and always renders the entire thing
-		// TODO - Creating a RenderOpMesh each call might be excessive considering this will be called a few thousand times a frame
-		RenderOpMesh ro;
-		ro.indexData = mIndexData;
-		ro.vertexData = mVertexData;
-		ro.useIndexes = true;
-		ro.operationType = mSubMeshes[subMeshIdx].drawOp;
+		// TODO - BIG TODO - Completely ignores subMeshIdx and always renders the entire thing because all submeshes
+		// will share the same buffers
 
 
-		return ro;
+		return mSubMeshes[subMeshIdx];
 	}
 	}
 
 
 	const AABox& Mesh::getBounds() const
 	const AABox& Mesh::getBounds() const

+ 1 - 2
CamelotCore/Source/CmMeshManager.cpp

@@ -53,7 +53,6 @@ namespace CamelotFramework
 		SyncedCoreAccessor& coreAccessor = gMainSyncedCA();
 		SyncedCoreAccessor& coreAccessor = gMainSyncedCA();
 
 
 		mDummyMesh = Mesh::create();
 		mDummyMesh = Mesh::create();
-		coreAccessor.writeSubresource(mDummyMesh.getInternalPtr(), 0, *mDummyMeshData);
-		coreAccessor.submitToCoreThread(true); // TODO - Only temporary until I fix write/read subresource
+		coreAccessor.writeSubresource(mDummyMesh.getInternalPtr(), 0, mDummyMeshData);
 	}
 	}
 }
 }

+ 2 - 3
CamelotCore/Source/CmMeshRTTI.h

@@ -16,7 +16,7 @@ namespace CamelotFramework
 
 
 			GpuResourcePtr sharedMeshPtr = std::static_pointer_cast<GpuResource>(obj->getThisPtr());
 			GpuResourcePtr sharedMeshPtr = std::static_pointer_cast<GpuResource>(obj->getThisPtr());
 
 
-			gMainSyncedCA().readSubresource(sharedMeshPtr, 0, *meshData);
+			gMainSyncedCA().readSubresource(sharedMeshPtr, 0, meshData);
 			gMainSyncedCA().submitToCoreThread(true); // We need the data right away, so execute the context and wait until we get it
 			gMainSyncedCA().submitToCoreThread(true); // We need the data right away, so execute the context and wait until we get it
 
 
 			return meshData;
 			return meshData;
@@ -26,8 +26,7 @@ namespace CamelotFramework
 		{ 
 		{ 
 			GpuResourcePtr sharedMeshPtr = std::static_pointer_cast<GpuResource>(obj->getThisPtr());
 			GpuResourcePtr sharedMeshPtr = std::static_pointer_cast<GpuResource>(obj->getThisPtr());
 
 
-			gMainSyncedCA().writeSubresource(sharedMeshPtr, 0, *meshData);
-			gMainSyncedCA().submitToCoreThread(true); // TODO - Possibly we can avoid this. I don't see a reason we need to wait for the update to complete.
+			gMainSyncedCA().writeSubresource(sharedMeshPtr, 0, meshData);
 		}
 		}
 
 
 	public:
 	public:

+ 3 - 2
CamelotCore/Source/CmRenderQueue.cpp

@@ -14,15 +14,16 @@ namespace CamelotFramework
 		mSortedRenderOps.clear();
 		mSortedRenderOps.clear();
 	}
 	}
 
 
-	void RenderQueue::add(const HMaterial& material, const RenderOpMesh& mesh, const Vector3& worldPosForSort)
+	void RenderQueue::add(const HMaterial& material, const HMesh& mesh, UINT32 submeshIdx, const Vector3& worldPosForSort)
 	{
 	{
 		// TODO - Make sure RenderOperations are cached so we dont allocate memory for them every frame
 		// TODO - Make sure RenderOperations are cached so we dont allocate memory for them every frame
 		mRenderOperations.push_back(RenderOperation());
 		mRenderOperations.push_back(RenderOperation());
 
 
 		RenderOperation& renderOp = mRenderOperations.back();
 		RenderOperation& renderOp = mRenderOperations.back();
 		renderOp.material = material;
 		renderOp.material = material;
-		renderOp.meshData = mesh;
+		renderOp.mesh = mesh;
 		renderOp.worldPosition = worldPosForSort;
 		renderOp.worldPosition = worldPosForSort;
+		renderOp.submeshIdx = submeshIdx;
 	}
 	}
 
 
 	const Vector<SortedRenderOp>::type& RenderQueue::getSortedRenderOps() const
 	const Vector<SortedRenderOp>::type& RenderQueue::getSortedRenderOps() const

+ 18 - 15
CamelotCore/Source/CmRenderSystem.cpp

@@ -42,6 +42,7 @@ THE SOFTWARE.
 #include "CmOcclusionQuery.h"
 #include "CmOcclusionQuery.h"
 #include "CmGpuResource.h"
 #include "CmGpuResource.h"
 #include "CmCoreThread.h"
 #include "CmCoreThread.h"
+#include "CmMesh.h"
 #include "boost/bind.hpp"
 #include "boost/bind.hpp"
 
 
 namespace CamelotFramework {
 namespace CamelotFramework {
@@ -205,11 +206,11 @@ namespace CamelotFramework {
         case GPT_FRAGMENT_PROGRAM:
         case GPT_FRAGMENT_PROGRAM:
             return mFragmentProgramBound;
             return mFragmentProgramBound;
 	    }
 	    }
-        // Make compiler happy
+
         return false;
         return false;
 	}
 	}
 
 
-	void RenderSystem::render(const RenderOpMesh& op)
+	void RenderSystem::render(const MeshPtr& mesh, UINT32 submeshIdx)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
@@ -221,21 +222,23 @@ namespace CamelotFramework {
 			mClipPlanesDirty = false;
 			mClipPlanesDirty = false;
 		}
 		}
 
 
-		setVertexDeclaration(op.vertexData->vertexDeclaration);
-		auto vertexBuffers = op.vertexData->getBuffers();
+		const SubMesh& subMesh = mesh->getSubMesh(submeshIdx);
+
+		setVertexDeclaration(subMesh.vertexData->vertexDeclaration);
+		auto vertexBuffers = subMesh.vertexData->getBuffers();
 
 
 		for(auto iter = vertexBuffers.begin(); iter != vertexBuffers.end() ; ++iter)
 		for(auto iter = vertexBuffers.begin(); iter != vertexBuffers.end() ; ++iter)
 			setVertexBuffer(iter->first, iter->second);
 			setVertexBuffer(iter->first, iter->second);
 
 
-		setDrawOperation(op.operationType);
+		setDrawOperation(subMesh.drawOp);
 
 
-		if (op.useIndexes)
+		if (subMesh.useIndexes)
 		{
 		{
-			setIndexBuffer(op.indexData->indexBuffer);
-			drawIndexed(op.indexData->indexStart, op.indexData->indexCount, op.vertexData->vertexCount);
+			setIndexBuffer(subMesh.indexData->indexBuffer);
+			drawIndexed(subMesh.indexData->indexStart, subMesh.indexData->indexCount, subMesh.vertexData->vertexCount);
 		}
 		}
 		else
 		else
-			draw(op.vertexData->vertexCount);
+			draw(subMesh.vertexData->vertexCount);
 	}
 	}
 
 
 	void RenderSystem::swapBuffers(RenderTargetPtr target)
 	void RenderSystem::swapBuffers(RenderTargetPtr target)
@@ -245,21 +248,21 @@ namespace CamelotFramework {
 		target->swapBuffers();
 		target->swapBuffers();
 	}
 	}
 
 
-	void RenderSystem::writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceData& data, AsyncOp& asyncOp)
+	void RenderSystem::writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceDataPtr& data, AsyncOp& asyncOp)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
-		resource->writeSubresource(subresourceIdx, data);
-		data.unlock();
+		resource->writeSubresource(subresourceIdx, *data);
+		data->unlock();
 		asyncOp.completeOperation();
 		asyncOp.completeOperation();
 	}
 	}
 
 
-	void RenderSystem::readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceData& data, AsyncOp& asyncOp)
+	void RenderSystem::readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceDataPtr& data, AsyncOp& asyncOp)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
-		resource->readSubresource(subresourceIdx, data);
-		data.unlock();
+		resource->readSubresource(subresourceIdx, *data);
+		data->unlock();
 		asyncOp.completeOperation();
 		asyncOp.completeOperation();
 	}
 	}
 }
 }

+ 1 - 1
CamelotCore/Source/CmTextureManager.cpp

@@ -58,7 +58,7 @@ namespace CamelotFramework
 		data->setColorAt(Color::Red, 1, 1);
 		data->setColorAt(Color::Red, 1, 1);
 
 
 		AsyncOp op;
 		AsyncOp op;
-		RenderSystem::instance().writeSubresource(mDummyTexture.getInternalPtr(), mDummyTexture->mapToSubresourceIdx(0, 0), *data, op);
+		RenderSystem::instance().writeSubresource(mDummyTexture.getInternalPtr(), mDummyTexture->mapToSubresourceIdx(0, 0), data, op);
 	}
 	}
 
 
     TexturePtr TextureManager::createTexture(TextureType texType, UINT32 width, UINT32 height, UINT32 depth, int numMipmaps,
     TexturePtr TextureManager::createTexture(TextureType texType, UINT32 width, UINT32 height, UINT32 depth, int numMipmaps,

+ 1 - 1
CamelotD3D11RenderSystem/Include/CmD3D11Mappings.h

@@ -8,7 +8,7 @@
 #include "CmVertexData.h"
 #include "CmVertexData.h"
 #include "CmIndexData.h"
 #include "CmIndexData.h"
 #include "CmSamplerState.h"
 #include "CmSamplerState.h"
-#include "CmRenderOpMesh.h"
+#include "CmDrawOps.h"
 
 
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {

+ 1 - 2
CamelotFBXImporter/Source/CmFBXImporter.cpp

@@ -51,8 +51,7 @@ namespace CamelotFramework
 		HMesh mesh = Mesh::create();
 		HMesh mesh = Mesh::create();
 
 
 		mesh.synchronize();
 		mesh.synchronize();
-		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, *meshData);
-		gMainSyncedCA().submitToCoreThread(true); // TODO - Possibly we can avoid this. I don't see a reason we need to wait for the update to complete.
+		gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
 
 
 		return mesh;
 		return mesh;
 	}
 	}

+ 3 - 4
CamelotFontImporter/Source/CmFontImporter.cpp

@@ -137,10 +137,10 @@ namespace CamelotFramework
 				UINT32 bufferSize = pageIter->width * pageIter->height * 2;
 				UINT32 bufferSize = pageIter->width * pageIter->height * 2;
 
 
 				// TODO - I don't actually need a 2 channel texture
 				// TODO - I don't actually need a 2 channel texture
-				PixelData pixelData(pageIter->width, pageIter->height, 1, PF_R8G8);
+				PixelDataPtr pixelData = cm_shared_ptr<PixelData>(pageIter->width, pageIter->height, 1, PF_R8G8);
 
 
-				pixelData.allocateInternalBuffer();
-				UINT8* pixelBuffer = pixelData.getData();
+				pixelData->allocateInternalBuffer();
+				UINT8* pixelBuffer = pixelData->getData();
 				memset(pixelBuffer, 0, bufferSize);
 				memset(pixelBuffer, 0, bufferSize);
 
 
 				for(size_t elementIdx = 0; elementIdx < atlasElements.size(); elementIdx++)
 				for(size_t elementIdx = 0; elementIdx < atlasElements.size(); elementIdx++)
@@ -273,7 +273,6 @@ namespace CamelotFramework
 
 
 				UINT32 subresourceIdx = newTex->mapToSubresourceIdx(0, 0);
 				UINT32 subresourceIdx = newTex->mapToSubresourceIdx(0, 0);
 				gMainSyncedCA().writeSubresource(newTex.getInternalPtr(), subresourceIdx, pixelData);
 				gMainSyncedCA().writeSubresource(newTex.getInternalPtr(), subresourceIdx, pixelData);
-				gMainSyncedCA().submitToCoreThread(true); // TODO - Possibly we can avoid this. I don't see a reason we need to wait for the update to complete.
 
 
 				fontData.texturePages.push_back(newTex);
 				fontData.texturePages.push_back(newTex);
 
 

+ 1 - 1
CamelotFreeImgImporter/Include/CmTextureData.h

@@ -71,7 +71,7 @@ namespace CamelotFramework
         */
         */
         bool getHasAlpha() const { return PixelUtil::getFlags(mFormat) & PFF_HASALPHA; }
         bool getHasAlpha() const { return PixelUtil::getFlags(mFormat) & PFF_HASALPHA; }
 
 
-		PixelData getPixels(UINT32 mip);
+		PixelDataPtr getPixels(UINT32 mip);
 
 
 	private:
 	private:
 		UINT32 mNumMipmaps;
 		UINT32 mNumMipmaps;

+ 1 - 2
CamelotFreeImgImporter/Source/CmFreeImgImporter.cpp

@@ -132,11 +132,10 @@ namespace CamelotFramework
 
 
 		for(UINT32 mip = 0; mip <= imgData->getNumMipmaps(); ++mip)
 		for(UINT32 mip = 0; mip <= imgData->getNumMipmaps(); ++mip)
 		{
 		{
-			PixelData src = imgData->getPixels(mip);
+			PixelDataPtr src = imgData->getPixels(mip);
 
 
 			UINT32 subresourceIdx = newTexture->mapToSubresourceIdx(0, mip);
 			UINT32 subresourceIdx = newTexture->mapToSubresourceIdx(0, mip);
 			gMainSyncedCA().writeSubresource(newTexture.getInternalPtr(), subresourceIdx, src);
 			gMainSyncedCA().writeSubresource(newTexture.getInternalPtr(), subresourceIdx, src);
-			gMainSyncedCA().submitToCoreThread(true); // TODO - Possibly we can avoid this. I don't see a reason we need to wait for the update to complete.
 		}
 		}
 
 
 		fileData->close();
 		fileData->close();

+ 6 - 3
CamelotFreeImgImporter/Source/CmTextureData.cpp

@@ -18,7 +18,7 @@ namespace CamelotFramework
 			cm_free<ScratchAlloc>(mData);
 			cm_free<ScratchAlloc>(mData);
 	}
 	}
 
 
-	PixelData TextureData::getPixels(UINT32 mip)
+	PixelDataPtr TextureData::getPixels(UINT32 mip)
 	{
 	{
 		if(mip < 0 || mip > mNumMipmaps)
 		if(mip < 0 || mip > mNumMipmaps)
 		{
 		{
@@ -52,8 +52,11 @@ namespace CamelotFramework
 		}
 		}
 
 
 		// Return subface as pixelbox
 		// Return subface as pixelbox
-		PixelData src(finalWidth, finalHeight, finalDepth, getFormat());
-		src.setExternalBuffer(offset);
+		PixelDataPtr src = cm_shared_ptr<PixelData>(finalWidth, finalHeight, finalDepth, getFormat());
+		src->allocateInternalBuffer();
+
+		memcpy(src->getData(), offset, src->getConsecutiveSize());
+
 		return src;
 		return src;
 	}
 	}
 }
 }

+ 2 - 0
CamelotUtility/Include/CmFwdDeclUtil.h

@@ -30,6 +30,7 @@ namespace CamelotFramework {
 	class MeshData;
 	class MeshData;
 	class FileSystem;
 	class FileSystem;
 	class Timer;
 	class Timer;
+	class GpuResourceData;
 	class PixelData;
 	class PixelData;
 	class HString;
 	class HString;
 	class StringTable;
 	class StringTable;
@@ -46,4 +47,5 @@ namespace CamelotFramework {
 	typedef std::shared_ptr<FileDataStream> FileDataStreamPtr;
 	typedef std::shared_ptr<FileDataStream> FileDataStreamPtr;
 	typedef std::shared_ptr<MeshData> MeshDataPtr;
 	typedef std::shared_ptr<MeshData> MeshDataPtr;
 	typedef std::shared_ptr<PixelData> PixelDataPtr;
 	typedef std::shared_ptr<PixelData> PixelDataPtr;
+	typedef std::shared_ptr<GpuResourceData> GpuResourceDataPtr;
 }
 }

+ 14 - 16
TODO.txt

@@ -1,34 +1,31 @@
 ----------------------- CAMELOT 2D / GUI -----------------------------------------------------------
 ----------------------- CAMELOT 2D / GUI -----------------------------------------------------------
 
 
 LONGTERM TODO:
 LONGTERM TODO:
-1. Finish localization
-2. Finish docking manager
-3. Window drag'n'drop detect
-4. Basic profiler
-  - When building a profiler have main Profiler class which just does measurements, then ProfilerOverlay for data display on-screen, ProfilerEditor for Unity-like Profiler, etc.
-  - For now just create a profiler with basic measuring stats (FPS, core & sim thread time, plus times for most important systems), and ProfilerOverlay to display them
+1. Finish docking manager
+2. OPTIMIZE GUI
+ - This should be a fairly long-term task, about 2 months. I need to study GUI system in detail and identify bottlenecks.
+   Then develop a clear and tight plan how to reorganize everything so it runs at maximum efficiency. GUI system is pretty much the 
+   only large fully fledged system in the engine, so investing this much time into optimizing it is worth it.
 
 
-WEEKEND - Finish up docking? Or get windows dock manager working
- - FIX THE DAMN 200 WARNINGS!
+Optimization notes:
+ - submitToCoreThread calls are EXTREMELY slow. In 10-50ms range.
+ - GUIManager updateMeshes seems to be executing every frame
+
+WEIRDNESS:
+Using gMainCA instead of gSyncedMainCA in GUIManager causes linker errors
+Calling syncedCA->submit in Application::update instead of GUIManager causes the textures to constantly switch out every frame
+ - Calling it right after GUIManager::update also works, but if I call it after BsApp update it doesnt!? Even though nothing is done in BsApp update except for calling GUIManager::update...
 
 
 TODO: Viewport can be modified from the sim thread, but is used on the core thread without any syncronization mechanisms. Maybe add a method that returns VIEWPORT_DATA, and have that used on the core thread.
 TODO: Viewport can be modified from the sim thread, but is used on the core thread without any syncronization mechanisms. Maybe add a method that returns VIEWPORT_DATA, and have that used on the core thread.
 
 
 I still re-create GUIWidget mesh every frame instead of just updating it.
 I still re-create GUIWidget mesh every frame instead of just updating it.
 
 
-MAJOR ISSUE: writeSubresource/readSubresoure doesn't require a shared ptr to GpuResourceData which means it could get destroyed while still in command queue. Right now it only works because I block right after I call those methods, which ensures nothing is destroyed.
-  - When fixed, make sure I remove blocking calls after writeSubresource where they're not needed (GUIManager for example)
 I call waitUntilLoaded too many times. Sometimes 5-6 times in a single function. Each of those calls will be extremely slow.
 I call waitUntilLoaded too many times. Sometimes 5-6 times in a single function. Each of those calls will be extremely slow.
 GUIWidget::updateMeshes leaks. If I leave the game running I can see memory continously going up
 GUIWidget::updateMeshes leaks. If I leave the game running I can see memory continously going up
  - BansheeApplication should probably derive from Camlelot application. Right now user needs to know the difference between 
  - BansheeApplication should probably derive from Camlelot application. Right now user needs to know the difference between 
    gApplication and gBansheeApp, which is non-intuitive (e.g. retrieving a window can be done on gApplication, but running main loop can happen on both
    gApplication and gBansheeApp, which is non-intuitive (e.g. retrieving a window can be done on gApplication, but running main loop can happen on both
 
 
- Windows drag and drop detect
-  - http://www.codeguru.com/cpp/misc/misc/draganddrop/article.php/c349/Drag-And-Drop-between-Window-Controls.htm
-  - http://www.catch22.net/tuts/drop-target
-  - http://msdn.microsoft.com/en-us/library/windows/desktop/bb776902(v=vs.85).aspx
-
 IMMEDIATE:
 IMMEDIATE:
- - OpenGL rendering slows to extremely with time (seems to be related to rendering, possibly GUI, possibly in general Pass/Material/Shader/PassParams)
  - Update debug camera so it uses callbacks
  - Update debug camera so it uses callbacks
  
  
  - I have disabled linear filtering because it doesn't look good on scale9grid textures. (Add another material so it works with stretched textures?)
  - I have disabled linear filtering because it doesn't look good on scale9grid textures. (Add another material so it works with stretched textures?)
@@ -156,3 +153,4 @@ Optional:
  - Vertex buffer start offset is not supported when calling Draw methods
  - Vertex buffer start offset is not supported when calling Draw methods
  - When rendering Scale9Grid GUI elements the stretched center will cause linear interpolation to kick in and blend the edges with the border parts of the texture.
  - When rendering Scale9Grid GUI elements the stretched center will cause linear interpolation to kick in and blend the edges with the border parts of the texture.
   - I should use point filtering for scale9grid, but that doesn't work in general case for stretched textures as they would look bad
   - I should use point filtering for scale9grid, but that doesn't work in general case for stretched textures as they would look bad
+ - Win32DropTarget: I need to be able to set drop DROPEFFECT when various IDropTarget methods are called. Otherwise the drag cursor always remains the same, whether the drag will be accepted or not.