diff --git a/components/renderers/cpp/include/ftl/cuda/mask.hpp b/components/renderers/cpp/include/ftl/cuda/mask.hpp
index 4e359e5046f619e2a96ee3c5648365a98b76aca3..3f49f3bfc65e67186cc8caf321743ae2800805e7 100644
--- a/components/renderers/cpp/include/ftl/cuda/mask.hpp
+++ b/components/renderers/cpp/include/ftl/cuda/mask.hpp
@@ -9,6 +9,7 @@ namespace cuda {
  */
 class Mask {
 	public:
+	__device__ inline Mask() : v_(0) {}
 	__device__ explicit inline Mask(int v) : v_(v) {}
 	#ifdef __CUDACC__
 	__device__ inline Mask(const ftl::cuda::TextureObject<int> &m, int x, int y) : v_(m.tex2D(x,y)) {}
diff --git a/components/renderers/cpp/src/splat_render.cpp b/components/renderers/cpp/src/splat_render.cpp
index 5829ff0557001c185d7d61f94ce0dc1442a805c4..80a6f2a1ba1b1131173451a1f6dc24de86b080ee 100644
--- a/components/renderers/cpp/src/splat_render.cpp
+++ b/components/renderers/cpp/src/splat_render.cpp
@@ -399,7 +399,7 @@ bool Splatter::render(ftl::rgbd::VirtualSource *src, ftl::rgbd::Frame &out) {
 	if (aligned_source >= 0 && aligned_source < scene_->frames.size()) {
 		// FIXME: Output may not be same resolution as source!
 		cudaSafeCall(cudaStreamSynchronize(stream_));
-		scene_->frames[aligned_source].swapTo(Channel::Depth + Channel::Colour, out);
+		scene_->frames[aligned_source].copyTo(Channel::Depth + Channel::Colour, out);
 		return true;
 	}
 
diff --git a/components/rgbd-sources/include/ftl/rgbd/frame.hpp b/components/rgbd-sources/include/ftl/rgbd/frame.hpp
index 5e38fe5cc319e2ac9930199386c3c25ec55b23df..b08673c973f42253670b51a3da8e28735406c952 100644
--- a/components/rgbd-sources/include/ftl/rgbd/frame.hpp
+++ b/components/rgbd-sources/include/ftl/rgbd/frame.hpp
@@ -59,6 +59,11 @@ public:
 
 	void swapChannels(ftl::codecs::Channel, ftl::codecs::Channel);
 
+	/**
+	 * Does a host or device memory copy into the given frame.
+	 */
+	void copyTo(ftl::codecs::Channels, Frame &);
+
 	/**
 	 * Create a channel with a given format. This will discard any existing
 	 * data associated with the channel and ensure all data structures and
diff --git a/components/rgbd-sources/src/frame.cpp b/components/rgbd-sources/src/frame.cpp
index 851e75af76b96543f1f404303b50a2e3682652ae..212ca55375993789bb832e678fe4f1a8f22d5c48 100644
--- a/components/rgbd-sources/src/frame.cpp
+++ b/components/rgbd-sources/src/frame.cpp
@@ -85,6 +85,19 @@ void Frame::swapChannels(ftl::codecs::Channel a, ftl::codecs::Channel b) {
 	m1.tex = std::move(temptex);
 }
 
+void Frame::copyTo(ftl::codecs::Channels channels, Frame &f) {
+	f.reset();
+
+	// For all channels in this frame object
+	for (auto c : channels_) {
+		// Should we copy this channel?
+		if (channels.has(c)) {
+			if (isCPU(c)) get<cv::Mat>(c).copyTo(f.create<cv::Mat>(c));
+			else get<cv::cuda::GpuMat>(c).copyTo(f.create<cv::cuda::GpuMat>(c));
+		}
+	}
+}
+
 template<> cv::Mat& Frame::get(ftl::codecs::Channel channel) {
 	if (channel == Channel::None) {
 		DLOG(WARNING) << "Cannot get the None channel from a Frame";