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