diff --git a/.gitignore b/.gitignore
index 0b73f9af34ab5a91eca36a8afc7886877f6167a6..5d9752c3ead704bad95228d16330f1bf8b758b30 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,4 +80,3 @@ aegisub/tests/*.json
 /packages
 .nuget
 /aegisub/include
-/deps/fftw
diff --git a/.gitmodules b/.gitmodules
index 2bb6ab81374fb29ac3310e1ae85de30b75984d0d..467ded8aa8bb051aaceaf30fb786f52611e5262f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -50,3 +50,7 @@
 	url = git://github.com/ittner/Lua-experimentation.git
 	branch = lua51
 	ignore = dirty
+[submodule "deps/fftw"]
+	path = deps/fftw
+	url = https://github.com/Aegisub/fftw3.git
+	ignore = dirty
diff --git a/aegisub/build/BuildTasks/DependencyFetchers.fs b/aegisub/build/BuildTasks/DependencyFetchers.fs
index cafbc1213ef9625502ee770082600a8371db2d77..5827acffad49628de3fb4716a8916c8fd87f7deb 100644
--- a/aegisub/build/BuildTasks/DependencyFetchers.fs
+++ b/aegisub/build/BuildTasks/DependencyFetchers.fs
@@ -31,45 +31,6 @@ let downloadArchive (url : String) unpackDest =
   use tarArchive = ICSharpCode.SharpZipLib.Tar.TarArchive.CreateInputTarArchive tarStream
   tarArchive.ExtractContents unpackDest
 
-type TarballProject() =
-  inherit Task()
-
-  member val Projects : ITaskItem[] = null with get, set
-  member val Root = "" with get, set
-
-  override this.Execute() =
-    let needsUpdate directory version =
-      try
-        not <| String.Equals(sprintf "%s\\version.aegisub" directory |> IO.File.ReadAllText, version)
-      with | :? IO.IOException -> true
-
-    let update directory (project : ITaskItem) version =
-      try IO.Directory.Delete(directory, true) with | :? IO.IOException -> ()
-
-      this.Log.LogMessage ("Downloading {0} {1} from {2}", project.ItemSpec, version, project.GetMetadata "Url")
-      downloadArchive (project.GetMetadata "Url") (sprintf @"%s\.." directory)
-
-      let dirname = project.GetMetadata "DirName"
-      if not <| String.IsNullOrWhiteSpace dirname
-      then IO.Directory.Move(dirname |> sprintf @"%s\..\%s" directory, directory)
-
-      IO.File.WriteAllText(sprintf @"%s\version.aegisub" directory, version)
-
-    let check (project : ITaskItem) =
-      let directory = sprintf "%s\\%s" this.Root project.ItemSpec
-      let version = project.GetMetadata "Version"
-
-      if needsUpdate directory <| version
-      then update directory project version
-      else this.Log.LogMessage <| sprintf "%s is up to date" project.ItemSpec
-
-    try
-      this.Projects |> Array.map check |> ignore
-      true
-    with e ->
-      this.Log.LogErrorFromException e
-      false
-
 type DownloadTgzFile() =
   inherit Task()
 
diff --git a/aegisub/build/deps/deps.vcxproj b/aegisub/build/deps/deps.vcxproj
index 6985fea9fa1881ba10d293ea468bb8e47e382001..e0d16a4e9a112aa8dc9732bfeb3dd86ffc98b6e5 100644
--- a/aegisub/build/deps/deps.vcxproj
+++ b/aegisub/build/deps/deps.vcxproj
@@ -22,21 +22,10 @@ Aegisub Project http://www.aegisub.org/
     <ProjectName>! Update Dependencies</ProjectName>
   </PropertyGroup>
 
-  <ItemGroup Label="tarball">
-    <TarballProject Include="fftw">
-      <Version>3.3.2</Version>
-      <Url>http://www.fftw.org/fftw-3.3.2.tar.gz</Url>
-      <DirName>fftw-3.3.2</DirName>
-    </TarballProject>
-  </ItemGroup>
-
   <Import Project="$(MSBuildThisFileDirectory)\..\aegisub.props" />
-  <UsingTask TaskName="TarballProject" AssemblyFile="$(AegisubBinaryDir)BuildTasks.dll" />
   <UsingTask TaskName="DownloadTgzFile" AssemblyFile="$(AegisubBinaryDir)BuildTasks.dll" />
 
   <Target Name="Build">
-    <TarballProject Projects="@(TarballProject)" Root="$(MSBuildThisFileDirectory)..\..\..\deps" />
-
     <!-- Generated with http://apps.icu-project.org/datacustom/ -->
     <!-- Includes Break Iterator and Collator data only -->
     <DownloadTgzFile
diff --git a/deps/fftw b/deps/fftw
new file mode 160000
index 0000000000000000000000000000000000000000..d68ca6315cafa5b8ff9367d9375314f32b7dbd81
--- /dev/null
+++ b/deps/fftw
@@ -0,0 +1 @@
+Subproject commit d68ca6315cafa5b8ff9367d9375314f32b7dbd81