Browse Source

Fix resource

Panagiotis Christopoulos Charitos 9 years ago
parent
commit
2474db1a90

+ 4 - 4
src/anki/gr/gl/CommandBuffer.cpp

@@ -836,7 +836,7 @@ void CommandBuffer::drawElements(
 	};
 	};
 
 
 	m_impl->m_state.checkIndexedDracall();
 	m_impl->m_state.checkIndexedDracall();
-	m_impl->flushDrawcall();
+	m_impl->flushDrawcall(*this);
 
 
 	U idxBytes;
 	U idxBytes;
 	if(m_impl->m_state.m_indexType == GL_UNSIGNED_SHORT)
 	if(m_impl->m_state.m_indexType == GL_UNSIGNED_SHORT)
@@ -881,7 +881,7 @@ void CommandBuffer::drawArrays(PrimitiveTopology topology, U32 count, U32 instan
 	};
 	};
 
 
 	m_impl->m_state.checkNonIndexedDrawcall();
 	m_impl->m_state.checkNonIndexedDrawcall();
-	m_impl->flushDrawcall();
+	m_impl->flushDrawcall(*this);
 
 
 	DrawArraysIndirectInfo info(count, instanceCount, first, baseInstance);
 	DrawArraysIndirectInfo info(count, instanceCount, first, baseInstance);
 	m_impl->pushBackNewCommand<DrawArraysCommand>(convertPrimitiveTopology(topology), info);
 	m_impl->pushBackNewCommand<DrawArraysCommand>(convertPrimitiveTopology(topology), info);
@@ -927,7 +927,7 @@ void CommandBuffer::drawElementsIndirect(
 	};
 	};
 
 
 	m_impl->m_state.checkIndexedDracall();
 	m_impl->m_state.checkIndexedDracall();
-	m_impl->flushDrawcall();
+	m_impl->flushDrawcall(*this);
 	m_impl->pushBackNewCommand<DrawElementsIndirectCommand>(
 	m_impl->pushBackNewCommand<DrawElementsIndirectCommand>(
 		convertPrimitiveTopology(topology), m_impl->m_state.m_indexType, drawCount, offset, indirectBuff);
 		convertPrimitiveTopology(topology), m_impl->m_state.m_indexType, drawCount, offset, indirectBuff);
 }
 }
@@ -970,7 +970,7 @@ void CommandBuffer::drawArraysIndirect(
 	};
 	};
 
 
 	m_impl->m_state.checkNonIndexedDrawcall();
 	m_impl->m_state.checkNonIndexedDrawcall();
-	m_impl->flushDrawcall();
+	m_impl->flushDrawcall(*this);
 	m_impl->pushBackNewCommand<DrawArraysIndirectCommand>(
 	m_impl->pushBackNewCommand<DrawArraysIndirectCommand>(
 		convertPrimitiveTopology(topology), drawCount, offset, indirectBuff);
 		convertPrimitiveTopology(topology), drawCount, offset, indirectBuff);
 }
 }

+ 144 - 1
src/anki/gr/gl/CommandBufferImpl.cpp

@@ -96,8 +96,99 @@ GrAllocator<U8> CommandBufferImpl::getAllocator() const
 	return m_manager->getAllocator();
 	return m_manager->getAllocator();
 }
 }
 
 
-void CommandBufferImpl::flushDrawcall()
+void CommandBufferImpl::flushDrawcall(CommandBuffer& cmdb)
 {
 {
+	ANKI_ASSERT(!!(m_flags & CommandBufferFlag::GRAPHICS_WORK));
+
+	//
+	// Set default state
+	//
+	if(ANKI_UNLIKELY(m_state.m_mayContainUnsetState))
+	{
+		m_state.m_mayContainUnsetState = false;
+
+		if(m_state.m_primitiveRestart == 2)
+		{
+			cmdb.enablePrimitiveRestart(false);
+		}
+
+		if(m_state.m_fillMode == FillMode::COUNT)
+		{
+			cmdb.setFillMode(FillMode::SOLID);
+		}
+
+		if(m_state.m_cullMode == static_cast<FaceSelectionMask>(0))
+		{
+			cmdb.setCullMode(FaceSelectionMask::BACK);
+		}
+
+		if(m_state.m_polyOffsetFactor == -1.0)
+		{
+			cmdb.setPolygonOffset(0.0, 0.0);
+		}
+
+		for(U i = 0; i < 2; ++i)
+		{
+			FaceSelectionMask face = (i == 0) ? FaceSelectionMask::FRONT : FaceSelectionMask::BACK;
+
+			if(m_state.m_stencilFail[i] == StencilOperation::COUNT)
+			{
+				cmdb.setStencilOperations(face, StencilOperation::KEEP, StencilOperation::KEEP, StencilOperation::KEEP);
+			}
+
+			if(m_state.m_stencilCompare[i] == CompareOperation::COUNT)
+			{
+				cmdb.setStencilCompareFunction(face, CompareOperation::ALWAYS);
+			}
+
+			if(m_state.m_stencilCompareMask[i] == StateTracker::DUMMY_STENCIL_MASK)
+			{
+				cmdb.setStencilCompareMask(face, MAX_U32);
+			}
+
+			if(m_state.m_stencilWriteMask[i] == StateTracker::DUMMY_STENCIL_MASK)
+			{
+				cmdb.setStencilWriteMask(face, MAX_U32);
+			}
+
+			if(m_state.m_stencilRef[i] == StateTracker::DUMMY_STENCIL_MASK)
+			{
+				cmdb.setStencilReference(face, 0);
+			}
+		}
+
+		if(m_state.m_depthWrite == 2)
+		{
+			cmdb.enableDepthWrite(true);
+		}
+
+		if(m_state.m_depthOp == CompareOperation::COUNT)
+		{
+			cmdb.setDepthCompareFunction(CompareOperation::LESS);
+		}
+
+		for(U i = 0; i < MAX_COLOR_ATTACHMENTS; ++i)
+		{
+			if(m_state.m_colorWriteMasks[i] == StateTracker::INVALID_COLOR_MASK)
+			{
+				cmdb.setColorChannelWriteMask(i, ColorBit::ALL);
+			}
+
+			if(m_state.m_blendSrcMethod[i] == BlendMethod::COUNT)
+			{
+				cmdb.setBlendMethods(i, BlendMethod::ONE, BlendMethod::ZERO);
+			}
+
+			if(m_state.m_blendFuncs[i] == BlendFunction::COUNT)
+			{
+				cmdb.setBlendFunction(i, BlendFunction::ADD);
+			}
+		}
+	}
+
+	//
+	// Fire commands to change some state
+	//
 	class Cmd final : public GlCommand
 	class Cmd final : public GlCommand
 	{
 	{
 	public:
 	public:
@@ -134,6 +225,58 @@ void CommandBufferImpl::flushDrawcall()
 			m_state.m_glStencilFuncSeparateDirty[i] = false;
 			m_state.m_glStencilFuncSeparateDirty[i] = false;
 		}
 		}
 	}
 	}
+
+	class DepthTestCmd final : public GlCommand
+	{
+	public:
+		Bool8 m_enable;
+
+		DepthTestCmd(Bool enable)
+			: m_enable(enable)
+		{
+		}
+
+		Error operator()(GlState&)
+		{
+			if(m_enable)
+			{
+				glEnable(GL_DEPTH_TEST);
+			}
+			else
+			{
+				glDisable(GL_DEPTH_TEST);
+			}
+			return ErrorCode::NONE;
+		}
+	};
+
+	m_state.maybeEnableDepthTest([=](Bool enable) { pushBackNewCommand<DepthTestCmd>(enable); });
+
+	class StencilTestCmd final : public GlCommand
+	{
+	public:
+		Bool8 m_enable;
+
+		StencilTestCmd(Bool enable)
+			: m_enable(enable)
+		{
+		}
+
+		Error operator()(GlState&)
+		{
+			if(m_enable)
+			{
+				glEnable(GL_STENCIL_TEST);
+			}
+			else
+			{
+				glDisable(GL_STENCIL_TEST);
+			}
+			return ErrorCode::NONE;
+		}
+	};
+
+	m_state.maybeEnableDepthTest([=](Bool enable) { pushBackNewCommand<StencilTestCmd>(enable); });
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 1 - 1
src/anki/gr/gl/CommandBufferImpl.h

@@ -117,7 +117,7 @@ public:
 		return !!(m_flags & CommandBufferFlag::SECOND_LEVEL);
 		return !!(m_flags & CommandBufferFlag::SECOND_LEVEL);
 	}
 	}
 
 
-	void flushDrawcall();
+	void flushDrawcall(CommandBuffer& cmdb);
 
 
 private:
 private:
 	void destroy();
 	void destroy();

+ 40 - 27
src/anki/gr/gl/StateTracker.h

@@ -9,6 +9,7 @@
 #include <anki/gr/ShaderProgram.h>
 #include <anki/gr/ShaderProgram.h>
 #include <anki/gr/Framebuffer.h>
 #include <anki/gr/Framebuffer.h>
 #include <anki/gr/gl/FramebufferImpl.h>
 #include <anki/gr/gl/FramebufferImpl.h>
+#include <anki/gr/common/Misc.h>
 
 
 namespace anki
 namespace anki
 {
 {
@@ -20,6 +21,9 @@ namespace anki
 class StateTracker
 class StateTracker
 {
 {
 public:
 public:
+	/// If it's false then there might be unset state.
+	Bool8 m_mayContainUnsetState = true;
+
 	/// @name vert_state
 	/// @name vert_state
 	/// @{
 	/// @{
 	class VertexAttribute
 	class VertexAttribute
@@ -72,6 +76,8 @@ public:
 	template<typename TFunc>
 	template<typename TFunc>
 	void setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy, TFunc func)
 	void setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy, TFunc func)
 	{
 	{
+		ANKI_ASSERT(m_viewport[0] != MAX_U16 && m_viewport[1] != MAX_U16 && m_viewport[2] != MAX_U16
+			&& m_viewport[3] != MAX_U16);
 		if(m_viewport[0] != minx || m_viewport[1] != miny || m_viewport[2] != maxx || m_viewport[3] != maxy)
 		if(m_viewport[0] != minx || m_viewport[1] != miny || m_viewport[2] != maxx || m_viewport[3] != maxy)
 		{
 		{
 			m_viewport = {minx, miny, maxx, maxy};
 			m_viewport = {minx, miny, maxx, maxy};
@@ -123,6 +129,24 @@ public:
 
 
 	/// @name depth_stencil
 	/// @name depth_stencil
 	/// @{
 	/// @{
+	Bool8 m_stencilTestEnabled = 2;
+
+	template<typename TFunc>
+	void maybeEnableStencilTest(TFunc func)
+	{
+		Bool enable = !stencilTestDisabled(
+			m_stencilFail[0], m_stencilPassDepthFail[0], m_stencilPassDepthPass[0], m_stencilCompare[0]);
+		enable = enable
+			|| !stencilTestDisabled(
+					 m_stencilFail[1], m_stencilPassDepthFail[1], m_stencilPassDepthPass[1], m_stencilCompare[1]);
+
+		if(enable != m_stencilTestEnabled)
+		{
+			m_stencilTestEnabled = enable;
+			func(enable);
+		}
+	}
+
 	Array<StencilOperation, 2> m_stencilFail = {{StencilOperation::COUNT, StencilOperation::COUNT}};
 	Array<StencilOperation, 2> m_stencilFail = {{StencilOperation::COUNT, StencilOperation::COUNT}};
 	Array<StencilOperation, 2> m_stencilPassDepthFail = {{StencilOperation::COUNT, StencilOperation::COUNT}};
 	Array<StencilOperation, 2> m_stencilPassDepthFail = {{StencilOperation::COUNT, StencilOperation::COUNT}};
 	Array<StencilOperation, 2> m_stencilPassDepthPass = {{StencilOperation::COUNT, StencilOperation::COUNT}};
 	Array<StencilOperation, 2> m_stencilPassDepthPass = {{StencilOperation::COUNT, StencilOperation::COUNT}};
@@ -245,6 +269,21 @@ public:
 		}
 		}
 	}
 	}
 
 
+	Bool8 m_depthTestEnabled = 2; ///< 2 means don't know
+
+	template<typename TFunc>
+	void maybeEnableDepthTest(TFunc func)
+	{
+		ANKI_ASSERT(m_depthWrite != 2 && m_depthOp = CompareOperation::COUNT);
+		Bool enable = m_depthWrite || m_depthOp != CompareOperation::ALWAYS;
+
+		if(enable != m_depthTestEnabled)
+		{
+			m_depthTestEnabled = enable;
+			func(enable);
+		}
+	}
+
 	Bool8 m_depthWrite = 2;
 	Bool8 m_depthWrite = 2;
 
 
 	template<typename TFunc>
 	template<typename TFunc>
@@ -353,6 +392,7 @@ public:
 
 
 	void endRenderPass()
 	void endRenderPass()
 	{
 	{
+		ANKI_ASSERT(m_fbUuid != MAX_U64 && "Not inside a renderpass");
 		m_fbUuid = MAX_U64;
 		m_fbUuid = MAX_U64;
 	}
 	}
 	/// @}
 	/// @}
@@ -375,33 +415,6 @@ public:
 		ANKI_ASSERT(m_viewport[1] != MAX_U16 && "Forgot to set the viewport");
 		ANKI_ASSERT(m_viewport[1] != MAX_U16 && "Forgot to set the viewport");
 		ANKI_ASSERT(m_progUuid != MAX_U64 && "Forgot to bound a program");
 		ANKI_ASSERT(m_progUuid != MAX_U64 && "Forgot to bound a program");
 		ANKI_ASSERT(m_fbUuid != MAX_U64 && "Forgot to begin a render pass");
 		ANKI_ASSERT(m_fbUuid != MAX_U64 && "Forgot to begin a render pass");
-		ANKI_ASSERT(m_fillMode != FillMode::COUNT && "Forgot to set fill mode");
-		ANKI_ASSERT(m_cullMode != static_cast<FaceSelectionMask>(0) && "Forgot to set cull mode");
-
-		for(U i = 0; i < m_colorBuffCount; ++i)
-		{
-			ANKI_ASSERT(m_colorWriteMasks[i] != INVALID_COLOR_MASK && "Forgot to set the color write mask");
-			ANKI_ASSERT(m_blendSrcMethod[i] != BlendMethod::COUNT && "Forgot to set blend methods");
-			ANKI_ASSERT(m_blendFuncs[i] != BlendFunction::COUNT && "Forgot to set blend functions");
-		}
-
-		if(m_fbHasDepth)
-		{
-			ANKI_ASSERT(m_depthWrite != 2 && "Forgot to set depth write");
-			ANKI_ASSERT(m_depthOp != CompareOperation::COUNT && "Forgot to set depth compare function");
-		}
-
-		if(m_fbHasStencil)
-		{
-			for(U i = 0; i < 2; ++i)
-			{
-				ANKI_ASSERT(m_stencilFail[i] != StencilOperation::COUNT && "Forgot to set stencil ops");
-				ANKI_ASSERT(m_stencilCompare[i] != CompareOperation::COUNT && "Forgot to set stencil compare");
-				ANKI_ASSERT(m_stencilCompareMask[i] != DUMMY_STENCIL_MASK && "Forgot to set stencil compare mask");
-				ANKI_ASSERT(m_stencilWriteMask[i] != DUMMY_STENCIL_MASK && "Forgot to set stencil write mask");
-				ANKI_ASSERT(m_stencilRef[i] != DUMMY_STENCIL_MASK && "Forgot to set stencil ref mask");
-			}
-		}
 	}
 	}
 
 
 	void checkDispatch() const
 	void checkDispatch() const

+ 10 - 44
src/anki/resource/Material.cpp

@@ -14,38 +14,11 @@
 #include <anki/util/File.h>
 #include <anki/util/File.h>
 #include <anki/util/Filesystem.h>
 #include <anki/util/Filesystem.h>
 #include <anki/misc/Xml.h>
 #include <anki/misc/Xml.h>
-#include <anki/renderer/Ms.h>
 #include <algorithm>
 #include <algorithm>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
-/// Visit the textures to bind them
-class UpdateTexturesVisitor
-{
-public:
-	ResourceGroupInitInfo* m_init = nullptr;
-	ResourceManager* m_manager = nullptr;
-
-	template<typename TMaterialVariableTemplate>
-	Error visit(const TMaterialVariableTemplate& var)
-	{
-		// Do nothing
-		return ErrorCode::NONE;
-	}
-};
-
-// Specialize for texture
-template<>
-Error UpdateTexturesVisitor::visit<MaterialVariableTemplate<TextureResourcePtr>>(
-	const MaterialVariableTemplate<TextureResourcePtr>& var)
-{
-	m_init->m_textures[var.getTextureUnit()].m_texture = var.getValue()->getGrTexture();
-	m_init->m_textures[var.getTextureUnit()].m_usage =
-		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_TESSELLATION_EVALUATION;
-	return ErrorCode::NONE;
-}
-
 template<typename T>
 template<typename T>
 Error MaterialVariableTemplate<T>::init(U idx, const MaterialLoader::Input& in, Material& mtl)
 Error MaterialVariableTemplate<T>::init(U idx, const MaterialLoader::Input& in, Material& mtl)
 {
 {
@@ -174,6 +147,7 @@ Error MaterialVariant::init(const RenderingKey& key2, Material& mtl, MaterialLoa
 	//
 	//
 	// Shaders
 	// Shaders
 	//
 	//
+	Array<ShaderPtr, 5> shaders;
 	for(ShaderType stype = ShaderType::VERTEX; stype <= ShaderType::FRAGMENT; ++stype)
 	for(ShaderType stype = ShaderType::VERTEX; stype <= ShaderType::FRAGMENT; ++stype)
 	{
 	{
 		if(stype == ShaderType::GEOMETRY)
 		if(stype == ShaderType::GEOMETRY)
@@ -192,14 +166,22 @@ Error MaterialVariant::init(const RenderingKey& key2, Material& mtl, MaterialLoa
 		StringAuto filename(mtl.getTempAllocator());
 		StringAuto filename(mtl.getTempAllocator());
 		ANKI_CHECK(mtl.createProgramSourceToCache(src, stype, filename));
 		ANKI_CHECK(mtl.createProgramSourceToCache(src, stype, filename));
 
 
-		ShaderResourcePtr& shader = m_shaders[U(stype)];
+		ShaderResourcePtr& shader = m_shaders[stype];
 
 
 		ANKI_CHECK(mtl.getManager().loadResource(filename.toCString(), shader));
 		ANKI_CHECK(mtl.getManager().loadResource(filename.toCString(), shader));
 
 
+		shaders[stype] = shader->getGrShader();
+
 		// Update the hash
 		// Update the hash
 		mtl.m_hash ^= computeHash(&src[0], src.getLength());
 		mtl.m_hash ^= computeHash(&src[0], src.getLength());
 	}
 	}
 
 
+	m_prog = mtl.getManager().getGrManager().newInstance<ShaderProgram>(shaders[ShaderType::VERTEX],
+		shaders[ShaderType::TESSELLATION_CONTROL],
+		shaders[ShaderType::TESSELLATION_EVALUATION],
+		shaders[ShaderType::GEOMETRY],
+		shaders[ShaderType::FRAGMENT]);
+
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
@@ -398,22 +380,6 @@ Error Material::createProgramSourceToCache(const String& source, ShaderType type
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
-void Material::fillResourceGroupInitInfo(ResourceGroupInitInfo& rcinit)
-{
-	rcinit.m_uniformBuffers[0].m_uploadedMemory = true;
-	rcinit.m_uniformBuffers[0].m_usage = BufferUsageBit::UNIFORM_FRAGMENT | BufferUsageBit::UNIFORM_VERTEX;
-
-	UpdateTexturesVisitor visitor;
-	visitor.m_init = &rcinit;
-	visitor.m_manager = &getManager();
-
-	for(const auto& var : m_vars)
-	{
-		Error err = var->acceptVisitor(visitor);
-		(void)err;
-	}
-}
-
 const MaterialVariant& Material::getVariant(const RenderingKey& key) const
 const MaterialVariant& Material::getVariant(const RenderingKey& key) const
 {
 {
 	U lod = min<U>(m_lodCount - 1, key.m_lod);
 	U lod = min<U>(m_lodCount - 1, key.m_lod);

+ 6 - 7
src/anki/resource/Material.h

@@ -169,9 +169,9 @@ public:
 
 
 	~MaterialVariant();
 	~MaterialVariant();
 
 
-	ShaderPtr getShader(ShaderType type) const
+	ShaderProgramPtr getShaderProgram() const
 	{
 	{
-		return m_shaders[U(type)]->getGrShader();
+		return m_prog;
 	}
 	}
 
 
 	U getDefaultBlockSize() const
 	U getDefaultBlockSize() const
@@ -187,11 +187,12 @@ public:
 	}
 	}
 
 
 private:
 private:
-	/// All shaders except compute and geometry.
+	/// All shaders except compute.
 	Array<ShaderResourcePtr, 5> m_shaders;
 	Array<ShaderResourcePtr, 5> m_shaders;
 	U32 m_shaderBlockSize = 0;
 	U32 m_shaderBlockSize = 0;
 	DynamicArray<ShaderVariableBlockInfo> m_blockInfo;
 	DynamicArray<ShaderVariableBlockInfo> m_blockInfo;
 	DynamicArray<Bool8> m_varActive;
 	DynamicArray<Bool8> m_varActive;
+	ShaderProgramPtr m_prog;
 
 
 	ANKI_USE_RESULT Error init(const RenderingKey& key, Material& mtl, MaterialLoader& loader);
 	ANKI_USE_RESULT Error init(const RenderingKey& key, Material& mtl, MaterialLoader& loader);
 
 
@@ -313,8 +314,6 @@ public:
 		return m_vars;
 		return m_vars;
 	}
 	}
 
 
-	void fillResourceGroupInitInfo(ResourceGroupInitInfo& rcinit);
-
 	static U getInstanceGroupIdx(U instanceCount);
 	static U getInstanceGroupIdx(U instanceCount);
 
 
 private:
 private:
@@ -329,8 +328,8 @@ private:
 
 
 	DynamicArray<MaterialVariant> m_variants;
 	DynamicArray<MaterialVariant> m_variants;
 
 
-	/// This is a matrix of variants. It holds indices to m_variants. If the
-	/// idx is MAX_U16 then the variant is not present
+	/// This is a matrix of variants. It holds indices to m_variants. If the idx is MAX_U16 then the variant is not
+	/// present.
 	Array4d<U16, U(Pass::COUNT), MAX_LODS, 2, MAX_INSTANCE_GROUPS> m_variantMatrix;
 	Array4d<U16, U(Pass::COUNT), MAX_LODS, 2, MAX_INSTANCE_GROUPS> m_variantMatrix;
 
 
 	DynamicArray<MaterialVariable*> m_vars;
 	DynamicArray<MaterialVariable*> m_vars;

+ 41 - 66
src/anki/resource/Model.cpp

@@ -31,74 +31,59 @@ void ModelPatch::getRenderingDataSub(
 	RenderingKey meshKey = key;
 	RenderingKey meshKey = key;
 	meshKey.m_lod = min<U>(key.m_lod, m_meshCount - 1);
 	meshKey.m_lod = min<U>(key.m_lod, m_meshCount - 1);
 	const Mesh& mesh = getMesh(meshKey);
 	const Mesh& mesh = getMesh(meshKey);
-	inf.m_resourceGroup = m_grResources[meshKey.m_lod];
 
 
-	// Get shaders
+	// Get program
 	{
 	{
 		RenderingKey mtlKey = key;
 		RenderingKey mtlKey = key;
 		mtlKey.m_lod = min<U>(key.m_lod, m_mtl->getLodCount() - 1);
 		mtlKey.m_lod = min<U>(key.m_lod, m_mtl->getLodCount() - 1);
 
 
-		if(mtlKey.m_tessellation && !m_mtl->getTessellationEnabled())
-		{
-			ANKI_ASSERT(0);
-		}
+		const MaterialVariant& variant = m_mtl->getVariant(mtlKey);
 
 
-		if(mtlKey.m_pass == Pass::SM && !m_mtl->getShadowEnabled())
-		{
-			ANKI_ASSERT(0);
-		}
+		inf.m_program = variant.getShaderProgram();
+	}
 
 
-		if(mtlKey.m_instanceCount > 1 && !m_mtl->isInstanced())
+	// Vertex info
+	{
+		inf.m_vertexBufferBindingCount = 1;
+		VertexBufferBinding& vertBuffBinding = inf.m_vertexBufferBindings[0];
+		vertBuffBinding.m_buffer = mesh.getVertexBuffer();
+		vertBuffBinding.m_binding = 0;
+		vertBuffBinding.m_offset = 0;
+		vertBuffBinding.m_stride = sizeof(Vec3) + sizeof(HVec2) + 2 * sizeof(U32);
+
+		inf.m_vertexAttributeCount = 4;
+		auto& attribs = inf.m_vertexAttributes;
+
+		attribs[0].m_location = 0;
+		attribs[0].m_bufferBinding = 0;
+		attribs[0].m_format = PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT);
+		attribs[0].m_relativeOffset = 0;
+
+		attribs[1].m_location = 0;
+		attribs[1].m_bufferBinding = 0;
+		attribs[1].m_format = PixelFormat(ComponentFormat::R16G16, TransformFormat::FLOAT);
+		attribs[1].m_relativeOffset = sizeof(Vec3);
+
+		if(key.m_pass == Pass::MS_FS)
 		{
 		{
-			ANKI_ASSERT(0);
+			attribs[2].m_location = 0;
+			attribs[2].m_bufferBinding = 0;
+			attribs[2].m_format = PixelFormat(ComponentFormat::R10G10B10A2, TransformFormat::SNORM);
+			attribs[2].m_relativeOffset = sizeof(Vec3) + sizeof(U32);
+
+			attribs[3].m_location = 0;
+			attribs[3].m_bufferBinding = 0;
+			attribs[3].m_format = PixelFormat(ComponentFormat::R10G10B10A2, TransformFormat::SNORM);
+			attribs[3].m_relativeOffset = sizeof(Vec3) + sizeof(U32) * 2;
 		}
 		}
-
-		const MaterialVariant& variant = m_mtl->getVariant(mtlKey);
-
-		inf.m_state.m_shaders[ShaderType::VERTEX] = variant.getShader(ShaderType::VERTEX);
-
-		if(mtlKey.m_tessellation)
+		else
 		{
 		{
-			inf.m_state.m_shaders[ShaderType::TESSELLATION_CONTROL] =
-				variant.getShader(ShaderType::TESSELLATION_CONTROL);
-
-			inf.m_state.m_shaders[ShaderType::TESSELLATION_EVALUATION] =
-				variant.getShader(ShaderType::TESSELLATION_EVALUATION);
+			inf.m_vertexAttributeCount = 2;
 		}
 		}
-
-		inf.m_state.m_shaders[ShaderType::FRAGMENT] = variant.getShader(ShaderType::FRAGMENT);
 	}
 	}
 
 
-	// Vertex
-	VertexStateInfo& vert = inf.m_state.m_vertex;
-	vert.m_bindingCount = 1;
-	vert.m_attributeCount = 4;
-	vert.m_bindings[0].m_stride = sizeof(Vec3) + sizeof(HVec2) + 2 * sizeof(U32);
-
-	vert.m_attributes[0].m_format = PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT);
-	vert.m_attributes[0].m_offset = 0;
-
-	vert.m_attributes[1].m_format = PixelFormat(ComponentFormat::R16G16, TransformFormat::FLOAT);
-	vert.m_attributes[1].m_offset = sizeof(Vec3);
-
-	if(key.m_pass == Pass::MS_FS)
-	{
-		vert.m_attributes[2].m_format = PixelFormat(ComponentFormat::R10G10B10A2, TransformFormat::SNORM);
-		vert.m_attributes[2].m_offset = sizeof(Vec3) + sizeof(U32);
-
-		vert.m_attributes[3].m_format = PixelFormat(ComponentFormat::R10G10B10A2, TransformFormat::SNORM);
-		vert.m_attributes[3].m_offset = sizeof(Vec3) + sizeof(U32) * 2;
-	}
-	else
-	{
-		vert.m_attributeCount = 2;
-	}
-
-	// Input assembly
-	inf.m_state.m_inputAssembler.m_topology = PrimitiveTopology::TRIANGLES;
-	inf.m_state.m_inputAssembler.m_primitiveRestartEnabled = false;
-
-	inf.m_stateMask = PipelineSubStateBit::VERTEX | PipelineSubStateBit::SHADERS | PipelineSubStateBit::INPUT_ASSEMBLER;
+	// Index buff
+	inf.m_indexBuffer = mesh.getIndexBuffer();
 
 
 	// Other
 	// Other
 	if(subMeshIndicesArray.getSize() == 0 || mesh.getSubMeshesCount() == 0)
 	if(subMeshIndicesArray.getSize() == 0 || mesh.getSubMeshesCount() == 0)
@@ -125,11 +110,7 @@ Error ModelPatch::create(WeakArray<CString> meshFNames, const CString& mtlFName,
 	// Load material
 	// Load material
 	ANKI_CHECK(manager->loadResource(mtlFName, m_mtl));
 	ANKI_CHECK(manager->loadResource(mtlFName, m_mtl));
 
 
-	// Iterate material variables for textures
-	ResourceGroupInitInfo rcinit;
-	m_mtl->fillResourceGroupInitInfo(rcinit);
-
-	// Load meshes and update resource group
+	// Load meshes
 	m_meshCount = 0;
 	m_meshCount = 0;
 	for(U i = 0; i < meshFNames.getSize(); i++)
 	for(U i = 0; i < meshFNames.getSize(); i++)
 	{
 	{
@@ -142,12 +123,6 @@ Error ModelPatch::create(WeakArray<CString> meshFNames, const CString& mtlFName,
 			return ErrorCode::USER_DATA;
 			return ErrorCode::USER_DATA;
 		}
 		}
 
 
-		rcinit.m_vertexBuffers[0].m_buffer = m_meshes[i]->getVertexBuffer();
-		rcinit.m_indexBuffer.m_buffer = m_meshes[i]->getIndexBuffer();
-		rcinit.m_indexSize = 2;
-
-		m_grResources[i] = manager->getGrManager().newInstance<ResourceGroup>(rcinit);
-
 		++m_meshCount;
 		++m_meshCount;
 	}
 	}
 
 

+ 25 - 9
src/anki/resource/Model.h

@@ -23,6 +23,24 @@ class PhysicsCollisionShape;
 /// @addtogroup resource
 /// @addtogroup resource
 /// @{
 /// @{
 
 
+class VertexBufferBinding
+{
+public:
+	BufferPtr m_buffer;
+	U32 m_binding;
+	PtrSize m_offset;
+	PtrSize m_stride;
+};
+
+class VertexAttributeInfo
+{
+public:
+	U32 m_location;
+	U32 m_bufferBinding;
+	PixelFormat m_format;
+	PtrSize m_relativeOffset;
+};
+
 class ModelRenderingInfo
 class ModelRenderingInfo
 {
 {
 public:
 public:
@@ -30,14 +48,14 @@ public:
 	Array<PtrSize, MAX_SUB_DRAWCALLS> m_indicesOffsetArray;
 	Array<PtrSize, MAX_SUB_DRAWCALLS> m_indicesOffsetArray;
 	U32 m_drawcallCount;
 	U32 m_drawcallCount;
 
 
-	ResourceGroupPtr m_resourceGroup;
-	PipelineInitInfo& m_state;
-	PipelineSubStateBit m_stateMask = PipelineSubStateBit::NONE;
+	ShaderProgramPtr m_program;
 
 
-	ModelRenderingInfo(PipelineInitInfo& state)
-		: m_state(state)
-	{
-	}
+	Array<VertexBufferBinding, MAX_VERTEX_ATTRIBUTES> m_vertexBufferBindings;
+	U32 m_vertexBufferBindingCount;
+	Array<VertexAttributeInfo, MAX_VERTEX_ATTRIBUTES> m_vertexAttributes;
+	U32 m_vertexAttributeCount;
+
+	BufferPtr m_indexBuffer;
 };
 };
 
 
 /// Model patch interface class. Its very important class and it binds the material with the mesh
 /// Model patch interface class. Its very important class and it binds the material with the mesh
@@ -92,8 +110,6 @@ private:
 	U8 m_meshCount = 0;
 	U8 m_meshCount = 0;
 	MaterialResourcePtr m_mtl;
 	MaterialResourcePtr m_mtl;
 
 
-	Array<ResourceGroupPtr, MAX_LODS> m_grResources;
-
 	/// Return the maximum number of LODs
 	/// Return the maximum number of LODs
 	U getLodCount() const;
 	U getLodCount() const;
 };
 };

+ 2 - 5
src/anki/resource/ParticleEmitterResource.cpp

@@ -8,7 +8,6 @@
 #include <anki/resource/Model.h>
 #include <anki/resource/Model.h>
 #include <anki/util/StringList.h>
 #include <anki/util/StringList.h>
 #include <anki/misc/Xml.h>
 #include <anki/misc/Xml.h>
-#include <anki/renderer/Ms.h>
 #include <cstring>
 #include <cstring>
 
 
 namespace anki
 namespace anki
@@ -198,15 +197,13 @@ Error ParticleEmitterResource::load(const ResourceFilename& filename)
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
-void ParticleEmitterResource::getRenderingInfo(U lod, PipelineInitInfo& state, PipelineSubStateBit& stateMask) const
+void ParticleEmitterResource::getRenderingInfo(U lod, ShaderProgramPtr& prog) const
 {
 {
 	lod = min<U>(lod, m_lodCount - 1);
 	lod = min<U>(lod, m_lodCount - 1);
 
 
 	RenderingKey key(Pass::MS_FS, lod, false, 1);
 	RenderingKey key(Pass::MS_FS, lod, false, 1);
 	const MaterialVariant& variant = m_material->getVariant(key);
 	const MaterialVariant& variant = m_material->getVariant(key);
-	state.m_shaders[ShaderType::VERTEX] = variant.getShader(ShaderType::VERTEX);
-	state.m_shaders[ShaderType::FRAGMENT] = variant.getShader(ShaderType::FRAGMENT);
-	stateMask = PipelineSubStateBit::SHADERS;
+	prog = variant.getShaderProgram();
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

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

@@ -116,8 +116,8 @@ public:
 		return *m_material;
 		return *m_material;
 	}
 	}
 
 
-	/// Get shaders for rendering.
-	void getRenderingInfo(U lod, PipelineInitInfo& state, PipelineSubStateBit& stateMask) const;
+	/// Get program for rendering.
+	void getRenderingInfo(U lod, ShaderProgramPtr& prog) const;
 
 
 	/// Load it
 	/// Load it
 	ANKI_USE_RESULT Error load(const ResourceFilename& filename);
 	ANKI_USE_RESULT Error load(const ResourceFilename& filename);