//============================================================================== 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; }
//============================================================================== 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; }