Browse Source

Vulkan: Some work on bindings

Panagiotis Christopoulos Charitos 9 years ago
parent
commit
c6b5ac36e3

+ 0 - 2
src/anki/gr/vulkan/CommandBufferImpl.h

@@ -145,7 +145,6 @@ public:
 		commandCommon();
 		commandCommon();
 		U realBinding = MAX_TEXTURE_BINDINGS + binding;
 		U realBinding = MAX_TEXTURE_BINDINGS + binding;
 		m_dsetState[set].bindUniformBuffer(realBinding, buff.get(), offset, range);
 		m_dsetState[set].bindUniformBuffer(realBinding, buff.get(), offset, range);
-		m_dsetDirty.set(set);
 	}
 	}
 
 
 private:
 private:
@@ -166,7 +165,6 @@ private:
 	PipelineStateTracker m_state;
 	PipelineStateTracker m_state;
 
 
 	Array<DescriptorSetState, MAX_DESCRIPTOR_SETS> m_dsetState;
 	Array<DescriptorSetState, MAX_DESCRIPTOR_SETS> m_dsetState;
-	BitSet<MAX_DESCRIPTOR_SETS, U8> m_dsetDirty = {false};
 
 
 	/// @name cleanup_references
 	/// @name cleanup_references
 	/// @{
 	/// @{

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

@@ -455,6 +455,31 @@ inline void CommandBufferImpl::drawcallCommon()
 	}
 	}
 
 
 	// Bind dsets
 	// Bind dsets
+	for(U i = 0; i < MAX_DESCRIPTOR_SETS; ++i)
+	{
+		if(m_graphicsProg->getReflectionInfo().m_descriptorSetMask.get(i))
+		{
+			DescriptorSet dset;
+			Bool dirty;
+			getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(m_tid, m_dsetState[i], dset, dirty);
+
+			if(dirty)
+			{
+				VkDescriptorSet dsHandle = dset.getHandle();
+
+				ANKI_ASSERT(!"TODO set dynamic handles");
+				ANKI_CMD(vkCmdBindDescriptorSets(m_handle,
+							 VK_PIPELINE_BIND_POINT_GRAPHICS,
+							 m_graphicsProg->getPipelineLayout().getHandle(),
+							 i,
+							 1,
+							 &dsHandle,
+							 0,
+							 nullptr),
+					ANY_OTHER_COMMAND);
+			}
+		}
+	}
 
 
 	ANKI_TRACE_INC_COUNTER(GR_DRAWCALLS, 1);
 	ANKI_TRACE_INC_COUNTER(GR_DRAWCALLS, 1);
 }
 }

+ 57 - 27
src/anki/gr/vulkan/DescriptorSet.cpp

@@ -452,6 +452,50 @@ Error DSLayoutCacheEntry::getOrCreateThreadAllocator(ThreadId tid, DSThreadAlloc
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
+void DescriptorSetState::flush(Bool& stateDirty, U64& hash)
+{
+	// Get cache entry
+	ANKI_ASSERT(m_layout.m_entry);
+	DSLayoutCacheEntry& entry = *m_layout.m_entry;
+
+	// Early out if nothing happened
+	if(!m_anyBindingDirty && !m_layoutDirty)
+	{
+		stateDirty = false;
+		return;
+	}
+
+	m_anyBindingDirty = false;
+	m_layoutDirty = false;
+
+	// Compute the hash
+	Array<U64, MAX_BINDINGS_PER_DESCRIPTOR_SET> uuids;
+	U uuidCount = 0;
+
+	const U minBinding = entry.m_minBinding;
+	const U maxBinding = entry.m_maxBinding;
+	for(U i = minBinding; i <= maxBinding; ++i)
+	{
+		if(entry.m_activeBindings.get(i))
+		{
+			uuids[uuidCount++] = m_bindings[i].m_uuids[0];
+			uuids[uuidCount++] = m_bindings[i].m_uuids[1];
+		}
+	}
+
+	hash = computeHash(&uuids[0], uuidCount * sizeof(U64));
+
+	if(hash != m_lastHash)
+	{
+		m_lastHash = hash;
+		stateDirty = true;
+	}
+	else
+	{
+		stateDirty = false;
+	}
+}
+
 DescriptorSetFactory::~DescriptorSetFactory()
 DescriptorSetFactory::~DescriptorSetFactory()
 {
 {
 }
 }
@@ -498,14 +542,12 @@ Error DescriptorSetFactory::newDescriptorSetLayout(const DescriptorSetLayoutInit
 	LockGuard<SpinLock> lock(m_cachesMtx);
 	LockGuard<SpinLock> lock(m_cachesMtx);
 
 
 	DSLayoutCacheEntry* cache = nullptr;
 	DSLayoutCacheEntry* cache = nullptr;
-	U cacheIdx = MAX_U;
 	U count = 0;
 	U count = 0;
 	for(DSLayoutCacheEntry* it : m_caches)
 	for(DSLayoutCacheEntry* it : m_caches)
 	{
 	{
 		if(it->m_hash == hash)
 		if(it->m_hash == hash)
 		{
 		{
 			cache = it;
 			cache = it;
-			cacheIdx = count;
 			break;
 			break;
 		}
 		}
 		++count;
 		++count;
@@ -518,47 +560,35 @@ Error DescriptorSetFactory::newDescriptorSetLayout(const DescriptorSetLayoutInit
 
 
 		m_caches.resize(m_alloc, m_caches.getSize() + 1);
 		m_caches.resize(m_alloc, m_caches.getSize() + 1);
 		m_caches[m_caches.getSize() - 1] = cache;
 		m_caches[m_caches.getSize() - 1] = cache;
-		cacheIdx = m_caches.getSize() - 1;
 	}
 	}
 
 
 	// Set the layout
 	// Set the layout
 	layout.m_handle = cache->m_layoutHandle;
 	layout.m_handle = cache->m_layoutHandle;
-	layout.m_cacheEntryIdx = cacheIdx;
+	layout.m_entry = cache;
 
 
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
-Error DescriptorSetFactory::newDescriptorSet(ThreadId tid, const DescriptorSetState& init, DescriptorSet& set)
+Error DescriptorSetFactory::newDescriptorSet(ThreadId tid, DescriptorSetState& state, DescriptorSet& set, Bool& dirty)
 {
 {
-	// Get cache entry
-	m_cachesMtx.lock();
-	DSLayoutCacheEntry& entry = *m_caches[init.m_layout.m_cacheEntryIdx];
-	m_cachesMtx.unlock();
-
-	// Get thread allocator
-	DSThreadAllocator* alloc;
-	ANKI_CHECK(entry.getOrCreateThreadAllocator(tid, alloc));
-
-	// Compute the hash
-	Array<U64, MAX_BINDINGS_PER_DESCRIPTOR_SET> uuids;
-	U uuidCount = 0;
+	U64 hash;
+	state.flush(dirty, hash);
 
 
-	const U minBinding = entry.m_minBinding;
-	const U maxBinding = entry.m_maxBinding;
-	for(U i = minBinding; i <= maxBinding; ++i)
+	if(!dirty)
 	{
 	{
-		if(entry.m_activeBindings.get(i))
-		{
-			uuids[uuidCount++] = init.m_bindings[i].m_uuids[0];
-			uuids[uuidCount++] = init.m_bindings[i].m_uuids[1];
-		}
+		return ErrorCode::NONE;
 	}
 	}
 
 
-	U64 hash = computeHash(&uuids[0], uuidCount * sizeof(U64));
+	DescriptorSetLayout layout = state.m_layout;
+	DSLayoutCacheEntry& entry = *layout.m_entry;
+
+	// Get thread allocator
+	DSThreadAllocator* alloc;
+	ANKI_CHECK(entry.getOrCreateThreadAllocator(tid, alloc));
 
 
 	// Finally, allocate
 	// Finally, allocate
 	const DS* s;
 	const DS* s;
-	ANKI_CHECK(alloc->getOrCreateSet(hash, init.m_bindings, s));
+	ANKI_CHECK(alloc->getOrCreateSet(hash, state.m_bindings, s));
 	set.m_handle = s->m_handle;
 	set.m_handle = s->m_handle;
 	ANKI_ASSERT(set.m_handle != VK_NULL_HANDLE);
 	ANKI_ASSERT(set.m_handle != VK_NULL_HANDLE);
 
 

+ 20 - 2
src/anki/gr/vulkan/DescriptorSet.h

@@ -43,6 +43,7 @@ public:
 class DescriptorSetLayout
 class DescriptorSetLayout
 {
 {
 	friend class DescriptorSetFactory;
 	friend class DescriptorSetFactory;
+	friend class DescriptorSetState;
 
 
 public:
 public:
 	VkDescriptorSetLayout getHandle() const
 	VkDescriptorSetLayout getHandle() const
@@ -58,7 +59,7 @@ public:
 
 
 private:
 private:
 	VkDescriptorSetLayout m_handle = VK_NULL_HANDLE;
 	VkDescriptorSetLayout m_handle = VK_NULL_HANDLE;
-	U32 m_cacheEntryIdx = MAX_U32;
+	DSLayoutCacheEntry* m_entry = nullptr;
 };
 };
 
 
 class TextureBinding
 class TextureBinding
@@ -116,6 +117,8 @@ public:
 		m_bindings[binding].m_tex.m_sampler = tex->m_impl->m_sampler->m_impl.get();
 		m_bindings[binding].m_tex.m_sampler = tex->m_impl->m_sampler->m_impl.get();
 		m_bindings[binding].m_tex.m_aspect = aspect;
 		m_bindings[binding].m_tex.m_aspect = aspect;
 		m_bindings[binding].m_tex.m_layout = layout;
 		m_bindings[binding].m_tex.m_layout = layout;
+
+		m_anyBindingDirty = true;
 	}
 	}
 
 
 	void bindTextureAndSampler(
 	void bindTextureAndSampler(
@@ -129,6 +132,8 @@ public:
 		m_bindings[binding].m_tex.m_sampler = sampler->m_impl.get();
 		m_bindings[binding].m_tex.m_sampler = sampler->m_impl.get();
 		m_bindings[binding].m_tex.m_aspect = aspect;
 		m_bindings[binding].m_tex.m_aspect = aspect;
 		m_bindings[binding].m_tex.m_layout = layout;
 		m_bindings[binding].m_tex.m_layout = layout;
+
+		m_anyBindingDirty = true;
 	}
 	}
 
 
 	void bindUniformBuffer(U binding, Buffer* buff, PtrSize offset, PtrSize range)
 	void bindUniformBuffer(U binding, Buffer* buff, PtrSize offset, PtrSize range)
@@ -139,6 +144,8 @@ public:
 		m_bindings[binding].m_buff.m_buff = buff->m_impl.get();
 		m_bindings[binding].m_buff.m_buff = buff->m_impl.get();
 		m_bindings[binding].m_buff.m_offset = offset;
 		m_bindings[binding].m_buff.m_offset = offset;
 		m_bindings[binding].m_buff.m_range = range;
 		m_bindings[binding].m_buff.m_range = range;
+
+		m_anyBindingDirty = true;
 	}
 	}
 
 
 	void bindStorageBuffer(U binding, Buffer* buff, PtrSize offset, PtrSize range)
 	void bindStorageBuffer(U binding, Buffer* buff, PtrSize offset, PtrSize range)
@@ -149,6 +156,8 @@ public:
 		m_bindings[binding].m_buff.m_buff = buff->m_impl.get();
 		m_bindings[binding].m_buff.m_buff = buff->m_impl.get();
 		m_bindings[binding].m_buff.m_offset = offset;
 		m_bindings[binding].m_buff.m_offset = offset;
 		m_bindings[binding].m_buff.m_range = range;
 		m_bindings[binding].m_buff.m_range = range;
+
+		m_anyBindingDirty = true;
 	}
 	}
 
 
 	void bindImage(U binding, Texture* tex, U32 level)
 	void bindImage(U binding, Texture* tex, U32 level)
@@ -158,12 +167,21 @@ public:
 
 
 		m_bindings[binding].m_image.m_tex = tex->m_impl.get();
 		m_bindings[binding].m_image.m_tex = tex->m_impl.get();
 		m_bindings[binding].m_image.m_level = level;
 		m_bindings[binding].m_image.m_level = level;
+
+		m_anyBindingDirty = true;
 	}
 	}
 
 
 private:
 private:
 	DescriptorSetLayout m_layout;
 	DescriptorSetLayout m_layout;
 
 
 	Array<AnyBinding, MAX_BINDINGS_PER_DESCRIPTOR_SET> m_bindings;
 	Array<AnyBinding, MAX_BINDINGS_PER_DESCRIPTOR_SET> m_bindings;
+
+	Bool8 m_anyBindingDirty = false;
+	Bool8 m_layoutDirty = false;
+	U64 m_lastHash = 0;
+
+	/// Only DescriptorSetFactory should call this.
+	void flush(Bool& stateDirty, U64& hash);
 };
 };
 
 
 /// Descriptor set thin wraper.
 /// Descriptor set thin wraper.
@@ -200,7 +218,7 @@ public:
 	ANKI_USE_RESULT Error newDescriptorSetLayout(const DescriptorSetLayoutInitInfo& init, DescriptorSetLayout& layout);
 	ANKI_USE_RESULT Error newDescriptorSetLayout(const DescriptorSetLayoutInitInfo& init, DescriptorSetLayout& layout);
 
 
 	/// @note Obviously not thread-safe.
 	/// @note Obviously not thread-safe.
-	ANKI_USE_RESULT Error newDescriptorSet(ThreadId tid, const DescriptorSetState& init, DescriptorSet& set);
+	ANKI_USE_RESULT Error newDescriptorSet(ThreadId tid, DescriptorSetState& state, DescriptorSet& set, Bool& dirty);
 
 
 	void endFrame()
 	void endFrame()
 	{
 	{

+ 2 - 0
src/anki/gr/vulkan/GrManagerImpl.cpp

@@ -595,6 +595,8 @@ void GrManagerImpl::endFrame()
 	ANKI_VK_CHECKF(vkQueuePresentKHR(m_queue, &present));
 	ANKI_VK_CHECKF(vkQueuePresentKHR(m_queue, &present));
 	ANKI_VK_CHECKF(res);
 	ANKI_VK_CHECKF(res);
 
 
+	m_descrFactory.endFrame();
+
 	// Finalize
 	// Finalize
 	++m_frame;
 	++m_frame;
 }
 }

+ 2 - 0
src/anki/util/Hash.cpp

@@ -4,6 +4,7 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include <anki/util/Hash.h>
 #include <anki/util/Hash.h>
+#include <anki/util/Assert.h>
 
 
 namespace anki
 namespace anki
 {
 {
@@ -53,6 +54,7 @@ U64 appendHash(const void* buffer, U32 bufferSize, U64 h)
 	h *= HASH_M;
 	h *= HASH_M;
 	h ^= h >> HASH_R;
 	h ^= h >> HASH_R;
 
 
+	ANKI_ASSERT(h != 0);
 	return h;
 	return h;
 }
 }