Browse Source

Vulkan: Add some missing functionality

Panagiotis Christopoulos Charitos 8 years ago
parent
commit
0d93aec167

+ 1 - 1
src/anki/gr/Buffer.h

@@ -14,7 +14,7 @@ namespace anki
 /// @{
 
 /// GPU buffer.
-class Buffer : public GrObject
+class Buffer final : public GrObject
 {
 	ANKI_GR_OBJECT
 

+ 7 - 2
src/anki/gr/Enums.h

@@ -212,10 +212,15 @@ enum class TextureUsageBit : U16
 	FRAMEBUFFER_ATTACHMENT_READ_WRITE = FRAMEBUFFER_ATTACHMENT_READ | FRAMEBUFFER_ATTACHMENT_WRITE,
 	/// @}
 
+	/// @name Transfer
+	/// @{
+	TRANSFER_DESTINATION = 1 << 10,
+	TRANSFER_ANY = TRANSFER_DESTINATION,
+	/// @}
+
 	/// @name Misc
 	/// @{
-	GENERATE_MIPMAPS = 1 << 10,
-	UPLOAD = 1 << 11,
+	GENERATE_MIPMAPS = 1 << 11,
 	CLEAR = 1 << 12 ///< Will be used in CommandBuffer::clearImage.
 	/// @}
 };

+ 1 - 1
src/anki/gr/Framebuffer.h

@@ -68,7 +68,7 @@ public:
 };
 
 /// GPU framebuffer.
-class Framebuffer : public GrObject
+class Framebuffer final : public GrObject
 {
 	ANKI_GR_OBJECT
 

+ 1 - 1
src/anki/gr/OcclusionQuery.h

@@ -14,7 +14,7 @@ namespace anki
 /// @{
 
 /// Occlusion query.
-class OcclusionQuery : public GrObject
+class OcclusionQuery final : public GrObject
 {
 	ANKI_GR_OBJECT
 

+ 1 - 1
src/anki/gr/Sampler.h

@@ -15,7 +15,7 @@ namespace anki
 /// @{
 
 /// GPU sampler.
-class Sampler : public GrObject
+class Sampler final : public GrObject
 {
 	ANKI_GR_OBJECT
 

+ 1 - 1
src/anki/gr/Shader.h

@@ -58,7 +58,7 @@ void writeShaderBlockMemory(ShaderVariableDataType type,
 	const void* buffEnd);
 
 /// GPU shader.
-class Shader : public GrObject
+class Shader final : public GrObject
 {
 	ANKI_GR_OBJECT
 

+ 1 - 1
src/anki/gr/ShaderProgram.h

@@ -14,7 +14,7 @@ namespace anki
 /// @{
 
 /// GPU program.
-class ShaderProgram : public GrObject
+class ShaderProgram final : public GrObject
 {
 	ANKI_GR_OBJECT
 

+ 1 - 1
src/anki/gr/Texture.h

@@ -58,7 +58,7 @@ public:
 };
 
 /// GPU texture
-class Texture : public GrObject
+class Texture final : public GrObject
 {
 	ANKI_GR_OBJECT
 

+ 5 - 0
src/anki/gr/gl/CommandBuffer.cpp

@@ -1489,4 +1489,9 @@ void CommandBuffer::writeOcclusionQueryResultToBuffer(OcclusionQueryPtr query, P
 	m_impl->pushBackNewCommand<WriteOcclResultToBuff>(query, offset, buff);
 }
 
+void CommandBuffer::informTextureCurrentUsage(TexturePtr tex, TextureUsageBit crntUsage)
+{
+	// Nothing for GL
+}
+
 } // end namespace anki

+ 19 - 14
src/anki/gr/vulkan/CommandBuffer.cpp

@@ -73,7 +73,7 @@ void CommandBuffer::bindIndexBuffer(BufferPtr buff, PtrSize offset, IndexType ty
 
 void CommandBuffer::setPrimitiveRestart(Bool enable)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->setPrimitiveRestart(enable);
 }
 
 void CommandBuffer::setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy)
@@ -93,12 +93,12 @@ void CommandBuffer::setScissorRect(U16 minx, U16 miny, U16 maxx, U16 maxy)
 
 void CommandBuffer::setFillMode(FillMode mode)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->setFillMode(mode);
 }
 
 void CommandBuffer::setCullMode(FaceSelectionBit mode)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->setCullMode(mode);
 }
 
 void CommandBuffer::setPolygonOffset(F32 factor, F32 units)
@@ -111,12 +111,12 @@ void CommandBuffer::setStencilOperations(FaceSelectionBit face,
 	StencilOperation stencilPassDepthFail,
 	StencilOperation stencilPassDepthPass)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->setStencilOperations(face, stencilFail, stencilPassDepthFail, stencilPassDepthPass);
 }
 
 void CommandBuffer::setStencilCompareOperation(FaceSelectionBit face, CompareOperation comp)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->setStencilCompareOperation(face, comp);
 }
 
 void CommandBuffer::setStencilCompareMask(FaceSelectionBit face, U32 mask)
@@ -136,44 +136,44 @@ void CommandBuffer::setStencilReference(FaceSelectionBit face, U32 ref)
 
 void CommandBuffer::setDepthWrite(Bool enable)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->setDepthWrite(enable);
 }
 
 void CommandBuffer::setDepthCompareOperation(CompareOperation op)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->setDepthCompareOperation(op);
 }
 
 void CommandBuffer::setAlphaToCoverage(Bool enable)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->setAlphaToCoverage(enable);
 }
 
 void CommandBuffer::setColorChannelWriteMask(U32 attachment, ColorBit mask)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->setColorChannelWriteMask(attachment, mask);
 }
 
 void CommandBuffer::setBlendFactors(
 	U32 attachment, BlendFactor srcRgb, BlendFactor dstRgb, BlendFactor srcA, BlendFactor dstA)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->setBlendFactors(attachment, srcRgb, dstRgb, srcA, dstA);
 }
 
 void CommandBuffer::setBlendOperation(U32 attachment, BlendOperation funcRgb, BlendOperation funcA)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->setBlendOperation(attachment, funcRgb, funcA);
 }
 
 void CommandBuffer::bindTexture(U32 set, U32 binding, TexturePtr tex, DepthStencilAspectBit aspect)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->bindTexture(set, binding, tex, aspect);
 }
 
 void CommandBuffer::bindTextureAndSampler(
 	U32 set, U32 binding, TexturePtr tex, SamplerPtr sampler, DepthStencilAspectBit aspect)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->bindTextureAndSampler(set, binding, tex, sampler, aspect);
 }
 
 void CommandBuffer::bindUniformBuffer(U32 set, U32 binding, BufferPtr buff, PtrSize offset, PtrSize range)
@@ -275,7 +275,7 @@ void CommandBuffer::clearTextureVolume(
 void CommandBuffer::copyBufferToTextureSurface(
 	BufferPtr buff, PtrSize offset, PtrSize range, TexturePtr tex, const TextureSurfaceInfo& surf)
 {
-	ANKI_ASSERT(!"TODO");
+	m_impl->copyBufferToTextureSurface(buff, offset, range, tex, surf);
 }
 
 void CommandBuffer::copyBufferToTextureVolume(
@@ -318,6 +318,11 @@ void CommandBuffer::setBufferBarrier(
 	m_impl->setBufferBarrier(buff, before, after, offset, size);
 }
 
+void CommandBuffer::informTextureCurrentUsage(TexturePtr tex, TextureUsageBit crntUsage)
+{
+	m_impl->informTextureCurrentUsage(tex, crntUsage);
+}
+
 void CommandBuffer::resetOcclusionQuery(OcclusionQueryPtr query)
 {
 	m_impl->resetOcclusionQuery(query);

+ 107 - 8
src/anki/gr/vulkan/CommandBufferImpl.cpp

@@ -4,6 +4,7 @@
 // http://www.anki3d.org/LICENSE
 
 #include <anki/gr/vulkan/CommandBufferImpl.h>
+#include <anki/gr/GrManager.h>
 #include <anki/gr/vulkan/GrManagerImpl.h>
 
 #include <anki/gr/Framebuffer.h>
@@ -42,6 +43,7 @@ CommandBufferImpl::~CommandBufferImpl()
 	m_bufferList.destroy(m_alloc);
 	m_cmdbList.destroy(m_alloc);
 	m_progs.destroy(m_alloc);
+	m_samplerList.destroy(m_alloc);
 
 	m_imgBarriers.destroy(m_alloc);
 	m_buffBarriers.destroy(m_alloc);
@@ -130,17 +132,13 @@ void CommandBufferImpl::beginRenderPassInternal()
 		Array<TextureUsageBit, MAX_COLOR_ATTACHMENTS> colAttUsages;
 		for(U i = 0; i < impl.getColorAttachmentCount(); ++i)
 		{
-			Bool found = m_texUsageTracker.findUsage(*impl.getColorAttachment(i), colAttUsages[i]);
-			ANKI_ASSERT(found);
-			(void)found;
+			colAttUsages[i] = m_texUsageTracker.findUsage(*impl.getColorAttachment(i));
 		}
 
 		TextureUsageBit dsAttUsage = TextureUsageBit::NONE;
 		if(impl.hasDepthStencil())
 		{
-			Bool found = m_texUsageTracker.findUsage(*impl.getDepthStencilAttachment(), dsAttUsage);
-			ANKI_ASSERT(found);
-			(void)found;
+			dsAttUsage = m_texUsageTracker.findUsage(*impl.getDepthStencilAttachment());
 		}
 
 		bi.renderPass = impl.getRenderPassHandle(colAttUsages, dsAttUsage);
@@ -314,7 +312,7 @@ void CommandBufferImpl::uploadTextureSurface(
 
 	TextureImpl& impl = *tex->m_impl;
 	impl.checkSurface(surf);
-	ANKI_ASSERT(impl.usageValid(TextureUsageBit::UPLOAD));
+	ANKI_ASSERT(impl.usageValid(TextureUsageBit::TRANSFER_DESTINATION));
 
 	if(!impl.m_workarounds)
 	{
@@ -418,7 +416,7 @@ void CommandBufferImpl::uploadTextureVolume(
 
 	TextureImpl& impl = *tex->m_impl;
 	impl.checkVolume(vol);
-	ANKI_ASSERT(impl.usageValid(TextureUsageBit::UPLOAD));
+	ANKI_ASSERT(impl.usageValid(TextureUsageBit::TRANSFER_DESTINATION));
 
 	if(!impl.m_workarounds)
 	{
@@ -781,4 +779,105 @@ void CommandBufferImpl::flushWriteQueryResults()
 	m_writeQueryAtomCount = 0;
 }
 
+void CommandBufferImpl::copyBufferToTextureSurface(
+	BufferPtr buff, PtrSize offset, PtrSize range, TexturePtr tex, const TextureSurfaceInfo& surf)
+{
+	commandCommon();
+
+	TextureImpl& impl = *tex->m_impl;
+	impl.checkSurface(surf);
+	ANKI_ASSERT(impl.usageValid(TextureUsageBit::TRANSFER_DESTINATION));
+	TextureUsageBit usage = m_texUsageTracker.findUsage(*tex);
+	const VkImageLayout layout = impl.computeLayout(usage, surf.m_level);
+
+	if(!impl.m_workarounds)
+	{
+		U width = impl.m_width >> surf.m_level;
+		U height = impl.m_height >> surf.m_level;
+		ANKI_ASSERT(range == computeSurfaceSize(width, height, impl.m_format));
+
+		// Copy
+		VkBufferImageCopy region;
+		region.imageSubresource.aspectMask = impl.m_aspect;
+		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;
+
+		ANKI_CMD(vkCmdCopyBufferToImage(m_handle, buff->m_impl->getHandle(), impl.m_imageHandle, layout, 1, &region),
+			ANY_OTHER_COMMAND);
+	}
+	else if(!!(impl.m_workarounds & TextureImplWorkaround::R8G8B8_TO_R8G8B8A8))
+	{
+		U width = impl.m_width >> surf.m_level;
+		U height = impl.m_height >> surf.m_level;
+
+		// Create a new shadow buffer
+		const PtrSize shadowSize =
+			computeSurfaceSize(width, height, PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM));
+		BufferPtr shadow =
+			getGrManager().newInstance<Buffer>(shadowSize, BufferUsageBit::TRANSFER_ALL, BufferMapAccessBit::NONE);
+		const VkBuffer shadowHandle = shadow->m_impl->getHandle();
+		m_bufferList.pushBack(m_alloc, shadow);
+
+		// Create the copy regions
+		DynamicArrayAuto<VkBufferCopy> copies(m_alloc);
+		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 = (y * width + x) * 3 + offset;
+				c.dstOffset = (y * width + x) * 4 + 0;
+				c.size = 3;
+			}
+		}
+
+		// Copy buffer to buffer
+		ANKI_CMD(vkCmdCopyBuffer(m_handle, buff->m_impl->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,
+			shadow->m_impl->getHandle());
+
+		// Do the copy to the image
+		VkBufferImageCopy region;
+		region.imageSubresource.aspectMask = impl.m_aspect;
+		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_texList.pushBack(m_alloc, tex);
+	m_bufferList.pushBack(m_alloc, buff);
+}
+
 } // end namespace anki

+ 118 - 11
src/anki/gr/vulkan/CommandBufferImpl.h

@@ -93,7 +93,23 @@ public:
 		m_bufferList.pushBack(m_alloc, buff);
 	}
 
-	void setPrimitiveRestart(Bool enable);
+	void setPrimitiveRestart(Bool enable)
+	{
+		commandCommon();
+		m_state.setPrimitiveRestart(enable);
+	}
+
+	void setFillMode(FillMode mode)
+	{
+		commandCommon();
+		m_state.setFillMode(mode);
+	}
+
+	void setCullMode(FaceSelectionBit mode)
+	{
+		commandCommon();
+		m_state.setCullMode(mode);
+	}
 
 	void setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy)
 	{
@@ -111,7 +127,26 @@ public:
 		}
 	}
 
-	void setPolygonOffset(F32 factor, F32 units);
+	void setPolygonOffset(F32 factor, F32 units)
+	{
+		commandCommon();
+		m_state.setPolygonOffset(factor, units);
+	}
+
+	void setStencilOperations(FaceSelectionBit face,
+		StencilOperation stencilFail,
+		StencilOperation stencilPassDepthFail,
+		StencilOperation stencilPassDepthPass)
+	{
+		commandCommon();
+		m_state.setStencilOperations(face, stencilFail, stencilPassDepthFail, stencilPassDepthPass);
+	}
+
+	void setStencilCompareOperation(FaceSelectionBit face, CompareOperation comp)
+	{
+		commandCommon();
+		m_state.setStencilCompareOperation(face, comp);
+	}
 
 	void setStencilCompareMask(FaceSelectionBit face, U32 mask);
 
@@ -119,6 +154,63 @@ public:
 
 	void setStencilReference(FaceSelectionBit face, U32 ref);
 
+	void setDepthWrite(Bool enable)
+	{
+		commandCommon();
+		m_state.setDepthWrite(enable);
+	}
+
+	void setDepthCompareOperation(CompareOperation op)
+	{
+		commandCommon();
+		m_state.setDepthCompareOperation(op);
+	}
+
+	void setAlphaToCoverage(Bool enable)
+	{
+		commandCommon();
+		m_state.setAlphaToCoverage(enable);
+	}
+
+	void setColorChannelWriteMask(U32 attachment, ColorBit mask)
+	{
+		commandCommon();
+		m_state.setColorChannelWriteMask(attachment, mask);
+	}
+
+	void setBlendFactors(U32 attachment, BlendFactor srcRgb, BlendFactor dstRgb, BlendFactor srcA, BlendFactor dstA)
+	{
+		commandCommon();
+		m_state.setBlendFactors(attachment, srcRgb, dstRgb, srcA, dstA);
+	}
+
+	void setBlendOperation(U32 attachment, BlendOperation funcRgb, BlendOperation funcA)
+	{
+		commandCommon();
+		m_state.setBlendOperation(attachment, funcRgb, funcA);
+	}
+
+	void bindTexture(U32 set, U32 binding, TexturePtr tex_, DepthStencilAspectBit aspect)
+	{
+		const U realBinding = binding;
+		Texture& tex = *tex_;
+		TextureUsageBit usage = m_texUsageTracker.findUsage(tex);
+		VkImageLayout lay = tex.m_impl->computeLayout(usage, 0);
+		m_dsetState[set].bindTexture(realBinding, &tex, aspect, lay);
+		m_texList.pushBack(m_alloc, tex_);
+	}
+
+	void bindTextureAndSampler(U32 set, U32 binding, TexturePtr tex_, SamplerPtr sampler, DepthStencilAspectBit aspect)
+	{
+		const U realBinding = binding;
+		Texture& tex = *tex_;
+		TextureUsageBit usage = m_texUsageTracker.findUsage(tex);
+		VkImageLayout lay = tex.m_impl->computeLayout(usage, 0);
+		m_dsetState[set].bindTextureAndSampler(realBinding, &tex, sampler.get(), aspect, lay);
+		m_texList.pushBack(m_alloc, tex_);
+		m_samplerList.pushBack(m_alloc, sampler);
+	}
+
 	void beginRenderPass(FramebufferPtr fb);
 
 	void endRenderPass();
@@ -180,11 +272,28 @@ public:
 	void bindUniformBuffer(U32 set, U32 binding, BufferPtr& buff, PtrSize offset, PtrSize range)
 	{
 		commandCommon();
-		U realBinding = MAX_TEXTURE_BINDINGS + binding;
+		const U realBinding = MAX_TEXTURE_BINDINGS + binding;
 		m_dsetState[set].bindUniformBuffer(realBinding, buff.get(), offset, range);
 		m_bufferList.pushBack(m_alloc, buff);
 	}
 
+	void bindStorageBuffer(U32 set, U32 binding, BufferPtr& buff, PtrSize offset, PtrSize range)
+	{
+		commandCommon();
+		const U realBinding = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS + binding;
+		m_dsetState[set].bindStorageBuffer(realBinding, buff.get(), offset, range);
+		m_bufferList.pushBack(m_alloc, buff);
+	}
+
+	void copyBufferToTextureSurface(
+		BufferPtr buff, PtrSize offset, PtrSize range, TexturePtr tex, const TextureSurfaceInfo& surf);
+
+	void informTextureCurrentUsage(TexturePtr& tex, TextureUsageBit crntUsage)
+	{
+		ANKI_ASSERT(tex->m_impl->usageValid(crntUsage));
+		m_texUsageTracker.setUsage(*tex, crntUsage, m_alloc);
+	}
+
 private:
 	StackAllocator<U8> m_alloc;
 
@@ -212,6 +321,7 @@ private:
 	List<BufferPtr> m_bufferList;
 	List<CommandBufferPtr> m_cmdbList;
 	List<ShaderProgramPtr> m_progs;
+	List<SamplerPtr> m_samplerList;
 /// @}
 
 #if ANKI_EXTRA_CHECKS
@@ -226,8 +336,6 @@ private:
 	/// @{
 	Array<U16, 4> m_viewport = {{0, 0, 0, 0}};
 	Bool8 m_viewportDirty = true;
-	F32 m_polygonOffsetFactor = MAX_F32;
-	F32 m_polygonOffsetUnits = MAX_F32;
 	Array<U32, 2> m_stencilCompareMasks = {{0x5A5A5A5A, 0x5A5A5A5A}}; ///< Use a stupid number to initialize.
 	Array<U32, 2> m_stencilWriteMasks = {{0x5A5A5A5A, 0x5A5A5A5A}};
 	Array<U32, 2> m_stencilReferenceMasks = {{0x5A5A5A5A, 0x5A5A5A5A}};
@@ -275,22 +383,21 @@ private:
 	class TextureUsageTracker
 	{
 	public:
-		Bool findUsage(const Texture& tex, TextureUsageBit& usage) const
+		ANKI_USE_RESULT TextureUsageBit findUsage(const Texture& tex) const
 		{
 			auto it = m_map.find(tex.getUuid());
 			if(it != m_map.getEnd())
 			{
-				usage = (*it);
-				return true;
+				return (*it);
 			}
 			else if(tex.m_impl->m_usageWhenEncountered != TextureUsageBit::NONE)
 			{
-				usage = tex.m_impl->m_usageWhenEncountered;
-				return true;
+				return tex.m_impl->m_usageWhenEncountered;
 			}
 			else
 			{
-				return false;
+				ANKI_ASSERT(!"Cannot find the layout of the image");
+				return TextureUsageBit::NONE;
 			}
 		}
 

+ 0 - 17
src/anki/gr/vulkan/CommandBufferImpl.inl.h

@@ -13,23 +13,6 @@
 namespace anki
 {
 
-inline void CommandBufferImpl::setPolygonOffset(F32 factor, F32 units)
-{
-	commandCommon();
-
-	if(m_polygonOffsetFactor != factor || m_polygonOffsetUnits != units)
-	{
-		ANKI_CMD(vkCmdSetDepthBias(m_handle, units, 0.0, factor), ANY_OTHER_COMMAND);
-
-		m_polygonOffsetFactor = factor;
-		m_polygonOffsetUnits = units;
-	}
-	else
-	{
-		// Skip
-	}
-}
-
 inline void CommandBufferImpl::setStencilCompareMask(FaceSelectionBit face, U32 mask)
 {
 	commandCommon();

+ 1 - 1
src/anki/gr/vulkan/Common.cpp

@@ -640,7 +640,7 @@ VkImageUsageFlags convertTextureUsage(TextureUsageBit ak, const PixelFormat& for
 		out |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
 	}
 
-	if(!!(ak & TextureUsageBit::UPLOAD))
+	if(!!(ak & TextureUsageBit::TRANSFER_DESTINATION))
 	{
 		out |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
 	}

+ 1 - 1
src/anki/gr/vulkan/DescriptorSet.h

@@ -122,7 +122,7 @@ public:
 	}
 
 	void bindTextureAndSampler(
-		U binding, Texture* tex, SamplerPtr& sampler, DepthStencilAspectBit aspect, VkImageLayout layout)
+		U binding, Texture* tex, Sampler* sampler, DepthStencilAspectBit aspect, VkImageLayout layout)
 	{
 		m_bindings[binding].m_type = DescriptorType::TEXTURE;
 		m_bindings[binding].m_uuids[0] = tex->getUuid();

+ 11 - 0
src/anki/gr/vulkan/Pipeline.h

@@ -330,6 +330,17 @@ public:
 		}
 	}
 
+	void setBlendOperation(U32 attachment, BlendOperation funcRgb, BlendOperation funcA)
+	{
+		ColorAttachmentStateInfo& c = m_state.m_color.m_attachments[attachment];
+		if(c.m_blendFunctionRgb != funcRgb || c.m_blendFunctionA != funcA)
+		{
+			c.m_blendFunctionRgb = funcRgb;
+			c.m_blendFunctionA = funcA;
+			m_dirty.m_colAttachments.set(attachment);
+		}
+	}
+
 	void bindShaderProgram(const ShaderProgramPtr& prog)
 	{
 		if(prog != m_state.m_prog)

+ 5 - 5
src/anki/gr/vulkan/TextureImpl.cpp

@@ -213,7 +213,7 @@ Error TextureImpl::initImage(const TextureInitInfo& init_)
 		else if(init.m_format.m_components == ComponentFormat::S8)
 		{
 			ANKI_ASSERT(
-				!(init.m_usage & (TextureUsageBit::IMAGE_ALL | TextureUsageBit::UPLOAD)) && "Can't do that ATM");
+				!(init.m_usage & (TextureUsageBit::IMAGE_ALL | TextureUsageBit::TRANSFER_ANY)) && "Can't do that ATM");
 			init.m_format = PixelFormat(ComponentFormat::D24S8, TransformFormat::UNORM);
 			m_format = init.m_format;
 			m_vkFormat = convertFormat(m_format);
@@ -224,7 +224,7 @@ Error TextureImpl::initImage(const TextureInitInfo& init_)
 		else if(init.m_format.m_components == ComponentFormat::D24S8)
 		{
 			ANKI_ASSERT(
-				!(init.m_usage & (TextureUsageBit::IMAGE_ALL | TextureUsageBit::UPLOAD)) && "Can't do that ATM");
+				!(init.m_usage & (TextureUsageBit::IMAGE_ALL | TextureUsageBit::TRANSFER_ANY)) && "Can't do that ATM");
 			init.m_format = PixelFormat(ComponentFormat::D32S8, TransformFormat::UNORM);
 			m_format = init.m_format;
 			m_vkFormat = convertFormat(m_format);
@@ -422,7 +422,7 @@ void TextureImpl::computeBarrierInfo(TextureUsageBit before,
 		}
 	}
 
-	if(!!(before & TextureUsageBit::UPLOAD))
+	if(!!(before & TextureUsageBit::TRANSFER_DESTINATION))
 	{
 		srcStages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
 		srcAccesses |= VK_ACCESS_TRANSFER_WRITE_BIT;
@@ -526,7 +526,7 @@ void TextureImpl::computeBarrierInfo(TextureUsageBit before,
 		}
 	}
 
-	if(!!(after & TextureUsageBit::UPLOAD))
+	if(!!(after & TextureUsageBit::TRANSFER_DESTINATION))
 	{
 		dstStages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
 		dstAccesses |= VK_ACCESS_TRANSFER_WRITE_BIT;
@@ -596,7 +596,7 @@ VkImageLayout TextureImpl::computeLayout(TextureUsageBit usage, U level) const
 	{
 		out = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
 	}
-	else if(!m_depthStencil && usage == TextureUsageBit::UPLOAD)
+	else if(!m_depthStencil && usage == TextureUsageBit::TRANSFER_DESTINATION)
 	{
 		out = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
 	}

+ 8 - 6
src/anki/renderer/Smaa.cpp

@@ -161,7 +161,7 @@ Error SmaaWeights::init(const ConfigSet& initializer)
 		texinit.m_width = AREATEX_WIDTH;
 		texinit.m_height = AREATEX_HEIGHT;
 		texinit.m_format = PixelFormat(ComponentFormat::R8G8, TransformFormat::UNORM);
-		texinit.m_usage = TextureUsageBit::UPLOAD | TextureUsageBit::SAMPLED_FRAGMENT;
+		texinit.m_usage = TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_sampling.m_minMagFilter = SamplingFilter::LINEAR;
 		texinit.m_sampling.m_repeat = false;
 		m_areaTex = gr.newInstance<Texture>(texinit);
@@ -172,9 +172,10 @@ Error SmaaWeights::init(const ConfigSet& initializer)
 		memcpy(stagingMem, &areaTexBytes[0], sizeof(areaTexBytes));
 
 		const TextureSurfaceInfo surf(0, 0, 0, 0);
-		cmdb->setTextureSurfaceBarrier(m_areaTex, TextureUsageBit::NONE, TextureUsageBit::UPLOAD, surf);
+		cmdb->setTextureSurfaceBarrier(m_areaTex, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, surf);
 		cmdb->copyBufferToTextureSurface(token.m_buffer, token.m_offset, token.m_range, m_areaTex, surf);
-		cmdb->setTextureSurfaceBarrier(m_areaTex, TextureUsageBit::UPLOAD, TextureUsageBit::SAMPLED_FRAGMENT, surf);
+		cmdb->setTextureSurfaceBarrier(
+			m_areaTex, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, surf);
 	}
 
 	// Create search texture
@@ -183,7 +184,7 @@ Error SmaaWeights::init(const ConfigSet& initializer)
 		texinit.m_width = SEARCHTEX_WIDTH;
 		texinit.m_height = SEARCHTEX_HEIGHT;
 		texinit.m_format = PixelFormat(ComponentFormat::R8, TransformFormat::UNORM);
-		texinit.m_usage = TextureUsageBit::UPLOAD | TextureUsageBit::SAMPLED_FRAGMENT;
+		texinit.m_usage = TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_sampling.m_minMagFilter = SamplingFilter::LINEAR;
 		texinit.m_sampling.m_repeat = false;
 		m_searchTex = gr.newInstance<Texture>(texinit);
@@ -194,9 +195,10 @@ Error SmaaWeights::init(const ConfigSet& initializer)
 		memcpy(stagingMem, &searchTexBytes[0], sizeof(searchTexBytes));
 
 		const TextureSurfaceInfo surf(0, 0, 0, 0);
-		cmdb->setTextureSurfaceBarrier(m_searchTex, TextureUsageBit::NONE, TextureUsageBit::UPLOAD, surf);
+		cmdb->setTextureSurfaceBarrier(m_searchTex, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, surf);
 		cmdb->copyBufferToTextureSurface(token.m_buffer, token.m_offset, token.m_range, m_searchTex, surf);
-		cmdb->setTextureSurfaceBarrier(m_searchTex, TextureUsageBit::UPLOAD, TextureUsageBit::SAMPLED_FRAGMENT, surf);
+		cmdb->setTextureSurfaceBarrier(
+			m_searchTex, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, surf);
 	}
 	cmdb->flush();
 

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

@@ -95,12 +95,13 @@ Error TexUploadTask::operator()(AsyncLoaderTaskContext& ctx)
 					{
 						TextureVolumeInfo vol(mip);
 
-						cmdb->setTextureVolumeBarrier(m_tex, TextureUsageBit::NONE, TextureUsageBit::UPLOAD, vol);
+						cmdb->setTextureVolumeBarrier(
+							m_tex, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, vol);
 
 						cmdb->copyBufferToTextureVolume(token.m_buffer, token.m_offset, token.m_range, m_tex, vol);
 
 						cmdb->setTextureVolumeBarrier(m_tex,
-							TextureUsageBit::UPLOAD,
+							TextureUsageBit::TRANSFER_DESTINATION,
 							TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_TESSELLATION_EVALUATION,
 							vol);
 					}
@@ -108,12 +109,13 @@ Error TexUploadTask::operator()(AsyncLoaderTaskContext& ctx)
 					{
 						TextureSurfaceInfo surf(mip, 0, face, layer);
 
-						cmdb->setTextureSurfaceBarrier(m_tex, TextureUsageBit::NONE, TextureUsageBit::UPLOAD, surf);
+						cmdb->setTextureSurfaceBarrier(
+							m_tex, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, surf);
 
 						cmdb->copyBufferToTextureSurface(token.m_buffer, token.m_offset, token.m_range, m_tex, surf);
 
 						cmdb->setTextureSurfaceBarrier(m_tex,
-							TextureUsageBit::UPLOAD,
+							TextureUsageBit::TRANSFER_DESTINATION,
 							TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_TESSELLATION_EVALUATION,
 							surf);
 					}
@@ -156,8 +158,8 @@ TextureResource::~TextureResource()
 Error TextureResource::load(const ResourceFilename& filename)
 {
 	TextureInitInfo init;
-	init.m_usage =
-		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_TESSELLATION_EVALUATION | TextureUsageBit::UPLOAD;
+	init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_TESSELLATION_EVALUATION
+		| TextureUsageBit::TRANSFER_DESTINATION;
 	U faces = 0;
 
 	// Load image

+ 22 - 14
tests/gr/Gr.cpp

@@ -696,7 +696,7 @@ ANKI_TEST(Gr, DrawWithTexture)
 	TextureInitInfo init;
 	init.m_depth = 1;
 	init.m_format = PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UNORM);
-	init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::UPLOAD;
+	init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::TRANSFER_DESTINATION;
 	init.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 	init.m_height = 2;
 	init.m_width = 2;
@@ -717,7 +717,8 @@ ANKI_TEST(Gr, DrawWithTexture)
 	init.m_width = 4;
 	init.m_height = 4;
 	init.m_mipmapsCount = 3;
-	init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::UPLOAD | TextureUsageBit::GENERATE_MIPMAPS;
+	init.m_usage =
+		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::GENERATE_MIPMAPS;
 	init.m_initialUsage = TextureUsageBit::NONE;
 
 	TexturePtr b = gr->newInstance<Texture>(init);
@@ -784,12 +785,13 @@ ANKI_TEST(Gr, DrawWithTexture)
 
 	// Set barriers
 	cmdb->setTextureSurfaceBarrier(
-		a, TextureUsageBit::SAMPLED_FRAGMENT, TextureUsageBit::UPLOAD, TextureSurfaceInfo(0, 0, 0, 0));
+		a, TextureUsageBit::SAMPLED_FRAGMENT, TextureUsageBit::TRANSFER_DESTINATION, TextureSurfaceInfo(0, 0, 0, 0));
 
 	cmdb->setTextureSurfaceBarrier(
-		a, TextureUsageBit::SAMPLED_FRAGMENT, TextureUsageBit::UPLOAD, TextureSurfaceInfo(1, 0, 0, 0));
+		a, TextureUsageBit::SAMPLED_FRAGMENT, TextureUsageBit::TRANSFER_DESTINATION, TextureSurfaceInfo(1, 0, 0, 0));
 
-	cmdb->setTextureSurfaceBarrier(b, TextureUsageBit::NONE, TextureUsageBit::UPLOAD, TextureSurfaceInfo(0, 0, 0, 0));
+	cmdb->setTextureSurfaceBarrier(
+		b, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, TextureSurfaceInfo(0, 0, 0, 0));
 
 	UPLOAD_TEX_SURFACE(cmdb, a, TextureSurfaceInfo(0, 0, 0, 0), &mip0[0], sizeof(mip0));
 
@@ -799,16 +801,16 @@ ANKI_TEST(Gr, DrawWithTexture)
 
 	// Gen mips
 	cmdb->setTextureSurfaceBarrier(
-		b, TextureUsageBit::UPLOAD, TextureUsageBit::GENERATE_MIPMAPS, TextureSurfaceInfo(0, 0, 0, 0));
+		b, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::GENERATE_MIPMAPS, TextureSurfaceInfo(0, 0, 0, 0));
 
 	cmdb->generateMipmaps2d(b, 0, 0);
 
 	// Set barriers
 	cmdb->setTextureSurfaceBarrier(
-		a, TextureUsageBit::UPLOAD, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(0, 0, 0, 0));
+		a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(0, 0, 0, 0));
 
 	cmdb->setTextureSurfaceBarrier(
-		a, TextureUsageBit::UPLOAD, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(1, 0, 0, 0));
+		a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(1, 0, 0, 0));
 
 	for(U i = 0; i < 3; ++i)
 	{
@@ -847,6 +849,8 @@ ANKI_TEST(Gr, DrawWithTexture)
 		cmdb->setViewport(0, 0, WIDTH, HEIGHT);
 		cmdb->bindShaderProgram(prog);
 		cmdb->beginRenderPass(fb);
+		cmdb->informTextureCurrentUsage(a, TextureUsageBit::SAMPLED_FRAGMENT);
+		cmdb->informTextureCurrentUsage(b, TextureUsageBit::SAMPLED_FRAGMENT);
 		cmdb->bindTexture(0, 0, a);
 		cmdb->bindTexture(0, 1, b);
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
@@ -1177,8 +1181,8 @@ ANKI_TEST(Gr, 3DTextures)
 	TextureInitInfo init;
 	init.m_depth = 1;
 	init.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
-	init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::UPLOAD;
-	init.m_initialUsage = TextureUsageBit::UPLOAD;
+	init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::TRANSFER_DESTINATION;
+	init.m_initialUsage = TextureUsageBit::TRANSFER_DESTINATION;
 	init.m_height = 2;
 	init.m_width = 2;
 	init.m_mipmapsCount = 2;
@@ -1234,17 +1238,21 @@ ANKI_TEST(Gr, 3DTextures)
 	cmdbinit.m_flags = CommandBufferFlag::TRANSFER_WORK;
 	CommandBufferPtr cmdb = gr->newInstance<CommandBuffer>(cmdbinit);
 
-	cmdb->setTextureVolumeBarrier(a, TextureUsageBit::NONE, TextureUsageBit::UPLOAD, TextureVolumeInfo(0));
+	cmdb->setTextureVolumeBarrier(
+		a, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, TextureVolumeInfo(0));
 
-	cmdb->setTextureVolumeBarrier(a, TextureUsageBit::NONE, TextureUsageBit::UPLOAD, TextureVolumeInfo(1));
+	cmdb->setTextureVolumeBarrier(
+		a, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, TextureVolumeInfo(1));
 
 	UPLOAD_TEX_VOL(cmdb, a, TextureVolumeInfo(0), &mip0[0], sizeof(mip0));
 
 	UPLOAD_TEX_VOL(cmdb, a, TextureVolumeInfo(1), &mip1[0], sizeof(mip1));
 
-	cmdb->setTextureVolumeBarrier(a, TextureUsageBit::UPLOAD, TextureUsageBit::SAMPLED_FRAGMENT, TextureVolumeInfo(0));
+	cmdb->setTextureVolumeBarrier(
+		a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureVolumeInfo(0));
 
-	cmdb->setTextureVolumeBarrier(a, TextureUsageBit::UPLOAD, TextureUsageBit::SAMPLED_FRAGMENT, TextureVolumeInfo(1));
+	cmdb->setTextureVolumeBarrier(
+		a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureVolumeInfo(1));
 
 	cmdb->flush();