Esempio n. 1
0
//==============================================================================
Error Material::createProgramSourceToCache(
	const TempResourceString& source, TempResourceString& out)
{
	Error err = ErrorCode::NONE;

	auto alloc = m_resources->_getTempAllocator();

	// Create the hash
	U64 h = computeHash(&source[0], source.getLength());
	TempResourceString prefix;
	TempResourceString::ScopeDestroyer prefixd(&prefix, alloc);

	ANKI_CHECK(prefix.toString(alloc, h));

	// Create path
	ANKI_CHECK(out.sprintf(alloc, "%s/mtl_%s.glsl", 
		&m_resources->_getCacheDirectory()[0],
		&prefix[0]));

	// If file not exists write it
	if(!fileExists(out.toCString()))
	{
		// If not create it
		File f;
		ANKI_CHECK(f.open(out.toCString(), File::OpenFlag::WRITE));
		ANKI_CHECK(f.writeText("%s\n", &source[0]));
	}

	return err;
}
Esempio n. 2
0
//==============================================================================
Error Material::parseMaterialTag(const XmlElement& materialEl,
	ResourceInitializer& rinit)
{
	Error err = ErrorCode::NONE;
	XmlElement el;

	// levelsOfDetail
	//
	XmlElement lodEl;
	ANKI_CHECK(materialEl.getChildElementOptional("levelsOfDetail", lodEl));

	if(lodEl)
	{
		I64 tmp;
		ANKI_CHECK(lodEl.getI64(tmp));
		m_lodsCount = (tmp < 1) ? 1 : tmp;
	}
	else
	{
		m_lodsCount = 1;
	}

	// shadow
	//
	XmlElement shadowEl;
	ANKI_CHECK(materialEl.getChildElementOptional("shadow", shadowEl));

	if(shadowEl)
	{
		I64 tmp;
		ANKI_CHECK(shadowEl.getI64(tmp));
		m_shadow = tmp;
	}

	// blendFunctions
	//
	XmlElement blendFunctionsEl;
	ANKI_CHECK(
		materialEl.getChildElementOptional("blendFunctions", blendFunctionsEl));

	if(blendFunctionsEl)
	{
		CString cstr;

		// sFactor
		ANKI_CHECK(blendFunctionsEl.getChildElement("sFactor", el));
		ANKI_CHECK(el.getText(cstr));
		m_blendingSfactor = blendToEnum(cstr);
		if(m_blendingSfactor == 0)
		{
			return ErrorCode::USER_DATA;
		}

		// dFactor
		ANKI_CHECK(blendFunctionsEl.getChildElement("dFactor", el));
		ANKI_CHECK(el.getText(cstr));
		m_blendingDfactor = blendToEnum(cstr);
		if(m_blendingDfactor == 0)
		{
			return ErrorCode::USER_DATA;
		}
	}
	else
	{
		m_passesCount = 2;
	}

	// depthTesting
	//
	XmlElement depthTestingEl;
	ANKI_CHECK(
		materialEl.getChildElementOptional("depthTesting", depthTestingEl));

	if(depthTestingEl)
	{
		I64 tmp;
		ANKI_CHECK(depthTestingEl.getI64(tmp));
		m_depthTesting = tmp;
	}

	// wireframe
	//
	XmlElement wireframeEl;
	ANKI_CHECK(materialEl.getChildElementOptional("wireframe", wireframeEl));

	if(wireframeEl)
	{
		I64 tmp;
		ANKI_CHECK(wireframeEl.getI64(tmp));
		m_wireframe = tmp;
	}

	// shaderProgram
	//
	ANKI_CHECK(materialEl.getChildElement("programs", el));
	MaterialProgramCreator loader(rinit.m_tempAlloc);
	ANKI_CHECK(loader.parseProgramsTag(el));

	m_tessellation = loader.hasTessellation();
	U tessCount = m_tessellation ? 2 : 1;

	// Alloc program vector
	ANKI_CHECK(m_progs.create(rinit.m_alloc,
		countShaders(ShaderType::VERTEX) 
		+ countShaders(ShaderType::TESSELLATION_CONTROL)
		+ countShaders(ShaderType::TESSELLATION_EVALUATION)
		+ countShaders(ShaderType::GEOMETRY)
		+ countShaders(ShaderType::FRAGMENT)));

	// Aloc progam descriptors
	m_pplines.resize(m_passesCount * m_lodsCount * tessCount);

	m_hash = 0;
	for(ShaderType shader = ShaderType::VERTEX; 
		shader <= ShaderType::FRAGMENT; 
		++shader)
	{
		Bool isTessellationShader = shader == ShaderType::TESSELLATION_CONTROL 
			|| shader == ShaderType::TESSELLATION_EVALUATION;

		if(!m_tessellation && isTessellationShader)
		{
			// Skip tessellation if not enabled
			continue;
		}

		if(shader == ShaderType::GEOMETRY)
		{
			// Skip geometry for now
			continue;
		}

		for(U level = 0; level < m_lodsCount; ++level)
		{
			if(level > 0 && isTessellationShader)
			{
				continue;
			}

			for(U pid = 0; pid < m_passesCount; ++pid)
			{
				for(U tess = 0; tess < tessCount; ++tess)
				{
					if(tess == 0 && isTessellationShader)
					{
						continue;
					}

					if(tess > 0 && shader == ShaderType::FRAGMENT)
					{
						continue;
					}

					TempResourceString src;
					TempResourceString::ScopeDestroyer srcd(
						&src, rinit.m_tempAlloc);

					ANKI_CHECK(src.sprintf(
						rinit.m_tempAlloc,
						"%s\n"
						"#define LOD %u\n"
						"#define PASS %u\n"
						"#define TESSELLATION %u\n"
						"%s\n",
						&rinit.m_resources._getShadersPrependedSource()[0],
						level, pid, tess, &loader.getProgramSource(shader)[0]));

					TempResourceString filename;
					TempResourceString::ScopeDestroyer filenamed(
						&filename, rinit.m_tempAlloc);

					ANKI_CHECK(createProgramSourceToCache(src, filename));

					RenderingKey key((Pass)pid, level, tess);
					ProgramResourcePointer& progr = getProgram(key, shader);
					ANKI_CHECK(
						progr.load(filename.toCString(), &rinit.m_resources));

					// Update the hash
					m_hash ^= computeHash(&src[0], src.getLength());
				}
			}
		}
	}

	ANKI_CHECK(populateVariables(loader));

	// Get uniform block size
	ANKI_ASSERT(m_progs.getSize() > 0);
	m_shaderBlockSize = loader.getUniformBlockSize();

	return err;
}
Esempio n. 3
0
//==============================================================================
void Material::parseMaterialTag(const XmlElement& materialEl,
	ResourceInitializer& rinit)
{
	// levelsOfDetail
	//
	XmlElement lodEl = materialEl.getChildElementOptional("levelsOfDetail");

	if(lodEl)
	{
		I tmp = lodEl.getInt();
		m_lodsCount = (tmp < 1) ? 1 : tmp;
	}
	else
	{
		m_lodsCount = 1;
	}

	// shadow
	//
	XmlElement shadowEl = materialEl.getChildElementOptional("shadow");

	if(shadowEl)
	{
		m_shadow = shadowEl.getInt();
	}

	// blendFunctions
	//
	XmlElement blendFunctionsEl =
		materialEl.getChildElementOptional("blendFunctions");

	if(blendFunctionsEl)
	{
		// sFactor
		m_blendingSfactor = blendToEnum(
			blendFunctionsEl.getChildElement("sFactor").getText());

		// dFactor
		m_blendingDfactor = blendToEnum(
			blendFunctionsEl.getChildElement("dFactor").getText());
	}
	else
	{
		m_passesCount = 2;
	}

	// depthTesting
	//
	XmlElement depthTestingEl =
		materialEl.getChildElementOptional("depthTesting");

	if(depthTestingEl)
	{
		m_depthTesting = depthTestingEl.getInt();
	}

	// wireframe
	//
	XmlElement wireframeEl = materialEl.getChildElementOptional("wireframe");

	if(wireframeEl)
	{
		m_wireframe = wireframeEl.getInt();
	}

	// shaderProgram
	//
	MaterialProgramCreator mspc(
		materialEl.getChildElement("programs"),
		rinit.m_tempAlloc);

	m_tessellation = mspc.hasTessellation();
	U tessCount = m_tessellation ? 2 : 1;

	// Alloc program vector
	U progCount = 0;
	progCount += m_passesCount * m_lodsCount * tessCount;
	if(m_tessellation)
	{
		progCount += m_passesCount * m_lodsCount * 2;
	}
	progCount += m_passesCount * m_lodsCount;
	m_progs.resize(progCount);

	// Aloc progam descriptors
	m_pplines.resize(m_passesCount * m_lodsCount * tessCount);

	m_hash = 0;
	for(U shader = 0; shader < 5; shader++)
	{
		if(!m_tessellation && (shader == 1 || shader == 2))
		{
			continue;
		}

		if(shader == 3)
		{
			continue;
		}

		for(U level = 0; level < m_lodsCount; ++level)
		{
			for(U pid = 0; pid < m_passesCount; ++pid)
			{
				for(U tess = 0; tess < tessCount; ++tess)
				{
					TempResourceString src(rinit.m_tempAlloc);

					src.sprintf("#define LOD %u\n"
						"#define PASS %u\n"
						"#define TESSELLATION %u\n", 
						level, pid, tess);

					TempResourceString filename =
						createProgramSourceToChache(src);

					RenderingKey key((Pass)pid, level, tess);
					ProgramResourcePointer& progr = getProgram(key, shader);
					progr.load(filename.toCString(), &rinit.m_resources);

					// Update the hash
					m_hash ^= computeHash(&src[0], src.getLength());
				}
			}
		}
	}

	populateVariables(mspc);

	// Get uniform block size
	ANKI_ASSERT(m_progs.size() > 0);
	m_shaderBlockSize = 
		m_progs[0]->getGlProgram().findBlock("bDefaultBlock").getSize();
}