Просмотр исходного кода

Rework a bit the bindless interface

Panagiotis Christopoulos Charitos 5 лет назад
Родитель
Сommit
4b128f7fd8

+ 3 - 11
anki/gr/CommandBuffer.h

@@ -294,17 +294,6 @@ public:
 	/// Bind the bindless descriptor set into a slot.
 	void bindAllBindless(U32 set);
 
-	/// Bind a texture as bindless. It's very lightweight and doesn't translate to a GPU operation.
-	/// @param tex The texture view to bind.
-	/// @param usage The state the tex is in.
-	/// @return The index to use to access the texture.
-	U32 bindBindlessTexture(TextureViewPtr tex, TextureUsageBit usage);
-
-	/// Bind an image as bindless. It's very lightweight and doesn't translate to a GPU operation.
-	/// @param img The image to bind.
-	/// @return The index to use to access the image.
-	U32 bindBindlessImage(TextureViewPtr img);
-
 	/// Set push constants.
 	void setPushConstants(const void* data, U32 dataSize);
 
@@ -458,6 +447,9 @@ public:
 	void pushSecondLevelCommandBuffer(CommandBufferPtr cmdb);
 
 	Bool isEmpty() const;
+
+	/// The command buffer will co-own a pointer. Useful to track the lifetime of bindless resources.
+	void addReference(GrObjectPtr ptr);
 	/// @}
 
 protected:

+ 4 - 2
anki/gr/Common.h

@@ -50,12 +50,14 @@ constexpr U32 COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS = 100;
 
 /// Smart pointer for resources.
 template<typename T>
-using GrObjectPtr = IntrusivePtr<T, DefaultPtrDeleter<T>>;
+using GrObjectPtrT = IntrusivePtr<T, DefaultPtrDeleter<GrObject>>;
+
+using GrObjectPtr = GrObjectPtrT<GrObject>;
 
 #define ANKI_GR_CLASS(x_) \
 	class x_##Impl; \
 	class x_; \
-	using x_##Ptr = GrObjectPtr<x_>;
+	using x_##Ptr = GrObjectPtrT<x_>;
 
 ANKI_GR_CLASS(Buffer)
 ANKI_GR_CLASS(Texture)

+ 8 - 0
anki/gr/TextureView.h

@@ -89,6 +89,14 @@ public:
 		return m_subresource;
 	}
 
+	/// Returns an index to be used for bindless access. Only for sampling.
+	/// @note It's thread-safe
+	U32 getOrCreateBindlessTextureIndex();
+
+	/// Returns an index to be used for bindless access. For image read/write.
+	/// @note It's thread-safe
+	U32 getOrCreateBindlessImageIndex();
+
 protected:
 	TextureType m_texType = TextureType::COUNT;
 	TextureSubresourceInfo m_subresource;

+ 6 - 12
anki/gr/vulkan/CommandBuffer.cpp

@@ -216,18 +216,6 @@ void CommandBuffer::bindAllBindless(U32 set)
 	self.bindAllBindlessInternal(set);
 }
 
-U32 CommandBuffer::bindBindlessTexture(TextureViewPtr tex, TextureUsageBit usage)
-{
-	ANKI_VK_SELF(CommandBufferImpl);
-	return self.bindBindlessTextureInternal(tex, usage);
-}
-
-U32 CommandBuffer::bindBindlessImage(TextureViewPtr img)
-{
-	ANKI_VK_SELF(CommandBufferImpl);
-	return self.bindBindlessImageInternal(img);
-}
-
 void CommandBuffer::bindShaderProgram(ShaderProgramPtr prog)
 {
 	ANKI_VK_SELF(CommandBufferImpl);
@@ -436,4 +424,10 @@ void CommandBuffer::setLineWidth(F32 width)
 	self.setLineWidth(width);
 }
 
+void CommandBuffer::addReference(GrObjectPtr ptr)
+{
+	ANKI_VK_SELF(CommandBufferImpl);
+	self.addReference(ptr);
+}
+
 } // end namespace anki

+ 5 - 17
anki/gr/vulkan/CommandBufferImpl.h

@@ -281,23 +281,6 @@ public:
 		m_dsetState[set].bindBindlessDescriptorSet();
 	}
 
-	U32 bindBindlessTextureInternal(TextureViewPtr tex, TextureUsageBit usage)
-	{
-		TextureViewImpl& view = static_cast<TextureViewImpl&>(*tex);
-		const VkImageLayout layout = view.getTextureImpl().computeLayout(usage, 0);
-		const U32 idx = view.getOrCreateBindlessIndex(layout, DescriptorType::TEXTURE);
-		m_microCmdb->pushObjectRef(tex);
-		return idx;
-	}
-
-	U32 bindBindlessImageInternal(TextureViewPtr img)
-	{
-		TextureViewImpl& view = static_cast<TextureViewImpl&>(*img);
-		const U32 idx = view.getOrCreateBindlessIndex(VK_IMAGE_LAYOUT_GENERAL, DescriptorType::IMAGE);
-		m_microCmdb->pushObjectRef(img);
-		return idx;
-	}
-
 	void beginRenderPass(FramebufferPtr fb, const Array<TextureUsageBit, MAX_COLOR_ATTACHMENTS>& colorAttachmentUsages,
 						 TextureUsageBit depthStencilAttachmentUsage, U32 minx, U32 miny, U32 width, U32 height);
 
@@ -387,6 +370,11 @@ public:
 
 	void setLineWidth(F32 width);
 
+	void addReference(GrObjectPtr& ptr)
+	{
+		m_microCmdb->pushObjectRef(ptr);
+	}
+
 private:
 	StackAllocator<U8> m_alloc;
 

+ 1 - 7
anki/gr/vulkan/TextureImpl.cpp

@@ -38,15 +38,9 @@ TextureImpl::~TextureImpl()
 
 		if(it.m_bindlessIndices[1] != MAX_U32)
 		{
-			getGrManagerImpl().getDescriptorSetFactory().unbindBindlessTexture(it.m_bindlessIndices[1]);
+			getGrManagerImpl().getDescriptorSetFactory().unbindBindlessImage(it.m_bindlessIndices[1]);
 			it.m_bindlessIndices[1] = MAX_U32;
 		}
-
-		if(it.m_bindlessIndices[2] != MAX_U32)
-		{
-			getGrManagerImpl().getDescriptorSetFactory().unbindBindlessImage(it.m_bindlessIndices[2]);
-			it.m_bindlessIndices[2] = MAX_U32;
-		}
 	}
 
 	m_viewsMap.destroy(getAllocator());

+ 3 - 4
anki/gr/vulkan/TextureImpl.h

@@ -36,10 +36,9 @@ class MicroImageView
 public:
 	VkImageView m_handle = {};
 
-	/// Index 0: Sampled image with SHADER_READ_ONLY layout
-	/// Index 1: Sampled image with GENERAL layout
-	/// Index 2: Storage image with ofcource GENERAL layout.
-	mutable Array<U32, 3> m_bindlessIndices = {MAX_U32, MAX_U32, MAX_U32};
+	/// Index 0: Sampled image with SHADER_READ_ONLY layout.
+	/// Index 1: Storage image with ofcource GENERAL layout.
+	mutable Array<U32, 2> m_bindlessIndices = {MAX_U32, MAX_U32};
 
 	/// Protect the m_bindlessIndices.
 	mutable SpinLock m_lock;

+ 15 - 0
anki/gr/vulkan/TextureView.cpp

@@ -22,4 +22,19 @@ TextureView* TextureView::newInstance(GrManager* manager, const TextureViewInitI
 	return impl;
 }
 
+U32 TextureView::getOrCreateBindlessTextureIndex()
+{
+	ANKI_VK_SELF(TextureViewImpl);
+	ANKI_ASSERT(self.getTextureImpl().computeLayout(TextureUsageBit::ALL_SAMPLED, 0)
+				== VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+	return self.getOrCreateBindlessIndex(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, DescriptorType::TEXTURE);
+}
+
+U32 TextureView::getOrCreateBindlessImageIndex()
+{
+	ANKI_VK_SELF(TextureViewImpl);
+	ANKI_ASSERT(self.getTextureImpl().computeLayout(TextureUsageBit::ALL_IMAGE, 0) == VK_IMAGE_LAYOUT_GENERAL);
+	return self.getOrCreateBindlessIndex(VK_IMAGE_LAYOUT_GENERAL, DescriptorType::IMAGE);
+}
+
 } // end namespace anki

+ 5 - 1
anki/gr/vulkan/TextureViewImpl.cpp

@@ -45,10 +45,14 @@ U32 TextureViewImpl::getOrCreateBindlessIndex(VkImageLayout layout, DescriptorTy
 	{
 		ANKI_ASSERT(layout == VK_IMAGE_LAYOUT_GENERAL);
 	}
+	else
+	{
+		ANKI_ASSERT(layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+	}
 
 	ANKI_ASSERT(m_microImageView);
 
-	const U arrayIdx = (resourceType == DescriptorType::IMAGE) ? 2 : ((layout == VK_IMAGE_LAYOUT_GENERAL) ? 1 : 0);
+	const U32 arrayIdx = (resourceType == DescriptorType::IMAGE) ? 1 : 0;
 
 	LockGuard<SpinLock> lock(m_microImageView->m_lock);
 

+ 1 - 1
anki/resource/MaterialResource.h

@@ -311,7 +311,7 @@ private:
 ///		</mutation>]
 ///
 /// 	[<inputs>
-/// 		<input name="name" value="" />
+/// 		<input name="name" value="value" />
 /// 	</inputs>]
 /// </rtMaterial>]
 /// @endcode

+ 8 - 5
tests/gr/Gr.cpp

@@ -2162,7 +2162,7 @@ ANKI_TEST(Gr, Bindless)
 	texInit.m_width = 1;
 	texInit.m_height = 1;
 	texInit.m_format = Format::R32G32B32A32_UINT;
-	texInit.m_usage = TextureUsageBit::ALL_COMPUTE | TextureUsageBit::ALL_TRANSFER;
+	texInit.m_usage = TextureUsageBit::ALL_IMAGE | TextureUsageBit::ALL_TRANSFER | TextureUsageBit::ALL_SAMPLED;
 	texInit.m_mipmapCount = 1;
 
 	TexturePtr texA = gr->newTexture(texInit);
@@ -2191,7 +2191,7 @@ ANKI_TEST(Gr, Bindless)
 	static const char* PROG_SRC = R"(
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 
-ANKI_BINDLESS_SET(0)
+ANKI_BINDLESS_SET(0);
 
 layout(set = 1, binding = 0) writeonly buffer ss_
 {
@@ -2250,9 +2250,12 @@ void main()
 	cmdb->bindSampler(1, 1, sampler);
 	cmdb->bindShaderProgram(prog);
 
-	const U32 idx0 = cmdb->bindBindlessImage(viewA);
-	const U32 idx1 = cmdb->bindBindlessTexture(viewB, TextureUsageBit::SAMPLED_COMPUTE);
-	const U32 idx2 = cmdb->bindBindlessTexture(viewC, TextureUsageBit::SAMPLED_COMPUTE);
+	cmdb->addReference(viewA);
+	cmdb->addReference(viewB);
+	cmdb->addReference(viewC);
+	const U32 idx0 = viewA->getOrCreateBindlessImageIndex();
+	const U32 idx1 = viewB->getOrCreateBindlessTextureIndex();
+	const U32 idx2 = viewC->getOrCreateBindlessTextureIndex();
 	UVec4 pc(idx0, idx1, idx2, 0);
 	cmdb->setPushConstants(&pc, sizeof(pc));