Browse Source

Vulkan: Adding some last bits in the uniform buffers

Panagiotis Christopoulos Charitos 9 years ago
parent
commit
5ee3a37711

+ 1 - 1
include/anki/gr/ResourceGroup.h

@@ -30,7 +30,7 @@ class BufferBinding
 public:
 	BufferPtr m_buffer;
 	PtrSize m_offset = 0;
-	PtrSize m_range = 0;
+	PtrSize m_range = 0; ///< If zero it means the whole buffer.
 	Bool m_uploadedMemory = false;
 };
 

+ 2 - 1
include/anki/gr/vulkan/CommandBufferImpl.inl.h

@@ -150,7 +150,8 @@ inline void CommandBufferImpl::uploadTextureSurface(TexturePtr tex,
 	region.bufferRowLength = 0;
 
 	vkCmdCopyBufferToImage(m_handle,
-		getGrManagerImpl().getTransientMemoryManager().getBufferHandle(token),
+		getGrManagerImpl().getTransientMemoryManager().getBufferHandle(
+			token.m_usage),
 		impl.m_imageHandle,
 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
 		1,

+ 9 - 0
include/anki/gr/vulkan/ResourceGroupImpl.h

@@ -6,6 +6,7 @@
 #pragma once
 
 #include <anki/gr/vulkan/VulkanObject.h>
+#include <anki/util/BitSet.h>
 
 namespace anki
 {
@@ -46,12 +47,20 @@ public:
 		bindingCount = m_bindingCount;
 	}
 
+	void setupDynamicOffsets(
+		const TransientMemoryInfo* dynInfo, U32 dynOffsets[]) const;
+
 private:
 	VkDescriptorSet m_handle = VK_NULL_HANDLE;
 	Array<VkBuffer, MAX_VERTEX_ATTRIBUTES> m_vertBuffs = {{}};
 	Array<VkDeviceSize, MAX_VERTEX_ATTRIBUTES> m_offsets = {{}};
 	U32 m_bindingCount = 0;
 
+	// For dynamic binding
+	U8 m_uniBindingCount = 0;
+	BitSet<MAX_UNIFORM_BUFFER_BINDINGS + MAX_STORAGE_BUFFER_BINDINGS>
+		m_dynamicBuffersMask = {false};
+
 	/// Holds the references to the resources. Used to release the references
 	/// gracefully
 	DynamicArray<GrObjectPtr<GrObject>> m_refs;

+ 2 - 4
include/anki/gr/vulkan/TransientMemoryManager.h

@@ -54,11 +54,9 @@ public:
 		return addr;
 	}
 
-	VkBuffer getBufferHandle(const TransientMemoryToken& token) const
+	VkBuffer getBufferHandle(BufferUsage usage) const
 	{
-		ANKI_ASSERT(
-			token.m_lifetime == TransientMemoryTokenLifetime::PER_FRAME);
-		const PerFrameBuffer& frame = m_perFrameBuffers[token.m_usage];
+		const PerFrameBuffer& frame = m_perFrameBuffers[usage];
 		ANKI_ASSERT(frame.m_bufferHandle);
 		return frame.m_bufferHandle;
 	}

+ 2 - 0
src/gr/vulkan/CommandBufferImpl.cpp

@@ -241,6 +241,8 @@ void CommandBufferImpl::bindResourceGroup(
 		Array<U32, MAX_UNIFORM_BUFFER_BINDINGS + MAX_STORAGE_BUFFER_BINDINGS>
 			dynOffsets = {{}};
 
+		impl.setupDynamicOffsets(dynInfo, &dynOffsets[0]);
+
 		VkDescriptorSet dset = impl.getHandle();
 		vkCmdBindDescriptorSets(m_handle,
 			VK_PIPELINE_BIND_POINT_GRAPHICS,

+ 1 - 1
src/gr/vulkan/GrManagerImpl.cpp

@@ -87,7 +87,7 @@ GrManagerImpl::~GrManagerImpl()
 		vkQueueWaitIdle(m_queue);
 		m_queue = VK_NULL_HANDLE;
 	}
-	
+
 	// SECOND THING: The destroy everything that has a reference to GrObjects.
 	for(auto& x : m_perFrame)
 	{

+ 44 - 1
src/gr/vulkan/ResourceGroupImpl.cpp

@@ -156,12 +156,26 @@ Error ResourceGroupImpl::init(const ResourceGroupInitInfo& init)
 							 .getHandle();
 			inf.offset = init.m_uniformBuffers[i].m_offset;
 			inf.range = init.m_uniformBuffers[i].m_range;
+			if(inf.range == 0)
+			{
+				inf.range = VK_WHOLE_SIZE;
+			}
 
 			m_refs[refCount++] = init.m_uniformBuffers[i].m_buffer;
+
+			m_uniBindingCount = i + 1;
 		}
 		else if(init.m_uniformBuffers[i].m_uploadedMemory)
 		{
-			ANKI_ASSERT(0 && "TODO");
+			VkDescriptorBufferInfo& inf = unis[uniCount++];
+			inf.buffer =
+				getGrManagerImpl().getTransientMemoryManager().getBufferHandle(
+					BufferUsage::UNIFORM);
+			inf.range = VK_WHOLE_SIZE;
+
+			m_dynamicBuffersMask.set(i);
+
+			m_uniBindingCount = i + 1;
 		}
 	}
 
@@ -181,6 +195,8 @@ Error ResourceGroupImpl::init(const ResourceGroupInitInfo& init)
 		w.dstSet = m_handle;
 	}
 
+	// TODO Storage buffers
+
 	// Check if it was created. It's not created only if the rc group contains
 	// only vertex info.
 	if(m_handle)
@@ -216,4 +232,31 @@ Error ResourceGroupImpl::init(const ResourceGroupInitInfo& init)
 	return ErrorCode::NONE;
 }
 
+//==============================================================================
+void ResourceGroupImpl::setupDynamicOffsets(
+	const TransientMemoryInfo* dynInfo, U32 dynOffsets[]) const
+{
+	if(m_dynamicBuffersMask.getAny())
+	{
+		// Has at least one uploaded buffer
+
+		ANKI_ASSERT(
+			dynInfo && "Need to provide dynInfo if there are uploaded buffers");
+
+		for(U i = 0; i < m_uniBindingCount; ++i)
+		{
+			if(m_dynamicBuffersMask.get(i))
+			{
+				// Uploaded
+				const TransientMemoryToken& token =
+					dynInfo->m_uniformBuffers[i];
+
+				ANKI_ASSERT(token.m_range);
+				ANKI_ASSERT(token.m_usage == BufferUsage::UNIFORM);
+				dynOffsets[i] = token.m_offset;
+			}
+		}
+	}
+}
+
 } // end namespace anki

+ 37 - 10
tests/gr/Gr.cpp

@@ -43,16 +43,25 @@ layout(ANKI_UBO_BINDING(0, 0)) uniform u0_
 	vec4 u_color[3];
 };
 
-out vec3 out_color;
+layout(ANKI_UBO_BINDING(0, 1)) uniform u1_
+{
+	vec4 u_rotation2d;
+};
+
+layout(location = 0) out vec3 out_color;
 
 void main()
 {
+	out_color = u_color[gl_VertexID].rgb;
+
 	const vec2 POSITIONS[3] =
 		vec2[](vec2(-1.0, 1.0), vec2(0.0, -1.0), vec2(1.0, 1.0));
 		
-	out_color = u_color[gl_VertexID].rgb;
+	mat2 rot = mat2(
+		u_rotation2d.x, u_rotation2d.y, u_rotation2d.z, u_rotation2d.w);
+	vec2 pos = rot * POSITIONS[gl_VertexID % 3];
 
-	gl_Position = vec4(POSITIONS[gl_VertexID % 3], 0.0, 1.0);
+	gl_Position = vec4(pos, 0.0, 1.0);
 #if defined(ANKI_VK)
 	gl_Position.y = -gl_Position.y;
 #endif
@@ -250,7 +259,7 @@ ANKI_TEST(Gr, SimpleDrawcall)
 		FramebufferPtr fb = createDefaultFb(*gr);
 
 		U iterations = 100;
-		while(--iterations)
+		while(iterations--)
 		{
 			HighRezTimer timer;
 			timer.start();
@@ -338,7 +347,7 @@ ANKI_TEST(Gr, DrawWithUniforms)
 	COMMON_BEGIN();
 
 	{
-		// The buffer
+		// A non-uploaded buffer
 		BufferPtr b = gr->newInstance<Buffer>(sizeof(Vec4) * 3,
 			BufferUsageBit::UNIFORM,
 			BufferAccessBit::CLIENT_MAP_WRITE);
@@ -354,6 +363,7 @@ ANKI_TEST(Gr, DrawWithUniforms)
 		// Resource group
 		ResourceGroupInitInfo rcinit;
 		rcinit.m_uniformBuffers[0].m_buffer = b;
+		rcinit.m_uniformBuffers[1].m_uploadedMemory = true;
 		ResourceGroupPtr rc = gr->newInstance<ResourceGroup>(rcinit);
 
 		// Ppline
@@ -363,12 +373,29 @@ ANKI_TEST(Gr, DrawWithUniforms)
 		// FB
 		FramebufferPtr fb = createDefaultFb(*gr);
 
-		U iterations = 100;
-		while(--iterations)
+		const U ITERATION_COUNT = 100;
+		U iterations = ITERATION_COUNT;
+		while(iterations--)
 		{
 			HighRezTimer timer;
 			timer.start();
 
+			// Uploaded buffer
+			TransientMemoryInfo transientInfo;
+			Error err = ErrorCode::NONE;
+			Vec4* rotMat = static_cast<Vec4*>(
+				gr->allocateFrameTransientMemory(sizeof(Vec4),
+					BufferUsage::UNIFORM,
+					transientInfo.m_uniformBuffers[1],
+					&err));
+			ANKI_TEST_EXPECT_NO_ERR(err);
+			F32 angle = toRad(360.0f / ITERATION_COUNT * iterations);
+			(*rotMat)[0] = cos(angle);
+			(*rotMat)[1] = -sin(angle);
+			(*rotMat)[2] = sin(angle);
+			(*rotMat)[3] = cos(angle);
+
+			// Start drawing
 			gr->beginFrame();
 
 			CommandBufferInitInfo cinit;
@@ -380,7 +407,7 @@ ANKI_TEST(Gr, DrawWithUniforms)
 			cmdb->setPolygonOffset(0.0, 0.0);
 			cmdb->bindPipeline(ppline);
 			cmdb->beginRenderPass(fb);
-			cmdb->bindResourceGroup(rc, 0, nullptr);
+			cmdb->bindResourceGroup(rc, 0, &transientInfo);
 			cmdb->drawArrays(3);
 			cmdb->endRenderPass();
 			cmdb->flush();
@@ -482,7 +509,7 @@ ANKI_TEST(Gr, DrawWithVertex)
 		FramebufferPtr fb = createDefaultFb(*gr);
 
 		U iterations = 100;
-		while(--iterations)
+		while(iterations--)
 		{
 			HighRezTimer timer;
 			timer.start();
@@ -663,7 +690,7 @@ ANKI_TEST(Gr, DrawWithTexture)
 		// Draw
 		//
 		U iterations = 100;
-		while(--iterations)
+		while(iterations--)
 		{
 			HighRezTimer timer;
 			timer.start();