diff --git a/Assets/Cube.003.shmesh.shmeta b/Assets/Cube.003.shmesh.shmeta
index d41be546..207f3999 100644
--- a/Assets/Cube.003.shmesh.shmeta
+++ b/Assets/Cube.003.shmesh.shmeta
@@ -1,3 +1,3 @@
 Name: Cube.003
 ID: 110152941
-Type: 
+Type: 6
diff --git a/Assets/Cube.012.shmesh.shmeta b/Assets/Cube.012.shmesh.shmeta
index d5cd1090..3af04f93 100644
--- a/Assets/Cube.012.shmesh.shmeta
+++ b/Assets/Cube.012.shmesh.shmeta
@@ -1,3 +1,3 @@
 Name: Cube.012
 ID: 107348815
-Type: 
+Type: 6
diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini
new file mode 100644
index 00000000..baced6b8
--- /dev/null
+++ b/Assets/Editor/Layouts/UserLayout.ini
@@ -0,0 +1,54 @@
+[Window][MainStatusBar]
+Pos=0,1060
+Size=1920,20
+Collapsed=0
+
+[Window][SHEditorMenuBar]
+Pos=0,48
+Size=1920,1012
+Collapsed=0
+
+[Window][Hierarchy Panel]
+Pos=0,142
+Size=387,918
+Collapsed=0
+DockId=0x00000004,0
+
+[Window][Debug##Default]
+Pos=60,60
+Size=400,400
+Collapsed=0
+
+[Window][Inspector]
+Pos=1649,48
+Size=271,1012
+Collapsed=0
+DockId=0x00000006,0
+
+[Window][Profiler]
+Pos=0,48
+Size=387,92
+Collapsed=0
+DockId=0x00000003,0
+
+[Window][Viewport]
+Pos=648,48
+Size=2519,1319
+Collapsed=0
+DockId=0x00000002,0
+
+[Window][ Viewport]
+Pos=389,48
+Size=1258,1012
+Collapsed=0
+DockId=0x00000002,0
+
+[Docking][Data]
+DockSpace       ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
+  DockNode      ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X
+    DockNode    ID=0x00000001 Parent=0x00000005 SizeRef=387,1036 Split=Y Selected=0x1E6EB881
+      DockNode  ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
+      DockNode  ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
+    DockNode    ID=0x00000002 Parent=0x00000005 SizeRef=1258,1036 CentralNode=1 Selected=0xB41284E7
+  DockNode      ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252
+
diff --git a/Assets/RaccoonPreTexturedVer1_Base9.shtex.shmeta b/Assets/RaccoonPreTexturedVer1_Base9.shtex.shmeta
index f8c267d9..3905aa4f 100644
--- a/Assets/RaccoonPreTexturedVer1_Base9.shtex.shmeta
+++ b/Assets/RaccoonPreTexturedVer1_Base9.shtex.shmeta
@@ -1,3 +1,3 @@
 Name: RaccoonPreTexturedVer1_Base9
 ID: 91918845
-Type: 
+Type: 4
diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp
index 63383a44..a93148d5 100644
--- a/SHADE_Application/src/Application/SBApplication.cpp
+++ b/SHADE_Application/src/Application/SBApplication.cpp
@@ -95,6 +95,7 @@ namespace Sandbox
     SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
 
     SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
+    SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::CameraSystemUpdate>();
     
 #ifdef SHEDITOR
     SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();
diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp
index ef25dd20..ad886aa8 100644
--- a/SHADE_Application/src/Scenes/SBTestScene.cpp
+++ b/SHADE_Application/src/Scenes/SBTestScene.cpp
@@ -14,6 +14,7 @@
 #include "Physics/Components/SHColliderComponent.h"
 
 #include "Assets/SHAssetManager.h"
+#include "Camera/SHCameraComponent.h"
 #include "Resource/SHResourceManager.h"
 
 using namespace SHADE;
@@ -51,7 +52,7 @@ namespace Sandbox
           if (asset.name == "Cube.012")
           handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
           break;
-        case AssetType::TEXTURE:
+        case AssetType::IMAGE:
           texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
           break;
       }
@@ -155,6 +156,10 @@ namespace Sandbox
     transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
     transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });
     scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
+
+    SHComponentManager::AddComponent<SHCameraComponent>(0);
+    SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
+    SHComponentManager::RemoveComponent <SHColliderComponent>(0);
   }
 
   void SBTestScene::Update(float dt)
diff --git a/SHADE_Engine/SHAnimationAsset.h b/SHADE_Engine/SHAnimationAsset.h
new file mode 100644
index 00000000..d8d0ffb1
--- /dev/null
+++ b/SHADE_Engine/SHAnimationAsset.h
@@ -0,0 +1,30 @@
+/*************************************************************************//**
+ * \file    SHAnimationAsset.h
+ * \author  Loh Xiao Qi
+ * \date    October 2022
+ * \brief    
+ *
+ * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
+ * disclosure of this file or its contents without the prior written consent
+ * of DigiPen Institute of Technology is prohibited.
+ *****************************************************************************/
+#pragma once
+
+#include <vector>
+#include <assimp/anim.h>
+#include "SH_API.power h"
+
+namespace SHADE
+{
+	struct SH_API SHAnimationAsset
+	{
+		std::string name;
+
+		std::vector<aiNodeAnim*> nodeChannels;
+		std::vector<aiMeshAnim*> meshChannels;
+		std::vector<aiMeshMorphAnim*> morphMeshChannels;
+
+		double duration;
+		double ticksPerSecond;
+	};
+}
\ No newline at end of file
diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAnimationAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHAnimationAsset.h
new file mode 100644
index 00000000..b411a11e
--- /dev/null
+++ b/SHADE_Engine/src/Assets/Asset Types/SHAnimationAsset.h	
@@ -0,0 +1,30 @@
+/*************************************************************************//**
+ * \file    SHAnimationAsset.h
+ * \author  Loh Xiao Qi
+ * \date    October 2022
+ * \brief    
+ *
+ * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
+ * disclosure of this file or its contents without the prior written consent
+ * of DigiPen Institute of Technology is prohibited.
+ *****************************************************************************/
+#pragma once
+
+#include <vector>
+#include <assimp/anim.h>
+#include "SHAssetData.h"
+
+namespace SHADE
+{
+	struct SH_API SHAnimationAsset : SHAssetData
+	{
+		std::string name;
+
+		std::vector<aiNodeAnim*> nodeChannels;
+		std::vector<aiMeshAnim*> meshChannels;
+		std::vector<aiMeshMorphAnim*> morphMeshChannels;
+
+		double duration;
+		double ticksPerSecond;
+	};
+}
\ No newline at end of file
diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAssetData.h b/SHADE_Engine/src/Assets/Asset Types/SHAssetData.h
new file mode 100644
index 00000000..8db9824c
--- /dev/null
+++ b/SHADE_Engine/src/Assets/Asset Types/SHAssetData.h	
@@ -0,0 +1,19 @@
+/*************************************************************************//**
+ * \file    SHAssetDataBase.h
+ * \author  Loh Xiao Qi
+ * \date    October 2022
+ * \brief    
+ *
+ * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
+ * disclosure of this file or its contents without the prior written consent
+ * of DigiPen Institute of Technology is prohibited.
+ *****************************************************************************/
+#pragma once
+
+namespace SHADE
+{
+	struct SHAssetData
+	{
+		virtual ~SHAssetData(){}
+	};
+}
diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAssetIncludes.h b/SHADE_Engine/src/Assets/Asset Types/SHAssetIncludes.h
new file mode 100644
index 00000000..1c1ed44a
--- /dev/null
+++ b/SHADE_Engine/src/Assets/Asset Types/SHAssetIncludes.h	
@@ -0,0 +1,4 @@
+#pragma once
+
+#include "SHMeshAsset.h"
+#include "SHTextureAsset.h"
\ No newline at end of file
diff --git a/SHADE_Engine/src/Assets/Asset Types/SHInternalAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHInternalAsset.h
new file mode 100644
index 00000000..8bef34e9
--- /dev/null
+++ b/SHADE_Engine/src/Assets/Asset Types/SHInternalAsset.h	
@@ -0,0 +1,21 @@
+/*************************************************************************//**
+ * \file    SHInternalAsset.h
+ * \author  Loh Xiao Qi
+ * \date    October 2022
+ * \brief    
+ *
+ * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
+ * disclosure of this file or its contents without the prior written consent
+ * of DigiPen Institute of Technology is prohibited.
+ *****************************************************************************/
+#pragma once
+
+#include "SHAsset.h"
+
+namespace SHADE
+{
+	struct SHInternalAsset : SHAsset
+	{
+		
+	};
+}
\ No newline at end of file
diff --git a/SHADE_Engine/src/Assets/Asset Types/SHMeshAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHMeshAsset.h
index 68c0d150..20b442ba 100644
--- a/SHADE_Engine/src/Assets/Asset Types/SHMeshAsset.h	
+++ b/SHADE_Engine/src/Assets/Asset Types/SHMeshAsset.h	
@@ -14,7 +14,7 @@
 
 #include <vector>
 #include "Math/SHMath.h"
-#include "SH_API.h"
+#include "SHAssetData.h"
 
 namespace SHADE
 {
@@ -22,10 +22,10 @@ namespace SHADE
 	{
 		uint32_t vertexCount;
 		uint32_t indexCount;
-		std::string meshName;
+		std::string name;
 	};
 
-	struct SH_API SHMeshAsset
+	struct SH_API SHMeshAsset : SHAssetData
 	{
 		bool compiled;
 		bool changed;
diff --git a/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h
index d24b6c02..d26a2c30 100644
--- a/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h	
+++ b/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h	
@@ -2,10 +2,11 @@
 
 #include "tinyddsloader.h"
 #include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
+#include "SHAssetData.h"
 
 namespace SHADE
 {
-	struct SHTextureAsset
+	struct SHTextureAsset : SHAssetData
 	{
 		bool compiled;
 
diff --git a/SHADE_Engine/src/Assets/Libraries/SHAssetLoader.h b/SHADE_Engine/src/Assets/Libraries/SHAssetLoader.h
new file mode 100644
index 00000000..41595519
--- /dev/null
+++ b/SHADE_Engine/src/Assets/Libraries/SHAssetLoader.h
@@ -0,0 +1,21 @@
+/*************************************************************************//**
+ * \file    SHAssetLoader.h
+ * \author  Loh Xiao Qi
+ * \date    October 2022
+ * \brief    
+ *
+ * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
+ * disclosure of this file or its contents without the prior written consent
+ * of DigiPen Institute of Technology is prohibited.
+ *****************************************************************************/
+#pragma once
+
+#include "Assets/Asset Types/SHAssetData.h"
+
+namespace SHADE
+{
+	struct SHAssetLoader
+	{
+		virtual SHAssetData* Load(AssetPath path) = 0;
+	};
+}
diff --git a/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.cpp b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.cpp
new file mode 100644
index 00000000..f4be0b68
--- /dev/null
+++ b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.cpp
@@ -0,0 +1,141 @@
+/*************************************************************************//**
+ * \file    SHAssimpLibrary.cpp
+ * \author  Loh Xiao Qi
+ * \date    October 2022
+ * \brief    
+ *
+ * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
+ * disclosure of this file or its contents without the prior written consent
+ * of DigiPen Institute of Technology is prohibited.
+ *****************************************************************************/
+#include "SHpch.h"
+#include "SHAssimpLibrary.h"
+#include <assimp/postprocess.h>
+
+namespace SHADE
+{
+	Assimp::Importer SHAssimpLibrary::aiImporter;
+
+	void SHAssimpLibrary::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept
+	{
+    for (size_t i {0}; i < node.mNumMeshes; ++i)
+    {
+      aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
+      meshes.push_back(ProcessMesh(*mesh));
+    }
+
+    for (size_t i{ 0 }; i < node.mNumChildren; ++i)
+    {
+      ProcessNode(*node.mChildren[i], scene, meshes);
+    }
+	}
+
+	void SHAssimpLibrary::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
+	{
+		if (scene.HasAnimations())
+    {
+			std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
+	    for (auto i{0}; i < scene.mNumAnimations; ++i)
+	    {
+		    auto const& anim {*scene.mAnimations[i]};
+
+        anims[i].name = anim.mName.C_Str();
+
+        anims[i].duration = anim.mDuration;
+        anims[i].ticksPerSecond = anim.mTicksPerSecond;
+
+        std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data());
+        std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data());
+        std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
+	    }
+    }
+	}
+
+	SHMeshAsset* SHAssimpLibrary::ProcessMesh(aiMesh const& mesh) noexcept
+	{
+    SHMeshAsset* result = new SHMeshAsset();
+    result->compiled = false;
+    result->changed = false;
+
+    for (size_t i{0}; i < mesh.mNumVertices; ++i)
+    {
+      // Vertex position
+      SHVec3 vertex;
+      vertex.x = mesh.mVertices[i].x;
+      vertex.y = mesh.mVertices[i].y;
+      vertex.z = mesh.mVertices[i].z;
+      result->vertexPosition.push_back(vertex);
+
+      // Tex coords
+      SHVec2 texCoord{0.f, 0.f};
+      if (mesh.mTextureCoords[0])
+      {
+        texCoord.x = mesh.mTextureCoords[0][i].x;
+        texCoord.y = mesh.mTextureCoords[0][i].y;
+      }
+      result->texCoords.push_back(texCoord);
+
+      // Normals
+      SHVec3 normal{0.f, 0.f, 0.f};
+      if (mesh.mNormals)
+      {
+        normal.x = mesh.mNormals[i].x;
+        normal.y = mesh.mNormals[i].y;
+        normal.z = mesh.mNormals[i].z;
+      }
+      result->vertexNormal.push_back(normal);
+
+      // Tangent
+      SHVec3 tangent{0.f, 0.f, 0.f};
+      if (mesh.mTangents)
+      {
+        tangent.x = mesh.mTangents[i].x;
+        tangent.y = mesh.mTangents[i].y;
+        tangent.z = mesh.mTangents[i].z;
+      }
+      result->vertexTangent.push_back(tangent);
+    }
+
+    for (size_t i {0}; i < mesh.mNumFaces; ++i)
+    {
+      aiFace face = mesh.mFaces[i];
+      for (size_t j{0}; j < face.mNumIndices; ++j)
+      {
+        result->indices.push_back(face.mIndices[j]);
+      }
+    }
+
+    result->header.vertexCount = static_cast<uint32_t>(result->vertexPosition.size());
+    result->header.indexCount = static_cast<uint32_t>(result->indices.size());
+    result->header.name = mesh.mName.C_Str();
+
+    return result;
+	}
+
+	void SHAssimpLibrary::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept
+	{
+    const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
+      aiProcess_Triangulate                 // Make sure we get triangles rather than nvert polygons
+      | aiProcess_GenUVCoords               // Convert any type of mapping to uv mapping
+      | aiProcess_TransformUVCoords         // preprocess UV transformations (scaling, translation ...)
+      | aiProcess_FindInstances             // search for instanced meshes and remove them by references to one master
+      | aiProcess_CalcTangentSpace          // calculate tangents and bitangents if possible
+      | aiProcess_JoinIdenticalVertices     // join identical vertices/ optimize indexing
+      | aiProcess_RemoveRedundantMaterials  // remove redundant materials
+      | aiProcess_FindInvalidData           // detect invalid model data, such as invalid normal vectors
+      | aiProcess_FlipUVs                   // flip the V to match the Vulkans way of doing UVs
+    );
+
+    if (!scene || !scene->HasMeshes())
+    {
+      SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
+      return;
+    }
+
+    ExtractAnimations(*scene, anims);
+
+    ProcessNode(*scene->mRootNode, *scene, meshes);
+
+    aiImporter.FreeScene();
+	}
+}
diff --git a/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.h b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.h
new file mode 100644
index 00000000..83755b4c
--- /dev/null
+++ b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.h
@@ -0,0 +1,36 @@
+/*************************************************************************//**
+ * \file    SHAssimpLibrary.h
+ * \author  Loh Xiao Qi
+ * \date    October 2022
+ * \brief    
+ *
+ * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
+ * disclosure of this file or its contents without the prior written consent
+ * of DigiPen Institute of Technology is prohibited.
+ *****************************************************************************/
+
+#pragma once
+#include <assimp/Importer.hpp>
+#include <assimp/scene.h>
+#include <vector>
+#include "../SHAssetMacros.h"
+#include "../Asset Types/SHMeshAsset.h"
+#include "../Asset Types/SHAnimationAsset.h"
+
+namespace SHADE
+{
+	class SHAssimpLibrary
+	{
+	private:
+		using MeshVectorRef = std::vector<SHMeshAsset*>&;
+		using AnimVectorRef = std::vector<SHAnimationAsset*>&;
+
+		static Assimp::Importer aiImporter;
+		static void ProcessNode(aiNode const& node, aiScene const& scene,MeshVectorRef meshes) noexcept;
+		static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
+		static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept;
+
+	public:
+		static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept;
+	};
+}
\ No newline at end of file
diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp b/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp
index 8026f0e1..2346714e 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp
+++ b/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp
@@ -20,7 +20,7 @@ std::string SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, A
 {
 	std::string newPath{ path.string() };
 	newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
-	newPath += asset.header.meshName + MESH_EXTENSION;
+	newPath += asset.header.name + MESH_EXTENSION.data();
 
 	std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
 	if (!file.is_open())
diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp
index 4bfa2d9b..90dd58d4 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp
+++ b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp
@@ -12,129 +12,11 @@
  *****************************************************************************/
 #include "SHpch.h"
 #include "SHMeshLoader.h"
-#include <assimp/postprocess.h>
 #include <fstream>
 
 namespace SHADE
 {
-	Assimp::Importer SHMeshLoader::aiImporter;
-
-	void SHMeshLoader::ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept
-	{
-    for (size_t i {0}; i < node.mNumMeshes; ++i)
-    {
-      aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
-      meshes.push_back(ProcessMesh(*mesh, scene));
-    }
-
-    for (size_t i{ 0 }; i < node.mNumChildren; ++i)
-    {
-      ProcessNode(*node.mChildren[i], scene, meshes);
-    }
-	}
-
-	SHMeshAsset SHMeshLoader::ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept
-	{
-    (void)scene;
-
-    SHMeshAsset result
-    {
-      .compiled { false},
-      .changed { false }
-    };
-
-    for (size_t i{0}; i < mesh.mNumVertices; ++i)
-    {
-      // Vertex position
-      SHVec3 vertex;
-      vertex.x = mesh.mVertices[i].x;
-      vertex.y = mesh.mVertices[i].y;
-      vertex.z = mesh.mVertices[i].z;
-      result.vertexPosition.push_back(vertex);
-
-      // Tex coords
-      SHVec2 texCoord{0.f, 0.f};
-      if (mesh.mTextureCoords[0])
-      {
-        texCoord.x = mesh.mTextureCoords[0][i].x;
-        texCoord.y = mesh.mTextureCoords[0][i].y;
-      }
-      result.texCoords.push_back(texCoord);
-
-      // Normals
-      SHVec3 normal{0.f, 0.f, 0.f};
-      if (mesh.mNormals)
-      {
-        normal.x = mesh.mNormals[i].x;
-        normal.y = mesh.mNormals[i].y;
-        normal.z = mesh.mNormals[i].z;
-      }
-      result.vertexNormal.push_back(normal);
-
-      // Tangent
-      SHVec3 tangent{0.f, 0.f, 0.f};
-      if (mesh.mTangents)
-      {
-        tangent.x = mesh.mTangents[i].x;
-        tangent.y = mesh.mTangents[i].y;
-        tangent.z = mesh.mTangents[i].z;
-      }
-      result.vertexTangent.push_back(tangent);
-    }
-
-    for (size_t i {0}; i < mesh.mNumFaces; ++i)
-    {
-      aiFace face = mesh.mFaces[i];
-      for (size_t j{0}; j < face.mNumIndices; ++j)
-      {
-        result.indices.push_back(face.mIndices[j]);
-      }
-    }
-
-    result.header.vertexCount = static_cast<uint32_t>(result.vertexPosition.size());
-    result.header.indexCount = static_cast<uint32_t>(result.indices.size());
-    result.header.meshName = mesh.mName.C_Str();
-
-    return result;
-	}
-
-	void SHMeshLoader::LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
-	{
-    const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
-      aiProcess_Triangulate                 // Make sure we get triangles rather than nvert polygons
-      | aiProcess_GenUVCoords               // Convert any type of mapping to uv mapping
-      | aiProcess_TransformUVCoords         // preprocess UV transformations (scaling, translation ...)
-      | aiProcess_FindInstances             // search for instanced meshes and remove them by references to one master
-      | aiProcess_CalcTangentSpace          // calculate tangents and bitangents if possible
-      | aiProcess_JoinIdenticalVertices     // join identical vertices/ optimize indexing
-      | aiProcess_RemoveRedundantMaterials  // remove redundant materials
-      | aiProcess_FindInvalidData           // detect invalid model data, such as invalid normal vectors
-      | aiProcess_FlipUVs                   // flip the V to match the Vulkans way of doing UVs
-    );
-
-    if (!scene || !scene->HasMeshes())
-    {
-      SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
-      return;
-    }
-
-    //TODO MATERIALS FROM MESHES
-    //if (scene->HasMaterials())
-    //{
-    //  for (int i{0}; i < scene->mNumMaterials; ++i)
-    //  {
-    //    if (scene->mMaterials[i]->mNumProperties > 0)
-    //    {
-     //     for (int j{0}; j < scene->mMaterials[i]->mProperties[j].)
-    //    }
-        //std::cout << scene->mMaterials[i]->;
-    //  }
-    //}
-
-    ProcessNode(*scene->mRootNode, *scene, meshes);
-	}
-
-	void SHMeshLoader::LoadSHMesh(SHMeshAsset& mesh, AssetPath path) noexcept
+	void SHMeshLoader::LoadSHMesh(AssetPath path, SHMeshAsset& mesh) noexcept
 	{
     std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
     if (!file.is_open())
@@ -168,45 +50,13 @@ namespace SHADE
     file.read(reinterpret_cast<char *>(vertNorm.data()), vertexVec3Byte);
     file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
     file.read(reinterpret_cast<char *>(indices.data()), sizeof(uint32_t) * indexCount);
-    
-    //for (auto i{ 0 }; i < vertCount; ++i)
-    //{
-    //  file >> vertPos[i].x;
-    //  file >> vertPos[i].y;
-    //  file >> vertPos[i].z;
-    //}
-    //
-    //for (auto i{ 0 }; i < vertCount; ++i)
-    //{
-    //  file >> vertTan[i].x;
-    //  file >> vertTan[i].y;
-    //  file >> vertTan[i].z;
-    //}
-
-    //for (auto i{ 0 }; i < vertCount; ++i)
-    //{
-    //  file >> vertNorm[i].x;
-    //  file >> vertNorm[i].y;
-    //  file >> vertNorm[i].z;
-    //}
-
-    //for (auto i{ 0 }; i < vertCount; ++i)
-    //{
-    //  file >> texCoord[i].x;
-    //  file >> texCoord[i].y;
-    //}
-
-    //for (auto i{ 0 }; i < indexCount; ++i)
-    //{
-    //  file >> indices[i];
-    //}
 
     mesh.compiled = true;
     mesh.changed  = false;
 
     mesh.header.indexCount  = indexCount;
     mesh.header.vertexCount = vertCount;
-    mesh.header.meshName    = name;
+    mesh.header.name = name;
 
     mesh.vertexPosition = std::move(vertPos);
     mesh.vertexTangent  = std::move(vertTan);
@@ -217,15 +67,12 @@ namespace SHADE
     file.close();
 	}
 
-	void SHMeshLoader::LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
-  {
-    if (path.extension().string() == GLTF_EXTENSION)
-    {
-      LoadExternal(meshes, path);
-      return;
-    }
+	SHAssetData* SHMeshLoader::Load(AssetPath path)
+	{
+    auto result = new SHMeshAsset();
 
-    meshes.emplace_back();
-    LoadSHMesh(meshes.back(), path);
+    LoadSHMesh(path, *result);
+
+    return result;
 	}
 }
diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h
index a27d63ea..34c4e5d2 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h
+++ b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h
@@ -10,27 +10,15 @@
  * of DigiPen Institute of Technology is prohibited.
  *****************************************************************************/
 #pragma once
-#include <assimp/Importer.hpp>
-#include <assimp/scene.h>
 #include "../SHAssetMacros.h"
 #include "../Asset Types/SHMeshAsset.h"
-#include <vector>
+#include "SHAssetLoader.h"
 
 namespace SHADE
 {
-	class SHMeshLoader
+	struct SHMeshLoader : public SHAssetLoader
 	{
-	private:
-		static Assimp::Importer aiImporter;
-
-		static void ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept;
-
-		static SHMeshAsset ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept;
-
-		static void LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
-
-	public:
-		static void LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
-		static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept;
+		void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept;
+		SHAssetData* Load(AssetPath path) override;
 	};
 }
\ No newline at end of file
diff --git a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp
index 5147562a..8b986524 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp
+++ b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp
@@ -133,6 +133,15 @@ namespace SHADE
 		file.close();
 	}
 
+	SHAssetData* SHTextureLoader::Load(AssetPath path)
+	{
+		auto result = new SHTextureAsset();
+
+		LoadImageAsset(path, *result);
+
+		return result;
+	}
+
 	void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
 	{
 		if (path.extension().string() == DDS_EXTENSION)
diff --git a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h
index eb61ea91..8bdf91b1 100644
--- a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h
+++ b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h
@@ -15,19 +15,20 @@
 #include "../SHAssetMacros.h"
 #include "../Asset Types/SHTextureAsset.h"
 #include "tinyddsloader.h"
+#include "SHAssetLoader.h"
 
 namespace SHADE
 {
-	class SHTextureLoader
+	class SHTextureLoader : public SHAssetLoader
 	{
 	private:
-		static std::string TinyDDSResultToString(tinyddsloader::Result value);
-		static vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
-
-
-		static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
+		std::string TinyDDSResultToString(tinyddsloader::Result value);
+		vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
+		
+		void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
 	public:
-		static void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
-		static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
+		void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
+		void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
+		SHAssetData* Load(AssetPath path) override;
 	};
 }
diff --git a/SHADE_Engine/src/Assets/SHAsset.h b/SHADE_Engine/src/Assets/SHAsset.h
index 8d7b55d1..86e8a722 100644
--- a/SHADE_Engine/src/Assets/SHAsset.h
+++ b/SHADE_Engine/src/Assets/SHAsset.h
@@ -12,11 +12,12 @@
 #pragma once
 
 #include "Filesystem/SHFileSystem.h"
-#include "SHAssetMacros.h"
+#include "Assets/SHAssetMacros.h"
+#include "SH_API.h"
 
 namespace SHADE
 {
-	struct SHAsset
+	struct SH_API SHAsset
 	{
 		AssetName name;
 		AssetID id;
diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h
index 61c5879d..0fdfa04e 100644
--- a/SHADE_Engine/src/Assets/SHAssetMacros.h
+++ b/SHADE_Engine/src/Assets/SHAssetMacros.h
@@ -32,12 +32,12 @@ typedef std::filesystem::path AssetPath;
 typedef unsigned char*				AssetData;
 typedef std::string						AssetMetaVersion;
 typedef std::string						AssetExtension;
-typedef unsigned char					AssetTypeMeta;
+typedef size_t					AssetTypeMeta;
 
 typedef FMOD::Sound*					SHSound;
 
 // Asset Meta Version
-#define ASSET_META_VER "1.0"
+constexpr std::string_view ASSET_META_VER { "1.0" };
 
 // Asset type enum
 enum class AssetType : AssetTypeMeta
@@ -53,34 +53,35 @@ enum class AssetType : AssetTypeMeta
 	SCENE,
 	PREFAB,
 	AUDIO_WAV,
-	DDS
+	DDS,
+	MAX_COUNT
 };
 
 //Directory
 #ifdef _PUBLISH
-#define ASSET_ROOT "Assets"
+constexpr std::string_view ASSET_ROOT {"Assets"};
 #else
-#define ASSET_ROOT "../../Assets"
+constexpr std::string_view ASSET_ROOT {"../../Assets"};
 #endif
 
 
 // ASSET EXTENSIONS
-#define META_EXTENSION ".shmeta"
-#define IMAGE_EXTENSION ".png"
-#define AUDIO_EXTENSION ".ogg"
-#define AUDIO_WAV_EXTENSION ".wav"
-#define SHADER_EXTENSION ".glsl"
-#define SCRIPT_EXTENSION ".cs"
-#define SCENE_EXTENSION ".SHADE"
-#define PREFAB_EXTENSION ".SHPrefab"
-#define MATERIAL_EXTENSION ".SHMat"
-#define TEXTURE_EXTENSION ".shtex"
-#define DDS_EXTENSION ".dds"
-#define FBX_EXTENSION ".fbx"
-#define GLTF_EXTENSION ".gltf"
-#define MESH_EXTENSION ".shmesh"
+constexpr std::string_view META_EXTENSION {".shmeta"};
+constexpr std::string_view IMAGE_EXTENSION {".png"};
+constexpr std::string_view AUDIO_EXTENSION {".ogg"};
+constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
+constexpr std::string_view SHADER_EXTENSION {".glsl"};
+constexpr std::string_view SCRIPT_EXTENSION {".cs"};
+constexpr std::string_view SCENE_EXTENSION {".SHADE"};
+constexpr std::string_view PREFAB_EXTENSION {".SHPrefab"};
+constexpr std::string_view MATERIAL_EXTENSION {".SHMat"};
+constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
+constexpr std::string_view DDS_EXTENSION {".dds"};
+constexpr std::string_view FBX_EXTENSION {".fbx"};
+constexpr std::string_view GLTF_EXTENSION {".gltf"};
+constexpr std::string_view MESH_EXTENSION {".shmesh"};
 
-std::string const EXTENSIONS[] = {
+constexpr std::string_view EXTENSIONS[] = {
 	AUDIO_EXTENSION,
 	SHADER_EXTENSION,
 	MATERIAL_EXTENSION,
@@ -96,10 +97,12 @@ std::string const EXTENSIONS[] = {
 	GLTF_EXTENSION
 };
 
+constexpr size_t TYPE_COUNT {static_cast<size_t>(AssetType::MAX_COUNT) };
+
 // Error flags
-#define FILE_NOT_FOUND_ERR "FILE NOT FOUND"
-#define META_NOT_FOUND_ERR "META NOT FOUND"
-#define ASSET_NOT_FOUND_ERR "ASSET NOT FOUND"
-#define EXT_DOES_NOT_EXIST "TYPE DOES NOT HAVE EXTENSION DEFINED"
+constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"};
+constexpr std::string_view META_NOT_FOUND_ERR {"META NOT FOUND"};
+constexpr std::string_view ASSET_NOT_FOUND_ERR {"ASSET NOT FOUND"};
+constexpr std::string_view EXT_DOES_NOT_EXIST {"TYPE DOES NOT HAVE EXTENSION DEFINED"};
 
 #endif // !SH_ASSET_MACROS_H
diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp
index 956d52e8..3032ba51 100644
--- a/SHADE_Engine/src/Assets/SHAssetManager.cpp
+++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp
@@ -14,6 +14,7 @@
 #include "SHAssetMetaHandler.h"
 #include "Filesystem/SHFileSystem.h"
 
+#include "Libraries/SHAssimpLibrary.h"
 #include "Libraries/SHMeshLoader.h"
 #include "Libraries/SHTextureLoader.h"
 
@@ -25,11 +26,10 @@ namespace SHADE
 	FMOD::System* SHAssetManager::audioSystem;
 	std::unordered_map<AssetID, SHSound >* SHAssetManager::audioSoundList;
 
-	std::vector<SHAsset> SHAssetManager::assetCollection;
-	std::unordered_map<AssetID, SHAsset> SHAssetManager::assetRegistry;
+	std::vector<SHAssetLoader*> SHAssetManager::loaders(TYPE_COUNT);
 
-	std::unordered_map<AssetID, SHMeshAsset> SHAssetManager::meshCollection;
-	std::unordered_map<AssetID, SHTextureAsset> SHAssetManager::textureCollection;
+	std::vector<SHAsset> SHAssetManager::assetCollection;
+	std::unordered_map<AssetID, SHAssetData * const> SHAssetManager::assetData;
 
 	/****************************************************************************
 	 * \brief   Static function to generate asset ID.
@@ -56,18 +56,15 @@ namespace SHADE
 	****************************************************************************/
 	void SHAssetManager::Unload() noexcept
 	{
-		for (auto const& asset : assetCollection)
-		{
-			SHAssetMetaHandler::WriteMetaData(asset);
-		}
+
 	}
 
-    void SHAssetManager::Unload(AssetID assetId) noexcept
-    {
-		// TODO
-    }
+	void SHAssetManager::Unload(AssetID assetId) noexcept
+	{
+	// TODO
+	}
 
-    AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
+		AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
 	{
 		if (!IsRecognised(path.extension().string().c_str()))
 		{
@@ -85,7 +82,37 @@ namespace SHADE
 		//	return std::filesystem::path();
 		//}
 
-		return std::filesystem::path(ASSET_ROOT + folder + path.filename().string());
+		return std::filesystem::path(std::string(ASSET_ROOT) + folder + path.filename().string());
+	}
+
+	AssetPath SHAssetManager::GenerateNewPath(AssetName name, AssetType type)
+	{
+		std::string folder;
+
+		switch(type)
+		{
+		case AssetType::SCENE:
+			folder = "scenes/";
+			break;
+
+		case AssetType::PREFAB:
+			folder = "prefabs/";
+			break;
+
+		case AssetType::MATERIAL:
+			folder = "materials/";
+			break;
+
+		default:
+			folder = "/";
+		}
+
+		return std::filesystem::path{
+			std::string(ASSET_ROOT) + 
+			folder + 
+			name + 
+			std::string(EXTENSIONS[static_cast<size_t>(type)])
+		};
 	}
 
 	/****************************************************************************
@@ -121,7 +148,7 @@ namespace SHADE
 		//	folder = "";
 		//	break;
 		//}
-		AssetPath path{ ASSET_ROOT + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
+		AssetPath path{ std::string{ASSET_ROOT} + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
 
 		SHAssetMetaHandler::WriteMetaData(meta);
 
@@ -130,6 +157,19 @@ namespace SHADE
 		return id;
 	}
 
+	AssetID SHAssetManager::CreateAsset(AssetName name, AssetType type) noexcept
+	{
+			AssetID id = GenerateAssetID(type);
+
+			assetCollection.emplace_back(
+				name,
+				id,
+				type,
+				GenerateNewPath(name, type),
+				0
+			); 
+			return id;
+		}
 	/****************************************************************************
 	 * \brief Import new asset from outside editor window.
 	 *
@@ -138,7 +178,10 @@ namespace SHADE
 	****************************************************************************/
 	AssetID SHAssetManager::ImportNewAsset(char const* p) noexcept
 	{
-		 std::filesystem::path const path{ p };
+		std::filesystem::path const path{ p };
+
+		auto const type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
+		auto const id = GenerateAssetID(type);
 
 		std::filesystem::path const newPath{ GenerateLocalPath(path) };
 		if (newPath.empty())
@@ -149,11 +192,7 @@ namespace SHADE
 
 		std::filesystem::copy(path, newPath);
 
-		AssetID id{ RetrieveAsset(newPath.string().c_str()) };
-		if (id != 0)
-		{
-			LoadData(id);
-		}
+		assetCollection.push_back(CreateAssetFromPath(newPath));
 
 		return id;
 	}
@@ -164,158 +203,14 @@ namespace SHADE
 	****************************************************************************/
 	void SHAssetManager::RefreshAllAssets() noexcept
 	{
-		std::vector<AssetPath> metaFiles;
-		std::vector<AssetPath> AssetFiles;
 
-		//SHFileSystem::LoadAllFiles(metaFiles, AssetFiles);
-		//std::vector<AssetPath> AssetFilesVerified;
-		std::vector<AssetPath> AssetFilesNew;
-
-		for (auto const& asset : AssetFiles)
-		{
-			bool found = false;
-		  for (auto it {metaFiles.begin()}; it != metaFiles.end(); ++it)
-		  {
-				std::string fileExtCheck{ asset.filename().string() };
-				fileExtCheck += META_EXTENSION;
-				if (it->filename().string() == fileExtCheck)
-				{
-					metaFiles.erase(it);
-					found = true;
-					break;
-				}
-		  }
-
-			if (!found && IsRecognised(asset.extension().string().c_str()))
-			{
-				AssetFilesNew.push_back(asset);
-			}
-		}
-
-		std::vector<SHAsset> newLoad;
-		newLoad.reserve(AssetFilesNew.size());
-
-		//TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
-		for (auto const& file : AssetFilesNew)
-		{
-			newLoad.push_back(RegisterAssetNew(file));
-		}
-
-    //UpdateAllSpriteSets();
-
-	}
-
-	void SHAssetManager::LoadDataTemp(std::string p) noexcept
-	{
-		AssetPath path{ p };
-
-		if (path.extension().string() == FBX_EXTENSION
-			|| path.extension().string() == GLTF_EXTENSION
-			|| path.extension().string() == MESH_EXTENSION)
-		{
-			LoadGLTF(
-				{
-					.name {path.filename().string()},
-					.id {0},
-					.type {AssetType::MESH},
-					.path {path},
-					.location {0}
-				}
-			);
-		}
-		else if (path.extension().string() == DDS_EXTENSION
-			|| path.extension().string() == TEXTURE_EXTENSION)
-		{
-			LoadDDS(
-				{
-					.name {path.filename().string()},
-					.id {0},
-					.type {AssetType::DDS},
-					.path {path},
-					.location {0}
-				}
-			);
-		}
-	}
-
-	std::vector<SHMeshAsset> SHAssetManager::GetAllMeshes() noexcept
-	{
-		std::vector<SHMeshAsset> result;
-		for (auto const& mesh : meshCollection)
-		{
-			result.push_back(mesh.second);
-		}
-
-		return result;
-	}
-
-	std::vector<SHTextureAsset> SHAssetManager::GetAllTextures() noexcept
-	{
-		std::vector<SHTextureAsset> result;
-		for (auto const& dds : textureCollection)
-		{
-			result.push_back(dds.second);
-		}
-
-		return result;
-	}
-
-	SHMeshAsset const* SHAssetManager::GetMesh(AssetID id) noexcept
-	{
-		if (meshCollection.find(id) == meshCollection.end())
-		{
-			return nullptr;
-		}
-
-		return &meshCollection[id];
-	}
-
-	SHTextureAsset const* SHAssetManager::GetTexture(AssetID id) noexcept
-	{
-		if (textureCollection.find(id) == textureCollection.end())
-		{
-			return nullptr;
-		}
-
-		return &textureCollection[id];
-	}
-
-	/****************************************************************************
-	 * \param   Path for meta data file
-	 * \param   Path for asset file
-
-	 * \brief   Links meta data to asset in registries. Meta data should
-	 *					already exist
-	****************************************************************************/
-	void SHAssetManager::RegisterAsset(AssetPath const& metaPath, AssetPath const& path) noexcept
-	{
-		SHAsset const meta = SHAssetMetaHandler::RetrieveMetaData(metaPath);
-
-		assetCollection.push_back(meta);
-	}
-
-	/****************************************************************************
-	 * \param   Path for asset file
-
-	 * \brief   Creates new meta data for new asset.
-	****************************************************************************/
-	SHAsset SHAssetManager::RegisterAssetNew(AssetPath const& asset) noexcept
-	{
-		SHAsset meta;
-		meta.type = SHAssetMetaHandler::GetTypeFromExtension(asset.extension().string());
-		meta.id = GenerateAssetID(meta.type);
-
-		assetCollection.push_back(meta);
-
-		SHAssetMetaHandler::WriteMetaData(meta);
-		return assetCollection.back();
 	}
 
 	bool SHAssetManager::IsRecognised(char const* ext) noexcept
 	{
 		for (auto const& e : EXTENSIONS)
 		{
-			if (strcmp(ext, e.c_str()) == 0)
+			if (strcmp(ext, e.data()) == 0)
 			{
 				return true;
 			}
@@ -324,54 +219,31 @@ namespace SHADE
 		return false;
 	}
 
-	void SHAssetManager::LoadGLTF(SHAsset asset) noexcept
+	SHAsset SHAssetManager::CreateAssetFromPath(AssetPath path) noexcept
 	{
-		std::vector<SHMeshAsset> meshes;
+		SHAsset result;
 
-		SHMeshLoader::LoadMesh(meshes, asset.path);
+		result.name = path.stem().string();
+		result.type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
+		result.id = GenerateAssetID(result.type);
+		result.path = path;
 
-		for (auto const& mesh : meshes)
-		{
-			auto id{ GenerateAssetID(AssetType::MESH) };
-			meshCollection.emplace(id, mesh);
-
-			AssetPath path;
-			if (!mesh.compiled)
-			{
-				path = SHMeshCompiler::CompileMeshBinary(mesh, asset.path);
-			}
-			
-			assetCollection.emplace_back(
-				mesh.header.meshName,
-				id,
-				AssetType::MESH,
-				path,
-				0
-			);
-		}
+		return result;
 	}
 
-	void SHAssetManager::LoadDDS(SHAsset asset) noexcept
+	void SHAssetManager::InitLoaders() noexcept
 	{
-		SHTextureAsset image;
-
-		SHTextureLoader::LoadImageAsset(asset.path, image);
-
-		if (!image.compiled)
-		{
-			auto id{ GenerateAssetID(AssetType::TEXTURE) };
-			textureCollection.emplace(id, image);
-
-			auto path{ SHTextureCompiler::CompileTextureBinary(image, asset.path) };
-
-			assetCollection.emplace_back(
-				image.name,
-				id,
-				AssetType::TEXTURE,
-				path,
-				0
-			);
-		}
+		loaders[static_cast<size_t>(AssetType::AUDIO)] = nullptr;
+		loaders[static_cast<size_t>(AssetType::SHADER)] = nullptr;
+		loaders[static_cast<size_t>(AssetType::MATERIAL)] = nullptr;
+		loaders[static_cast<size_t>(AssetType::IMAGE)] = dynamic_cast<SHAssetLoader*>(new SHTextureLoader());
+		loaders[static_cast<size_t>(AssetType::TEXTURE)] = nullptr;
+		loaders[static_cast<size_t>(AssetType::MESH)] = dynamic_cast<SHAssetLoader*>(new SHMeshLoader());
+		loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
+		loaders[static_cast<size_t>(AssetType::SCENE)] = nullptr;
+		loaders[static_cast<size_t>(AssetType::PREFAB)] = nullptr;
+		loaders[static_cast<size_t>(AssetType::AUDIO_WAV)] = nullptr;
+		loaders[static_cast<size_t>(AssetType::DDS)] = nullptr;
 	}
 
 	/****************************************************************************
@@ -379,8 +251,9 @@ namespace SHADE
 	****************************************************************************/
 	void SHAssetManager::Load() noexcept
 	{
-		RetrieveAssets();
-		LoadAllData();
+		InitLoaders();
+		BuildAssetCollection();
+		//LoadAllData();
 	}
 
 	/****************************************************************************
@@ -388,143 +261,40 @@ namespace SHADE
 	****************************************************************************/
 	void SHAssetManager::LoadAllData() noexcept
 	{
-		//TODO Remove when on demand loading is done
 		for (auto const& asset : assetCollection)
 		{
-			switch (asset.type)
-			{
-			case AssetType::MESH:
-				meshCollection.emplace(asset.id, SHMeshAsset());
-				SHMeshLoader::LoadSHMesh(meshCollection[asset.id], asset.path);
-				break;
-
-			case AssetType::TEXTURE:
-				textureCollection.emplace(asset.id, SHTextureAsset());
-				SHTextureLoader::LoadSHTexture(asset.path, textureCollection[asset.id]);
-				break;
-
-			default:
-				void;
-			}
+			SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
+			assetData.emplace(asset.id, data);
 		}
 	}
 
-	void SHAssetManager::LoadData(AssetID id) noexcept
+	SHAssetData* SHAssetManager::LoadData(SHAsset const& asset) noexcept
 	{
-		(void)id;
-	}
+		SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
 
-	/****************************************************************************
-	 * \brief   Retrieve all asset files and meta files from filesystem
-	****************************************************************************/
-	void SHAssetManager::RetrieveAssets() noexcept
-	{
-		std::vector<AssetPath> metaFiles;
-		std::vector<AssetPath> AssetFiles;
-
-		for (auto const dir : std::filesystem::recursive_directory_iterator(ASSET_ROOT))
+		if (data == nullptr)
 		{
-			if (dir.path().extension().string() == META_EXTENSION)
-			{
-				auto meta{ SHAssetMetaHandler::RetrieveMetaData(dir.path()) };
-
-				assetCollection.push_back(meta);
-				assetRegistry.emplace(meta.id, meta);
-			}
-		}
-
-		//TODO: Write new function for file manager to loop through all files
-		//SHFileSystem::StartupFillDirectories(ASSET_ROOT);
-		//FolderPointer rootFolder = SHFileSystem::GetRoot();
-
-		//for (auto const& meta : metaFiles)
-		//{
-		//	for (std::vector<AssetPath>::const_iterator it{ AssetFiles.cbegin() };
-		//		it != AssetFiles.cend();
-		//		++it)
-		//	{
-		//		// Asset exists for meta file
-		//		std::string fileExtCheck{ it->filename().string() };
-		//		fileExtCheck += META_EXTENSION;
-		//		if (meta.filename().string() == fileExtCheck)
-		//		{
-		//			RegisterAsset(meta, *it);
-		//			AssetFiles.erase(it);
-		//			break;
-		//		}
-		//	}
-		//}
-
-		//TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
-		//for (auto const& file : AssetFiles)
-		//{
-		//	if (IsRecognised(file.extension().string().c_str()))
-		//	{
-		//		SHAssetMetaHandler::WriteMetaData(RegisterAssetNew(file));
-		//	}
-		//	else
-		//	{
-		//		std::cout << "Unsupported File Format: " << file.filename() << "\n";
-		//	}
-		//}
-	}
-
-	AssetID SHAssetManager::RetrieveAsset(char const* path) noexcept
-	{
-		std::filesystem::path p{ path };
-		if (IsRecognised(p.extension().string().c_str()))
-		{
-			SHAsset const& meta{ RegisterAssetNew(p) };
-			SHAssetMetaHandler::WriteMetaData(meta);
-			return meta.id;
+			SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string());
 		}
 		else
 		{
-			std::cout << "Unsupported File Format: " << p.filename() << "\n";
+			assetData.emplace(asset.id, data);
 		}
 
-		// Assert that file imported is not recognised
-		return 0;
+		return data;
 	}
 
-	/****************************************************************************
-	 * \param   Full path of file
-
-	 * \brief   Extracts file name from path. Formats file name into readable
-	 *					with spaces and capitalises first letter of every word
-	****************************************************************************/
-	AssetName SHAssetManager::GetNameFromPath(AssetPath filepath) noexcept
+	void SHAssetManager::BuildAssetCollection() noexcept
 	{
-		std::string name{ filepath.filename().string() };
-		name = name.substr(0, name.find_last_of('.'));
-
-		//if (name[0] <= 122 && name[0] >= 97)
-		//{
-		//	name[0] -= 32;
-		//}
-
-		//for (size_t i{ 1 }; i < name.length(); ++i)
-		//{
-		//	// Replace all underscores with spaces
-		//	if (name[i] == '_')
-		//	{
-		//		name[i] = ' ';
-		//		continue;
-		//	}
-
-		//	if (name[i + 1] <= 'Z' && name[i + 1] >= 'A'
-		//		&& name[i] <= 'z' && name[i] >= 'a')
-		//	{
-		//		name.insert(i + 1, 1, ' ');
-		//		continue;
-		//	}
-
-		//	if (name[i - 1] == ' ' && name[i] <= 'z' && name[i] >= 'a')
-		//	{
-		//		name[i] -= 32;
-		//	}
-		//}
-
-		return name;
+		for (auto const& dir : std::filesystem::recursive_directory_iterator{ASSET_ROOT})
+		{
+			if (dir.is_regular_file())
+			{
+				if (dir.path().extension().string() == META_EXTENSION.data())
+				{
+					assetCollection.push_back(SHAssetMetaHandler::RetrieveMetaData(dir.path()));
+				}
+			}
+		}
 	}
 }
diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h
index 2469165a..9ee7ab92 100644
--- a/SHADE_Engine/src/Assets/SHAssetManager.h
+++ b/SHADE_Engine/src/Assets/SHAssetManager.h
@@ -11,9 +11,10 @@
 #pragma once
 #include "tinyddsloader.h"
 #include "SHAsset.h"
+#include "Asset Types/SHAssetData.h"
+#include "Libraries/SHAssetLoader.h"
+#include <memory>
 
-#include "Asset Types/SHMeshAsset.h"	
-#include "Asset Types/SHTextureAsset.h"	
 #include "SH_API.h"
 
 namespace SHADE
@@ -28,6 +29,8 @@ namespace SHADE
 
 		static AssetPath GenerateLocalPath(AssetPath path) noexcept;
 
+		static AssetPath GenerateNewPath(AssetName name, AssetType type);
+
 		/****************************************************************************
 		 * \brief   Deallocate all memory used by resource data
 		****************************************************************************/
@@ -55,6 +58,7 @@ namespace SHADE
 		 * \return resource id generated for new asset
 		****************************************************************************/
 		static AssetID CreateNewAsset(AssetType, AssetName) noexcept;
+		static AssetID CreateAsset(AssetName name, AssetType type) noexcept;
 
 		/****************************************************************************
 		 * \brief Import new resource from outside editor window.
@@ -71,66 +75,33 @@ namespace SHADE
 		static void RefreshAllAssets() noexcept;
 		// -------------------------------------------------------------------------/
 
-		//TODO: TEMPORARY FOR TESTING GLTF & DDS
-		static void LoadDataTemp(std::string path) noexcept;
-		static std::vector<SHMeshAsset> GetAllMeshes() noexcept;
-		static std::vector<SHTextureAsset> GetAllTextures() noexcept;
-
-		static SHMeshAsset const* GetMesh(AssetID id) noexcept;
-		static SHTextureAsset const* GetTexture(AssetID id) noexcept;
+		template<typename T>
+		static std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> GetData(AssetID id) noexcept;
 	private:
 		/****************************************************************************
 		 * \brief   Load resource data into memory
 		****************************************************************************/
 		static void LoadAllData() noexcept;
 
-		static void LoadData(AssetID id) noexcept;
+		static SHAssetData* LoadData(SHAsset const& asset) noexcept;
 
-		/****************************************************************************
-		 * \brief   Retrieve all resource files and meta files from filesystem
-		****************************************************************************/
-		static void RetrieveAssets() noexcept;
-
-		static AssetID RetrieveAsset(char const* path) noexcept;
-
-		/****************************************************************************
-		 * \param   Full path of file
-		
-		 * \brief   Extracts file name from path. Formats file name into readable
-		 *					with spaces and capitalises first letter of every word
-		****************************************************************************/
-		static AssetName GetNameFromPath(AssetPath) noexcept;
-
-		/****************************************************************************
-		 * \param   Path for meta data file
-		 * \param   Path for resource file
-		
-		 * \brief   Links meta data to resource in registries. Meta data should 
-		 *					already exist
-		****************************************************************************/
-		static void RegisterAsset(AssetPath const&, AssetPath const&) noexcept;
-
-		/****************************************************************************
-		 * \param   Path for resource file
-		
-		 * \brief   Creates new meta data for new resource.
-		****************************************************************************/
-		static SHAsset RegisterAssetNew(AssetPath const&) noexcept;
+		inline static void BuildAssetCollection() noexcept;
 
 		static bool IsRecognised(char const*) noexcept;
+		
+		static SHAsset CreateAssetFromPath(AssetPath	path) noexcept;
 
-		// Specialised load calls
-		static void LoadGLTF(SHAsset asset) noexcept;
-		static void LoadDDS(SHAsset asset) noexcept;
+		static void InitLoaders() noexcept;
 
 		static FMOD::System* audioSystem;
 		static std::unordered_map<AssetID,SHSound>* audioSoundList;
 
+		static std::vector<SHAssetLoader*> loaders;
+
 		// For all resources
 		static std::vector<SHAsset> assetCollection;
-		static std::unordered_map<AssetID, SHAsset> assetRegistry;
-
-		static std::unordered_map<AssetID, SHMeshAsset> meshCollection;
-		static std::unordered_map<AssetID, SHTextureAsset> textureCollection;
+		static std::unordered_map<AssetID, SHAssetData * const> assetData;
 	};
 }
+
+#include "SHAssetManager.hpp"
diff --git a/SHADE_Engine/src/Assets/SHAssetManager.hpp b/SHADE_Engine/src/Assets/SHAssetManager.hpp
new file mode 100644
index 00000000..6c420778
--- /dev/null
+++ b/SHADE_Engine/src/Assets/SHAssetManager.hpp
@@ -0,0 +1,26 @@
+
+#include "SHAssetManager.h"
+
+namespace SHADE
+{
+	template<typename T>
+	std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> SHAssetManager::GetData(AssetID id) noexcept
+	{
+		if (!assetData.contains(id))
+		{
+			for (auto const& asset : assetCollection)
+			{
+				if (asset.id == id)
+				{
+					assetData.emplace(id, LoadData(asset));
+					return dynamic_cast<T const* const>(assetData[id]);
+				}
+			}
+
+			SHLOG_ERROR("Asset ID provided does not exist: {}", id);
+			return nullptr;
+		}
+
+		return dynamic_cast<T const* const>(assetData[id]);
+	}
+}
diff --git a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp
index 442c3d96..1bfec00d 100644
--- a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp
+++ b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp
@@ -37,7 +37,7 @@ namespace SHADE
 	{
 		for (int i{0}; i < EXTENSIONS->size(); ++i)
 		{
-			if (ext == EXTENSIONS[i])
+			if (strcmp(ext.c_str(), EXTENSIONS[i].data()) == 0)
 			{
 				return static_cast<AssetType>(i);
 			}
@@ -53,7 +53,7 @@ namespace SHADE
 	****************************************************************************/
 	AssetExtension SHAssetMetaHandler::GetExtensionFromType(AssetType type) noexcept
 	{
-		return EXTENSIONS[static_cast<size_t>(type)];
+		return AssetExtension(EXTENSIONS[static_cast<size_t>(type)]);
 	}
 
 	/****************************************************************************
@@ -124,16 +124,6 @@ namespace SHADE
 		metaFile << "ID: " << meta.id << "\n";
 		metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl;
 
-		////TODO Add in information that is specific to types like mesh
-		//switch(meta.type)
-		//{
-		//case AssetType::MESH:
-		//	break;
-
-		//default:
-		//	break;
-		//}
-
 		metaFile.close();
 	}
 
diff --git a/SHADE_Engine/src/Camera/SHCameraSystem.cpp b/SHADE_Engine/src/Camera/SHCameraSystem.cpp
index 07995fc5..0d86c17a 100644
--- a/SHADE_Engine/src/Camera/SHCameraSystem.cpp
+++ b/SHADE_Engine/src/Camera/SHCameraSystem.cpp
@@ -69,7 +69,7 @@ namespace SHADE
 
     if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A))
     {
-      std::cout << "Camera movement: "<<right.x<<", " << right.y << std::endl;
+      //std::cout << "Camera movement: "<<right.x<<", " << right.y << std::endl;
       camera.position -= right * dt * camera.movementSpeed;
       camera.dirtyView = true;
     }
@@ -110,7 +110,7 @@ namespace SHADE
       camera.dirtyView = true;
     }
 
-    std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl;
+    //std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl;
     system->UpdateCameraComponent(system->editorCamera);
 	}
 
@@ -140,10 +140,11 @@ namespace SHADE
     {
       auto transform = SHComponentManager::GetComponent<SHTransformComponent>(camera.GetEID());
       SHVec3 rotation = transform->GetWorldRotation();
-      camera.pitch = rotation.x;
-      camera.yaw = rotation.y;
-      camera.roll = rotation.z;
+      camera.pitch = SHMath::RadiansToDegrees(rotation.x);
+      camera.yaw =   SHMath::RadiansToDegrees(rotation.y);
+      camera.roll =  SHMath::RadiansToDegrees(rotation.z);
       camera.position = transform->GetWorldPosition();    
+      camera.dirtyView = true;
     }
     
 
diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp
index 4501ba7b..a744c795 100644
--- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp
+++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp
@@ -10,6 +10,7 @@
 #include "Graphics/Buffers/SHVkBuffer.h"
 #include "Graphics/Images/SHVkImage.h"
 #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
+#include "Graphics/SHVkUtil.h"
 
 
 namespace SHADE
@@ -299,7 +300,7 @@ namespace SHADE
       SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. ");
       return;
     }
-    boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
+    bindPointData[static_cast<uint32_t>(pipelineHdl->GetPipelineType())].boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
     vkCommandBuffer.bindPipeline(pipelineHdl->GetPipelineBindPoint(), pipelineHdl->GetVkPipeline());
   }
 
@@ -358,9 +359,10 @@ namespace SHADE
     }
   }
 
-  void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
+  void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
   {
-    vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
+    uint32_t bindPointIndex = static_cast<uint32_t>(bindPoint);
+    vkCommandBuffer.bindDescriptorSets(SHVkUtil::GetPipelineBindPointFromType(bindPoint), bindPointData[bindPointIndex].boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
   }
 
   /***************************************************************************/
@@ -452,6 +454,11 @@ namespace SHADE
       vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand));
   }
 
+  void SHVkCommandBuffer::ComputeDispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept
+  {
+    vkCommandBuffer.dispatch (groupCountX, groupCountY, groupCountZ);
+  }
+
   void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo)
   {
     vkCommandBuffer.copyBufferToImage
@@ -500,9 +507,9 @@ namespace SHADE
   //  //vkCommandBuffer.pipelineBarrier()
   //}
 
-  void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout) noexcept
+  void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept
   {
-    boundPipelineLayoutHdl = pipelineLayout;
+    bindPointData[static_cast<uint32_t>(pipelineType)].boundPipelineLayoutHdl = pipelineLayout;
   }
 
   /***************************************************************************/
@@ -513,12 +520,13 @@ namespace SHADE
 
   */
   /***************************************************************************/
-  void SHVkCommandBuffer::SubmitPushConstants(void) const noexcept
+  void SHVkCommandBuffer::SubmitPushConstants(SH_PIPELINE_TYPE bindPoint) const noexcept
   {
-    vkCommandBuffer.pushConstants(boundPipelineLayoutHdl->GetVkPipelineLayout(),
-      boundPipelineLayoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
+    auto layoutHdl = bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl;
+    vkCommandBuffer.pushConstants(layoutHdl->GetVkPipelineLayout(),
+      layoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
       0,
-      boundPipelineLayoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
+      layoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
   }
 
   /***************************************************************************/
@@ -695,7 +703,7 @@ namespace SHADE
     , usageFlags{ rhs.usageFlags }
     , commandBufferCount{ rhs.commandBufferCount }
     , parentPool{ rhs.parentPool }
-    , boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl }
+    , bindPointData{ std::move (rhs.bindPointData)}
   {
     memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
 
@@ -728,7 +736,7 @@ namespace SHADE
     usageFlags = rhs.usageFlags;
     commandBufferCount = rhs.commandBufferCount;
     parentPool = rhs.parentPool;
-    boundPipelineLayoutHdl = rhs.boundPipelineLayoutHdl;
+    bindPointData = std::move(rhs.bindPointData);
     memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
 
     rhs.vkCommandBuffer = VK_NULL_HANDLE;
diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h
index deb1131c..4c978c34 100644
--- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h
+++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h
@@ -6,6 +6,7 @@
 #include "SHCommandPoolResetMode.h"
 #include "Resource/SHResourceLibrary.h"
 #include "Graphics/Pipeline/SHVkPipelineLayout.h"
+#include "Graphics/Pipeline/SHPipelineType.h"
 
 namespace SHADE
 {
@@ -39,7 +40,14 @@ namespace SHADE
     friend class SHResourceLibrary<SHVkCommandBuffer>;
 
     static constexpr uint16_t PUSH_CONSTANT_SIZE = 512;
+    
   private:
+    struct PipelineBindPointData
+    {
+      //! The currently bound pipeline
+      Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
+    };
+
     /*-----------------------------------------------------------------------*/
     /* PRIVATE MEMBER VARIABLES                                              */
     /*-----------------------------------------------------------------------*/
@@ -66,8 +74,8 @@ namespace SHADE
     //! The command pool that this command buffer belongs to
     Handle<SHVkCommandPool> parentPool;
 
-    //! The currently bound pipeline
-    Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
+    //! Every command buffer will have a set of pipeline bind point specific data
+    std::array<PipelineBindPointData, static_cast<uint32_t>(SH_PIPELINE_TYPE::NUM_TYPES)> bindPointData;
 
     //! The push constant data for the command buffer 
     uint8_t pushConstantData[PUSH_CONSTANT_SIZE];
@@ -112,13 +120,16 @@ namespace SHADE
     void BindPipeline       (Handle<SHVkPipeline> const& pipelineHdl) noexcept;
     void BindVertexBuffer   (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept;
     void BindIndexBuffer    (Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept;
-    void BindDescriptorSet  (Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets);
+    void BindDescriptorSet  (Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets);
     
     // Draw Commands
     void DrawArrays         (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept;
     void DrawIndexed        (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept;
     void DrawMultiIndirect  (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
 
+    // Compute Commands
+    void ComputeDispatch    (uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept;
+
     // Buffer Copy
     void CopyBufferToImage  (const vk::Buffer& src, const vk::Image&  dst, const std::vector<vk::BufferImageCopy>& copyInfo);
     void CopyImageToBuffer  (const vk::Image&  src, const vk::Buffer& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
@@ -138,13 +149,13 @@ namespace SHADE
 
     // Push Constant variable setting
     template <typename T>
-    void SetPushConstantVariable(std::string variableName, T const& data) noexcept
+    void SetPushConstantVariable(std::string variableName, T const& data, SH_PIPELINE_TYPE bindPoint) noexcept
     {
-      memcpy (static_cast<uint8_t*>(pushConstantData) + boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T));
+      memcpy (static_cast<uint8_t*>(pushConstantData) + bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T));
     };
-    void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout) noexcept;
+    void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept;
 
-    void SubmitPushConstants (void) const noexcept;
+    void SubmitPushConstants (SH_PIPELINE_TYPE bindPoint) const noexcept;
 
     /*-----------------------------------------------------------------------*/
     /* GETTERS AND SETTERS                                                   */
diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp
index 6b770c3d..e5618c9c 100644
--- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp
+++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp
@@ -25,7 +25,8 @@ namespace SHADE
   }
 
   SHVkDescriptorPool::SHVkDescriptorPool(SHVkDescriptorPool&& rhs) noexcept
-    : device{ rhs.device }
+    : ISelfHandle (rhs)
+    , device{ rhs.device }
     , pool{ rhs.pool }
   {
     rhs.pool = VK_NULL_HANDLE;
diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp
index ea859718..de68c583 100644
--- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp
+++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp
@@ -91,7 +91,7 @@ namespace SHADE
 
         // new write for the binding
         updater.writeInfos.emplace_back();
-        updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1);
+        updater.writeHashMap.try_emplace(writeHash, static_cast<uint32_t>(updater.writeInfos.size()) - 1u);
         auto& writeInfo = updater.writeInfos.back();
 
         // Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in
@@ -102,10 +102,10 @@ namespace SHADE
           //case vk::DescriptorType::eSampler:
           //case vk::DescriptorType::eSampledImage:
         case vk::DescriptorType::eCombinedImageSampler:
+        case vk::DescriptorType::eStorageImage:
+        case vk::DescriptorType::eInputAttachment:
           writeInfo.descImageInfos.resize(descriptorCount);
-        break;
-        //case vk::DescriptorType::eStorageImage:
-        //  break;
+          break;
         case vk::DescriptorType::eUniformTexelBuffer:
         case vk::DescriptorType::eStorageTexelBuffer:
         case vk::DescriptorType::eUniformBuffer:
@@ -165,6 +165,7 @@ namespace SHADE
     if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size())
     {
       SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. ");
+      return;
     }
 
     for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i)
diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h
index b2536de8..3f42afcc 100644
--- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h
+++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h
@@ -31,6 +31,8 @@ namespace SHADE
   class SHVkDescriptorSetGroup
   {
   public:
+    using viewSamplerLayout = std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>;
+
     /*-----------------------------------------------------------------------------*/
     /* Constructor/Destructors                                                     */
     /*-----------------------------------------------------------------------------*/
diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp
index 7c7acfc5..a6b415a9 100644
--- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp
+++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp
@@ -233,6 +233,8 @@ namespace SHADE
     , vmaAllocator{rhs.vmaAllocator}
     , nonDedicatedBestIndex {0}
     , parentPhysicalDeviceHdl {rhs.parentPhysicalDeviceHdl}
+    , uboBufferMemoryAlignment{ 0 }
+    , ssboBufferMemoryAlignment{ 0 }
   {
     rhs.vkLogicalDevice = VK_NULL_HANDLE;
   }
@@ -261,6 +263,8 @@ namespace SHADE
     vmaAllocator = rhs.vmaAllocator;
     nonDedicatedBestIndex = 0;
     parentPhysicalDeviceHdl = rhs.parentPhysicalDeviceHdl;
+    uboBufferMemoryAlignment = rhs.uboBufferMemoryAlignment;
+    ssboBufferMemoryAlignment = rhs.ssboBufferMemoryAlignment;
 
     rhs.vkLogicalDevice = VK_NULL_HANDLE;
 
@@ -529,6 +533,11 @@ namespace SHADE
 
   }
 
+  Handle<SHVkPipeline> SHVkLogicalDevice::CreateComputePipeline(Handle<SHVkPipelineLayout> const& pipelineLayoutHdl) noexcept
+  {
+    return SHVkInstance::GetResourceManager().Create <SHVkPipeline>(GetHandle(), pipelineLayoutHdl);
+  }
+
   Handle<SHVkSampler> SHVkLogicalDevice::CreateSampler(const SHVkSamplerParams& params) noexcept
   {
     return SHVkInstance::GetResourceManager().Create <SHVkSampler>(GetHandle(), params);
diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h
index 3d59d5c6..2aa59941 100644
--- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h
+++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h
@@ -175,12 +175,17 @@ namespace SHADE
                                                                std::string const&               shaderName
                                                               ) noexcept;
                                     
-    Handle<SHVkPipeline>            CreateGraphicsPipeline            (
+    Handle<SHVkPipeline>            CreateGraphicsPipeline    (
                                                                Handle<SHVkPipelineLayout> const& pipelineLayoutHdl, 
                                                                SHVkPipelineState const* const    state, 
                                                                Handle<SHVkRenderpass> const&     renderpassHdl,
                                                                Handle<SHSubpass>                 subpass
                                                               ) noexcept;
+
+    Handle<SHVkPipeline>            CreateComputePipeline     ( 
+                                                               Handle<SHVkPipelineLayout> const& pipelineLayoutHdl
+                                                              ) noexcept;
+
     Handle<SHVkSampler>             CreateSampler             (const SHVkSamplerParams& params) noexcept;
                                     
     Handle<SHVkRenderpass>          CreateRenderpass          (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept;
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp
index 2705b4d1..40826047 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp
@@ -369,7 +369,7 @@ namespace SHADE
     /*---------------------------------------------------------------------------------*/
     void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
     {
-        if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
+      if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
         {
             SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index.");
             return;
@@ -385,7 +385,7 @@ namespace SHADE
           cmdBuffer->BindDescriptorSet
           (
             matPropsDescSet[frameIndex],
-            vk::PipelineBindPoint::eGraphics,
+            SH_PIPELINE_TYPE::GRAPHICS,
             SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
             dynamicOffset
           );
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp
index add51196..14f2aa76 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp
@@ -20,91 +20,91 @@ of DigiPen Institute of Technology is prohibited.
 
 namespace SHADE
 {
-    /*---------------------------------------------------------------------------------*/
-    /* Constructor/Destructors                                                         */
-    /*---------------------------------------------------------------------------------*/
+  /*---------------------------------------------------------------------------------*/
+  /* Constructor/Destructors                                                         */
+  /*---------------------------------------------------------------------------------*/
 
-    SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp)
-    : subpass { sp }
-    {}
+  SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp)
+    : subpass{ sp }
+  {}
 
-    /*---------------------------------------------------------------------------------*/
-    /* Usage Functions                                                                 */
-    /*---------------------------------------------------------------------------------*/
-    void SHSuperBatch::Add(const SHRenderable* renderable) noexcept
+  /*---------------------------------------------------------------------------------*/
+  /* Usage Functions                                                                 */
+  /*---------------------------------------------------------------------------------*/
+  void SHSuperBatch::Add(const SHRenderable* renderable) noexcept
+  {
+    const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
+
+    // Check if we have a batch with the same pipeline first
+    auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
+      {
+        return batch.GetPipeline() == PIPELINE;
+      });
+
+
+    // Create one if not found
+    if (batch == batches.end())
     {
-        const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
-
-        // Check if we have a batch with the same pipeline first
-        auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
-        {
-            return batch.GetPipeline() == PIPELINE;
-        });
-
-
-        // Create one if not found
-        if (batch == batches.end())
-        {
-            batches.emplace_back(PIPELINE);
-            batch = batches.end() - 1;
-        }
-
-        // Add renderable in
-        batch->Add(renderable);
+      batches.emplace_back(PIPELINE);
+      batch = batches.end() - 1;
     }
 
-    void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept
+    // Add renderable in
+    batch->Add(renderable);
+  }
+
+  void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept
+  {
+    const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
+
+    // Check if we have a Batch with the same pipeline yet
+    auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
+      {
+        return batch.GetPipeline() == PIPELINE;
+      });
+
+    // Attempt to remove if it exists
+    if (batch == batches.end())
+      return;
+
+    batch->Remove(renderable);
+  }
+
+  void SHSuperBatch::Clear() noexcept
+  {
+    for (auto& batch : batches)
     {
-        const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
-
-        // Check if we have a Batch with the same pipeline yet
-        auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
-        {
-            return batch.GetPipeline() == PIPELINE;
-        });
-
-        // Attempt to remove if it exists
-        if (batch == batches.end())
-            return;
-
-        batch->Remove(renderable);
+      batch.Clear();
     }
+    batches.clear();
+  }
 
-    void SHSuperBatch::Clear() noexcept
+  void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
+  {
+    for (auto& batch : batches)
     {
-        for (auto& batch : batches)
-        {
-            batch.Clear();
-        }
-        batches.clear();
+      batch.UpdateMaterialBuffer(frameIndex, descPool);
+      batch.UpdateTransformBuffer(frameIndex);
+      batch.UpdateEIDBuffer(frameIndex);
     }
+  }
 
-	void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
+  void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
+  {
+    // Build all batches
+    for (auto& batch : batches)
     {
-        for (auto& batch : batches)
-        {
-			      batch.UpdateMaterialBuffer(frameIndex, descPool);
-            batch.UpdateTransformBuffer(frameIndex);
-            batch.UpdateEIDBuffer(frameIndex);
-        }
+      batch.Build(device, descPool, frameIndex);
     }
+  }
 
-    void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
+  void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
+  {
+    // Build all batches
+    for (auto& batch : batches)
     {
-        // Build all batches
-        for (auto& batch : batches)
-        {
-            batch.Build(device, descPool, frameIndex);
-        }
-    }
-
-    void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
-    {
-        // Build all batches
-        for (auto& batch : batches)
-        {
-            batch.Draw(cmdBuffer, frameIndex);
-        }
+      batch.Draw(cmdBuffer, frameIndex);
     }
+  }
 
 }
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h
index 67cbc001..a0457b65 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h
@@ -63,6 +63,14 @@ namespace SHADE
       */
       /***************************************************************************/
       static constexpr uint32_t PER_INSTANCE = 3;
+      /***************************************************************************/
+      /*!
+        \brief
+          DescriptorSet Index for render graph resources.
+      */
+      /***************************************************************************/
+      static constexpr uint32_t RENDERGRAPH_RESOURCE = 4;
+
 
     };
 
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp
index 44404bc7..7ecd92d2 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp
@@ -115,6 +115,23 @@ namespace SHADE
     graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
     transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
     graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
+
+
+    // TODO: This is VERY temporarily here until a more solid resource management system is implemented
+    shaderSourceLibrary.Init("../../TempShaderFolder/");
+
+    shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
+    shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
+
+    shaderSourceLibrary.LoadShader(2, "KirschCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
+
+    shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
+    auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
+    auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
+    auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
+    cubeVS->Reflect();
+    cubeFS->Reflect();
+    greyscale->Reflect();
   }
 
   void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
@@ -130,6 +147,7 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     auto windowDims = window->GetWindowSize();
 
+    auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
 
     // Set Up Cameras
     screenCamera = resourceManager.Create<SHCamera>();
@@ -154,21 +172,21 @@ namespace SHADE
 
     // Initialize world render graph
     worldRenderGraph->Init(device, swapchain);
-    worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT }, windowDims.first, windowDims.second);
+    worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
+    worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
     worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
     worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
 
-    auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene"}, {}); // no predecessors
+    auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors
 
      //First subpass to write to G-Buffer
     auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
-    gBufferWriteSubpass->AddColorOutput("Scene");
+    gBufferWriteSubpass->AddColorOutput("Scene Pre-Process");
     gBufferWriteSubpass->AddColorOutput("Entity ID");
     gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
 
-    // We do this to just transition our scene layout to shader read
-    auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition");
-    sceneLayoutTransitionSubpass->AddInput("Scene");
+    auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
+    node->AddNodeCompute (greyscale, {"Scene Pre-Process", "Scene"});
 
     // Generate world render graph
     worldRenderGraph->Generate();
@@ -177,20 +195,13 @@ namespace SHADE
     worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
     worldRenderer->SetCamera(worldCamera);
 
+    worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
 
-    // TODO: This is VERY temporarily here until a more solid resource management system is implemented
-    shaderSourceLibrary.Init("../../TempShaderFolder/");
-
-    shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
-    shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
-
-    shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
     auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
     auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
-    cubeVS->Reflect();
-    cubeFS->Reflect();
 
     defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
+
   }
 
   void SHGraphicsSystem::InitMiddleEnd(void) noexcept
@@ -323,21 +334,7 @@ namespace SHADE
     
     auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
     
-#ifdef SHEDITOR
 
-    auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
-    if (editorSystem->editorState != SHEditor::State::PLAY)
-    {
-      worldRenderer->SetViewProjectionMatrix(SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
-    }
-    else
-    {
-      // main camera
-    }
-
-#else
-    // main camera
-#endif
 
     // For every viewport 
     for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
@@ -360,7 +357,7 @@ namespace SHADE
         uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
         currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
 
-        currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout());
+        currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
 
         // Bind all the buffers required for meshes
         for (auto& [buffer, bindingPoint] : MESH_DATA)
@@ -380,14 +377,29 @@ namespace SHADE
           currentCmdBuffer->BindDescriptorSet
           (
             textureDescSet,
-            vk::PipelineBindPoint::eGraphics,
+            SH_PIPELINE_TYPE::GRAPHICS,
             0,
             texDynamicOffset
           );
         }
 
         // bind camera data
+        //renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
+
+#ifdef SHEDITOR
+        if (renderers[renIndex] == worldRenderer)
+        {
+          auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
+          if (editorSystem->editorState != SHEditor::State::PLAY)
+            worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
+          else
+            renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
+        }
+        else
+          renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
+#else
         renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
+#endif
 
         // Draw first
         renderers[renIndex]->Draw(frameIndex, descPool);
@@ -726,8 +738,8 @@ namespace SHADE
 
     auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
 #ifdef SHEDITOR
-    cameraSystem->GetEditorCamera()->SetWidth(resizeWidth);
-    cameraSystem->GetEditorCamera()->SetHeight(resizeHeight);
+    cameraSystem->GetEditorCamera()->SetWidth(static_cast<float>(resizeWidth));
+    cameraSystem->GetEditorCamera()->SetHeight(static_cast<float>(resizeHeight));
 #else
 
 #endif
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp
index 8b41a979..ebce5c9e 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp
@@ -68,7 +68,7 @@ namespace SHADE
   {
     std::vector combinedImageSampler
     {
-      std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eShaderReadOnlyOptimal),
+      std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eGeneral),
     };
 
     // Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp
index 2532f308..962130be 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp
@@ -21,6 +21,7 @@ of DigiPen Institute of Technology is prohibited.
 #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
 #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
 #include "Graphics/Buffers/SHVkBuffer.h"
+#include "Camera/SHCameraDirector.h"
 
 namespace SHADE
 {
@@ -65,6 +66,11 @@ namespace SHADE
     camera = _camera;
   }
 
+  void SHRenderer::SetCameraDirector(Handle<SHCameraDirector> director) noexcept
+  {
+    cameraDirector = director;
+  }
+
   /*-----------------------------------------------------------------------------------*/
   /* Drawing Functions                                                                 */
   /*-----------------------------------------------------------------------------------*/
@@ -75,17 +81,24 @@ namespace SHADE
 
   void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
   {
-    if (camera)
+    if (camera && cameraDirector)
     {
-      //cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
-      cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
-
-        std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
-
-      cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
+      UpdateDataAndBind(cmdBuffer, frameIndex, SHMatrix::Transpose(cameraDirector->GetVPMatrix()));
     }
   }
 
+  void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept
+  {
+    SetViewProjectionMatrix(exteriorMatrix);
+
+    //cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
+    cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
+
+    std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
+
+    cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
+  }
+
   void SHRenderer::UpdateCameraDataToBuffer(void) noexcept
   {
   }
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h
index dbd1e415..87cf8ee9 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h
@@ -40,6 +40,7 @@ namespace SHADE
     class SHGraphicsGlobalData;
     class SHVkDescriptorPool;
     class SHVkBuffer;
+    class SHCameraDirector;
 
     struct SHShaderCameraData
     {
@@ -71,12 +72,14 @@ namespace SHADE
         /* Camera Registration                                                         */
         /*-----------------------------------------------------------------------------*/
         void SetCamera(Handle<SHCamera> _camera);
+        void SetCameraDirector (Handle<SHCameraDirector> director) noexcept;
 
         /*-----------------------------------------------------------------------------*/
         /* Drawing Functions                                                           */
         /*-----------------------------------------------------------------------------*/
         void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
-        void UpdateDataAndBind (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
+        void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
+        void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept;
         void UpdateCameraDataToBuffer (void) noexcept;
         void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept;
 
@@ -99,6 +102,8 @@ namespace SHADE
         Handle<SHVkDescriptorSetGroup>  cameraDescriptorSet;
         Handle<SHVkBuffer>              cameraBuffer;
 
+        Handle<SHCameraDirector>        cameraDirector;
+
         // we really only need 1 copy even though we need %swapchainImages copies for
         // GPU.
         SHShaderCameraData              cpuCameraData; 
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp
index 682b549c..495a3d37 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp
@@ -8,7 +8,7 @@
 namespace SHADE
 {
   
-  Handle<SHVkPipeline> SHPipelineLibrary::CreateDrawPipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept
+  Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept
   {
     SHPipelineLayoutParams params
     {
@@ -52,7 +52,7 @@ namespace SHADE
     newPipeline->ConstructPipeline();
 
     // Emplace the new pipeline
-    pipelines.emplace (vsFsPair, newPipeline);
+    graphicsPipelines.emplace (vsFsPair, newPipeline);
 
     return newPipeline;
   }
@@ -62,19 +62,19 @@ namespace SHADE
     logicalDevice = device;
   }
 
-  Handle<SHVkPipeline> SHPipelineLibrary::GetDrawPipline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
+  Handle<SHVkPipeline> SHPipelineLibrary::GetGraphicsPipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
   {
     // return the pipeline requested for
-    if (pipelines.contains(vsFsPair))
-      return pipelines.at(vsFsPair);
+    if (graphicsPipelines.contains(vsFsPair))
+      return graphicsPipelines.at(vsFsPair);
     else
       return {};
   }
 
-  bool SHPipelineLibrary::CheckDrawPipelineExistence(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
+  bool SHPipelineLibrary::CheckGraphicsPipelineExistence(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
   {
     // Returns if a pipeline exists or not
-    return pipelines.contains(vsFsPair);
+    return graphicsPipelines.contains(vsFsPair);
   }
 
 }
\ No newline at end of file
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h
index 9a411d25..aeb023c5 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h
@@ -23,19 +23,19 @@ namespace SHADE
     Handle<SHVkLogicalDevice> logicalDevice;
 
     //! a map of pipelines that are hashed using a pair of shader module handles
-    std::unordered_map<std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>>, Handle<SHVkPipeline>> pipelines;
+    std::unordered_map<std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>>, Handle<SHVkPipeline>> graphicsPipelines;
     
   public:
     void Init (Handle<SHVkLogicalDevice> device) noexcept;
     
     // Draw pipeline functions. used only when creating pipelines for drawing using a vertex and fragment shader
-    Handle<SHVkPipeline> CreateDrawPipeline         (
+    Handle<SHVkPipeline> CreateGraphicsPipelines         (
                                                      std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair,
                                                      Handle<SHVkRenderpass>                                               renderpass,
                                                      Handle<SHSubpass>                                                    subpass
                                                     ) noexcept;
-    Handle<SHVkPipeline> GetDrawPipline             (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
-    bool                 CheckDrawPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
+    Handle<SHVkPipeline> GetGraphicsPipeline             (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
+    bool                 CheckGraphicsPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
 
   };
 }
diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineType.h b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineType.h
index e7f5b6a8..2c1c80ff 100644
--- a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineType.h
+++ b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineType.h
@@ -5,9 +5,13 @@ namespace SHADE
 {
   enum class SH_PIPELINE_TYPE
   {
-    GRAPHICS,
+    GRAPHICS = 0,
     COMPUTE,
+    RAY_TRACING,
+    NUM_TYPES,
   };
+
+  
 }
 
 #endif
\ No newline at end of file
diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp
index c03fd2a7..973ae72f 100644
--- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp
+++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp
@@ -4,6 +4,7 @@
 #include "Graphics/Shaders/SHVkShaderModule.h"
 #include "Graphics/Debugging/SHVulkanDebugUtil.h"
 #include "Graphics/RenderGraph/SHRenderGraph.h"
+#include "Graphics/SHVkUtil.h"
 
 namespace SHADE
 {
@@ -171,6 +172,29 @@ namespace SHADE
   
   void SHVkPipeline::CreateComputePipeline(void) noexcept
   {
+    auto shaderModule = pipelineLayout->GetShaderModules()[0];
+
+    vk::PipelineShaderStageCreateInfo shaderStageCreateInfo
+    {
+      .stage = vk::ShaderStageFlagBits::eCompute,
+      .module = shaderModule->GetVkShaderModule(),
+      .pName = shaderModule->GetEntryPoint().c_str(),
+    };
+
+    vk::ComputePipelineCreateInfo cpCreateInfo
+    {
+      .flags = {},
+      .stage = shaderStageCreateInfo,
+      .layout = pipelineLayout->GetVkPipelineLayout(),
+    };
+
+    if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createComputePipelines({}, 1, &cpCreateInfo, nullptr, &vkPipeline); result != vk::Result::eSuccess)
+      SHVulkanDebugUtil::ReportVkError(result, "Failed to create Compute Pipeline. ");
+    else
+    {
+      SHVulkanDebugUtil::ReportVkSuccess("Successfully created a Compute Pipeline. ");
+      created = true;
+    }
 
   }
 
@@ -245,7 +269,7 @@ namespace SHADE
     , logicalDeviceHdl{ rhs.logicalDeviceHdl }
     , pipelineLayout { rhs.pipelineLayout }
   {
-    vkPipeline = VK_NULL_HANDLE;
+    rhs.vkPipeline = VK_NULL_HANDLE;
   }
 
   /***************************************************************************/
@@ -285,7 +309,8 @@ namespace SHADE
   /***************************************************************************/
   SHVkPipeline::~SHVkPipeline(void) noexcept
   {
-    logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr);
+    if (vkPipeline)
+      logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr);
   }
 
   /***************************************************************************/
@@ -313,7 +338,7 @@ namespace SHADE
     created = rhs.created;
     logicalDeviceHdl = rhs.logicalDeviceHdl;
 
-    vkPipeline = VK_NULL_HANDLE;
+    rhs.vkPipeline = VK_NULL_HANDLE;
 
     return *this;
   }
@@ -399,18 +424,7 @@ namespace SHADE
   /***************************************************************************/
   vk::PipelineBindPoint SHVkPipeline::GetPipelineBindPoint(void) const noexcept
   {
-    switch (pipelineType)
-    {
-    case SH_PIPELINE_TYPE::GRAPHICS:
-      return vk::PipelineBindPoint::eGraphics;
-    case SH_PIPELINE_TYPE::COMPUTE:
-      return vk::PipelineBindPoint::eCompute;
-      break;
-    default:
-      return vk::PipelineBindPoint::eGraphics;
-      break;
-
-    }
+    return SHVkUtil::GetPipelineBindPointFromType(pipelineType);
   }
 
   /***************************************************************************/
@@ -450,4 +464,9 @@ namespace SHADE
     return pipelineLayout;
   }
 
+  SH_PIPELINE_TYPE SHVkPipeline::GetPipelineType(void) const noexcept
+  {
+    return pipelineType;
+  }
+
 }
\ No newline at end of file
diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h
index 1103d3d0..7378cc48 100644
--- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h
+++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h
@@ -77,6 +77,7 @@ namespace SHADE
     vk::Pipeline               GetVkPipeline        (void) const noexcept;
     bool                       GetIsCreated         (void) const noexcept;
     Handle<SHVkPipelineLayout> GetPipelineLayout    (void) const noexcept;
+    SH_PIPELINE_TYPE           GetPipelineType      (void) const noexcept;
   };
 }
 
diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp
index 7a76447d..37d00795 100644
--- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp
+++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp
@@ -216,9 +216,18 @@ namespace SHADE
   /***************************************************************************/
   void SHVkPipelineLayout::PrepareVkDescriptorSetLayouts(void) noexcept
   {
+    // pipeline layouts contain global layouts first, then layouts for allocation
     descriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
+    vkDescriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
 
-    // Settle allocate layouts first
+    // First we insert the global layouts
+    for (auto const& layout : descriptorSetLayoutsGlobal)
+    {
+      descriptorSetLayoutsPipeline.emplace_back(layout);
+      //vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
+    }
+
+    // Then the allocate layouts
     vkDescriptorSetLayoutsAllocate.reserve(descriptorSetLayoutsAllocate.size());
     for (auto const& layout : descriptorSetLayoutsAllocate)
     {
@@ -226,18 +235,13 @@ namespace SHADE
       vkDescriptorSetLayoutsAllocate.emplace_back(layout->GetVkHandle());
     }
 
-    // pipeline layouts contain global layouts first, then layouts for allocation
-    vkDescriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
-
-    // First we insert the global layouts
-    for (auto const& layout : descriptorSetLayoutsGlobal)
+    for (auto const& layout : descriptorSetLayoutsPipeline)
     {
-      descriptorSetLayoutsPipeline.emplace_back(layout);
       vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
     }
 
     // Then we append layouts for allocation at the back of the vector
-    std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline));
+    //std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline));
   }
 
   /***************************************************************************/
@@ -294,6 +298,7 @@ namespace SHADE
     , descriptorSetLayoutsGlobal{pipelineLayoutParams.globalDescSetLayouts } // do a copy, some other pipeline layout might need this
     , descriptorSetLayoutsAllocate{}
     , vkDescriptorSetLayoutsAllocate{}
+    , descriptorSetLayoutsPipeline{}
     , vkDescriptorSetLayoutsPipeline{}
   {
     for (auto& mod : shaderModules)
@@ -318,6 +323,7 @@ namespace SHADE
     , descriptorSetLayoutsGlobal{} 
     , descriptorSetLayoutsAllocate{}
     , vkDescriptorSetLayoutsAllocate{}
+    , descriptorSetLayoutsPipeline{}
     , vkDescriptorSetLayoutsPipeline{}
 
   {
@@ -368,7 +374,8 @@ namespace SHADE
     , descriptorSetLayoutsGlobal    {std::move (rhs.descriptorSetLayoutsGlobal)}
     , descriptorSetLayoutsAllocate  {std::move (rhs.descriptorSetLayoutsAllocate)}
     , vkDescriptorSetLayoutsAllocate{std::move (rhs.vkDescriptorSetLayoutsAllocate)}
-    , vkDescriptorSetLayoutsPipeline{std::move (rhs.vkDescriptorSetLayoutsAllocate)}
+    , descriptorSetLayoutsPipeline  { std::move(rhs.descriptorSetLayoutsPipeline) }
+    , vkDescriptorSetLayoutsPipeline{ std::move(rhs.vkDescriptorSetLayoutsPipeline) }
   {
     rhs.vkPipelineLayout = VK_NULL_HANDLE;
   }
@@ -441,12 +448,12 @@ namespace SHADE
     return {};
   }
 
-  std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept
+  std::vector<Handle<SHVkDescriptorSetLayout>> const& SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept
   {
     return descriptorSetLayoutsPipeline;
   }
 
-  std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept
+  std::vector<Handle<SHVkDescriptorSetLayout>> const& SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept
   {
     return descriptorSetLayoutsAllocate;
   }
@@ -464,7 +471,8 @@ namespace SHADE
     descriptorSetLayoutsGlobal     = std::move(rhs.descriptorSetLayoutsGlobal);
     descriptorSetLayoutsAllocate   = std::move(rhs.descriptorSetLayoutsAllocate);
     vkDescriptorSetLayoutsAllocate = std::move(rhs.vkDescriptorSetLayoutsAllocate);
-    vkDescriptorSetLayoutsPipeline = std::move(rhs.vkDescriptorSetLayoutsAllocate);
+    descriptorSetLayoutsPipeline   = std::move(rhs.descriptorSetLayoutsPipeline);
+    vkDescriptorSetLayoutsPipeline = std::move(rhs.vkDescriptorSetLayoutsPipeline);
 
     rhs.vkPipelineLayout = VK_NULL_HANDLE;
 
diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h
index f5d363fa..b4298e00 100644
--- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h
+++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h
@@ -74,12 +74,12 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* SETTERS AND GETTERS                                                   */
     /*-----------------------------------------------------------------------*/
-    std::vector<Handle<SHVkShaderModule>> const& GetShaderModules                (void) const noexcept;
-    vk::PipelineLayout                           GetVkPipelineLayout             (void) const noexcept;
-    SHPushConstantInterface const&               GetPushConstantInterface        (void) const noexcept;
-    Handle<SHShaderBlockInterface>               GetShaderBlockInterface         (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept;
-    std::vector<Handle<SHVkDescriptorSetLayout>> GetDescriptorSetLayoutsPipeline(void) const noexcept;
-    std::vector<Handle<SHVkDescriptorSetLayout>> GetDescriptorSetLayoutsAllocate(void) const noexcept;
+    std::vector<Handle<SHVkShaderModule>> const&        GetShaderModules                (void) const noexcept;
+    vk::PipelineLayout                                  GetVkPipelineLayout             (void) const noexcept;
+    SHPushConstantInterface const&                      GetPushConstantInterface        (void) const noexcept;
+    Handle<SHShaderBlockInterface>                      GetShaderBlockInterface         (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept;
+    std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescriptorSetLayoutsPipeline(void) const noexcept;
+    std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescriptorSetLayoutsAllocate(void) const noexcept;
   };
 }
 
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h
index 241292d4..c4d44ea8 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h
@@ -10,6 +10,8 @@ namespace SHADE
     DEPTH = 0x04,
     STENCIL = 0x08,
     DEPTH_STENCIL = 0x10,
-    INPUT = 0x20
+    INPUT = 0x20,
+    STORAGE = 0x40
   };
+
 }
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp
index 0bc2c98b..4684419a 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp
@@ -9,6 +9,8 @@
 #include "Graphics/Buffers/SHVkBuffer.h"
 #include "Tools/SHLogger.h"
 #include "SHAttachmentDescInitParams.h"
+#include "SHRenderGraphStorage.h"
+#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
 
 namespace SHADE
 {
@@ -52,12 +54,12 @@ namespace SHADE
     // If we set to 
     if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
     {
-      w = swapchainHdl->GetSwapchainImage(0)->GetWidth();
-      h = swapchainHdl->GetSwapchainImage(0)->GetHeight();
-      format = swapchainHdl->GetSurfaceFormatKHR().format;
+      w = renderGraphStorage->swapchain->GetSwapchainImage(0)->GetWidth();
+      h = renderGraphStorage->swapchain->GetSwapchainImage(0)->GetHeight();
+      format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format;
     }
 
-    graphResources.try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(logicalDeviceHdl, swapchainHdl, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags));
+    renderGraphStorage->graphResources->try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags));
   }
 
   /***************************************************************************/
@@ -77,36 +79,38 @@ namespace SHADE
 
     for (uint32_t i = 0; auto& node : nodes)
     {
-      // key is handle ID, value is pair (first is initial layout, second is final layout).
-      std::unordered_map<uint32_t, vk::ImageLayout> resourceAttLayouts;
+      // key is handle ID, value is final layout.
+      std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
       if (node->subpasses.empty())
       {
         SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. ");
         return;
       }
 
+      // attempt to get all final layouts for all resources
       for (auto& subpass : node->subpasses)
       {
         for (auto& color : subpass->colorReferences)
         {
+          // If final renderpass and attachment is a COLOR_PRESENT resource, make resource transition to present after last subpass
           if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)))
-            resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
+            resourceAttFinalLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
           else
-            resourceAttLayouts[color.attachment] = color.layout;
+            resourceAttFinalLayouts[color.attachment] = color.layout;
         }
 
         for (auto& depth : subpass->depthReferences)
-          resourceAttLayouts[depth.attachment] = depth.layout;
+          resourceAttFinalLayouts[depth.attachment] = depth.layout;
 
         for (auto& input : subpass->inputReferences)
-          resourceAttLayouts[input.attachment] = input.layout;
+          resourceAttFinalLayouts[input.attachment] = input.layout;
       }
 
       for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
       {
         auto& att = node->attachmentDescriptions[j];
         att.initialLayout = vk::ImageLayout::eUndefined;
-        att.finalLayout = resourceAttLayouts[j];
+        att.finalLayout = resourceAttFinalLayouts[j];
       }
       ++i;
     }
@@ -292,6 +296,9 @@ namespace SHADE
         dep.dstAccessMask = dstAccess;
 
         dep.srcStageMask = srcStage;
+
+        // initialize input descriptors
+        node->subpasses[i]->CreateInputDescriptors();
       }
     }
   }
@@ -343,10 +350,18 @@ namespace SHADE
 
   */
   /***************************************************************************/
-  void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept
+  void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept
   {
-    logicalDeviceHdl = logicalDevice;
-    swapchainHdl = swapchain;
+    resourceManager = std::make_shared<SHResourceHub>();
+
+    renderGraphStorage = resourceManager->Create<SHRenderGraphStorage>();
+    renderGraphStorage->graphResources = resourceManager->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>();
+
+    renderGraphStorage->logicalDevice = logicalDevice;
+    renderGraphStorage->swapchain = swapchain;
+
+    renderGraphStorage->resourceManager = resourceManager;
+    renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools();
   }
 
   /***************************************************************************/
@@ -361,24 +376,19 @@ namespace SHADE
   */
   /***************************************************************************/
   SHRenderGraph::SHRenderGraph(void) noexcept
-    : logicalDeviceHdl{ }
-    , swapchainHdl{ }
+    : renderGraphStorage{}
     , nodes{}
-    , graphResources{}
     , resourceManager{nullptr}
   {
-    resourceManager = std::make_shared<SHResourceHub>();
   }
 
   SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept
-    : logicalDeviceHdl{ rhs.logicalDeviceHdl }
-    , swapchainHdl{ rhs.swapchainHdl }
+    : renderGraphStorage{ rhs.renderGraphStorage }
     , nodeIndexing{ std::move(rhs.nodeIndexing) }
     , nodes{ std::move(rhs.nodes) }
-    , graphResources{ std::move(rhs.graphResources) }
     , resourceManager{ std::move(rhs.resourceManager) }
   {
-
+    
   }
 
   SHRenderGraph& SHRenderGraph::operator=(SHRenderGraph&& rhs) noexcept
@@ -386,11 +396,9 @@ namespace SHADE
     if (&rhs == this)
       return *this;
 
-    logicalDeviceHdl = rhs.logicalDeviceHdl;
-    swapchainHdl = rhs.swapchainHdl;
+    renderGraphStorage = rhs.renderGraphStorage;
     nodeIndexing = std::move(rhs.nodeIndexing);
     nodes = std::move(rhs.nodes);
-    graphResources = std::move(rhs.graphResources);
     resourceManager = std::move(rhs.resourceManager);
 
     return *this;
@@ -426,12 +434,12 @@ namespace SHADE
     for (auto const& instruction : resourceInstruction)
     {
       // If the resource that the new node is requesting for exists, allow the graph to reference it
-      if (graphResources.contains(instruction.resourceName))
+      if (renderGraphStorage->graphResources->contains(instruction.resourceName))
       {
         descInitParams.push_back(
           {
-            .resourceHdl = graphResources.at(instruction.resourceName),
-            .dontClearOnLoad = false, 
+            .resourceHdl = renderGraphStorage->graphResources->at(instruction.resourceName),
+            .dontClearOnLoad = instruction.dontClearOnLoad, 
           }
         );
       }
@@ -456,7 +464,7 @@ namespace SHADE
       }
     }
 
-    nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(descInitParams), std::move(predecessors), &graphResources));
+    nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(renderGraphStorage, std::move(descInitParams), std::move(predecessors)));
     nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
     return nodes.at(nodeIndexing[nodeName]);
   }
@@ -476,12 +484,31 @@ namespace SHADE
   /***************************************************************************/
   void SHRenderGraph::Generate(void) noexcept
   {
+    CheckForNodeComputes();
     ConfigureAttachmentDescriptions();
     ConfigureSubpasses();
     ConfigureRenderpasses();
     ConfigureFramebuffers();
   }
 
+  /***************************************************************************/
+  /*!
+  
+    \brief
+      This function goes through all renderpasses and checks for existence of 
+      node computes. If they exist, adds dummy subpasses to transition resources
+      into general.
+    
+  */
+  /***************************************************************************/
+  void SHRenderGraph::CheckForNodeComputes(void) noexcept
+  {
+    for (auto& node : nodes)
+    {
+    	node->AddDummySubpassIfNeeded();
+    }
+  }
+
   // TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a 
   // better way to manage these 
   void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
@@ -501,7 +528,7 @@ namespace SHADE
   void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept
   {
     // resize resources
-    for (auto& [name, resource]: graphResources)
+    for (auto& [name, resource] : *renderGraphStorage->graphResources)
     	resource->HandleResize(newWidth, newHeight);
 
     for (auto& node : nodes)
@@ -521,9 +548,9 @@ namespace SHADE
 
   Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept
   {
-    if (graphResources.contains(resourceName))
+    if (renderGraphStorage->graphResources->contains(resourceName))
     {
-      return graphResources.at(resourceName);
+      return renderGraphStorage->graphResources->at(resourceName);
     }
     return {};
   }
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h
index a919c4ff..d90b66df 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h
@@ -30,7 +30,8 @@ namespace SHADE
   class SHVkCommandBuffer;
   class SHRenderGraphNode;
   class SHGraphicsGlobalData;
-
+  class SHVkDescriptorPool;
+  class SHRenderGraphStorage;
 
   class SH_API SHRenderGraph
   {
@@ -56,10 +57,8 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* PRIVATE MEMBER VARIABLES                                              */
     /*-----------------------------------------------------------------------*/
-    Handle<SHVkLogicalDevice> logicalDeviceHdl;
 
-    //! swapchain used for querying image count
-    Handle<SHVkSwapchain> swapchainHdl;
+    Handle<SHRenderGraphStorage> renderGraphStorage;
 
     //! For indexing render graph node container
     std::map<std::string, uint32_t> nodeIndexing;
@@ -67,9 +66,6 @@ namespace SHADE
     //! Render graph nodes
     std::vector<Handle<SHRenderGraphNode>> nodes;
 
-    //! Resources that exist for the entire render graph
-    std::unordered_map<std::string, Handle<SHRenderGraphResource>> graphResources;
-
     //! Resource library for graph handles
     std::shared_ptr<SHResourceHub> resourceManager;
 
@@ -85,14 +81,15 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* PUBLIC MEMBER FUNCTIONS                                               */
     /*-----------------------------------------------------------------------*/
-    void                      Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept;
+    void                      Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept;
     void                      AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
     Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;
     
-    void                      Generate     (void) noexcept;
-    void                      Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
-    void                      FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
-    void                      HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
+    void                      Generate             (void) noexcept;
+    void                      CheckForNodeComputes (void) noexcept;
+    void                      Execute              (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
+    void                      FinaliseBatch        (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
+    void                      HandleResize         (uint32_t newWidth, uint32_t newHeight) noexcept;
 
     /*-----------------------------------------------------------------------*/
     /* SETTERS AND GETTERS                                                   */
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp
index 5950426e..c315bffd 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp
@@ -6,6 +6,9 @@
 #include "Graphics/Framebuffer/SHVkFramebuffer.h"
 #include "SHRenderGraphResource.h"
 #include "SHSubpass.h"
+#include "SHRenderGraphStorage.h"
+#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
+#include "Graphics/SHVkUtil.h"
 
 namespace SHADE
 {
@@ -21,7 +24,7 @@ namespace SHADE
   /***************************************************************************/
   void SHRenderGraphNode::CreateRenderpass(void) noexcept
   {
-    renderpass = logicalDeviceHdl->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
+    renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
   }
 
   /***************************************************************************/
@@ -53,7 +56,7 @@ namespace SHADE
       }
 
 
-      framebuffers[i] = logicalDeviceHdl->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
+      framebuffers[i] = graphStorage->logicalDevice->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
     }
   }
 
@@ -79,9 +82,18 @@ namespace SHADE
           fbHeight = attResources[j]->height;
       }
 
-
       framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
     }
+
+    for (auto& subpass : subpasses)
+    {
+    	subpass->HandleResize();
+    }
+
+    for (auto& nodeCompute : nodeComputes)
+    {
+    	nodeCompute->HandleResize();
+    }
   }
 
   /***************************************************************************/
@@ -104,8 +116,8 @@ namespace SHADE
 
   */
   /***************************************************************************/
-  SHRenderGraphNode::SHRenderGraphNode(std::shared_ptr<SHResourceHub> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
-    : logicalDeviceHdl{ logicalDevice }
+  SHRenderGraphNode::SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept
+    : graphStorage{ renderGraphStorage}
     , renderpass{}
     , framebuffers{}
     , prereqNodes{ std::move(predecessors) }
@@ -115,11 +127,10 @@ namespace SHADE
     , subpasses{}
     , executed{ false }
     , configured{ false }
-    , resourceManager{ rm }
-    , ptrToResources{ resources }
+    , nodeComputes{}
   {
     // pipeline library initialization
-    pipelineLibrary.Init(logicalDeviceHdl);
+    pipelineLibrary.Init(graphStorage->logicalDevice);
 
     // Store all the handles to resources
     attResources.reserve (attDescInitParams.size());
@@ -155,15 +166,14 @@ namespace SHADE
     if (!containsSwapchainImage)
       framebuffers.resize(1);
     else
-      framebuffers.resize(swapchain->GetNumImages());
+      framebuffers.resize(graphStorage->swapchain->GetNumImages());
 
     // At this point, we could configure framebuffers if we had the renderpass object but we don't so their creation has to be
     // deferred to when renderpasses are also created.
   }
 
   SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept
-    : resourceManager{ std::move (rhs.resourceManager) }
-    , logicalDeviceHdl{ rhs.logicalDeviceHdl }
+    : graphStorage{ rhs.graphStorage}
     , renderpass{ rhs.renderpass }
     , framebuffers{ std::move(rhs.framebuffers) }
     , prereqNodes{ std::move(rhs.prereqNodes) }
@@ -174,11 +184,11 @@ namespace SHADE
     , subpassIndexing{ std::move(rhs.subpassIndexing) }
     , configured{ rhs.configured }
     , executed{ rhs.executed }
-    , ptrToResources{ rhs.ptrToResources }
     , pipelineLibrary{ std::move(rhs.pipelineLibrary) }
     , batcher{ std::move(rhs.batcher) }
     , spDescs{ std::move(rhs.spDescs) }
     , spDeps{ std::move(rhs.spDeps) }
+    , nodeComputes{ std::move(rhs.nodeComputes) }
 
   {
     rhs.renderpass = {};
@@ -189,8 +199,7 @@ namespace SHADE
     if (&rhs == this)
       return *this;
 
-    resourceManager = std::move(rhs.resourceManager);
-    logicalDeviceHdl = rhs.logicalDeviceHdl;
+    graphStorage = rhs.graphStorage;
     renderpass = rhs.renderpass;
     framebuffers = std::move(rhs.framebuffers);
     prereqNodes = std::move(rhs.prereqNodes);
@@ -199,11 +208,11 @@ namespace SHADE
     subpasses = std::move(rhs.subpasses);
     resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping);
     subpassIndexing = std::move(rhs.subpassIndexing);
-    ptrToResources = std::move(rhs.ptrToResources);
     pipelineLibrary = std::move(rhs.pipelineLibrary);
     batcher = std::move(rhs.batcher);
     spDescs = std::move(rhs.spDescs);
     spDeps = std::move(rhs.spDeps);
+    nodeComputes = std::move(rhs.nodeComputes);
 
 
     rhs.renderpass = {};
@@ -235,10 +244,10 @@ namespace SHADE
     }
 
     // Add subpass to container and create mapping for it
-    subpasses.emplace_back(resourceManager->Create<SHSubpass>(GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
+    subpasses.emplace_back(graphStorage->resourceManager->Create<SHSubpass>(graphStorage, GetHandle(), static_cast<uint32_t>(subpasses.size()), &resourceAttachmentMapping));
     subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
     Handle<SHSubpass> subpass = subpasses.back();
-    subpass->Init(*resourceManager);
+    subpass->Init(*graphStorage->resourceManager);
 
     // Register the SuperBatch
     batcher.RegisterSuperBatch(subpass->GetSuperBatch());
@@ -246,21 +255,84 @@ namespace SHADE
     return subpass;
   }
 
+  Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale/* = 1.0f*/) noexcept
+  {
+    // Look for the required resources in the graph
+    std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{};
+    nodeComputeResources.reserve(resources.size());
+
+    for (auto& resourceName : resources)
+    {
+      auto resource = graphStorage->graphResources->at(resourceName);
+    	nodeComputeResources.push_back(resource);
+    }
+
+    // Create the subpass compute with the resources
+    auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(graphStorage, computeShaderModule, std::move(nodeComputeResources));
+    nodeComputes.push_back(nodeCompute);
+
+    return nodeCompute;
+  }
+
+  /***************************************************************************/
+  /*!
+  
+    \brief
+      This function checks all node computes and adds a subpass to transition
+      all needed resources to general.
+    
+  */
+  /***************************************************************************/
+  void SHRenderGraphNode::AddDummySubpassIfNeeded(void) noexcept
+  {
+    if (!nodeComputes.empty())
+    {
+      // we save the resource names involved
+      std::unordered_set<std::string> resourcesInvolved;
+      for (auto& compute : nodeComputes)
+      {
+        for (auto& resource : compute->resources)
+        {
+          resourcesInvolved.emplace(resource->GetName());
+        }
+      }
+
+      // insert them all for a subpass to transition them. This subpass is the last subpass
+      auto dummySubpass = AddSubpass("dummy");
+      for (auto& resource : resourcesInvolved)
+      {
+        dummySubpass->AddGeneralInput(resource);
+
+        if (SHVkUtil::IsDepthStencilAttachment(graphStorage->graphResources->at(resource)->GetResourceFormat()))
+          dummySubpass->AddGeneralDepthOutput(resource);
+        else
+          dummySubpass->AddGeneralColorOutput(resource);
+      }
+    }
+  }
+
   void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
   {
-    frameIndex = (framebuffers.size() > 1) ? frameIndex : 0;
-    commandBuffer->BeginRenderpass(renderpass, framebuffers[frameIndex]);
+    uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
+    commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
 
     for (uint32_t i = 0; i < subpasses.size(); ++i)
     {
       subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
 
       // Go to next subpass if not last subpass
-      if (i != subpasses.size() - 1)
+      if (i != static_cast<uint32_t>(subpasses.size()) - 1u)
         commandBuffer->NextSubpass();
     }
 
     commandBuffer->EndRenderpass();
+
+
+    // Execute all subpass computes
+    for (auto& sbCompute : nodeComputes)
+    {
+      sbCompute->Execute(commandBuffer, frameIndex);
+    }
   }
 
   Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
@@ -273,10 +345,10 @@ namespace SHADE
     }
 
 
-    Handle<SHVkPipeline> pipeline = pipelineLibrary.GetDrawPipline(vsFsPair);
+    Handle<SHVkPipeline> pipeline = pipelineLibrary.GetGraphicsPipeline(vsFsPair);
     if (!pipeline)
     {
-      pipeline = pipelineLibrary.CreateDrawPipeline
+      pipeline = pipelineLibrary.CreateGraphicsPipelines
       (
         vsFsPair,
         renderpass,
@@ -289,7 +361,7 @@ namespace SHADE
 
   void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
   {
-    batcher.FinaliseBatches(logicalDeviceHdl, descPool, frameIndex);
+    batcher.FinaliseBatches(graphStorage->logicalDevice, descPool, frameIndex);
   }
 
   /***************************************************************************/
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h
index 3cb1c4ee..16f3f914 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h
@@ -19,6 +19,9 @@ namespace SHADE
   class SHVkLogicalDevice;
   class SHVkRenderpass;
   class SHVkDescriptorPool;
+  class SHGraphicsGlobalData;
+  class SHRenderGraphStorage;
+  class SHRenderGraphNodeCompute;
 
   class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode>
   {
@@ -26,10 +29,9 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* PRIVATE MEMBER VARIABLES                                              */
     /*-----------------------------------------------------------------------*/
-    std::shared_ptr<SHResourceHub> resourceManager;
-
     //! For Vulkan object creation
-    Handle<SHVkLogicalDevice> logicalDeviceHdl;
+    //Handle<SHVkLogicalDevice> logicalDeviceHdl;
+    Handle<SHRenderGraphStorage> graphStorage;
 
     //! Each node will have a renderpass and each renderpass will have its own subpasses.
     //! These subpasses will execute sequentially. 
@@ -63,12 +65,13 @@ namespace SHADE
     //! For indexing subpasses
     std::map<std::string, uint32_t> subpassIndexing;
 
-    //! Pointer to resources in the render graph (for getting handle IDs)
-    std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
-
     //! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass 
     SHPipelineLibrary pipelineLibrary;
 
+    //! Sometimes we want the subpass to do something to the images instead
+    //! of drawing objects on the image (i.e. compute).
+    std::vector<Handle<SHRenderGraphNodeCompute>> nodeComputes;
+
     //! Whether or not the node has finished execution
     bool executed;
 
@@ -77,6 +80,7 @@ namespace SHADE
 
     SHBatcher batcher;
 
+
     /*-----------------------------------------------------------------------*/
     /* PRIVATE MEMBER FUNCTIONS                                              */
     /*-----------------------------------------------------------------------*/
@@ -88,7 +92,7 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* CTORS AND DTORS                                                       */
     /*-----------------------------------------------------------------------*/
-    SHRenderGraphNode(std::shared_ptr<SHResourceHub> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept;
+    SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept;
     SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
     SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
 
@@ -96,6 +100,9 @@ namespace SHADE
     /* PUBLIC MEMBER FUNCTIONS                                               */
     /*-----------------------------------------------------------------------*/
     Handle<SHSubpass>    AddSubpass(std::string subpassName) noexcept;
+    Handle<SHRenderGraphNodeCompute> AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale = 1.0f) noexcept;
+    void AddDummySubpassIfNeeded (void) noexcept;
+
     // TODO: RemoveSubpass()
     void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
     Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp
new file mode 100644
index 00000000..a5208fcf
--- /dev/null
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp
@@ -0,0 +1,109 @@
+#include "SHpch.h"
+#include "SHRenderGraphNodeCompute.h"
+#include "Graphics/Pipeline/SHVkPipeline.h"
+#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
+#include "Graphics/Descriptors/SHVkDescriptorPool.h"
+#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
+#include "Graphics/Devices/SHVkLogicalDevice.h"
+#include "Graphics/Pipeline/SHVkPipelineLayout.h"
+#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
+#include "SHRenderGraphStorage.h"
+#include "SHRenderGraphResource.h"
+#include "Graphics/Commands/SHVkCommandBuffer.h"
+
+namespace SHADE
+{
+  SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, float inNumWorkGroupScale/* = 1.0f*/) noexcept
+    : computePipeline{}
+    , pipelineLayout{}
+    , resources{}
+    , groupSizeX{0}
+    , groupSizeY{0}
+    , numWorkGroupScale {std::clamp(inNumWorkGroupScale, 0.0f, 1.0f)}
+  {
+    SHPipelineLayoutParams pipelineLayoutParams
+    {
+      .shaderModules = {computeShaderModule},
+      .globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
+    };
+
+    // Create pipeline layout from parameters
+    pipelineLayout = graphStorage->logicalDevice->CreatePipelineLayout (pipelineLayoutParams);
+
+    // Create the compute pipeline 
+    computePipeline = graphStorage->logicalDevice->CreateComputePipeline(pipelineLayout);
+
+    // and construct it
+    computePipeline->ConstructPipeline();
+
+    // save the resources
+    resources = std::move (subpassComputeResources);
+
+     //Get the descriptor set layouts required to allocate. We only want the ones for allocate because 
+     //global descriptors are already bound in the main system. 
+    auto const& layouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate();
+
+     //Variable counts for the descriptor sets (all should be 1).
+    std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(layouts.size()) };
+    std::fill(variableCounts.begin(), variableCounts.end(), 0);
+
+    // Allocate descriptor sets to hold the images for reading (STORAGE_IMAGE)
+    for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
+    {
+      descSetGroups[i] = graphStorage->descriptorPool->Allocate(layouts, variableCounts);
+    }
+
+
+    HandleResize();
+  }
+
+  void SHRenderGraphNodeCompute::Execute(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
+  {
+    // bind the compute pipeline
+    cmdBuffer->BindPipeline(computePipeline);
+    
+    // bind descriptor sets
+    cmdBuffer->BindDescriptorSet(descSetGroups[frameIndex], SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, {});
+
+    // dispatch compute
+    cmdBuffer->ComputeDispatch(groupSizeX, groupSizeY, 1);
+
+    // TODO: barrier
+
+  }
+
+  void SHRenderGraphNodeCompute::HandleResize(void) noexcept
+  {
+    // Get the layout for the render graph resource. We can index it this way because the container returned is a container of layouts that includes the global ones
+    auto pipelineDescSetLayouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsPipeline()[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE];
+
+    // everything below here needs resizing
+    for (uint32_t frameIndex = 0; frameIndex < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++frameIndex)
+    {
+      uint32_t i = 0;
+
+      // loop through bindings and write descriptor sets
+      for (auto& binding : pipelineDescSetLayouts->GetBindings())
+      {
+        uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0;
+
+        SHVkDescriptorSetGroup::viewSamplerLayout vsl = std::make_tuple(resources[i]->GetImageView(imageIndex), Handle<SHVkSampler>{}, vk::ImageLayout::eGeneral);
+        descSetGroups[frameIndex]->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, { &vsl, 1 });
+        descSetGroups[frameIndex]->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint);
+        ++i;
+      }
+    }
+
+    // Get the group size from the max width and height
+    uint32_t maxWidth = 0, maxHeight = 0;
+    for (auto& resource : resources)
+    {
+      maxWidth = std::max(resource->GetWidth(), maxWidth);
+      maxHeight = std::max(resource->GetHeight(), maxHeight);
+    }
+
+    groupSizeX = maxWidth / workGroupSizeX;
+    groupSizeY = maxHeight / workGroupSizeY;
+  }
+
+}
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.h
new file mode 100644
index 00000000..ba4cf387
--- /dev/null
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.h
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "Resource/SHHandle.h"
+#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
+#include <initializer_list>
+#include <string>
+#include <unordered_set>
+
+namespace SHADE
+{
+  class SHVkPipeline;
+  class SHVkDescriptorSetGroup;
+  class SHVkDescriptorPool;
+  class SHVkLogicalDevice;
+  class SHVkPipelineLayout;
+  class SHRenderGraphStorage;
+  class SHRenderGraphResource;
+  class SHVkShaderModule;
+  class SHVkCommandBuffer;
+
+  class SHRenderGraphNodeCompute
+  {
+  private:
+    static constexpr uint32_t workGroupSizeX = 16;
+    static constexpr uint32_t workGroupSizeY = 16;
+
+    //! To run the dispatch command
+    Handle<SHVkPipeline>                       computePipeline;
+
+    //! Pipeline layout for the pipeline creation
+    Handle<SHVkPipelineLayout>                 pipelineLayout;
+
+    //! Descriptor set group to hold the images for reading (STORAGE_IMAGE)
+    std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS> descSetGroups;
+
+    //! vector of resources needed by the subpass compute
+    std::vector<Handle<SHRenderGraphResource>> resources;
+
+    //! X dimension work group size. Should scale with resource size.
+    uint32_t groupSizeX;
+
+    //! Y dimension work group size 
+    uint32_t groupSizeY;
+
+    float numWorkGroupScale;
+
+  public:
+    SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, float inNumWorkGroupScale = 1.0f) noexcept;
+
+    void Execute (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
+    void HandleResize (void) noexcept;
+
+    friend class SHRenderGraph;
+    friend class SHRenderGraphNode;
+  };
+}
+
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp
index adf3b6cd..502e09b2 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp
@@ -5,6 +5,7 @@
 #include "Graphics/Images/SHVkImageView.h"
 #include "Graphics/Buffers/SHVkBuffer.h"
 #include "Graphics/SHVkUtil.h"
+#include "SHRenderGraphStorage.h"
 
 namespace SHADE
 {
@@ -45,9 +46,8 @@ namespace SHADE
 
   */
   /***************************************************************************/
-  SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
-    : logicalDevice {logicalDevice}
-    , swapchain{ swapchain }
+  SHRenderGraphResource::SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
+    : graphStorage{renderGraphStorage}
     , resourceTypeFlags{ }
     , resourceFormat{ format }
     , images{}
@@ -66,7 +66,7 @@ namespace SHADE
       SHImageViewDetails viewDetails
       {
         .viewType = vk::ImageViewType::e2D,
-        .format = swapchain->GetSurfaceFormatKHR().format,
+        .format = graphStorage->swapchain->GetSurfaceFormatKHR().format,
         .imageAspectFlags = vk::ImageAspectFlagBits::eColor,
         .baseMipLevel = 0,
         .mipLevelCount = 1,
@@ -75,13 +75,13 @@ namespace SHADE
       };
 
       // We want an image handle for every swapchain image
-      images.resize(swapchain->GetNumImages());
-      imageViews.resize(swapchain->GetNumImages());
+      images.resize(graphStorage->swapchain->GetNumImages());
+      imageViews.resize(graphStorage->swapchain->GetNumImages());
 
-      for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
+      for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
       {
-        images[i] = swapchain->GetSwapchainImage(i);
-        imageViews[i] = images[i]->CreateImageView(logicalDevice, images[i], viewDetails);
+        images[i] = graphStorage->swapchain->GetSwapchainImage(i);
+        imageViews[i] = images[i]->CreateImageView(graphStorage->logicalDevice, images[i], viewDetails);
       }
     }
     else // if swapchain image resource
@@ -117,6 +117,9 @@ namespace SHADE
           usage |= vk::ImageUsageFlagBits::eInputAttachment;
           usage |= vk::ImageUsageFlagBits::eSampled;
           break;
+        case SH_ATT_DESC_TYPE_FLAGS::STORAGE:
+          usage |= vk::ImageUsageFlagBits::eStorage;
+          break;
         case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT:
           {
             SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
@@ -126,7 +129,7 @@ namespace SHADE
       }
 
       // The resource is not a swapchain image, just use the first slot of the vector 
-      images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
+      images.push_back(graphStorage->logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
 
       // prepare image view details
       SHImageViewDetails viewDetails
@@ -141,7 +144,7 @@ namespace SHADE
       };
 
       // just 1 image view created
-      imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails));
+      imageViews.push_back(images[0]->CreateImageView(graphStorage->logicalDevice, images[0], viewDetails));
     }
   }
 
@@ -166,7 +169,7 @@ namespace SHADE
     , height{ rhs.height }
     , mipLevels{ rhs.mipLevels }
     , imageAspectFlags{ rhs.imageAspectFlags }
-    , swapchain {rhs.swapchain}
+    , graphStorage{rhs.graphStorage}
   {
 
   }
@@ -198,7 +201,7 @@ namespace SHADE
     height = rhs.height;
     mipLevels = rhs.mipLevels;
     imageAspectFlags = rhs.imageAspectFlags;
-    swapchain = rhs.swapchain;
+    graphStorage = rhs.graphStorage;
 
     return *this;
   }
@@ -247,7 +250,7 @@ namespace SHADE
       SHImageViewDetails viewDetails
       {
         .viewType = vk::ImageViewType::e2D,
-        .format = swapchain->GetSurfaceFormatKHR().format,
+        .format = graphStorage->swapchain->GetSurfaceFormatKHR().format,
         .imageAspectFlags = vk::ImageAspectFlagBits::eColor,
         .baseMipLevel = 0,
         .mipLevelCount = 1,
@@ -255,9 +258,9 @@ namespace SHADE
         .layerCount = 1,
       };
 
-      for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
+      for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
       {
-        images[i] = swapchain->GetSwapchainImage(i);
+        images[i] = graphStorage->swapchain->GetSwapchainImage(i);
         imageViews[i]->ViewNewImage(images[i], viewDetails);
       }
     }
@@ -308,6 +311,7 @@ namespace SHADE
     return resourceFormat;
   }
 
+
   uint32_t SHRenderGraphResource::GetWidth(void) const noexcept
   {
     return width;
@@ -323,4 +327,19 @@ namespace SHADE
     return imageViews [index];
   }
 
+  Handle<SHVkImage> SHRenderGraphResource::GetImage(uint32_t index /*= NON_SWAPCHAIN_RESOURCE_INDEX*/) const noexcept
+  {
+    return images[index];
+  }
+
+  uint8_t SHRenderGraphResource::GetMipLevels(void) const noexcept
+  {
+    return mipLevels;
+  }
+
+  std::string SHRenderGraphResource::GetName(void) const noexcept
+  {
+    return resourceName;
+  }
+
 }
\ No newline at end of file
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h
index fc8b05f7..e2fc5d8d 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h
@@ -15,6 +15,7 @@ namespace SHADE
   class SHVkSwapchain;
   class SHVkCommandBuffer;
   class SHVkBuffer;
+  class SHRenderGraphStorage;
 
   static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0;
 
@@ -24,11 +25,8 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* PRIVATE MEMBER VARIABLES                                              */
     /*-----------------------------------------------------------------------*/
-    // for creation/recreation
-    Handle<SHVkLogicalDevice> logicalDevice;
-
-    // for creation/recreation
-    Handle<SHVkSwapchain> swapchain;
+    //! Storage from the render graph
+    Handle<SHRenderGraphStorage> graphStorage;
 
     //! Name of the resource
     std::string resourceName;
@@ -69,7 +67,7 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* CTORS AND DTORS                                                       */
     /*-----------------------------------------------------------------------*/
-    SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
+    SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
     SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
     SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
     ~SHRenderGraphResource(void) noexcept;
@@ -84,12 +82,17 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* SETTERS AND GETTERS                                                   */
     /*-----------------------------------------------------------------------*/
-    vk::Format            GetResourceFormat (void) const noexcept;
-    uint32_t              GetWidth          (void) const noexcept;
-    uint32_t              GetHeight         (void) const noexcept;
-    Handle<SHVkImageView> GetImageView      (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
+    vk::Format                 GetResourceFormat (void) const noexcept;
+    uint32_t                   GetWidth          (void) const noexcept;
+    uint32_t                   GetHeight         (void) const noexcept;
+    Handle<SHVkImageView>      GetImageView      (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
+    Handle<SHVkImage>          GetImage          (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
+    uint8_t                    GetMipLevels      (void) const noexcept;
+    std::string                GetName           (void) const noexcept;
 
     friend class SHRenderGraphNode;
     friend class SHRenderGraph;
+    friend class SHSubpass;
+    friend class SHRenderGraphNodeCompute;
   };
 }
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphStorage.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphStorage.h
new file mode 100644
index 00000000..54ef705a
--- /dev/null
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphStorage.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "Resource/SHHandle.h"
+#include <memory>
+
+namespace SHADE
+{
+  class SHVkLogicalDevice;
+  class SHVkSwapchain;
+  class SHGraphicsGlobalData;
+  class SHVkDescriptorPool;
+  class SHRenderGraphResource;
+
+  class SHRenderGraphStorage
+  {
+    //! Logical device for creation of vulkan objects
+    Handle<SHVkLogicalDevice> logicalDevice;
+
+    //! swapchain handle
+    Handle<SHVkSwapchain> swapchain;
+
+    //! Resource manager for creation of objects
+    std::shared_ptr<SHResourceHub> resourceManager;
+
+    //! Descriptor pool for the descriptor sets to be created in the subpasses
+    Handle<SHVkDescriptorPool> descriptorPool;
+
+    //! For accessing resources anywhere in the graph
+    Handle<std::unordered_map<std::string, Handle<SHRenderGraphResource>>> graphResources;
+
+    //SHRenderGraphStorage(void) noexcept;
+    //SHRenderGraphStorage(SHRenderGraphStorage&& rhs) noexcept;
+    //SHRenderGraphStorage& operator=(SHRenderGraphStorage&& rhs) noexcept;
+
+    friend class SHRenderGraph;
+    friend class SHRenderGraphNode;
+    friend class SHSubpass;
+    friend class SHRenderGraphResource;
+    friend class SHRenderGraphNodeCompute;
+  };
+
+
+}
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp
index 7c5021f8..af6f3089 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp
@@ -4,6 +4,13 @@
 #include "Graphics/Devices/SHVkLogicalDevice.h"
 #include "SHRenderGraphNode.h"
 #include "SHRenderGraphResource.h"
+#include "Graphics/Shaders/SHVkShaderModule.h"
+#include "SHRenderGraphNode.h"
+#include "SHRenderGraphStorage.h"
+#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
+#include "Graphics/Swapchain/SHVkSwapchain.h"
+#include "Graphics/Images/SHVkSampler.h"
+#include "SHRenderGraphResource.h"
 
 namespace SHADE
 {
@@ -23,15 +30,16 @@ namespace SHADE
 
   */
   /***************************************************************************/
-  SHSubpass::SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
+  SHSubpass::SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept
     : resourceAttachmentMapping{ mapping }
-    , ptrToResources{ resources }
     , parentNode{ parent }
     , subpassIndex{ index }
     , superBatch{}
     , colorReferences{}
     , depthReferences{}
     , inputReferences{}
+    , graphStorage{ renderGraphStorage }
+    , inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS}
   {
   }
 
@@ -54,9 +62,14 @@ namespace SHADE
     , depthReferences{ std::move(rhs.depthReferences) }
     , inputReferences{ std::move(rhs.inputReferences) }
     , resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
-    , ptrToResources{ rhs.ptrToResources }
     , descriptorSetLayout{ rhs.descriptorSetLayout }
-    , exteriorDrawCalls{ std::move (rhs.exteriorDrawCalls) }
+    , exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) }
+    , graphStorage{ rhs.graphStorage }
+    , inputNames{ std::move(rhs.inputNames) }
+    , inputImageDescriptors{ std::move(rhs.inputImageDescriptors) }
+    , inputDescriptorLayout{ rhs.inputDescriptorLayout }
+    , inputSamplers{ rhs.inputSamplers }
+
   {
 
   }
@@ -84,9 +97,13 @@ namespace SHADE
     depthReferences = std::move(rhs.depthReferences);
     inputReferences = std::move(rhs.inputReferences);
     resourceAttachmentMapping = rhs.resourceAttachmentMapping;
-    ptrToResources = rhs.ptrToResources;
     descriptorSetLayout = rhs.descriptorSetLayout;
     exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
+    graphStorage = rhs.graphStorage;
+    inputNames = std::move(rhs.inputNames);
+    inputImageDescriptors = std::move(rhs.inputImageDescriptors);
+    inputDescriptorLayout = rhs.inputDescriptorLayout;
+    inputSamplers = rhs.inputSamplers;
 
     return *this;
   }
@@ -105,7 +122,12 @@ namespace SHADE
   /***************************************************************************/
   void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept
   {
-    colorReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
+    colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
+  }
+
+  void SHSubpass::AddGeneralColorOutput(std::string resourceToReference) noexcept
+  {
+    colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
   }
 
   /***************************************************************************/
@@ -142,7 +164,13 @@ namespace SHADE
       //Invalid
       return;
     }
-    depthReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), imageLayout });
+    depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), imageLayout });
+  }
+
+  void SHSubpass::AddGeneralDepthOutput(std::string resourceToReference) noexcept
+  {
+    depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
+
   }
 
   /***************************************************************************/
@@ -159,7 +187,14 @@ namespace SHADE
   /***************************************************************************/
   void SHSubpass::AddInput(std::string resourceToReference) noexcept
   {
-    inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
+    inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
+
+    inputNames.push_back(resourceToReference);
+  }
+
+  void SHSubpass::AddGeneralInput(std::string resourceToReference) noexcept
+  {
+    inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
   }
 
   void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
@@ -175,6 +210,12 @@ namespace SHADE
     {
       drawCall(commandBuffer);
     }
+
+  }
+
+  void SHSubpass::HandleResize(void) noexcept
+  {
+    UpdateWriteDescriptors();
   }
 
   void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept
@@ -188,6 +229,152 @@ namespace SHADE
 
   }
 
+  void SHSubpass::CreateInputDescriptors(void) noexcept
+  {
+    if (inputNames.empty())
+      return;
+
+    std::vector<SHVkDescriptorSetLayout::Binding> bindings{};
+
+    for (auto& input : inputReferences)
+    {
+      SHVkDescriptorSetLayout::Binding newBinding
+      {
+        .Type = (input.layout == vk::ImageLayout::eShaderReadOnlyOptimal) ? vk::DescriptorType::eInputAttachment : vk::DescriptorType::eStorageImage,
+        .Stage = vk::ShaderStageFlagBits::eFragment,
+        .BindPoint = static_cast<uint32_t>(bindings.size()),
+        .DescriptorCount = 1,
+        .flags = {},
+      };
+
+      bindings.push_back(newBinding);
+    }
+
+    // We build a new descriptor set layout to store our images
+    inputDescriptorLayout = graphStorage->logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, bindings);
+
+    // we store a sampler if its an input attachment. if it is storage image, no need sampler, store an empty handle.
+    for (uint32_t i = 0; i < bindings.size(); ++i)
+    {
+      if (bindings[i].Type == vk::DescriptorType::eInputAttachment)
+      {
+        auto newSampler = graphStorage->logicalDevice->CreateSampler(SHVkSamplerParams
+          {
+          .minFilter = vk::Filter::eLinear,
+          .magFilter = vk::Filter::eLinear,
+          .addressMode = vk::SamplerAddressMode::eRepeat,
+          .mipmapMode = vk::SamplerMipmapMode::eLinear,
+          .minLod = -1000,
+          .maxLod = 1000
+          }
+        );
+
+        inputSamplers.push_back(newSampler);
+      }
+      else
+      {
+        inputSamplers.push_back({});
+      }
+    }
+
+    //// maybe do this in handle resize? 
+    //UpdateWriteDescriptors();
+  }
+
+  void SHSubpass::UpdateWriteDescriptors(void) noexcept
+  {
+    if (inputNames.empty())
+      return;
+
+    auto const& bindings = inputDescriptorLayout->GetBindings();
+
+    std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(bindings.size()) };
+    std::fill (variableCounts.begin(), variableCounts.end(), 0u);
+
+
+    // For every frame's descriptor set
+    for (auto& group : inputImageDescriptors)
+    {
+      if (group)
+        group.Free();
+
+      group = graphStorage->descriptorPool->Allocate({ inputDescriptorLayout }, variableCounts);
+
+      uint32_t i = 0;
+      for (auto& binding : bindings)
+      {
+        // get the resource
+        auto resource = graphStorage->graphResources->at(inputNames[binding.BindPoint]);
+
+        // If resource is swapchain image, get the correct image, if not just get 0.
+        uint32_t viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0; 
+
+        // layout is GENERAL if image is meant to be used as storage image, if not use SHADER_READ_ONLY_OPTINAL
+        vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;
+
+        // Update descriptor sets
+        auto args = std::make_tuple(resource->GetImageView(viewIndex), inputSamplers[i], descriptorLayout);
+        group->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, std::span{&args, 1});
+        group->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint);
+      }
+
+      ++i;
+    }
+  }
+
+  //void SHSubpass::InitComputeBarriers(void) noexcept
+  //{
+  //  std::unordered_set <uint64_t> handleBarriers{};
+
+  //  // we will have swapchainNumImages vectors of vector of barriers 
+  //  subpassComputeBarriers.resize(graphStorage->swapchain->GetNumImages());
+
+  //  for (auto sbCompute : subpassComputes)
+  //  {
+  //    // for every resource the subpass compute is using
+  //  	for (auto resource : sbCompute->resources)
+  //  	{
+  //      // Get the resource handle
+  //      uint64_t resourceRaw = resource.GetId().Raw;
+
+  //      // if the barrier is not registered
+  //      if (!handleBarriers.contains(resourceRaw))
+  //      {
+  //        // If the resource is a swapchain image
+  //        bool isSwapchainImage = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT));
+  //        for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
+  //        {
+  //          // if swapchain image, we want the index of the swapchain image, if not take base image
+  //          uint32_t imageIndex = isSwapchainImage ? i : 0;
+
+  //          // Prepare image barrier
+  //          vk::ImageMemoryBarrier imageBarrier
+  //          {
+  //            .oldLayout = colorReferences[resourceAttachmentMapping->at(resource.GetId().Raw)].layout,
+  //            .newLayout = vk::ImageLayout::eGeneral,
+  //            .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+  //            .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+  //            .image = resource->GetImage(imageIndex)->GetVkImage(),
+  //            .subresourceRange = 
+  //            {
+  //              .aspectMask = resource->imageAspectFlags,
+  //              .levelCount = resource->GetMipLevels(),
+  //              .baseArrayLayer = 0,
+  //              .layerCount = 1
+  //            }
+  //          };
+
+  //          // push the barrier
+  //          subpassComputeBarriers[i].push_back(imageBarrier);
+  //        }
+
+  //        // Image transition registered
+  //        handleBarriers.emplace(resourceRaw);
+  //      }
+  //  	}
+  //  }
+  //}
+
   /***************************************************************************/
   /*!
 
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h
index e5094708..166f0d76 100644
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h
+++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h
@@ -14,7 +14,11 @@ namespace SHADE
   class SHRenderGraphResource;
   class SHVkCommandBuffer;
   class SHVkDescriptorSetLayout;
+  class SHVkDescriptorSetGroup;
   class SHVkDescriptorPool;
+  class SHRenderGraphStorage;
+  class SHVkShaderModule;
+  class SHVkSampler;
 
   class SH_API SHSubpass : public ISelfHandle<SHSubpass>
   {
@@ -22,32 +26,49 @@ namespace SHADE
     /*---------------------------------------------------------------------*/
     /* PRIVATE MEMBER VARIABLES                                            */
     /*---------------------------------------------------------------------*/
+    Handle<SHRenderGraphStorage>                  graphStorage;
+
     //! The index of the subpass in the render graph
-    uint32_t                             subpassIndex;
+    uint32_t                                      subpassIndex;
 
     //! The parent renderpass that this subpass belongs to
-    Handle<SHRenderGraphNode>            parentNode;
+    Handle<SHRenderGraphNode>                     parentNode;
 
     //! 
-    Handle<SHSuperBatch>                 superBatch;
+    Handle<SHSuperBatch>                          superBatch;
 
     //! Descriptor set layout to hold attachments
-    Handle<SHVkDescriptorSetLayout>      descriptorSetLayout;
+    Handle<SHVkDescriptorSetLayout>               descriptorSetLayout;
 
     //! Color attachments
-    std::vector<vk::AttachmentReference> colorReferences;
+    std::vector<vk::AttachmentReference>          colorReferences;
 
     //! Depth attachments
-    std::vector<vk::AttachmentReference> depthReferences;
+    std::vector<vk::AttachmentReference>          depthReferences;
 
     //! Input attachments
-    std::vector<vk::AttachmentReference> inputReferences;
+    std::vector<vk::AttachmentReference>          inputReferences;
+
+    //! This is mainly for when we want to retrieve resources using names.
+    std::vector<std::string>                      inputNames;
 
     //! For getting attachment reference indices using handles
     std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping;
 
-    //! Pointer to resources in the render graph (for getting handle IDs)
-    std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
+    //! Descriptor set group to hold the images for input
+    std::vector<Handle<SHVkDescriptorSetGroup>>   inputImageDescriptors;
+
+    //! Descriptor set layout for allocating descriptor set for inputs
+    Handle<SHVkDescriptorSetLayout>               inputDescriptorLayout;
+
+    std::vector<Handle<SHVkSampler>>              inputSamplers;
+
+
+    ////! subpass compute image barriers. We do this because every frame has a different
+    ////! swapchain image. If the resource we want to transition is not a swapchain image,
+    ////! we duplicate the barrier anyway, not much memory wasted. ;)
+    //std::vector<std::vector<vk::ImageMemoryBarrier>> subpassComputeBarriers{};
+
 
     //! Sometimes there exists entities that we want to render onto a render target
     //! but don't want it to come from the batching system. An example would be ImGUI.
@@ -62,7 +83,7 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     /* CTORS AND DTORS                                                       */
     /*-----------------------------------------------------------------------*/
-    SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept;
+    SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept;
     SHSubpass(SHSubpass&& rhs) noexcept;
     SHSubpass& operator=(SHSubpass&& rhs) noexcept;
 
@@ -71,14 +92,22 @@ namespace SHADE
     /*-----------------------------------------------------------------------*/
     // Preparation functions
     void AddColorOutput(std::string resourceToReference) noexcept;
+    void AddGeneralColorOutput(std::string resourceToReference) noexcept;
     void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept;
+    void AddGeneralDepthOutput(std::string resourceToReference) noexcept;
     void AddInput(std::string resourceToReference) noexcept;
+    void AddGeneralInput (std::string resourceToReference) noexcept;
+    void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
 
     // Runtime functions
     void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
-    void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
+    void HandleResize (void) noexcept;
 
     void Init(SHResourceHub& resourceManager) noexcept;
+    
+    //void InitComputeBarriers (void) noexcept;
+    void CreateInputDescriptors (void) noexcept;
+    void UpdateWriteDescriptors (void) noexcept;
 
     /*-----------------------------------------------------------------------*/
     /* GETTERS AND SETTERS                                                   */
@@ -91,5 +120,6 @@ namespace SHADE
 
     friend class SHRenderGraphNode;
     friend class SHRenderGraph;
+    friend class SHSubpass;
   };
 }
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.cpp
deleted file mode 100644
index ccd0e6c3..00000000
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "SHpch.h"
-#include "SHSubpassCompute.h"
-#include "Graphics/Pipeline/SHVkPipeline.h"
-#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
-#include "Graphics/Descriptors/SHVkDescriptorPool.h"
-
-namespace SHADE
-{
-  SHSubpassCompute::SHSubpassCompute(Handle<SHVkPipeline> inPipeline, Handle<SHVkDescriptorPool> descPool) noexcept
-    : pipeline {inPipeline}
-  {
-    // Get the descriptor set layouts required to allocate. we will bind a different pipeline layout, one that includes the layout for global.
-    auto const& layouts = pipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate();
-
-    // Variable counts for the descriptor sets (all should be 1).
-    std::vector<uint32_t> variableCounts{static_cast<uint32_t>(layouts.size())};
-    std::fill (variableCounts.begin(), variableCounts.end(), 0);
-
-    // Allocate descriptor sets to hold the images for reading (STORAGE_IMAGE)
-    descPool->Allocate(layouts, variableCounts);
-  }
-
-}
diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.h b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.h
deleted file mode 100644
index 7bbbe051..00000000
--- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include <Resource/SHHandle.h>
-
-namespace SHADE
-{
-  class SHVkPipeline;
-  class SHVkDescriptorSetGroup;
-  class SHVkDescriptorPool;
-
-  class SHSubpassCompute
-  {
-  private:
-    //! To run the dispatch command
-    Handle<SHVkPipeline>       pipeline;
-
-    //! Descriptor set group
-    Handle<SHVkDescriptorSetGroup> descSetGroup;
-  	
-  public:
-    SHSubpassCompute (Handle<SHVkPipeline> inPipeline, Handle<SHVkDescriptorPool> descPool) noexcept;
-
-  };
-}
-
diff --git a/SHADE_Engine/src/Graphics/SHVkUtil.cpp b/SHADE_Engine/src/Graphics/SHVkUtil.cpp
index c8c563a1..cf486a7a 100644
--- a/SHADE_Engine/src/Graphics/SHVkUtil.cpp
+++ b/SHADE_Engine/src/Graphics/SHVkUtil.cpp
@@ -55,6 +55,21 @@ namespace SHADE
     return 0;
   }
 
+  vk::PipelineBindPoint SHVkUtil::GetPipelineBindPointFromType(SH_PIPELINE_TYPE pipelineType) noexcept
+  {
+    switch (pipelineType)
+    {
+    case SH_PIPELINE_TYPE::GRAPHICS:
+      return vk::PipelineBindPoint::eGraphics;
+    case SH_PIPELINE_TYPE::COMPUTE:
+      return vk::PipelineBindPoint::eCompute;
+    case SH_PIPELINE_TYPE::RAY_TRACING:
+      return vk::PipelineBindPoint::eRayTracingKHR;
+    default:
+      return vk::PipelineBindPoint::eGraphics;
+    }
+  }
+
   void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage)
   {
       if (bufferHandle)
diff --git a/SHADE_Engine/src/Graphics/SHVkUtil.h b/SHADE_Engine/src/Graphics/SHVkUtil.h
index dbf17826..de700ea5 100644
--- a/SHADE_Engine/src/Graphics/SHVkUtil.h
+++ b/SHADE_Engine/src/Graphics/SHVkUtil.h
@@ -4,6 +4,7 @@
 #include "SHVulkanIncludes.h"
 
 #include "Resource/SHHandle.h"
+#include "Graphics/Pipeline/SHPipelineType.h"
 
 namespace SHADE
 {
@@ -20,11 +21,12 @@ namespace SHADE
   class SHVkUtil
   {
   public:                                  
-    static bool     IsDepthOnlyFormat          (vk::Format format) noexcept;
-    static bool     IsDepthStencilAttachment   (vk::Format format) noexcept;
-    static bool     IsBlendCompatible          (vk::Format format) noexcept;
-    static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept;
-
+    static bool                  IsDepthOnlyFormat            (vk::Format format) noexcept;
+    static bool                  IsDepthStencilAttachment     (vk::Format format) noexcept;
+    static bool                  IsBlendCompatible            (vk::Format format) noexcept;
+    static uint32_t              GetBytesPerPixelFromFormat   (vk::Format format) noexcept;
+    static vk::PipelineBindPoint GetPipelineBindPointFromType (SH_PIPELINE_TYPE pipelineType) noexcept;
+ 
     /***********************************************************************************/
     /*! 
      
diff --git a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp
index 41327988..e635f763 100644
--- a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp
+++ b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp
@@ -177,6 +177,9 @@ namespace SHADE
       return vk::DescriptorType::eStorageBufferDynamic;
     case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
       return vk::DescriptorType::eInputAttachment;
+    case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+      return vk::DescriptorType::eStorageImage;
+      break;
     default:
       return vk::DescriptorType::eCombinedImageSampler;
       break;
diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp
index 54ced715..cff4e84b 100644
--- a/SHADE_Engine/src/Resource/SHResourceManager.hpp
+++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp
@@ -15,6 +15,7 @@ of DigiPen Institute of Technology is prohibited.
 #include "SHResourceManager.h"
 // Project Includes
 #include "Assets/SHAssetManager.h"
+#include "Assets/Asset Types/SHAssetIncludes.h"
 #include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
 #include "ECS_Base/Managers/SHSystemManager.h"
 #include "Tools/SHLog.h"
@@ -48,7 +49,7 @@ namespace SHADE
         throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
 
       // Load
-      const SHMeshAsset* assetData = SHAssetManager::GetMesh(assetId);
+      const SHMeshAsset* assetData = SHAssetManager::GetData<SHMeshAsset>(assetId);
       if (assetData == nullptr)
       {
         SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
@@ -80,7 +81,7 @@ namespace SHADE
         throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
 
       // Load
-      const SHTextureAsset* assetData = SHAssetManager::GetTexture(assetId);
+      const SHTextureAsset* assetData = SHAssetManager::GetData<SHTextureAsset>(assetId);
       if (assetData == nullptr)
       {
         SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
@@ -133,7 +134,7 @@ namespace SHADE
   /* Query Functions                                                                   */
   /*-----------------------------------------------------------------------------------*/
   template<typename T>
-  static std::optional<AssetID> SHResourceManager::GetAssetID(Handle<T> handle)
+  std::optional<AssetID> SHResourceManager::GetAssetID(Handle<T> handle)
   {
     const Handle GENERIC_HANDLE = Handle(handle);
     auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<T>();
diff --git a/TempShaderFolder/KirschCs.glsl b/TempShaderFolder/KirschCs.glsl
new file mode 100644
index 00000000..3dec174d
--- /dev/null
+++ b/TempShaderFolder/KirschCs.glsl
@@ -0,0 +1,167 @@
+//#version 450
+//
+//layout(local_size_x = 16, local_size_y = 16) in;
+//layout(set = 4, binding = 0, rgba8) uniform image2D targetImage;
+//
+//
+//void main()
+//{
+//  ivec2 imageSize = imageSize (targetImage);
+//
+//  if (gl_GlobalInvocationID.x >= imageSize.x && gl_GlobalInvocationID.y >= imageSize.y)
+//    return;
+//
+//  // load the image
+//  vec4 color = imageLoad (targetImage, ivec2 (gl_GlobalInvocationID));
+//  
+//  // get the average
+//  float average = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
+//
+//  // store result into result image
+//  imageStore(targetImage, ivec2(gl_GlobalInvocationID), vec4(average, average, average, 1.0f));
+//
+//}
+//
+//
+//
+//
+
+/* Start Header *****************************************************************/
+
+/*! \file (e.g. kirsch.comp)
+
+     \author William Zheng, william.zheng, 60001906. Brandon Mak, brandon.hao 390003920.
+
+     \par william.zheng\@digipen.edu. brandon.hao\@digipen.edu.
+
+     \date Sept 20, 2022
+
+     \brief Copyright (C) 20xx DigiPen Institute of Technology.
+
+  Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. */
+
+  /* End Header *******************************************************************/
+
+#version 450
+
+#define MASK_WIDTH 3
+#define HALF_M_WIDTH MASK_WIDTH / 2
+#define SHM_WIDTH 18
+#define NUM_MASKS 8
+
+layout(local_size_x = 16, local_size_y = 16) in;
+layout(set = 4, binding = 0, rgba8) uniform image2D inputImage;
+layout(set = 4, binding = 1, rgba8) uniform image2D resultImage;
+
+const    float kirsch[8][3][3] = {
+        {
+         {5, 5, 5},
+         {-3, 0, -3},           /*rotation 1 */
+         {-3, -3, -3}
+         },
+        {
+         {5, 5, -3},
+         {5, 0, -3},            /*rotation 2 */
+         {-3, -3, -3}
+         },
+        {
+         {5, -3, -3},
+         {5, 0, -3},            /*rotation 3 */
+         {5, -3, -3}
+         },
+        {
+         {-3, -3, -3},
+         {5, 0, -3},            /*rotation 4 */
+         {5, 5, -3}
+         },
+        {
+         {-3, -3, -3},
+         {-3, 0, -3},           /*rotation 5 */
+         {5, 5, 5}
+         },
+        {
+         {-3, -3, -3},
+         {-3, 0, 5},            /*rotation 6 */
+         {-3, 5, 5}
+         },
+        {
+         {-3, -3, 5},
+         {-3, 0, 5},            /*rotation 7 */
+         {-3, -3, 5}
+         },
+        {
+         {-3, 5, 5},
+         {-3, 0, 5},            /*rotation 8 */
+         {-3, -3, -3}
+         }
+};
+
+vec3 GetImageValues(ivec2 uv, ivec2 inputImageSize)
+{
+  if (uv.x >= 0 && uv.y >= 0 && uv.x < inputImageSize.x && uv.y < inputImageSize.y)
+  {
+    return imageLoad(inputImage, uv).rgb;
+  }
+  else
+    return vec3(0.0f);
+}
+
+//two extra row/col
+shared vec3 sData[16 + 2][16 + 2];
+
+void main()
+{
+  // convenient variables
+  ivec3 globalThread = ivec3(gl_GlobalInvocationID);
+  ivec3 localThread = ivec3(gl_LocalInvocationID);
+  ivec2 inputImageSize = imageSize(inputImage);
+
+  // load shared memory
+  ivec2 start = ivec2(gl_WorkGroupID) * ivec2(gl_WorkGroupSize) - ivec2(HALF_M_WIDTH);
+  for (int i = localThread.x; i < SHM_WIDTH; i += int(gl_WorkGroupSize.x))
+  {
+    for (int j = localThread.y; j < SHM_WIDTH; j += int(gl_WorkGroupSize.y))
+    {
+      // get from source image (either real values or 0)
+      vec3 sourceValue = GetImageValues(start + ivec2(i, j), inputImageSize);
+      sData[i][j] = sourceValue;
+    }
+  }
+
+  // wait for shared memory to finish loading
+  barrier();
+
+  // max (between all 8 masks)
+  vec3 maxSum = vec3(0.0f);
+
+  // loop through all masks 
+  for (int i = 0; i < NUM_MASKS; ++i)
+  {
+    vec3 sum = vec3(0.0f);
+
+    // start of shared memory
+    ivec2 shmStart = ivec2(localThread + HALF_M_WIDTH);
+    for (int j = -1; j < HALF_M_WIDTH + 1; ++j)
+    {
+      for (int k = -1; k < HALF_M_WIDTH + 1; ++k)
+      {
+        // Perform convolution using shared_memory
+        sum += sData[shmStart.x + j][shmStart.y + k] * kirsch[i][j + 1][k + 1];
+      }
+    }
+
+    // Get highest sum
+    maxSum = max(sum, maxSum);
+  }
+
+  // average the max sum
+  maxSum = min(max(maxSum / 8, 0), 1.0f);
+
+  // store result into result image
+  imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), vec4(maxSum, 1.0f));
+
+}
+
+
+
+
diff --git a/TempShaderFolder/KirschCs.spv b/TempShaderFolder/KirschCs.spv
new file mode 100644
index 00000000..1ae5408b
Binary files /dev/null and b/TempShaderFolder/KirschCs.spv differ
