Browse Source

Add VRS shading rate image support

Panagiotis Christopoulos Charitos 4 years ago
parent
commit
c04bc696e8

+ 1 - 1
AnKi/Gr/CommandBuffer.h

@@ -106,7 +106,7 @@ class CommandBufferInitInfo : public GrBaseInitInfo
 {
 public:
 	FramebufferPtr m_framebuffer; ///< For second level command buffers.
-	Array<TextureUsageBit, MAX_COLOR_ATTACHMENTS> m_colorAttachmentUsages{};
+	Array<TextureUsageBit, MAX_COLOR_ATTACHMENTS> m_colorAttachmentUsages = {};
 	TextureUsageBit m_depthStencilAttachmentUsage = TextureUsageBit::NONE;
 
 	CommandBufferFlag m_flags = CommandBufferFlag::NONE;

+ 6 - 5
AnKi/Gr/Enums.h

@@ -250,11 +250,12 @@ enum class TextureUsageBit : U32
 
 	FRAMEBUFFER_ATTACHMENT_READ = 1 << 12,
 	FRAMEBUFFER_ATTACHMENT_WRITE = 1 << 13,
+	FRAMEBUFFER_SHADING_RATE = 1 << 14,
 
-	TRANSFER_DESTINATION = 1 << 14,
-	GENERATE_MIPMAPS = 1 << 15,
+	TRANSFER_DESTINATION = 1 << 15,
+	GENERATE_MIPMAPS = 1 << 16,
 
-	PRESENT = 1 << 16,
+	PRESENT = 1 << 17,
 
 	// Derived
 	ALL_SAMPLED = SAMPLED_GEOMETRY | SAMPLED_FRAGMENT | SAMPLED_COMPUTE | SAMPLED_TRACE_RAYS,
@@ -264,12 +265,12 @@ enum class TextureUsageBit : U32
 
 	ALL_GRAPHICS = SAMPLED_GEOMETRY | SAMPLED_FRAGMENT | IMAGE_GEOMETRY_READ | IMAGE_GEOMETRY_WRITE
 				   | IMAGE_FRAGMENT_READ | IMAGE_FRAGMENT_WRITE | FRAMEBUFFER_ATTACHMENT_READ
-				   | FRAMEBUFFER_ATTACHMENT_WRITE,
+				   | FRAMEBUFFER_ATTACHMENT_WRITE | FRAMEBUFFER_SHADING_RATE,
 	ALL_COMPUTE = SAMPLED_COMPUTE | IMAGE_COMPUTE_READ | IMAGE_COMPUTE_WRITE,
 	ALL_TRANSFER = TRANSFER_DESTINATION | GENERATE_MIPMAPS,
 
 	ALL_READ = ALL_SAMPLED | IMAGE_GEOMETRY_READ | IMAGE_FRAGMENT_READ | IMAGE_COMPUTE_READ | IMAGE_TRACE_RAYS_READ
-			   | FRAMEBUFFER_ATTACHMENT_READ | PRESENT | GENERATE_MIPMAPS,
+			   | FRAMEBUFFER_ATTACHMENT_READ | FRAMEBUFFER_SHADING_RATE | PRESENT | GENERATE_MIPMAPS,
 	ALL_WRITE = IMAGE_GEOMETRY_WRITE | IMAGE_FRAGMENT_WRITE | IMAGE_COMPUTE_WRITE | IMAGE_TRACE_RAYS_WRITE
 				| FRAMEBUFFER_ATTACHMENT_WRITE | TRANSFER_DESTINATION | GENERATE_MIPMAPS
 };

+ 15 - 0
AnKi/Gr/Framebuffer.h

@@ -36,6 +36,14 @@ public:
 	U32 m_colorAttachmentCount = 0;
 	FramebufferAttachmentInfo m_depthStencilAttachment;
 
+	class
+	{
+	public:
+		TextureViewPtr m_textureView;
+		U32 m_texelWidth = 0;
+		U32 m_texelHeight = 0;
+	} m_shadingRateImage;
+
 	FramebufferInitInfo()
 		: GrBaseInitInfo()
 	{
@@ -65,6 +73,7 @@ public:
 
 		m_colorAttachmentCount = b.m_colorAttachmentCount;
 		m_depthStencilAttachment = b.m_depthStencilAttachment;
+		m_shadingRateImage = b.m_shadingRateImage;
 		return *this;
 	}
 
@@ -83,6 +92,12 @@ public:
 			return false;
 		}
 
+		if(m_shadingRateImage.m_textureView
+		   && (m_shadingRateImage.m_texelHeight == 0 || m_shadingRateImage.m_texelWidth))
+		{
+			return false;
+		}
+
 		return true;
 	}
 };

+ 40 - 2
AnKi/Gr/RenderGraph.cpp

@@ -205,8 +205,9 @@ void FramebufferDescription::bake()
 	if(!!m_depthStencilAttachment.m_aspect)
 	{
 		ANKI_BEGIN_PACKED_STRUCT
-		struct DSAttachment
+		class DSAttachment
 		{
+		public:
 			TextureSurfaceInfo m_surf;
 			U32 m_loadOp;
 			U32 m_storeOp;
@@ -234,6 +235,27 @@ void FramebufferDescription::bake()
 		m_hash = (m_hash != 0) ? appendHash(&outAtt, sizeof(outAtt), m_hash) : computeHash(&outAtt, sizeof(outAtt));
 	}
 
+	// SRI
+	if(m_shadingRateAttachmentTexelWidth > 0 && m_shadingRateAttachmentTexelHeight > 0)
+	{
+		ANKI_BEGIN_PACKED_STRUCT
+		class SriToHash
+		{
+		public:
+			U32 m_sriTexelWidth;
+			U32 m_sriTexelHeight;
+			TextureSurfaceInfo m_surface;
+		} sriToHash;
+		ANKI_END_PACKED_STRUCT
+
+		sriToHash.m_sriTexelWidth = m_shadingRateAttachmentTexelWidth;
+		sriToHash.m_sriTexelHeight = m_shadingRateAttachmentTexelHeight;
+		sriToHash.m_surface = m_shadingRateAttachmentSurface;
+
+		m_hash = (m_hash != 0) ? appendHash(&sriToHash, sizeof(sriToHash), m_hash)
+							   : computeHash(&sriToHash, sizeof(sriToHash));
+	}
+
 	ANKI_ASSERT(m_hash != 0 && m_hash != 1);
 }
 
@@ -405,7 +427,7 @@ FramebufferPtr RenderGraph::getOrCreateFramebuffer(const FramebufferDescription&
 	drawsToPresentable = false;
 
 	// Create a hash that includes the render targets
-	Array<U64, MAX_COLOR_ATTACHMENTS + 1> uuids;
+	Array<U64, MAX_COLOR_ATTACHMENTS + 2> uuids;
 	U count = 0;
 	for(U i = 0; i < fbDescr.m_colorAttachmentCount; ++i)
 	{
@@ -422,6 +444,11 @@ FramebufferPtr RenderGraph::getOrCreateFramebuffer(const FramebufferDescription&
 		uuids[count++] = m_ctx->m_rts[rtHandles[MAX_COLOR_ATTACHMENTS].m_idx].m_texture->getUuid();
 	}
 
+	if(fbDescr.m_shadingRateAttachmentTexelWidth > 0)
+	{
+		uuids[count++] = m_ctx->m_rts[rtHandles[MAX_COLOR_ATTACHMENTS + 1].m_idx].m_texture->getUuid();
+	}
+
 	hash = appendHash(&uuids[0], sizeof(U64) * count, hash);
 
 	FramebufferPtr fb;
@@ -471,6 +498,17 @@ FramebufferPtr RenderGraph::getOrCreateFramebuffer(const FramebufferDescription&
 			outAtt.m_textureView = view;
 		}
 
+		if(fbDescr.m_shadingRateAttachmentTexelWidth > 0)
+		{
+			TextureViewInitInfo viewInit(m_ctx->m_rts[rtHandles[MAX_COLOR_ATTACHMENTS + 1].m_idx].m_texture,
+										 fbDescr.m_shadingRateAttachmentSurface, "RenderGraph SRI");
+			TextureViewPtr view = getManager().newTextureView(viewInit);
+
+			fbInit.m_shadingRateImage.m_texelWidth = fbDescr.m_shadingRateAttachmentTexelWidth;
+			fbInit.m_shadingRateImage.m_texelHeight = fbDescr.m_shadingRateAttachmentTexelHeight;
+			fbInit.m_shadingRateImage.m_textureView = view;
+		}
+
 		// Set FB name
 		Array<char, MAX_GR_OBJECT_NAME_LENGTH + 1> cutName;
 		const U cutNameLen = min<U>(name.getLength(), MAX_GR_OBJECT_NAME_LENGTH);

+ 8 - 3
AnKi/Gr/RenderGraph.h

@@ -408,6 +408,9 @@ public:
 	Array<FramebufferDescriptionAttachment, MAX_COLOR_ATTACHMENTS> m_colorAttachments;
 	U32 m_colorAttachmentCount = 0;
 	FramebufferDescriptionAttachment m_depthStencilAttachment;
+	U32 m_shadingRateAttachmentTexelWidth = 0;
+	U32 m_shadingRateAttachmentTexelHeight = 0;
+	TextureSurfaceInfo m_shadingRateAttachmentSurface;
 
 	/// Calculate the hash for the framebuffer.
 	void bake();
@@ -433,16 +436,18 @@ class GraphicsRenderPassDescription : public RenderPassDescriptionBase
 public:
 	void setFramebufferInfo(const FramebufferDescription& fbInfo,
 							ConstWeakArray<RenderTargetHandle> colorRenderTargetHandles,
-							RenderTargetHandle depthStencilRenderTargetHandle, U32 minx = 0, U32 miny = 0,
+							RenderTargetHandle depthStencilRenderTargetHandle = {},
+							RenderTargetHandle shadingRateRenderTargetHandle = {}, U32 minx = 0, U32 miny = 0,
 							U32 maxx = MAX_U32, U32 maxy = MAX_U32);
 
 	void setFramebufferInfo(const FramebufferDescription& fbInfo,
 							std::initializer_list<RenderTargetHandle> colorRenderTargetHandles,
-							RenderTargetHandle depthStencilRenderTargetHandle, U32 minx = 0, U32 miny = 0,
+							RenderTargetHandle depthStencilRenderTargetHandle = {},
+							RenderTargetHandle shadingRateRenderTargetHandle = {}, U32 minx = 0, U32 miny = 0,
 							U32 maxx = MAX_U32, U32 maxy = MAX_U32);
 
 private:
-	Array<RenderTargetHandle, MAX_COLOR_ATTACHMENTS + 1> m_rtHandles;
+	Array<RenderTargetHandle, MAX_COLOR_ATTACHMENTS + 2> m_rtHandles;
 	FramebufferDescription m_fbDescr;
 	Array<U32, 4> m_fbRenderArea = {};
 

+ 16 - 4
AnKi/Gr/RenderGraph.inl.h

@@ -164,7 +164,8 @@ inline void RenderPassDescriptionBase::newDependency(const RenderPassDependency&
 
 inline void GraphicsRenderPassDescription::setFramebufferInfo(
 	const FramebufferDescription& fbInfo, std::initializer_list<RenderTargetHandle> colorRenderTargetHandles,
-	RenderTargetHandle depthStencilRenderTargetHandle, U32 minx, U32 miny, U32 maxx, U32 maxy)
+	RenderTargetHandle depthStencilRenderTargetHandle, RenderTargetHandle shadingRateRenderTargetHandle, U32 minx,
+	U32 miny, U32 maxx, U32 maxy)
 {
 	Array<RenderTargetHandle, MAX_COLOR_ATTACHMENTS> rts;
 	U32 count = 0;
@@ -172,13 +173,14 @@ inline void GraphicsRenderPassDescription::setFramebufferInfo(
 	{
 		rts[count++] = h;
 	}
-	setFramebufferInfo(fbInfo, ConstWeakArray<RenderTargetHandle>(&rts[0], count), depthStencilRenderTargetHandle, minx,
-					   miny, maxx, maxy);
+	setFramebufferInfo(fbInfo, ConstWeakArray<RenderTargetHandle>(&rts[0], count), depthStencilRenderTargetHandle,
+					   shadingRateRenderTargetHandle, minx, miny, maxx, maxy);
 }
 
 inline void GraphicsRenderPassDescription::setFramebufferInfo(
 	const FramebufferDescription& fbInfo, ConstWeakArray<RenderTargetHandle> colorRenderTargetHandles,
-	RenderTargetHandle depthStencilRenderTargetHandle, U32 minx, U32 miny, U32 maxx, U32 maxy)
+	RenderTargetHandle depthStencilRenderTargetHandle, RenderTargetHandle shadingRateRenderTargetHandle, U32 minx,
+	U32 miny, U32 maxx, U32 maxy)
 {
 #if ANKI_ENABLE_ASSERTIONS
 	ANKI_ASSERT(fbInfo.isBacked() && "Forgot call GraphicsRenderPassFramebufferInfo::bake");
@@ -202,11 +204,21 @@ inline void GraphicsRenderPassDescription::setFramebufferInfo(
 	{
 		ANKI_ASSERT(depthStencilRenderTargetHandle.isValid());
 	}
+
+	if(fbInfo.m_shadingRateAttachmentTexelWidth > 0 && fbInfo.m_shadingRateAttachmentTexelHeight > 0)
+	{
+		ANKI_ASSERT(shadingRateRenderTargetHandle.isValid());
+	}
+	else
+	{
+		ANKI_ASSERT(!shadingRateRenderTargetHandle.isValid());
+	}
 #endif
 
 	m_fbDescr = fbInfo;
 	memcpy(m_rtHandles.getBegin(), colorRenderTargetHandles.getBegin(), colorRenderTargetHandles.getSizeInBytes());
 	m_rtHandles[MAX_COLOR_ATTACHMENTS] = depthStencilRenderTargetHandle;
+	m_rtHandles[MAX_COLOR_ATTACHMENTS + 1] = shadingRateRenderTargetHandle;
 	m_fbRenderArea = {minx, miny, maxx, maxy};
 }
 

+ 16 - 2
AnKi/Gr/Vulkan/CommandBufferImpl.cpp

@@ -93,7 +93,14 @@ void CommandBufferImpl::beginRecording()
 			dsAttLayout = view.getTextureImpl().computeLayout(m_depthStencilAttachmentUsage, 0);
 		}
 
-		inheritance.renderPass = impl.getRenderPassHandle(colAttLayouts, dsAttLayout);
+		VkImageLayout sriAttachmentLayout = VK_IMAGE_LAYOUT_MAX_ENUM;
+		if(impl.hasSri())
+		{
+			// Technically it's possible for SRI to be in other layout. Don't bother though
+			sriAttachmentLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
+		}
+
+		inheritance.renderPass = impl.getRenderPassHandle(colAttLayouts, dsAttLayout, sriAttachmentLayout);
 		inheritance.subpass = 0;
 		inheritance.framebuffer = impl.getFramebufferHandle();
 
@@ -179,7 +186,14 @@ void CommandBufferImpl::beginRenderPassInternal()
 		dsAttLayout = view.getTextureImpl().computeLayout(m_depthStencilAttachmentUsage, 0);
 	}
 
-	bi.renderPass = impl.getRenderPassHandle(colAttLayouts, dsAttLayout);
+	VkImageLayout sriAttachmentLayout = VK_IMAGE_LAYOUT_MAX_ENUM;
+	if(impl.hasSri())
+	{
+		// Technically it's possible for SRI to be in other layout. Don't bother though
+		sriAttachmentLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
+	}
+
+	bi.renderPass = impl.getRenderPassHandle(colAttLayouts, dsAttLayout, sriAttachmentLayout);
 
 	const Bool flipvp = flipViewport();
 	bi.renderArea.offset.x = m_renderArea[0];

+ 5 - 0
AnKi/Gr/Vulkan/Common.cpp

@@ -413,6 +413,11 @@ VkImageUsageFlags convertTextureUsage(const TextureUsageBit ak, const Format for
 		}
 	}
 
+	if(!!(ak & TextureUsageBit::FRAMEBUFFER_SHADING_RATE))
+	{
+		out |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+	}
+
 	if(!!(ak & TextureUsageBit::TRANSFER_DESTINATION))
 	{
 		out |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;

+ 118 - 42
AnKi/Gr/Vulkan/FramebufferImpl.cpp

@@ -12,23 +12,23 @@ namespace anki {
 
 FramebufferImpl::~FramebufferImpl()
 {
-	if(m_fb)
+	if(m_fbHandle)
 	{
-		vkDestroyFramebuffer(getDevice(), m_fb, nullptr);
+		vkDestroyFramebuffer(getDevice(), m_fbHandle, nullptr);
 	}
 
-	for(auto it : m_rpasses)
+	for(auto it : m_renderpassHandles)
 	{
 		VkRenderPass rpass = it;
 		ANKI_ASSERT(rpass);
 		vkDestroyRenderPass(getDevice(), rpass, nullptr);
 	}
 
-	m_rpasses.destroy(getAllocator());
+	m_renderpassHandles.destroy(getAllocator());
 
-	if(m_compatibleRpass)
+	if(m_compatibleRenderpassHandle)
 	{
-		vkDestroyRenderPass(getDevice(), m_compatibleRpass, nullptr);
+		vkDestroyRenderPass(getDevice(), m_compatibleRenderpassHandle, nullptr);
 	}
 }
 
@@ -48,13 +48,15 @@ Error FramebufferImpl::init(const FramebufferInitInfo& init)
 		m_aspect = init.m_depthStencilAttachment.m_textureView->getSubresource().m_depthStencilAspect;
 	}
 
+	m_hasSri = init.m_shadingRateImage.m_textureView.isCreated();
+
 	initClearValues(init);
 
 	// Create a renderpass.
 	initRpassCreateInfo(init);
-	ANKI_VK_CHECK(vkCreateRenderPass2KHR(getDevice(), &m_rpassCi, nullptr, &m_compatibleRpass));
+	ANKI_VK_CHECK(vkCreateRenderPass2KHR(getDevice(), &m_rpassCi, nullptr, &m_compatibleRenderpassHandle));
 	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
-											  m_compatibleRpass);
+											  m_compatibleRenderpassHandle);
 
 	// Create the FB
 	ANKI_CHECK(initFbs(init));
@@ -96,17 +98,23 @@ void FramebufferImpl::initClearValues(const FramebufferInitInfo& init)
 			m_clearVals[m_colorAttCount] = {};
 		}
 	}
+
+	// Put something for SRI. Value doesn't matter
+	if(hasSri())
+	{
+		m_clearVals[m_colorAttCount + hasDepthStencil()] = {};
+	}
 }
 
 Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
 {
 	VkFramebufferCreateInfo ci = {};
 	ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
-	ci.renderPass = m_compatibleRpass;
-	ci.attachmentCount = init.m_colorAttachmentCount + ((hasDepthStencil()) ? 1 : 0);
+	ci.renderPass = m_compatibleRenderpassHandle;
+	ci.attachmentCount = getTotalAttachmentCount();
 	ci.layers = 1;
 
-	Array<VkImageView, MAX_COLOR_ATTACHMENTS + 1> imgViews;
+	Array<VkImageView, MAX_ATTACHMENTS> imgViews;
 	U count = 0;
 
 	for(U i = 0; i < init.m_colorAttachmentCount; ++i)
@@ -116,7 +124,7 @@ Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
 		const TextureImpl& tex = view.getTextureImpl();
 		ANKI_ASSERT(tex.isSubresourceGoodForFramebufferAttachment(view.getSubresource()));
 
-		imgViews[count++] = view.getHandle();
+		imgViews[count] = view.getHandle();
 
 		if(m_width == 0)
 		{
@@ -124,12 +132,14 @@ Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
 			m_height = tex.getHeight() >> view.getSubresource().m_firstMipmap;
 		}
 
-		m_refs[i] = att.m_textureView;
+		m_viewRefs.m_color[i] = att.m_textureView;
 
 		if(!!(tex.getTextureUsage() & TextureUsageBit::PRESENT))
 		{
 			m_presentableTex = true;
 		}
+
+		++count;
 	}
 
 	if(hasDepthStencil())
@@ -139,7 +149,7 @@ Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
 		const TextureImpl& tex = view.getTextureImpl();
 		ANKI_ASSERT(tex.isSubresourceGoodForFramebufferAttachment(view.getSubresource()));
 
-		imgViews[count++] = view.getHandle();
+		imgViews[count] = view.getHandle();
 
 		if(m_width == 0)
 		{
@@ -147,7 +157,17 @@ Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
 			m_height = tex.getHeight() >> view.getSubresource().m_firstMipmap;
 		}
 
-		m_refs[MAX_COLOR_ATTACHMENTS] = att.m_textureView;
+		m_viewRefs.m_depthStencil = att.m_textureView;
+		++count;
+	}
+
+	if(hasSri())
+	{
+		const TextureViewImpl& view = static_cast<const TextureViewImpl&>(*init.m_shadingRateImage.m_textureView);
+		ANKI_ASSERT(view.getTextureImpl().usageValid(TextureUsageBit::FRAMEBUFFER_SHADING_RATE));
+		imgViews[count] = view.getHandle();
+		m_viewRefs.m_sri = init.m_shadingRateImage.m_textureView;
+		++count;
 	}
 
 	ci.width = m_width;
@@ -156,8 +176,8 @@ Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
 	ci.pAttachments = &imgViews[0];
 	ANKI_ASSERT(count == ci.attachmentCount);
 
-	ANKI_VK_CHECK(vkCreateFramebuffer(getDevice(), &ci, nullptr, &m_fb));
-	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, m_fb);
+	ANKI_VK_CHECK(vkCreateFramebuffer(getDevice(), &ci, nullptr, &m_fbHandle));
+	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, m_fbHandle);
 
 	return Error::NONE;
 }
@@ -185,9 +205,10 @@ void FramebufferImpl::initRpassCreateInfo(const FramebufferInitInfo& init)
 		setupAttachmentDescriptor(init.m_colorAttachments[i], m_attachmentDescriptions[i],
 								  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
 
-		m_references[i].sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
-		m_references[i].attachment = i;
-		m_references[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+		VkAttachmentReference2& ref = m_references[i];
+		ref.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
+		ref.attachment = i;
+		ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 	}
 
 	if(hasDepthStencil())
@@ -195,16 +216,37 @@ void FramebufferImpl::initRpassCreateInfo(const FramebufferInitInfo& init)
 		setupAttachmentDescriptor(init.m_depthStencilAttachment, m_attachmentDescriptions[init.m_colorAttachmentCount],
 								  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
 
-		VkAttachmentReference2& dsReference = m_references[init.m_colorAttachmentCount];
-		dsReference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
-		dsReference.attachment = init.m_colorAttachmentCount;
-		dsReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+		VkAttachmentReference2& ref = m_references[init.m_colorAttachmentCount];
+		ref.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
+		ref.attachment = init.m_colorAttachmentCount;
+		ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 	}
 
-	// Setup the render pass
-	m_rpassCi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2;
-	m_rpassCi.pAttachments = &m_attachmentDescriptions[0];
-	m_rpassCi.attachmentCount = init.m_colorAttachmentCount + ((hasDepthStencil()) ? 1 : 0);
+	U32 sriAttachmentIdx = MAX_U32;
+	if(init.m_shadingRateImage.m_textureView)
+	{
+		ANKI_ASSERT(getGrManagerImpl().getDeviceCapabilities().m_vrs && "This requires VRS to be enabled");
+
+		sriAttachmentIdx = init.m_colorAttachmentCount + hasDepthStencil();
+
+		VkAttachmentDescription2& desc = m_attachmentDescriptions[sriAttachmentIdx];
+		desc = {};
+		desc.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
+		desc.format = convertFormat(
+			static_cast<const TextureViewImpl&>(*init.m_shadingRateImage.m_textureView).getTextureImpl().getFormat());
+		desc.samples = VK_SAMPLE_COUNT_1_BIT;
+		desc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+		desc.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+		desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+		desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+		desc.initialLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
+		desc.finalLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
+
+		VkAttachmentReference2& ref = m_references[sriAttachmentIdx];
+		ref.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
+		ref.attachment = sriAttachmentIdx;
+		ref.layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
+	}
 
 	// Subpass
 	m_subpassDescr.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2;
@@ -213,17 +255,31 @@ void FramebufferImpl::initRpassCreateInfo(const FramebufferInitInfo& init)
 	m_subpassDescr.pColorAttachments = (init.m_colorAttachmentCount) ? &m_references[0] : nullptr;
 	m_subpassDescr.pDepthStencilAttachment = (hasDepthStencil()) ? &m_references[init.m_colorAttachmentCount] : nullptr;
 
+	if(init.m_shadingRateImage.m_textureView)
+	{
+		m_sriAttachmentInfo.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
+		m_sriAttachmentInfo.shadingRateAttachmentTexelSize.width = init.m_shadingRateImage.m_texelWidth;
+		m_sriAttachmentInfo.shadingRateAttachmentTexelSize.height = init.m_shadingRateImage.m_texelHeight;
+		m_sriAttachmentInfo.pFragmentShadingRateAttachment = &m_references[sriAttachmentIdx];
+
+		m_subpassDescr.pNext = &m_sriAttachmentInfo;
+	}
+
+	// Setup the render pass
+	m_rpassCi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2;
+	m_rpassCi.pAttachments = &m_attachmentDescriptions[0];
+	m_rpassCi.attachmentCount = getTotalAttachmentCount();
 	m_rpassCi.subpassCount = 1;
 	m_rpassCi.pSubpasses = &m_subpassDescr;
 }
 
 VkRenderPass FramebufferImpl::getRenderPassHandle(const Array<VkImageLayout, MAX_COLOR_ATTACHMENTS>& colorLayouts,
-												  VkImageLayout dsLayout)
+												  VkImageLayout dsLayout, VkImageLayout shadingRateImageLayout)
 {
 	VkRenderPass out = VK_NULL_HANDLE;
 
 	// Create hash
-	Array<VkImageLayout, MAX_COLOR_ATTACHMENTS + 1> allLayouts;
+	Array<VkImageLayout, MAX_ATTACHMENTS> allLayouts;
 	U allLayoutCount = 0;
 	for(U i = 0; i < m_colorAttCount; ++i)
 	{
@@ -237,13 +293,19 @@ VkRenderPass FramebufferImpl::getRenderPassHandle(const Array<VkImageLayout, MAX
 		allLayouts[allLayoutCount++] = dsLayout;
 	}
 
+	if(hasSri())
+	{
+		ANKI_ASSERT(shadingRateImageLayout != VK_IMAGE_LAYOUT_UNDEFINED);
+		allLayouts[allLayoutCount++] = shadingRateImageLayout;
+	}
+
 	const U64 hash = computeHash(&allLayouts[0], allLayoutCount * sizeof(allLayouts[0]));
 
 	// Try get it
 	{
-		RLockGuard<RWMutex> lock(m_rpassesMtx);
-		auto it = m_rpasses.find(hash);
-		if(it != m_rpasses.getEnd())
+		RLockGuard<RWMutex> lock(m_renderpassHandlesMtx);
+		auto it = m_renderpassHandles.find(hash);
+		if(it != m_renderpassHandles.getEnd())
 		{
 			out = *it;
 		}
@@ -253,21 +315,21 @@ VkRenderPass FramebufferImpl::getRenderPassHandle(const Array<VkImageLayout, MAX
 	{
 		// Create it
 
-		WLockGuard<RWMutex> lock(m_rpassesMtx);
+		WLockGuard<RWMutex> lock(m_renderpassHandlesMtx);
 
 		// Check again
-		auto it = m_rpasses.find(hash);
-		if(it != m_rpasses.getEnd())
+		auto it = m_renderpassHandles.find(hash);
+		if(it != m_renderpassHandles.getEnd())
 		{
 			out = *it;
 		}
 		else
 		{
 			VkRenderPassCreateInfo2 ci = m_rpassCi;
-			Array<VkAttachmentDescription2, MAX_COLOR_ATTACHMENTS + 1> attachmentDescriptions =
-				m_attachmentDescriptions;
-			Array<VkAttachmentReference2, MAX_COLOR_ATTACHMENTS + 1> references = m_references;
+			Array<VkAttachmentDescription2, MAX_ATTACHMENTS> attachmentDescriptions = m_attachmentDescriptions;
+			Array<VkAttachmentReference2, MAX_ATTACHMENTS> references = m_references;
 			VkSubpassDescription2 subpassDescr = m_subpassDescr;
+			VkFragmentShadingRateAttachmentInfoKHR sriAttachmentInfo = m_sriAttachmentInfo;
 
 			// Fix pointers
 			subpassDescr.pColorAttachments = &references[0];
@@ -294,14 +356,28 @@ VkRenderPass FramebufferImpl::getRenderPassHandle(const Array<VkImageLayout, MAX
 				attachmentDescriptions[i].initialLayout = lay;
 				attachmentDescriptions[i].finalLayout = lay;
 
-				references[subpassDescr.colorAttachmentCount].layout = lay;
-				subpassDescr.pDepthStencilAttachment = &references[subpassDescr.colorAttachmentCount];
+				references[i].layout = lay;
+				subpassDescr.pDepthStencilAttachment = &references[i];
+			}
+
+			if(hasSri())
+			{
+				const U i = subpassDescr.colorAttachmentCount + hasDepthStencil();
+				const VkImageLayout lay = shadingRateImageLayout;
+
+				attachmentDescriptions[i].initialLayout = lay;
+				attachmentDescriptions[i].finalLayout = lay;
+
+				references[i].layout = lay;
+
+				sriAttachmentInfo.pFragmentShadingRateAttachment = &references[i];
+				subpassDescr.pNext = &sriAttachmentInfo;
 			}
 
 			ANKI_VK_CHECKF(vkCreateRenderPass2KHR(getDevice(), &ci, nullptr, &out));
 			getGrManagerImpl().trySetVulkanHandleName(getName(), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, out);
 
-			m_rpasses.emplace(getAllocator(), hash, out);
+			m_renderpassHandles.emplace(getAllocator(), hash, out);
 		}
 	}
 

+ 43 - 20
AnKi/Gr/Vulkan/FramebufferImpl.h

@@ -35,18 +35,18 @@ public:
 	/// Good for pipeline creation.
 	VkRenderPass getCompatibleRenderPass() const
 	{
-		ANKI_ASSERT(m_compatibleRpass);
-		return m_compatibleRpass;
+		ANKI_ASSERT(m_compatibleRenderpassHandle);
+		return m_compatibleRenderpassHandle;
 	}
 
 	/// Use it for binding. It's thread-safe
 	VkRenderPass getRenderPassHandle(const Array<VkImageLayout, MAX_COLOR_ATTACHMENTS>& colorLayouts,
-									 VkImageLayout dsLayout);
+									 VkImageLayout dsLayout, VkImageLayout shadingRateImageLayout);
 
 	VkFramebuffer getFramebufferHandle() const
 	{
-		ANKI_ASSERT(m_fb);
-		return m_fb;
+		ANKI_ASSERT(m_fbHandle);
+		return m_fbHandle;
 	}
 
 	void getAttachmentInfo(BitSet<MAX_COLOR_ATTACHMENTS, U8>& colorAttachments, Bool& depth, Bool& stencil) const
@@ -68,19 +68,22 @@ public:
 
 	U32 getAttachmentCount() const
 	{
-		return m_colorAttCount + (hasDepthStencil() ? 1 : 0);
+		return getTotalAttachmentCount();
 	}
 
 	const TextureViewPtr& getColorAttachment(U att) const
 	{
-		ANKI_ASSERT(m_refs[att].get());
-		return m_refs[att];
+		return m_viewRefs.m_color[att];
 	}
 
 	const TextureViewPtr& getDepthStencilAttachment() const
 	{
-		ANKI_ASSERT(m_refs[MAX_COLOR_ATTACHMENTS].get());
-		return m_refs[MAX_COLOR_ATTACHMENTS];
+		return m_viewRefs.m_depthStencil;
+	}
+
+	const TextureViewPtr& getSriAttachment() const
+	{
+		return m_viewRefs.m_sri;
 	}
 
 	const VkClearValue* getClearValues() const
@@ -100,30 +103,45 @@ public:
 		return m_presentableTex;
 	}
 
+	Bool hasSri() const
+	{
+		return m_hasSri;
+	}
+
 private:
+	static constexpr U32 MAX_ATTACHMENTS = MAX_COLOR_ATTACHMENTS + 2; ///< Color + depth/stencil + SRI
+
 	BitSet<MAX_COLOR_ATTACHMENTS, U8> m_colorAttachmentMask = {false};
 	DepthStencilAspectBit m_aspect = DepthStencilAspectBit::NONE;
 
 	U8 m_colorAttCount = 0;
-	Array<VkClearValue, MAX_COLOR_ATTACHMENTS + 1> m_clearVals;
+	Array<VkClearValue, MAX_ATTACHMENTS> m_clearVals;
 
 	U32 m_width = 0;
 	U32 m_height = 0;
 	Bool m_presentableTex = false;
+	Bool m_hasSri = false;
 
-	Array<TextureViewPtr, MAX_COLOR_ATTACHMENTS + 1> m_refs; ///< @note The pos of every attachment is fixed.
+	class
+	{
+	public:
+		Array<TextureViewPtr, MAX_COLOR_ATTACHMENTS> m_color;
+		TextureViewPtr m_depthStencil;
+		TextureViewPtr m_sri;
+	} m_viewRefs;
+
+	// VK objects
+	VkRenderPass m_compatibleRenderpassHandle = VK_NULL_HANDLE; ///< Compatible renderpass. Good for pipeline creation.
+	HashMap<U64, VkRenderPass> m_renderpassHandles;
+	RWMutex m_renderpassHandlesMtx;
+	VkFramebuffer m_fbHandle = VK_NULL_HANDLE;
 
 	// RenderPass create info
 	VkRenderPassCreateInfo2 m_rpassCi = {};
-	Array<VkAttachmentDescription2, MAX_COLOR_ATTACHMENTS + 1> m_attachmentDescriptions = {};
-	Array<VkAttachmentReference2, MAX_COLOR_ATTACHMENTS + 1> m_references = {};
+	Array<VkAttachmentDescription2, MAX_ATTACHMENTS> m_attachmentDescriptions = {};
+	Array<VkAttachmentReference2, MAX_ATTACHMENTS> m_references = {};
 	VkSubpassDescription2 m_subpassDescr = {};
-
-	// VK objects
-	VkRenderPass m_compatibleRpass = {}; ///< Compatible renderpass.
-	HashMap<U64, VkRenderPass> m_rpasses;
-	RWMutex m_rpassesMtx;
-	VkFramebuffer m_fb = VK_NULL_HANDLE;
+	VkFragmentShadingRateAttachmentInfoKHR m_sriAttachmentInfo = {};
 
 	// Methods
 	ANKI_USE_RESULT Error initFbs(const FramebufferInitInfo& init);
@@ -131,6 +149,11 @@ private:
 	void initClearValues(const FramebufferInitInfo& init);
 	void setupAttachmentDescriptor(const FramebufferAttachmentInfo& att, VkAttachmentDescription2& desc,
 								   VkImageLayout layout) const;
+
+	U32 getTotalAttachmentCount() const
+	{
+		return m_colorAttCount + hasDepthStencil() + hasSri();
+	}
 };
 /// @}
 

+ 12 - 32
AnKi/Gr/Vulkan/TextureImpl.cpp

@@ -218,37 +218,6 @@ Error TextureImpl::initInternal(VkImage externalImage, const TextureInitInfo& in
 	return Error::NONE;
 }
 
-VkFormatFeatureFlags TextureImpl::calcFeatures(const TextureInitInfo& init)
-{
-	VkFormatFeatureFlags flags = 0;
-
-	if(init.m_mipmapCount > 1 && !!(init.m_usage & TextureUsageBit::GENERATE_MIPMAPS))
-	{
-		// May be used for mip gen.
-		flags |= VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT;
-	}
-
-	if(!!(init.m_usage & TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT))
-	{
-		if(formatIsDepthStencil(init.m_format))
-		{
-			flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
-		}
-		else
-		{
-			flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
-		}
-	}
-
-	if(!!(init.m_usage & TextureUsageBit::ALL_SAMPLED))
-	{
-		flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
-	}
-
-	ANKI_ASSERT(flags);
-	return flags;
-}
-
 VkImageCreateFlags TextureImpl::calcCreateFlags(const TextureInitInfo& init)
 {
 	VkImageCreateFlags flags = 0;
@@ -264,7 +233,7 @@ Bool TextureImpl::imageSupported(const TextureInitInfo& init)
 {
 	VkImageFormatProperties props = {};
 
-	VkResult res = vkGetPhysicalDeviceImageFormatProperties(
+	const VkResult res = vkGetPhysicalDeviceImageFormatProperties(
 		getGrManagerImpl().getPhysicalDevice(), m_vkFormat, convertTextureType(init.m_type), VK_IMAGE_TILING_OPTIMAL,
 		convertTextureUsage(init.m_usage, init.m_format), calcCreateFlags(init), &props);
 
@@ -530,6 +499,12 @@ void TextureImpl::computeBarrierInfo(TextureUsageBit usage, Bool src, U32 level,
 		}
 	}
 
+	if(!!(usage & TextureUsageBit::FRAMEBUFFER_SHADING_RATE))
+	{
+		stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+		accesses |= VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
+	}
+
 	if(!!(usage & TextureUsageBit::GENERATE_MIPMAPS))
 	{
 		stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
@@ -615,6 +590,11 @@ VkImageLayout TextureImpl::computeLayout(TextureUsageBit usage, U level) const
 		// Color attachment
 		out = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 	}
+	else if(!(usage & ~TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT))
+	{
+		// SRI
+		out = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
+	}
 	else if(!(usage & ~TextureUsageBit::ALL_IMAGE))
 	{
 		// Only image load/store

+ 0 - 8
AnKi/Gr/Vulkan/TextureImpl.h

@@ -220,20 +220,12 @@ private:
 	mutable SpinLock m_usedForMtx;
 #endif
 
-	ANKI_USE_RESULT static VkFormatFeatureFlags calcFeatures(const TextureInitInfo& init);
-
 	ANKI_USE_RESULT static VkImageCreateFlags calcCreateFlags(const TextureInitInfo& init);
 
 	ANKI_USE_RESULT Bool imageSupported(const TextureInitInfo& init);
 
 	ANKI_USE_RESULT Error initImage(const TextureInitInfo& init);
 
-	template<typename TextureInfo>
-	void updateUsageState(const TextureInfo& surfOrVol, TextureUsageBit usage, StackAllocator<U8>& alloc,
-						  TextureUsageState& state) const;
-
-	void updateUsageState(TextureUsageBit usage, StackAllocator<U8>& alloc, TextureUsageState& state) const;
-
 	/// Compute the new type of a texture view.
 	TextureType computeNewTexTypeOfSubresource(const TextureSubresourceInfo& subresource) const;
 

+ 2 - 2
AnKi/Renderer/Bloom.cpp

@@ -104,7 +104,7 @@ void Bloom::populateRenderGraph(RenderingContext& ctx)
 		else
 		{
 			GraphicsRenderPassDescription& rpass = rgraph.newGraphicsRenderPass("Bloom Main");
-			rpass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_exposureRt}, {});
+			rpass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_exposureRt});
 
 			rpass.newDependency(RenderPassDependency(m_r->getDownscaleBlur().getRt(), TextureUsageBit::SAMPLED_FRAGMENT,
 													 inputTexSubresource));
@@ -165,7 +165,7 @@ void Bloom::populateRenderGraph(RenderingContext& ctx)
 		else
 		{
 			GraphicsRenderPassDescription& rpass = rgraph.newGraphicsRenderPass("Bloom Upscale");
-			rpass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_upscaleRt}, {});
+			rpass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_upscaleRt});
 
 			rpass.newDependency({m_runCtx.m_exposureRt, TextureUsageBit::SAMPLED_FRAGMENT});
 			rpass.newDependency({m_runCtx.m_upscaleRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});

+ 1 - 1
AnKi/Renderer/DownscaleBlur.cpp

@@ -124,7 +124,7 @@ void DownscaleBlur::populateRenderGraph(RenderingContext& ctx)
 			pass.setWork([this, i](RenderPassWorkContext& rgraphCtx) {
 				run(i, rgraphCtx);
 			});
-			pass.setFramebufferInfo(m_fbDescrs[i], {m_runCtx.m_rt}, {});
+			pass.setFramebufferInfo(m_fbDescrs[i], {m_runCtx.m_rt});
 
 			if(i > 0)
 			{

+ 1 - 1
AnKi/Renderer/FinalComposite.cpp

@@ -97,7 +97,7 @@ void FinalComposite::populateRenderGraph(RenderingContext& ctx)
 	pass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
 		run(ctx, rgraphCtx);
 	});
-	pass.setFramebufferInfo(m_fbDescr, {ctx.m_outRenderTarget}, {});
+	pass.setFramebufferInfo(m_fbDescr, {ctx.m_outRenderTarget});
 
 	pass.newDependency({ctx.m_outRenderTarget, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
 

+ 1 - 1
AnKi/Renderer/GBufferPost.cpp

@@ -60,7 +60,7 @@ void GBufferPost::populateRenderGraph(RenderingContext& ctx)
 		run(ctx, rgraphCtx);
 	});
 
-	rpass.setFramebufferInfo(m_fbDescr, {m_r->getGBuffer().getColorRt(0), m_r->getGBuffer().getColorRt(1)}, {});
+	rpass.setFramebufferInfo(m_fbDescr, {m_r->getGBuffer().getColorRt(0), m_r->getGBuffer().getColorRt(1)});
 
 	rpass.newDependency(
 		RenderPassDependency(m_r->getGBuffer().getColorRt(0), TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT));

+ 2 - 2
AnKi/Renderer/IndirectDiffuse.cpp

@@ -116,7 +116,7 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 		else
 		{
 			GraphicsRenderPassDescription& rpass = rgraph.newGraphicsRenderPass("IndirectDiffuse");
-			rpass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_mainRtHandles[WRITE]}, {});
+			rpass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_mainRtHandles[WRITE]});
 			readUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 			writeUsage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
 			prpass = &rpass;
@@ -206,7 +206,7 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 		{
 			GraphicsRenderPassDescription& rpass =
 				rgraph.newGraphicsRenderPass((dir == 0) ? "IndirectDiffuseDenoiseH" : "IndirectDiffuseDenoiseV");
-			rpass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_mainRtHandles[!readIdx]}, {});
+			rpass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_mainRtHandles[!readIdx]});
 			readUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 			writeUsage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
 			prpass = &rpass;

+ 1 - 1
AnKi/Renderer/IndirectDiffuseProbes.cpp

@@ -345,7 +345,7 @@ void IndirectDiffuseProbes::populateRenderGraph(RenderingContext& rctx)
 
 		// Pass
 		GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI LS");
-		pass.setFramebufferInfo(m_lightShading.m_fbDescr, {{giCtx->m_lightShadingRt}}, {});
+		pass.setFramebufferInfo(m_lightShading.m_fbDescr, {giCtx->m_lightShadingRt});
 		pass.setWork(1, [this, giCtx](RenderPassWorkContext& rgraphCtx) {
 			runLightShading(rgraphCtx, *giCtx);
 		});

+ 1 - 1
AnKi/Renderer/LightShading.cpp

@@ -237,7 +237,7 @@ void LightShading::populateRenderGraph(RenderingContext& ctx)
 				 [this, &ctx](RenderPassWorkContext& rgraphCtx) {
 					 run(ctx, rgraphCtx);
 				 });
-	pass.setFramebufferInfo(m_lightShading.m_fbDescr, {{m_runCtx.m_rt}}, {m_r->getGBuffer().getDepthRt()});
+	pass.setFramebufferInfo(m_lightShading.m_fbDescr, {m_runCtx.m_rt}, m_r->getGBuffer().getDepthRt());
 
 	const TextureUsageBit readUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 

+ 1 - 1
AnKi/Renderer/MainRenderer.cpp

@@ -120,7 +120,7 @@ Error MainRenderer::render(RenderQueue& rqueue, TexturePtr presentTex)
 	{
 		GraphicsRenderPassDescription& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Final Blit");
 
-		pass.setFramebufferInfo(m_fbDescr, {{presentRt}}, {});
+		pass.setFramebufferInfo(m_fbDescr, {presentRt});
 		pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
 			CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 			cmdb->setViewport(0, 0, m_swapchainResolution.x(), m_swapchainResolution.y());

+ 1 - 1
AnKi/Renderer/MotionVectors.cpp

@@ -74,7 +74,7 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 	else
 	{
 		GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("Motion vectors");
-		pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_motionVectorsRtHandle, m_runCtx.m_rejectionFactorRtHandle}, {});
+		pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_motionVectorsRtHandle, m_runCtx.m_rejectionFactorRtHandle});
 
 		readUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		writeUsage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;

+ 1 - 1
AnKi/Renderer/ProbeReflections.cpp

@@ -623,7 +623,7 @@ void ProbeReflections::populateRenderGraph(RenderingContext& rctx)
 		{
 			GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
 			pass.setFramebufferInfo(m_cacheEntries[probeToUpdateCacheEntryIdx].m_lightShadingFbDescrs[faceIdx],
-									{{m_ctx.m_lightShadingRt}}, {});
+									{m_ctx.m_lightShadingRt});
 			pass.setWork([this, faceIdx](RenderPassWorkContext& rgraphCtx) {
 				runLightShading(faceIdx, rgraphCtx);
 			});

+ 2 - 2
AnKi/Renderer/Scale.cpp

@@ -130,7 +130,7 @@ void Scale::populateRenderGraph(RenderingContext& ctx)
 		else
 		{
 			GraphicsRenderPassDescription& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Scale");
-			pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_scaledRt}, {});
+			pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_scaledRt});
 
 			pass.newDependency(
 				RenderPassDependency(m_r->getTemporalAA().getTonemappedRt(), TextureUsageBit::SAMPLED_FRAGMENT));
@@ -162,7 +162,7 @@ void Scale::populateRenderGraph(RenderingContext& ctx)
 		else
 		{
 			GraphicsRenderPassDescription& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Sharpen");
-			pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_sharpenedRt}, {});
+			pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_sharpenedRt});
 
 			pass.newDependency(
 				RenderPassDependency((!doScaling()) ? m_r->getTemporalAA().getTonemappedRt() : m_runCtx.m_scaledRt,

+ 4 - 4
AnKi/Renderer/ShadowMapping.cpp

@@ -253,7 +253,7 @@ void ShadowMapping::populateRenderGraph(RenderingContext& ctx)
 			GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("SM scratch");
 
 			m_scratch.m_rt = rgraph.newRenderTarget(m_scratch.m_rtDescr);
-			pass.setFramebufferInfo(m_scratch.m_fbDescr, {}, m_scratch.m_rt, minx, miny, width, height);
+			pass.setFramebufferInfo(m_scratch.m_fbDescr, {}, m_scratch.m_rt, {}, minx, miny, width, height);
 			ANKI_ASSERT(threadCountForScratchPass
 						&& threadCountForScratchPass <= m_r->getThreadHive().getThreadCount());
 			pass.setWork(threadCountForScratchPass, [this](RenderPassWorkContext& rgraphCtx) {
@@ -278,7 +278,7 @@ void ShadowMapping::populateRenderGraph(RenderingContext& ctx)
 
 			if(getConfig().getRPreferCompute())
 			{
-				ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("SM atlas");
+				ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("EVSM resolve");
 
 				pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
 					runAtlas(rgraphCtx);
@@ -290,8 +290,8 @@ void ShadowMapping::populateRenderGraph(RenderingContext& ctx)
 			}
 			else
 			{
-				GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("SM atlas");
-				pass.setFramebufferInfo(m_atlas.m_fbDescr, {m_atlas.m_rt}, {});
+				GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("EVSM resolve");
+				pass.setFramebufferInfo(m_atlas.m_fbDescr, {m_atlas.m_rt});
 
 				pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
 					runAtlas(rgraphCtx);

+ 1 - 1
AnKi/Renderer/ShadowmapsResolve.cpp

@@ -85,7 +85,7 @@ void ShadowmapsResolve::populateRenderGraph(RenderingContext& ctx)
 	else
 	{
 		GraphicsRenderPassDescription& rpass = rgraph.newGraphicsRenderPass("SM resolve");
-		rpass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_rt}, {});
+		rpass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_rt});
 
 		rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
 			run(ctx, rgraphCtx);

+ 1 - 1
AnKi/Renderer/Ssr.cpp

@@ -79,7 +79,7 @@ void Ssr::populateRenderGraph(RenderingContext& ctx)
 	else
 	{
 		GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("SSR");
-		pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_rt}, {});
+		pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_rt});
 
 		ppass = &pass;
 		readUsage = TextureUsageBit::SAMPLED_FRAGMENT;

+ 1 - 1
AnKi/Renderer/TemporalAA.cpp

@@ -122,7 +122,7 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 	else
 	{
 		GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("TemporalAA");
-		pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_renderRt, m_runCtx.m_tonemappedRt}, {});
+		pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_renderRt, m_runCtx.m_tonemappedRt});
 
 		pass.newDependency(RenderPassDependency(m_runCtx.m_renderRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
 		pass.newDependency(