Browse Source

[REFACTOR] Make buffer-copy-to-texture to use texture views

Panagiotis Christopoulos Charitos 8 years ago
parent
commit
1e19c91979

+ 6 - 7
src/anki/gr/CommandBuffer.h

@@ -316,13 +316,12 @@ public:
 	/// @param[in] clearValue The value to clear it with.
 	void clearTextureView(TextureViewPtr texView, const ClearValue& clearValue);
 
-	/// Copy a buffer to a texture surface.
-	void copyBufferToTextureSurface(
-		BufferPtr buff, PtrSize offset, PtrSize range, TexturePtr tex, const TextureSurfaceInfo& surf);
-
-	/// Copy buffer to a texture volume.
-	void copyBufferToTextureVolume(
-		BufferPtr buff, PtrSize offset, PtrSize range, TexturePtr tex, const TextureVolumeInfo& vol);
+	/// Copy a buffer to a texture surface or volume.
+	/// @param buff The source buffer to copy from.
+	/// @param offset The offset in the buffer to start reading from.
+	/// @param range The size of the buffer to read.
+	/// @param texView The texture view that points to a surface or volume to write to.
+	void copyBufferToTextureView(BufferPtr buff, PtrSize offset, PtrSize range, TextureViewPtr texView);
 
 	/// Fill a buffer with some value.
 	/// @param[in,out] buff The buffer to fill.

+ 11 - 0
src/anki/gr/Common.h

@@ -230,6 +230,17 @@ public:
 		, m_depthStencilAspect(aspect)
 	{
 	}
+
+	TextureSubresourceInfo(const TextureVolumeInfo& vol)
+		: m_baseMipmap(vol.m_level)
+		, m_mipmapCount(1)
+		, m_baseLayer(0)
+		, m_layerCount(1)
+		, m_baseFace(0)
+		, m_faceCount(1)
+		, m_depthStencilAspect(DepthStencilAspectBit::NONE)
+	{
+	}
 };
 
 enum class DescriptorType : U8

+ 13 - 14
src/anki/gr/Texture.h

@@ -138,19 +138,7 @@ public:
 		ANKI_TEX_SUBRESOURCE_ASSERT(subresource.m_baseFace + subresource.m_faceCount <= faceCount);
 
 		// Aspect
-		const PixelFormat fmt = m_format;
-		DepthStencilAspectBit aspect =
-			(componentFormatIsDepth(fmt.m_components)) ? DepthStencilAspectBit::DEPTH : DepthStencilAspectBit::NONE;
-		aspect |=
-			(componentFormatIsStencil(fmt.m_components)) ? DepthStencilAspectBit::STENCIL : DepthStencilAspectBit::NONE;
-		if(!!aspect)
-		{
-			ANKI_TEX_SUBRESOURCE_ASSERT(!!(aspect & subresource.m_depthStencilAspect));
-		}
-		else
-		{
-			ANKI_TEX_SUBRESOURCE_ASSERT(aspect == DepthStencilAspectBit::NONE);
-		}
+		ANKI_TEX_SUBRESOURCE_ASSERT((m_aspect & subresource.m_depthStencilAspect) == subresource.m_depthStencilAspect);
 
 		// Misc
 		if(type == TextureType::CUBE_ARRAY && subresource.m_layerCount > 1)
@@ -191,8 +179,19 @@ public:
 	/// Return true if the subresource can be bound for sampling.
 	Bool isSubresourceGoodForSampling(const TextureSubresourceInfo& subresource) const
 	{
+		ANKI_ASSERT(isSubresourceValid(subresource));
 		/// Can bound only one aspect at a time.
-		return subresource.m_depthStencilAspect != DepthStencilAspectBit::DEPTH;
+		return subresource.m_depthStencilAspect == DepthStencilAspectBit::DEPTH
+			|| subresource.m_depthStencilAspect == DepthStencilAspectBit::STENCIL
+			|| subresource.m_depthStencilAspect == DepthStencilAspectBit::NONE;
+	}
+
+	/// Return true if the subresource can be used in CommandBuffer::copyBufferToTextureView.
+	Bool isSubresourceGoodForCopyFromBuffer(const TextureSubresourceInfo& subresource) const
+	{
+		ANKI_ASSERT(isSubresourceValid(subresource));
+		return subresource.m_faceCount == 1 && subresource.m_mipmapCount == 1 && subresource.m_layerCount == 1
+			&& subresource.m_depthStencilAspect == DepthStencilAspectBit::NONE;
 	}
 
 protected:

+ 2 - 10
src/anki/gr/vulkan/CommandBuffer.cpp

@@ -281,18 +281,10 @@ void CommandBuffer::clearTextureView(TextureViewPtr texView, const ClearValue& c
 	self.clearTextureView(texView, clearValue);
 }
 
-void CommandBuffer::copyBufferToTextureSurface(
-	BufferPtr buff, PtrSize offset, PtrSize range, TexturePtr tex, const TextureSurfaceInfo& surf)
+void CommandBuffer::copyBufferToTextureView(BufferPtr buff, PtrSize offset, PtrSize range, TextureViewPtr texView)
 {
 	ANKI_VK_SELF(CommandBufferImpl);
-	self.copyBufferToTextureSurface(buff, offset, range, tex, surf);
-}
-
-void CommandBuffer::copyBufferToTextureVolume(
-	BufferPtr buff, PtrSize offset, PtrSize range, TexturePtr tex, const TextureVolumeInfo& vol)
-{
-	ANKI_VK_SELF(CommandBufferImpl);
-	self.copyBufferToTextureVolume(buff, offset, range, tex, vol);
+	self.copyBufferToTextureViewInternal(buff, offset, range, texView);
 }
 
 void CommandBuffer::fillBuffer(BufferPtr buff, PtrSize offset, PtrSize size, U32 value)

+ 60 - 138
src/anki/gr/vulkan/CommandBufferImpl.cpp

@@ -656,135 +656,44 @@ void CommandBufferImpl::flushWriteQueryResults()
 	m_writeQueryAtomCount = 0;
 }
 
-void CommandBufferImpl::copyBufferToTextureSurface(
-	BufferPtr buff, PtrSize offset, PtrSize range, TexturePtr tex, const TextureSurfaceInfo& surf)
+void CommandBufferImpl::copyBufferToTextureViewInternal(
+	BufferPtr buff, PtrSize offset, PtrSize range, TextureViewPtr texView)
 {
 	commandCommon();
 
-	const TextureImpl& impl = static_cast<const TextureImpl&>(*tex);
-	impl.checkSurfaceOrVolume(surf);
-	ANKI_ASSERT(impl.usageValid(TextureUsageBit::TRANSFER_DESTINATION));
+	const TextureViewImpl& view = static_cast<const TextureViewImpl&>(*texView);
+	const TextureImpl& tex = static_cast<const TextureImpl&>(*view.m_tex);
+	ANKI_ASSERT(tex.usageValid(TextureUsageBit::TRANSFER_DESTINATION));
 	const VkImageLayout layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+	const Bool is3D = tex.getTextureType() == TextureType::_3D;
+	const VkImageAspectFlags aspect = convertImageAspect(view.getDepthStencilAspect());
 
-	if(!impl.m_workarounds)
-	{
-		U width = impl.getWidth() >> surf.m_level;
-		U height = impl.getHeight() >> surf.m_level;
-		ANKI_ASSERT(range == computeSurfaceSize(width, height, impl.getPixelFormat()));
+	const TextureSurfaceInfo surf(view.getBaseMipmap(), view.getBaseFace(), 0, view.getBaseLayer());
+	const TextureVolumeInfo vol(view.getBaseMipmap());
 
-		// Copy
-		VkBufferImageCopy region;
-		region.imageSubresource.aspectMask = convertImageAspect(impl.getDepthStencilAspect());
-		region.imageSubresource.baseArrayLayer = impl.computeVkArrayLayer(surf);
-		region.imageSubresource.layerCount = 1;
-		region.imageSubresource.mipLevel = surf.m_level;
-		region.imageOffset = {0, 0, I32(surf.m_depth)};
-		region.imageExtent.width = width;
-		region.imageExtent.height = height;
-		region.imageExtent.depth = 1;
-		region.bufferOffset = offset;
-		region.bufferImageHeight = 0;
-		region.bufferRowLength = 0;
+	// Compute the sizes of the mip
+	const U width = tex.getWidth() >> surf.m_level;
+	const U height = tex.getHeight() >> surf.m_level;
+	ANKI_ASSERT(width && height);
+	const U depth = (is3D) ? (tex.getDepth() >> surf.m_level) : 1u;
 
-		ANKI_CMD(
-			vkCmdCopyBufferToImage(
-				m_handle, static_cast<const BufferImpl&>(*buff).getHandle(), impl.m_imageHandle, layout, 1, &region),
-			ANY_OTHER_COMMAND);
-	}
-	else if(!!(impl.m_workarounds & TextureImplWorkaround::R8G8B8_TO_R8G8B8A8))
+	if(!tex.m_workarounds)
 	{
-		U width = impl.getWidth() >> surf.m_level;
-		U height = impl.getHeight() >> surf.m_level;
-
-		// Create a new shadow buffer
-		const PtrSize shadowSize =
-			computeSurfaceSize(width, height, PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM));
-		BufferPtr shadow = getManager().newBuffer(
-			BufferInitInfo(shadowSize, BufferUsageBit::TRANSFER_ALL, BufferMapAccessBit::NONE, "Workaround"));
-		const VkBuffer shadowHandle = static_cast<const BufferImpl&>(*shadow).getHandle();
-		m_microCmdb->pushObjectRef(shadow);
-
-		// Create the copy regions
-		DynamicArrayAuto<VkBufferCopy> copies(m_alloc);
-		copies.create(width * height);
-		U count = 0;
-		for(U x = 0; x < width; ++x)
+		if(!is3D)
 		{
-			for(U y = 0; y < height; ++y)
-			{
-				VkBufferCopy& c = copies[count++];
-				c.srcOffset = (y * width + x) * 3 + offset;
-				c.dstOffset = (y * width + x) * 4 + 0;
-				c.size = 3;
-			}
+			ANKI_ASSERT(range == computeSurfaceSize(width, height, tex.getPixelFormat()));
+		}
+		else
+		{
+			ANKI_ASSERT(range == computeVolumeSize(width, height, depth, tex.getPixelFormat()));
 		}
-
-		// Copy buffer to buffer
-		ANKI_CMD(vkCmdCopyBuffer(m_handle,
-					 static_cast<const BufferImpl&>(*buff).getHandle(),
-					 shadowHandle,
-					 copies.getSize(),
-					 &copies[0]),
-			ANY_OTHER_COMMAND);
-
-		// Set barrier
-		setBufferBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
-			VK_ACCESS_TRANSFER_WRITE_BIT,
-			VK_PIPELINE_STAGE_TRANSFER_BIT,
-			VK_ACCESS_TRANSFER_READ_BIT,
-			0,
-			shadowSize,
-			static_cast<const BufferImpl&>(*shadow).getHandle());
-
-		// Do the copy to the image
-		VkBufferImageCopy region;
-		region.imageSubresource.aspectMask = convertImageAspect(impl.getDepthStencilAspect());
-		region.imageSubresource.baseArrayLayer = impl.computeVkArrayLayer(surf);
-		region.imageSubresource.layerCount = 1;
-		region.imageSubresource.mipLevel = surf.m_level;
-		region.imageOffset = {0, 0, I32(surf.m_depth)};
-		region.imageExtent.width = width;
-		region.imageExtent.height = height;
-		region.imageExtent.depth = 1;
-		region.bufferOffset = 0;
-		region.bufferImageHeight = 0;
-		region.bufferRowLength = 0;
-
-		ANKI_CMD(
-			vkCmdCopyBufferToImage(m_handle, shadowHandle, impl.m_imageHandle, layout, 1, &region), ANY_OTHER_COMMAND);
-	}
-	else
-	{
-		ANKI_ASSERT(0);
-	}
-
-	m_microCmdb->pushObjectRef(tex);
-	m_microCmdb->pushObjectRef(buff);
-}
-
-void CommandBufferImpl::copyBufferToTextureVolume(
-	BufferPtr buff, PtrSize offset, PtrSize range, TexturePtr tex, const TextureVolumeInfo& vol)
-{
-	commandCommon();
-
-	const TextureImpl& impl = static_cast<const TextureImpl&>(*tex);
-	impl.checkSurfaceOrVolume(vol);
-	ANKI_ASSERT(impl.usageValid(TextureUsageBit::TRANSFER_DESTINATION));
-	const VkImageLayout layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
-
-	if(!impl.m_workarounds)
-	{
-		U width = impl.getWidth() >> vol.m_level;
-		U height = impl.getHeight() >> vol.m_level;
-		U depth = impl.getDepth() >> vol.m_level;
-		ANKI_ASSERT(range == computeVolumeSize(width, height, depth, impl.getPixelFormat()));
 
 		// Copy
 		VkBufferImageCopy region;
-		region.imageSubresource.aspectMask = convertImageAspect(impl.getDepthStencilAspect());
-		region.imageSubresource.baseArrayLayer = impl.computeVkArrayLayer(vol);
+		region.imageSubresource.aspectMask = aspect;
+		region.imageSubresource.baseArrayLayer = (is3D) ? tex.computeVkArrayLayer(surf) : tex.computeVkArrayLayer(vol);
 		region.imageSubresource.layerCount = 1;
-		region.imageSubresource.mipLevel = vol.m_level;
+		region.imageSubresource.mipLevel = surf.m_level;
 		region.imageOffset = {0, 0, 0};
 		region.imageExtent.width = width;
 		region.imageExtent.height = height;
@@ -795,19 +704,15 @@ void CommandBufferImpl::copyBufferToTextureVolume(
 
 		ANKI_CMD(
 			vkCmdCopyBufferToImage(
-				m_handle, static_cast<const BufferImpl&>(*buff).getHandle(), impl.m_imageHandle, layout, 1, &region),
+				m_handle, static_cast<const BufferImpl&>(*buff).getHandle(), tex.m_imageHandle, layout, 1, &region),
 			ANY_OTHER_COMMAND);
 	}
-	else if(!!(impl.m_workarounds & TextureImplWorkaround::R8G8B8_TO_R8G8B8A8))
+	else if(!!(tex.m_workarounds & TextureImplWorkaround::R8G8B8_TO_R8G8B8A8))
 	{
-		// Find the offset to the RGBA staging buff
-		U width = impl.getWidth() >> vol.m_level;
-		U height = impl.getHeight() >> vol.m_level;
-		U depth = impl.getDepth() >> vol.m_level;
-
 		// Create a new shadow buffer
-		const PtrSize shadowSize =
-			computeVolumeSize(width, height, depth, PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM));
+		const PtrSize shadowSize = (is3D)
+			? computeVolumeSize(width, height, depth, PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM))
+			: computeSurfaceSize(width, height, PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM));
 		BufferPtr shadow = getManager().newBuffer(
 			BufferInitInfo(shadowSize, BufferUsageBit::TRANSFER_ALL, BufferMapAccessBit::NONE, "Workaround"));
 		const VkBuffer shadowHandle = static_cast<const BufferImpl&>(*shadow).getHandle();
@@ -815,17 +720,35 @@ void CommandBufferImpl::copyBufferToTextureVolume(
 
 		// Create the copy regions
 		DynamicArrayAuto<VkBufferCopy> copies(m_alloc);
-		copies.create(width * height * depth);
-		U count = 0;
-		for(U x = 0; x < width; ++x)
+		if(is3D)
 		{
-			for(U y = 0; y < height; ++y)
+			copies.create(width * height * depth);
+			U count = 0;
+			for(U x = 0; x < width; ++x)
 			{
-				for(U d = 0; d < depth; ++d)
+				for(U y = 0; y < height; ++y)
+				{
+					for(U d = 0; d < depth; ++d)
+					{
+						VkBufferCopy& c = copies[count++];
+						c.srcOffset = (d * height * width + y * width + x) * 3 + offset;
+						c.dstOffset = (d * height * width + y * width + x) * 4 + 0;
+						c.size = 3;
+					}
+				}
+			}
+		}
+		else
+		{
+			copies.create(width * height);
+			U count = 0;
+			for(U x = 0; x < width; ++x)
+			{
+				for(U y = 0; y < height; ++y)
 				{
 					VkBufferCopy& c = copies[count++];
-					c.srcOffset = (d * height * width + y * width + x) * 3 + offset;
-					c.dstOffset = (d * height * width + y * width + x) * 4 + 0;
+					c.srcOffset = (y * width + x) * 3 + offset;
+					c.dstOffset = (y * width + x) * 4 + 0;
 					c.size = 3;
 				}
 			}
@@ -850,10 +773,10 @@ void CommandBufferImpl::copyBufferToTextureVolume(
 
 		// Do the copy to the image
 		VkBufferImageCopy region;
-		region.imageSubresource.aspectMask = convertImageAspect(impl.getDepthStencilAspect());
-		region.imageSubresource.baseArrayLayer = impl.computeVkArrayLayer(vol);
+		region.imageSubresource.aspectMask = aspect;
+		region.imageSubresource.baseArrayLayer = (is3D) ? tex.computeVkArrayLayer(vol) : tex.computeVkArrayLayer(surf);
 		region.imageSubresource.layerCount = 1;
-		region.imageSubresource.mipLevel = vol.m_level;
+		region.imageSubresource.mipLevel = surf.m_level;
 		region.imageOffset = {0, 0, 0};
 		region.imageExtent.width = width;
 		region.imageExtent.height = height;
@@ -862,16 +785,15 @@ void CommandBufferImpl::copyBufferToTextureVolume(
 		region.bufferImageHeight = 0;
 		region.bufferRowLength = 0;
 
-		ANKI_CMD(vkCmdCopyBufferToImage(
-					 m_handle, shadowHandle, impl.m_imageHandle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region),
-			ANY_OTHER_COMMAND);
+		ANKI_CMD(
+			vkCmdCopyBufferToImage(m_handle, shadowHandle, tex.m_imageHandle, layout, 1, &region), ANY_OTHER_COMMAND);
 	}
 	else
 	{
 		ANKI_ASSERT(0);
 	}
 
-	m_microCmdb->pushObjectRef(tex);
+	m_microCmdb->pushObjectRef(texView);
 	m_microCmdb->pushObjectRef(buff);
 }
 

+ 1 - 5
src/anki/gr/vulkan/CommandBufferImpl.h

@@ -323,11 +323,7 @@ public:
 		m_microCmdb->pushObjectRef(buff);
 	}
 
-	void copyBufferToTextureSurface(
-		BufferPtr buff, PtrSize offset, PtrSize range, TexturePtr tex, const TextureSurfaceInfo& surf);
-
-	void copyBufferToTextureVolume(
-		BufferPtr buff, PtrSize offset, PtrSize range, TexturePtr tex, const TextureVolumeInfo& vol);
+	void copyBufferToTextureViewInternal(BufferPtr buff, PtrSize offset, PtrSize range, TextureViewPtr texView);
 
 	void copyBufferToBuffer(BufferPtr& src, PtrSize srcOffset, BufferPtr& dst, PtrSize dstOffset, PtrSize range);
 

+ 8 - 7
src/anki/resource/TextureResource.cpp

@@ -267,19 +267,20 @@ Error TextureResource::load(LoadingContext& ctx)
 
 			memcpy(data, surfOrVolData, surfOrVolSize);
 
+			// Create temp tex view
+			TextureSubresourceInfo subresource;
 			if(ctx.m_texType == TextureType::_3D)
 			{
-				TextureVolumeInfo vol(mip);
-				cmdb->copyBufferToTextureVolume(
-					handle.getBuffer(), handle.getOffset(), handle.getRange(), ctx.m_tex, vol);
+				subresource = TextureSubresourceInfo(TextureVolumeInfo(mip));
 			}
 			else
 			{
-				TextureSurfaceInfo surf(mip, 0, face, layer);
-
-				cmdb->copyBufferToTextureSurface(
-					handle.getBuffer(), handle.getOffset(), handle.getRange(), ctx.m_tex, surf);
+				subresource = TextureSubresourceInfo(TextureSurfaceInfo(mip, 0, face, layer));
 			}
+
+			TextureViewPtr tmpView = ctx.m_gr->newTextureView(TextureViewInitInfo(ctx.m_tex, subresource, "RsrcTmp"));
+
+			cmdb->copyBufferToTextureView(handle.getBuffer(), handle.getOffset(), handle.getRange(), tmpView);
 		}
 
 		// Set the barriers of the batch

+ 15 - 10
src/anki/ui/Font.cpp

@@ -77,7 +77,7 @@ void Font::createTexture(const void* data, U32 width, U32 height)
 	buff->unmap();
 
 	// Create the texture
-	TextureInitInfo texInit;
+	TextureInitInfo texInit("Font");
 	texInit.m_width = width;
 	texInit.m_height = height;
 	texInit.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
@@ -87,21 +87,26 @@ void Font::createTexture(const void* data, U32 width, U32 height)
 
 	m_tex = m_manager->getGrManager().newTexture(texInit);
 
+	// Create the whole texture view
+	m_texView = m_manager->getGrManager().newTextureView(TextureViewInitInfo(m_tex, "Font"));
+
 	// Do the copy
+	static const TextureSurfaceInfo surf(0, 0, 0, 0);
 	CommandBufferInitInfo cmdbInit;
 	cmdbInit.m_flags = CommandBufferFlag::TRANSFER_WORK | CommandBufferFlag::SMALL_BATCH;
 	CommandBufferPtr cmdb = m_manager->getGrManager().newCommandBuffer(cmdbInit);
+	{
+		TextureViewInitInfo viewInit(m_tex, surf, DepthStencilAspectBit::NONE, "TempFont");
+		TextureViewPtr tmpView = m_manager->getGrManager().newTextureView(viewInit);
 
-	TextureSurfaceInfo surf(0, 0, 0, 0);
-
-	cmdb->setTextureSurfaceBarrier(m_tex, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, surf);
-	cmdb->copyBufferToTextureSurface(buff, 0, buffSize, m_tex, surf);
-	cmdb->setTextureSurfaceBarrier(
-		m_tex, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::GENERATE_MIPMAPS, surf);
+		cmdb->setTextureSurfaceBarrier(m_tex, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, surf);
+		cmdb->copyBufferToTextureView(buff, 0, buffSize, tmpView);
+		cmdb->setTextureSurfaceBarrier(
+			m_tex, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::GENERATE_MIPMAPS, surf);
+	}
 
-	TextureSubresourceInfo subresource(surf);
-	subresource.m_mipmapCount = texInit.m_mipmapsCount;
-	cmdb->generateMipmaps2d(m_manager->getGrManager().newTextureView(TextureViewInitInfo(m_tex, subresource)));
+	// Gen mips
+	cmdb->generateMipmaps2d(m_texView);
 	cmdb->setTextureSurfaceBarrier(m_tex, TextureUsageBit::GENERATE_MIPMAPS, TextureUsageBit::SAMPLED_FRAGMENT, surf);
 
 	cmdb->flush();

+ 3 - 2
src/anki/ui/Font.h

@@ -31,9 +31,9 @@ public:
 
 anki_internal:
 	/// Get font image atlas.
-	const TexturePtr& getTexture() const
+	const TextureViewPtr& getTextureView() const
 	{
-		return m_tex;
+		return m_texView;
 	}
 
 	const nk_user_font& getFont(U32 fontHeight) const
@@ -62,6 +62,7 @@ private:
 	DynamicArray<NkFont> m_fonts;
 
 	TexturePtr m_tex;
+	TextureViewPtr m_texView; ///< Whole texture view
 
 	void createTexture(const void* data, U32 width, U32 height);
 };

+ 16 - 14
tests/gr/Gr.cpp

@@ -330,22 +330,24 @@ static void* setStorage(PtrSize size, CommandBufferPtr& cmdb, U set, U binding)
 #define SET_UNIFORMS(type_, size_, cmdb_, set_, binding_) static_cast<type_>(setUniforms(size_, cmdb_, set_, binding_))
 #define SET_STORAGE(type_, size_, cmdb_, set_, binding_) static_cast<type_>(setStorage(size_, cmdb_, set_, binding_))
 
-#define UPLOAD_TEX_SURFACE(cmdb_, tex_, surf_, ptr_, size_, handle_)                                                  \
-	do                                                                                                                \
-	{                                                                                                                 \
-		ANKI_TEST_EXPECT_NO_ERR(transfAlloc->allocate(size_, handle_));                                               \
-		void* f = handle_.getMappedMemory();                                                                          \
-		memcpy(f, ptr_, size_);                                                                                       \
-		cmdb_->copyBufferToTextureSurface(handle_.getBuffer(), handle_.getOffset(), handle_.getRange(), tex_, surf_); \
+#define UPLOAD_TEX_SURFACE(cmdb_, tex_, surf_, ptr_, size_, handle_)                                        \
+	do                                                                                                      \
+	{                                                                                                       \
+		ANKI_TEST_EXPECT_NO_ERR(transfAlloc->allocate(size_, handle_));                                     \
+		void* f = handle_.getMappedMemory();                                                                \
+		memcpy(f, ptr_, size_);                                                                             \
+		TextureViewPtr view = gr->newTextureView(TextureViewInitInfo(tex_, surf_));                         \
+		cmdb_->copyBufferToTextureView(handle_.getBuffer(), handle_.getOffset(), handle_.getRange(), view); \
 	} while(0)
 
-#define UPLOAD_TEX_VOL(cmdb_, tex_, vol_, ptr_, size_, handle_)                                                     \
-	do                                                                                                              \
-	{                                                                                                               \
-		ANKI_TEST_EXPECT_NO_ERR(transfAlloc->allocate(size_, handle_));                                             \
-		void* f = handle_.getMappedMemory();                                                                        \
-		memcpy(f, ptr_, size_);                                                                                     \
-		cmdb_->copyBufferToTextureVolume(handle_.getBuffer(), handle_.getOffset(), handle_.getRange(), tex_, vol_); \
+#define UPLOAD_TEX_VOL(cmdb_, tex_, vol_, ptr_, size_, handle_)                                             \
+	do                                                                                                      \
+	{                                                                                                       \
+		ANKI_TEST_EXPECT_NO_ERR(transfAlloc->allocate(size_, handle_));                                     \
+		void* f = handle_.getMappedMemory();                                                                \
+		memcpy(f, ptr_, size_);                                                                             \
+		TextureViewPtr view = gr->newTextureView(TextureViewInitInfo(tex_, vol_));                          \
+		cmdb_->copyBufferToTextureView(handle_.getBuffer(), handle_.getOffset(), handle_.getRange(), view); \
 	} while(0)
 
 const PixelFormat DS_FORMAT = PixelFormat(ComponentFormat::D24S8, TransformFormat::UNORM);