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

1st step towards render queue. Move uniform updates in the render component

Panagiotis Christopoulos Charitos 8 лет назад
Родитель
Сommit
cb0455833e

+ 0 - 2
src/anki/core/App.cpp

@@ -282,8 +282,6 @@ Error App::initInternal(const ConfigSet& config_, AllocAlignedCallback allocCb,
 	ANKI_CHECK(m_renderer->create(
 		m_threadpool, m_resources, m_gr, m_stagingMem, m_allocCb, m_allocCbData, config, &m_globalTimestamp));
 
-	m_resources->_setShadersPrependedSource(m_renderer->getMaterialShaderSource().toCString());
-
 	//
 	// Scene
 	//

+ 12 - 160
src/anki/renderer/Drawer.cpp

@@ -151,166 +151,18 @@ RenderableDrawer::~RenderableDrawer()
 
 void RenderableDrawer::setupUniforms(DrawContext& ctx, CompleteRenderingBuildInfo& build)
 {
-	const Material& mtl = build.m_rc->getMaterial();
-	const MaterialVariant& variant = mtl.getOrCreateVariant(build.m_in.m_key);
-	const ShaderProgramResourceVariant& progVariant = variant.getShaderProgramResourceVariant();
-
-	const U cachedTrfs = ctx.m_cachedTrfCount;
-	ANKI_ASSERT(cachedTrfs <= MAX_INSTANCES);
-
-	// Get some memory for uniforms
-	U8* uniforms = static_cast<U8*>(m_r->getStagingGpuMemoryManager().allocateFrame(
-		variant.getUniformBlockSize(), StagingGpuMemoryType::UNIFORM, ctx.m_uboToken));
-	void* const uniformsBegin = uniforms;
-	const void* const uniformsEnd = uniforms + variant.getUniformBlockSize();
-
-	// Iterate variables
-	for(auto it = build.m_rc->getVariablesBegin(); it != build.m_rc->getVariablesEnd(); ++it)
-	{
-		const RenderComponentVariable& var = *it;
-		const MaterialVariable& mvar = var.getMaterialVariable();
-		const ShaderProgramResourceInputVariable& progvar = mvar.getShaderProgramResourceInputVariable();
-
-		if(!variant.variableActive(mvar))
-		{
-			continue;
-		}
-
-		switch(progvar.getShaderVariableDataType())
-		{
-		case ShaderVariableDataType::FLOAT:
-		{
-			F32 val = mvar.getValue<F32>();
-			progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
-			break;
-		}
-		case ShaderVariableDataType::VEC2:
-		{
-			Vec2 val = mvar.getValue<Vec2>();
-			progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
-			break;
-		}
-		case ShaderVariableDataType::VEC3:
-		{
-			Vec3 val = mvar.getValue<Vec3>();
-			progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
-			break;
-		}
-		case ShaderVariableDataType::VEC4:
-		{
-			Vec4 val = mvar.getValue<Vec4>();
-			progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
-			break;
-		}
-		case ShaderVariableDataType::MAT3:
-		{
-			switch(mvar.getBuiltin())
-			{
-			case BuiltinMaterialVariableId::NONE:
-			{
-				Mat3 val = mvar.getValue<Mat3>();
-				progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
-				break;
-			}
-			case BuiltinMaterialVariableId::NORMAL_MATRIX:
-			{
-				ANKI_ASSERT(cachedTrfs > 0);
-
-				DynamicArrayAuto<Mat3> normMats(m_r->getFrameAllocator());
-				normMats.create(cachedTrfs);
-
-				for(U i = 0; i < cachedTrfs; i++)
-				{
-					Mat4 mv = ctx.m_viewMat * ctx.m_cachedTrfs[i];
-					normMats[i] = mv.getRotationPart();
-					normMats[i].reorthogonalize();
-				}
-
-				progVariant.writeShaderBlockMemory(progvar, &normMats[0], cachedTrfs, uniformsBegin, uniformsEnd);
-				break;
-			}
-			case BuiltinMaterialVariableId::CAMERA_ROTATION_MATRIX:
-			{
-				Mat3 rot = ctx.m_viewMat.getRotationPart().getTransposed();
-				progVariant.writeShaderBlockMemory(progvar, &rot, 1, uniformsBegin, uniformsEnd);
-				break;
-			}
-			default:
-				ANKI_ASSERT(0);
-			}
-
-			break;
-		}
-		case ShaderVariableDataType::MAT4:
-		{
-			switch(mvar.getBuiltin())
-			{
-			case BuiltinMaterialVariableId::NONE:
-			{
-				Mat4 val = mvar.getValue<Mat4>();
-				progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
-				break;
-			}
-			case BuiltinMaterialVariableId::MODEL_VIEW_PROJECTION_MATRIX:
-			{
-				ANKI_ASSERT(cachedTrfs > 0);
-
-				DynamicArrayAuto<Mat4> mvp(m_r->getFrameAllocator());
-				mvp.create(cachedTrfs);
-
-				for(U i = 0; i < cachedTrfs; i++)
-				{
-					mvp[i] = ctx.m_viewProjMat * ctx.m_cachedTrfs[i];
-				}
-
-				progVariant.writeShaderBlockMemory(progvar, &mvp[0], cachedTrfs, uniformsBegin, uniformsEnd);
-				break;
-			}
-			case BuiltinMaterialVariableId::MODEL_VIEW_MATRIX:
-			{
-				ANKI_ASSERT(cachedTrfs > 0);
-
-				DynamicArrayAuto<Mat4> mv(m_r->getFrameAllocator());
-				mv.create(cachedTrfs);
-
-				for(U i = 0; i < cachedTrfs; i++)
-				{
-					mv[i] = ctx.m_viewMat * ctx.m_cachedTrfs[i];
-				}
-
-				progVariant.writeShaderBlockMemory(progvar, &mv[0], cachedTrfs, uniformsBegin, uniformsEnd);
-				break;
-			}
-			case BuiltinMaterialVariableId::VIEW_PROJECTION_MATRIX:
-			{
-				ANKI_ASSERT(cachedTrfs == 0 && "Cannot have transform");
-				progVariant.writeShaderBlockMemory(progvar, &ctx.m_viewProjMat, 1, uniformsBegin, uniformsEnd);
-				break;
-			}
-			case BuiltinMaterialVariableId::VIEW_MATRIX:
-			{
-				progVariant.writeShaderBlockMemory(progvar, &ctx.m_viewMat, 1, uniformsBegin, uniformsEnd);
-				break;
-			}
-			default:
-				ANKI_ASSERT(0);
-			}
-
-			break;
-		}
-		case ShaderVariableDataType::SAMPLER_2D:
-		case ShaderVariableDataType::SAMPLER_2D_ARRAY:
-		case ShaderVariableDataType::SAMPLER_3D:
-		case ShaderVariableDataType::SAMPLER_CUBE:
-		{
-			ctx.m_cmdb->bindTexture(
-				0, progVariant.getTextureUnit(progvar), mvar.getValue<TextureResourcePtr>()->getGrTexture());
-			break;
-		}
-		default:
-			ANKI_ASSERT(0);
-		} // end switch
-	}
+	RenderQueueDrawContext dctx;
+	dctx.m_cameraTransform = ctx.m_viewMat.getInverse();
+	dctx.m_cmdb = ctx.m_cmdb;
+	dctx.m_key = build.m_in.m_key;
+	dctx.m_projectionMatrix = Mat4::getIdentity();
+	dctx.m_viewMatrix = ctx.m_viewMat;
+	dctx.m_viewProjectionMatrix = ctx.m_viewProjMat;
+
+	build.m_rc->allocateAndSetupUniforms(dctx,
+		WeakArray<const Mat4>(&ctx.m_cachedTrfs[0], ctx.m_cachedTrfCount),
+		m_r->getStagingGpuMemoryManager(),
+		ctx.m_uboToken);
 }
 
 Error RenderableDrawer::drawRange(Pass pass,

+ 0 - 8
src/anki/renderer/MainRenderer.cpp

@@ -29,7 +29,6 @@ MainRenderer::MainRenderer()
 MainRenderer::~MainRenderer()
 {
 	ANKI_R_LOGI("Destroying main renderer");
-	m_materialShaderSource.destroy(m_alloc);
 }
 
 Error MainRenderer::create(ThreadPool* threadpool,
@@ -68,13 +67,6 @@ Error MainRenderer::create(ThreadPool* threadpool,
 	ANKI_CHECK(m_r->init(
 		threadpool, resources, gr, stagingMem, m_alloc, m_frameAlloc, config2, globTimestamp, m_rDrawToDefaultFb));
 
-	// Set the default preprocessor string
-	m_materialShaderSource.sprintf(m_alloc,
-		"#define ANKI_RENDERER_WIDTH %u\n"
-		"#define ANKI_RENDERER_HEIGHT %u\n",
-		m_r->getWidth(),
-		m_r->getHeight());
-
 	// Init other
 	if(!m_rDrawToDefaultFb)
 	{

+ 0 - 7
src/anki/renderer/MainRenderer.h

@@ -42,11 +42,6 @@ public:
 
 	ANKI_USE_RESULT Error render(SceneGraph& scene);
 
-	const String& getMaterialShaderSource() const
-	{
-		return m_materialShaderSource;
-	}
-
 	Dbg& getDbg();
 
 	F32 getAspectRatio() const;
@@ -75,8 +70,6 @@ private:
 	U32 m_width = 0; ///< Default FB size.
 	U32 m_height = 0; ///< Default FB size.
 
-	String m_materialShaderSource; ///< String to append in user shaders
-
 	F32 m_renderingQuality = 1.0;
 
 	/// Optimize job chain

+ 3 - 4
src/anki/renderer/RenderQueue.h

@@ -41,13 +41,12 @@ public:
 class RenderQueueDrawContext final : public RenderingMatrices
 {
 public:
-	U8 m_lod;
-	Pass m_pass;
+	RenderingKey m_key;
 	CommandBufferPtr m_cmdb;
 };
 
 /// Draw callback.
-using RenderQueueElementDrawCallback = void(*)(
+using RenderQueueElementDrawCallback = void (*)(
 	const RenderQueueDrawContext& ctx, RenderQueueElement* elements, U elementCount);
 
 class RenderQueueElement final
@@ -167,7 +166,7 @@ inline void TRenderQueue<T>::mergeBack(StackAllocator<T> alloc, TRenderQueue& b)
 }
 
 /// The combination of all the results.
-class VisibilityTestResults
+class CombinedRenderQueues
 {
 public:
 	RenderQueue m_renderables; ///< Deferred shading or shadow renderables.

+ 19 - 0
src/anki/resource/Common.cpp

@@ -4,10 +4,29 @@
 // http://www.anki3d.org/LICENSE
 
 #include <anki/resource/Common.h>
+#include <anki/Resource.h>
 
 namespace anki
 {
 
+// Instan
+
+template<typename T>
+void ResourcePtrDeleter<T>::operator()(T* ptr)
+{
+	ptr->getManager().unregisterResource(ptr);
+	auto alloc = ptr->getAllocator();
+	alloc.deleteInstance(ptr);
+}
+
+#define ANKI_INSTANTIATE_RESOURCE(rsrc_, ptr_) template void ResourcePtrDeleter<rsrc_>::operator()(rsrc_* ptr);
+
+#define ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+
+#include <anki/resource/InstantiationMacros.h>
+#undef ANKI_INSTANTIATE_RESOURCE
+#undef ANKI_INSTANSIATE_RESOURCE_DELIMITER
+
 const CString& shaderTypeToFileExtension(ShaderType type)
 {
 	static const Array<CString, U(ShaderType::COUNT)> mapping = {

+ 8 - 24
src/anki/resource/Common.h

@@ -46,12 +46,7 @@ template<typename T>
 class ResourcePtrDeleter
 {
 public:
-	void operator()(T* ptr)
-	{
-		ptr->getManager().unregisterResource(ptr);
-		auto alloc = ptr->getAllocator();
-		alloc.deleteInstance(ptr);
-	}
+	void operator()(T* ptr);
 };
 
 /// Smart pointer for resources.
@@ -59,26 +54,15 @@ template<typename T>
 using ResourcePtr = IntrusivePtr<T, ResourcePtrDeleter<T>>;
 
 // NOTE: Add resources in 3 places
-#define ANKI_FORWARD(rsrc_, name_) \
-	class rsrc_;                   \
+#define ANKI_INSTANTIATE_RESOURCE(rsrc_, name_) \
+	class rsrc_;                                \
 	using name_ = ResourcePtr<rsrc_>;
 
-ANKI_FORWARD(Animation, AnimationResourcePtr)
-ANKI_FORWARD(TextureResource, TextureResourcePtr)
-ANKI_FORWARD(ShaderResource, ShaderResourcePtr)
-ANKI_FORWARD(Material, MaterialResourcePtr)
-ANKI_FORWARD(Mesh, MeshResourcePtr)
-ANKI_FORWARD(Skeleton, SkeletonResourcePtr)
-ANKI_FORWARD(ParticleEmitterResource, ParticleEmitterResourcePtr)
-ANKI_FORWARD(Model, ModelResourcePtr)
-ANKI_FORWARD(Script, ScriptResourcePtr)
-ANKI_FORWARD(DummyRsrc, DummyResourcePtr)
-ANKI_FORWARD(CollisionResource, CollisionResourcePtr)
-ANKI_FORWARD(GenericResource, GenericResourcePtr)
-ANKI_FORWARD(TextureAtlas, TextureAtlasResourcePtr)
-ANKI_FORWARD(ShaderProgramResource, ShaderProgramResourcePtr)
-
-#undef ANKI_FORWARD
+#define ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+
+#include <anki/resource/InstantiationMacros.h>
+#undef ANKI_INSTANTIATE_RESOURCE
+#undef ANKI_INSTANSIATE_RESOURCE_DELIMITER
 
 template<typename T>
 using ResourceAllocator = HeapAllocator<T>;

+ 34 - 0
src/anki/resource/InstantiationMacros.h

@@ -0,0 +1,34 @@
+// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+// An awful trick to instantiate stuff with the resource type
+
+ANKI_INSTANTIATE_RESOURCE(Animation, AnimationResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(TextureResource, TextureResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(ShaderResource, ShaderResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(Material, MaterialResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(Mesh, MeshResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(Skeleton, SkeletonResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(ParticleEmitterResource, ParticleEmitterResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(Model, ModelResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(Script, ScriptResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(DummyRsrc, DummyResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(CollisionResource, CollisionResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(GenericResource, GenericResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(TextureAtlas, TextureAtlasResourcePtr)
+ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+ANKI_INSTANTIATE_RESOURCE(ShaderProgramResource, ShaderProgramResourcePtr)

+ 1 - 1
src/anki/resource/Model.cpp

@@ -95,7 +95,7 @@ void ModelPatch::getRenderingDataSub(
 
 U ModelPatch::getLodCount() const
 {
-	return max<U>(m_meshCount, getMaterial().getLodCount());
+	return max<U>(m_meshCount, getMaterial()->getLodCount());
 }
 
 Error ModelPatch::create(WeakArray<CString> meshFNames, const CString& mtlFName, ResourceManager* manager)

+ 2 - 2
src/anki/resource/Model.h

@@ -84,9 +84,9 @@ public:
 
 	~ModelPatch();
 
-	const Material& getMaterial() const
+	MaterialResourcePtr getMaterial() const
 	{
-		return *m_mtl;
+		return m_mtl;
 	}
 
 	const Mesh& getMesh(const RenderingKey& key) const

+ 2 - 7
src/anki/resource/ParticleEmitterResource.h

@@ -106,14 +106,9 @@ public:
 		return *this;
 	}
 
-	const Material& getMaterial() const
+	MaterialResourcePtr getMaterial() const
 	{
-		return *m_material;
-	}
-
-	Material& getMaterial()
-	{
-		return *m_material;
+		return m_material;
 	}
 
 	/// Get program for rendering.

+ 7 - 19
src/anki/resource/ResourceManager.cpp

@@ -30,7 +30,6 @@ ResourceManager::ResourceManager()
 ResourceManager::~ResourceManager()
 {
 	m_cacheDir.destroy(m_alloc);
-	m_shadersPrependedSource.destroy(m_alloc);
 	m_alloc.deleteInstance(m_asyncLoader);
 	m_transferGpuAlloc.destroy();
 }
@@ -53,24 +52,13 @@ Error ResourceManager::init(ResourceManagerInitInfo& init)
 
 // Init type resource managers
 //
-#define ANKI_RESOURCE(type_) TypeResourceManager<type_>::init(m_alloc);
-
-	ANKI_RESOURCE(Animation)
-	ANKI_RESOURCE(TextureResource)
-	ANKI_RESOURCE(ShaderResource)
-	ANKI_RESOURCE(Material)
-	ANKI_RESOURCE(Mesh)
-	ANKI_RESOURCE(Skeleton)
-	ANKI_RESOURCE(ParticleEmitterResource)
-	ANKI_RESOURCE(Model)
-	ANKI_RESOURCE(Script)
-	ANKI_RESOURCE(DummyRsrc)
-	ANKI_RESOURCE(CollisionResource)
-	ANKI_RESOURCE(GenericResource)
-	ANKI_RESOURCE(TextureAtlas)
-	ANKI_RESOURCE(ShaderProgramResource)
-
-#undef ANKI_RESOURCE
+#define ANKI_INSTANTIATE_RESOURCE(rsrc_, ptr_) TypeResourceManager<rsrc_>::init(m_alloc);
+
+#define ANKI_INSTANSIATE_RESOURCE_DELIMITER()
+
+#include <anki/resource/InstantiationMacros.h>
+#undef ANKI_INSTANTIATE_RESOURCE
+#undef ANKI_INSTANSIATE_RESOURCE_DELIMITER
 
 	// Init the thread
 	m_asyncLoader = m_alloc.newInstance<AsyncLoader>();

+ 13 - 27
src/anki/resource/ResourceManager.h

@@ -101,20 +101,18 @@ public:
 };
 
 /// Resource manager. It holds a few global variables
-class ResourceManager : public TypeResourceManager<Animation>,
-						public TypeResourceManager<TextureResource>,
-						public TypeResourceManager<ShaderResource>,
-						public TypeResourceManager<Material>,
-						public TypeResourceManager<Mesh>,
-						public TypeResourceManager<Skeleton>,
-						public TypeResourceManager<ParticleEmitterResource>,
-						public TypeResourceManager<Model>,
-						public TypeResourceManager<Script>,
-						public TypeResourceManager<DummyRsrc>,
-						public TypeResourceManager<CollisionResource>,
-						public TypeResourceManager<GenericResource>,
-						public TypeResourceManager<TextureAtlas>,
-						public TypeResourceManager<ShaderProgramResource>
+class ResourceManager:
+
+#define ANKI_INSTANTIATE_RESOURCE(rsrc_, ptr_) \
+public                                         \
+	TypeResourceManager<rsrc_>
+
+#define ANKI_INSTANSIATE_RESOURCE_DELIMITER() ,
+
+#include <anki/resource/InstantiationMacros.h>
+#undef ANKI_INSTANTIATE_RESOURCE
+#undef ANKI_INSTANSIATE_RESOURCE_DELIMITER
+
 {
 	template<typename T>
 	friend class ResourcePtrDeleter;
@@ -178,22 +176,11 @@ anki_internal:
 		return *m_fs;
 	}
 
-	const String& _getCacheDirectory() const
+	const String& getCacheDirectory() const
 	{
 		return m_cacheDir;
 	}
 
-	/// Set it with information from the renderer
-	void _setShadersPrependedSource(const CString& cstr)
-	{
-		m_shadersPrependedSource.create(m_alloc, cstr);
-	}
-
-	const String& _getShadersPrependedSource() const
-	{
-		return m_shadersPrependedSource;
-	}
-
 	template<typename T>
 	T* findLoadedResource(const CString& filename)
 	{
@@ -235,7 +222,6 @@ private:
 	String m_cacheDir;
 	U32 m_maxTextureSize;
 	U32 m_textureAnisotropy;
-	String m_shadersPrependedSource;
 	AsyncLoader* m_asyncLoader = nullptr; ///< Async loading thread
 	U64 m_uuid = 0;
 	U64 m_loadRequestCount = 0;

+ 1 - 3
src/anki/resource/ShaderResource.cpp

@@ -39,8 +39,6 @@ Error ShaderResource::load(const ResourceFilename& filename, const CString& extr
 	// Allocate new source
 	StringAuto source(alloc);
 
-	source.append(getManager()._getShadersPrependedSource());
-
 	if(extraSrc.getLength() > 0)
 	{
 		source.append(extraSrc);
@@ -91,7 +89,7 @@ Error ShaderResource::createToCache(const ResourceFilename& filename,
 	// Compose cached filename
 	StringAuto newFilename(alloc);
 
-	newFilename.sprintf("%s/%s", &manager._getCacheDirectory()[0], &out[0]);
+	newFilename.sprintf("%s/%s", &manager.getCacheDirectory()[0], &out[0]);
 
 	if(fileExists(newFilename.toCString()))
 	{

+ 1 - 1
src/anki/scene/ModelNode.cpp

@@ -25,7 +25,7 @@ public:
 	}
 
 	ModelPatchRenderComponent(ModelPatchNode* node)
-		: RenderComponent(node, &node->m_modelPatch->getMaterial())
+		: RenderComponent(node, node->m_modelPatch->getMaterial())
 	{
 	}
 

+ 1 - 1
src/anki/scene/ParticleEmitter.cpp

@@ -170,7 +170,7 @@ public:
 	}
 
 	ParticleEmitterRenderComponent(ParticleEmitter* node)
-		: RenderComponent(node, &node->m_particleEmitterResource->getMaterial())
+		: RenderComponent(node, node->m_particleEmitterResource->getMaterial())
 	{
 	}
 

+ 167 - 1
src/anki/scene/RenderComponent.cpp

@@ -12,7 +12,7 @@
 namespace anki
 {
 
-RenderComponent::RenderComponent(SceneNode* node, const Material* mtl)
+RenderComponent::RenderComponent(SceneNode* node, MaterialResourcePtr mtl)
 	: SceneComponent(SceneComponentType::RENDER, node)
 	, m_mtl(mtl)
 {
@@ -38,4 +38,170 @@ Error RenderComponent::init()
 	return ErrorCode::NONE;
 }
 
+void RenderComponent::allocateAndSetupUniforms(const RenderQueueDrawContext& ctx,
+	WeakArray<const Mat4> transforms,
+	StagingGpuMemoryManager& alloc,
+	StagingGpuMemoryToken& token) const
+{
+	ANKI_ASSERT(transforms.getSize() <= MAX_INSTANCES);
+
+	const MaterialVariant& variant = m_mtl->getOrCreateVariant(ctx.m_key);
+	const ShaderProgramResourceVariant& progVariant = variant.getShaderProgramResourceVariant();
+
+	// Allocate uniform memory
+	U8* uniforms =
+		static_cast<U8*>(alloc.allocateFrame(variant.getUniformBlockSize(), StagingGpuMemoryType::UNIFORM, token));
+	void* const uniformsBegin = uniforms;
+	const void* const uniformsEnd = uniforms + variant.getUniformBlockSize();
+
+	// Iterate variables
+	for(auto it = m_vars.getBegin(); it != m_vars.getEnd(); ++it)
+	{
+		const RenderComponentVariable& var = *it;
+		const MaterialVariable& mvar = var.getMaterialVariable();
+		const ShaderProgramResourceInputVariable& progvar = mvar.getShaderProgramResourceInputVariable();
+
+		if(!variant.variableActive(mvar))
+		{
+			continue;
+		}
+
+		switch(progvar.getShaderVariableDataType())
+		{
+		case ShaderVariableDataType::FLOAT:
+		{
+			F32 val = mvar.getValue<F32>();
+			progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
+			break;
+		}
+		case ShaderVariableDataType::VEC2:
+		{
+			Vec2 val = mvar.getValue<Vec2>();
+			progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
+			break;
+		}
+		case ShaderVariableDataType::VEC3:
+		{
+			Vec3 val = mvar.getValue<Vec3>();
+			progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
+			break;
+		}
+		case ShaderVariableDataType::VEC4:
+		{
+			Vec4 val = mvar.getValue<Vec4>();
+			progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
+			break;
+		}
+		case ShaderVariableDataType::MAT3:
+		{
+			switch(mvar.getBuiltin())
+			{
+			case BuiltinMaterialVariableId::NONE:
+			{
+				Mat3 val = mvar.getValue<Mat3>();
+				progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
+				break;
+			}
+			case BuiltinMaterialVariableId::NORMAL_MATRIX:
+			{
+				ANKI_ASSERT(transforms.getSize() > 0);
+
+				DynamicArrayAuto<Mat3> normMats(getFrameAllocator());
+				normMats.create(transforms.getSize());
+
+				for(U i = 0; i < transforms.getSize(); i++)
+				{
+					Mat4 mv = ctx.m_viewMatrix * transforms[i];
+					normMats[i] = mv.getRotationPart();
+					normMats[i].reorthogonalize();
+				}
+
+				progVariant.writeShaderBlockMemory(
+					progvar, &normMats[0], transforms.getSize(), uniformsBegin, uniformsEnd);
+				break;
+			}
+			case BuiltinMaterialVariableId::CAMERA_ROTATION_MATRIX:
+			{
+				Mat3 rot = ctx.m_cameraTransform.getRotationPart();
+				progVariant.writeShaderBlockMemory(progvar, &rot, 1, uniformsBegin, uniformsEnd);
+				break;
+			}
+			default:
+				ANKI_ASSERT(0);
+			}
+
+			break;
+		}
+		case ShaderVariableDataType::MAT4:
+		{
+			switch(mvar.getBuiltin())
+			{
+			case BuiltinMaterialVariableId::NONE:
+			{
+				Mat4 val = mvar.getValue<Mat4>();
+				progVariant.writeShaderBlockMemory(progvar, &val, 1, uniformsBegin, uniformsEnd);
+				break;
+			}
+			case BuiltinMaterialVariableId::MODEL_VIEW_PROJECTION_MATRIX:
+			{
+				ANKI_ASSERT(transforms.getSize() > 0);
+
+				DynamicArrayAuto<Mat4> mvp(getFrameAllocator());
+				mvp.create(transforms.getSize());
+
+				for(U i = 0; i < transforms.getSize(); i++)
+				{
+					mvp[i] = ctx.m_viewProjectionMatrix * transforms[i];
+				}
+
+				progVariant.writeShaderBlockMemory(progvar, &mvp[0], transforms.getSize(), uniformsBegin, uniformsEnd);
+				break;
+			}
+			case BuiltinMaterialVariableId::MODEL_VIEW_MATRIX:
+			{
+				ANKI_ASSERT(transforms.getSize() > 0);
+
+				DynamicArrayAuto<Mat4> mv(getFrameAllocator());
+				mv.create(transforms.getSize());
+
+				for(U i = 0; i < transforms.getSize(); i++)
+				{
+					mv[i] = ctx.m_viewMatrix * transforms[i];
+				}
+
+				progVariant.writeShaderBlockMemory(progvar, &mv[0], transforms.getSize(), uniformsBegin, uniformsEnd);
+				break;
+			}
+			case BuiltinMaterialVariableId::VIEW_PROJECTION_MATRIX:
+			{
+				ANKI_ASSERT(transforms.getSize() == 0 && "Cannot have transform");
+				progVariant.writeShaderBlockMemory(progvar, &ctx.m_viewProjectionMatrix, 1, uniformsBegin, uniformsEnd);
+				break;
+			}
+			case BuiltinMaterialVariableId::VIEW_MATRIX:
+			{
+				progVariant.writeShaderBlockMemory(progvar, &ctx.m_viewMatrix, 1, uniformsBegin, uniformsEnd);
+				break;
+			}
+			default:
+				ANKI_ASSERT(0);
+			}
+
+			break;
+		}
+		case ShaderVariableDataType::SAMPLER_2D:
+		case ShaderVariableDataType::SAMPLER_2D_ARRAY:
+		case ShaderVariableDataType::SAMPLER_3D:
+		case ShaderVariableDataType::SAMPLER_CUBE:
+		{
+			ctx.m_cmdb->bindTexture(
+				0, progVariant.getTextureUnit(progvar), mvar.getValue<TextureResourcePtr>()->getGrTexture());
+			break;
+		}
+		default:
+			ANKI_ASSERT(0);
+		} // end switch
+	}
+}
+
 } // end namespace anki

+ 8 - 25
src/anki/scene/RenderComponent.h

@@ -9,8 +9,8 @@
 #include <anki/scene/SceneComponent.h>
 #include <anki/resource/Material.h>
 #include <anki/resource/Model.h>
-#include <anki/util/HashMap.h>
 #include <anki/core/StagingGpuMemoryManager.h>
+#include <anki/renderer/RenderQueue.h>
 
 namespace anki
 {
@@ -153,7 +153,7 @@ public:
 
 	using Variables = DynamicArray<RenderComponentVariable>;
 
-	RenderComponent(SceneNode* node, const Material* mtl);
+	RenderComponent(SceneNode* node, MaterialResourcePtr mtl);
 
 	~RenderComponent();
 
@@ -209,31 +209,14 @@ public:
 		return err;
 	}
 
-private:
-	using Key = U64;
-
-	/// Hash the hash.
-	class Hasher
-	{
-	public:
-		U64 operator()(const Key& b) const
-		{
-			return b;
-		}
-	};
-
-	/// Hash compare.
-	class Compare
-	{
-	public:
-		Bool operator()(const Key& a, const Key& b) const
-		{
-			return a == b;
-		}
-	};
+	void allocateAndSetupUniforms(const RenderQueueDrawContext& ctx,
+		WeakArray<const Mat4> transforms,
+		StagingGpuMemoryManager& alloc,
+		StagingGpuMemoryToken& token) const;
 
+private:
 	Variables m_vars;
-	const Material* m_mtl;
+	MaterialResourcePtr m_mtl;
 };
 /// @}
 

+ 5 - 0
src/anki/scene/SceneComponent.cpp

@@ -64,6 +64,11 @@ SceneAllocator<U8> SceneComponent::getAllocator() const
 	return m_node->getSceneAllocator();
 }
 
+SceneFrameAllocator<U8> SceneComponent::getFrameAllocator() const
+{
+	return m_node->getFrameAllocator();
+}
+
 void SceneComponentLists::insertNew(SceneComponent* comp)
 {
 	ANKI_ASSERT(comp);

+ 2 - 0
src/anki/scene/SceneComponent.h

@@ -93,6 +93,8 @@ public:
 
 	SceneAllocator<U8> getAllocator() const;
 
+	SceneFrameAllocator<U8> getFrameAllocator() const;
+
 	SceneGraph& getSceneGraph();
 	const SceneGraph& getSceneGraph() const;
 

+ 1 - 1
src/anki/scene/StaticGeometryNode.cpp

@@ -18,7 +18,7 @@ public:
 	StaticGeometryPatchNode* m_node;
 
 	StaticGeometryRenderComponent(StaticGeometryPatchNode* node)
-		: RenderComponent(node, &node->m_modelPatch->getMaterial())
+		: RenderComponent(node, node->m_modelPatch->getMaterial())
 		, m_node(node)
 	{
 	}