void UProgramPermutor::GenerateProgramPermutationFile(const eastl::string& inOutputFilePath, const eastl::string& inProgramFileName, const eastl::vector<char>& inCompiledByteCode, const SShaderUsageDescription& inTargetUsage, ProgramId_t inTargetProgramID, const eastl::string& inTargetProgramStringDesc) { eastl::string outputFilePath = inOutputFilePath; outputFilePath += '\\'; outputFilePath += inProgramFileName; outputFilePath += '_'; outputFilePath += std::to_string(inTargetProgramID).c_str(); // Linker error if I try to use eastl::to_string (??) seems to not support using uint64_t outputFilePath += '_'; outputFilePath += inTargetProgramStringDesc; outputFilePath += '_'; outputFilePath += inTargetUsage.ShaderEntryName; outputFilePath += '-'; outputFilePath += inTargetUsage.ShaderModelName; outputFilePath += ".cso"; std::ofstream outputProgramFileStream(outputFilePath.c_str(), std::ios::out | std::ios::binary); if (outputProgramFileStream.is_open()) { outputProgramFileStream.write(inCompiledByteCode.data(), inCompiledByteCode.size()); outputProgramFileStream.flush(); } }
void pre(const eastl::vector<int>& observated, const eastl::vector<int>& simulated) noexcept { assert(observated.size() == simulated.size() and "weighted_kappa_calculator observated and simulated sizes " "are different"); eastl::fill(observed.begin(), observed.end(), 0.0); eastl::fill(distributions.begin(), distributions.end(), 0.0); for (int i = 0; i != (int)simulated.size(); ++i) { ++observed(observated[i], simulated[i]); ++distributions(observated[i], 0); ++distributions(simulated[i], 1); } for (auto& elem : observed) elem /= (double)simulated.size(); for (auto& elem : distributions) elem /= (double)simulated.size(); for (int i = 0; i != (int)NC; ++i) for (int j = 0; j != (int)NC; ++j) expected(i, j) = distributions(i, 0) * distributions(j, 1); }
//--------------------------------------------------------------------------------------------- void TextureFileMetadata::GetIdentifier( eastl::vector<byte>& bytes ) const { bytes.insert( bytes.end(), m_Path.begin(), m_Path.end() ); bytes.push_back( m_eSWarp ); bytes.push_back( m_eTWarp ); bytes.push_back( m_eMagFilter ); bytes.push_back( m_eMinFilter ); bytes.push_back( m_ePixelFormat ); bytes.push_back( m_uAnisotropic ); }
static eastl::optional<long int> get_basic_attribute_id(const eastl::vector<const attribute*>& att, const eastl::string& name) { auto it = eastl::find_if(att.begin(), att.end(), [&name](const attribute* att) { return att->name == name; }); return it == att.end() ? eastl::nullopt : eastl::make_optional(it - att.begin()); }
void SetCVar(CCommand* pCommand, eastl::vector<tstring>& asTokens, const tstring& sCommand) { CVar* pCVar = dynamic_cast<CVar*>(pCommand); TAssert(pCVar); if (!pCVar) return; if (asTokens.size() > 1) pCVar->SetValue(asTokens[1]); TMsg(sprintf(tstring("%s = %s\n"), pCVar->GetName().c_str(), pCVar->GetValue().c_str())); }
inline double rmsep(const eastl::vector<int>& observated, const eastl::vector<int>& simulated, const size_t N, const size_t NC) { matrix<int> mat(NC, NC, 0); for (size_t i = 0, e = observated.size(); i != e; ++i) mat(observated[i], simulated[i])++; unsigned long sum = 0.0; for (size_t i = 0; i != NC; ++i) for (size_t j = 0; j != NC; ++j) sum += mat(i, j) * ((i - j) * (i - j)); return sqrt((double)sum / (double)N); }
/////////////////////////////////////////////////////////////////////// // Javascript Callstack Helper /////////////////////////////////////////////////////////////////////// void JSCallstackCallback(const eastl::vector<eastl::string8> &names, const eastl::vector<eastl::string8> &args, const eastl::vector<int> &lines, const eastl::vector<eastl::string8> &urls) { if (EAWebKitClient *pClient = GetEAWebKitClient()) { const char **nameArray = new const char*[names.size()]; const char **argArray = new const char*[args.size()]; int *lineArray = new int[lines.size()]; const char **urlArray = new const char*[urls.size()]; EAW_ASSERT(names.size() == args.size() && names.size() == lines.size() && names.size() == urls.size()); for (int i = 0; i < (int) names.size(); ++i) { nameArray[i] = names[i].c_str(); argArray[i] = args[i].c_str(); lineArray[i] = lines[i]; urlArray[i] = urls[i].c_str(); } ReportJSCallstackInfo info; info.mDepth = (int)names.size(); info.mNames = nameArray; info.mArgs = argArray; info.mLines = lineArray; info.mUrls = urlArray; pClient->ReportJSCallstack(info); delete[] nameArray; delete[] argArray; delete[] lineArray; delete[] urlArray; } }
// Parses the entire shader string buffer to match instances of the program meta flag // Format of the shader usage flags: "!!>:(Flag Type, <Values, sep. by comma>)" // Flag Type can be either Usage or Permute void UProgramPermutor::ParseProgramMetaFlags(const eastl::string& inShaderBufferString, eastl::vector<SShaderMetaFlagInstance>& outMetaFlagInstances) { // Find all occurrences of shader meta flag string size_t currentFindIndex = inShaderBufferString.find(s_shaderMetaFlagString, 0); outMetaFlagInstances.clear(); while (currentFindIndex != eastl::string::npos) { eastl::string metaFlagInstanceString; currentFindIndex += UProgramPermutor::s_shaderMetaFlagString.length(); while (inShaderBufferString[currentFindIndex] != ')') { metaFlagInstanceString += inShaderBufferString[currentFindIndex]; ++currentFindIndex; } ++currentFindIndex; // Skip past the ending parentheses if (metaFlagInstanceString.empty()) { LOG(LogProgramPermutor, Warning, "Warning: Shader usage instance #%d has an empty description pair!", outMetaFlagInstances.size()); return; } eastl::vector<eastl::string> metaFlagSubstrings; SShaderMetaFlagInstance currentMetaFlagInstance; // Split the meta flag string by coma size_t currentCommaIndex = 0; size_t nextCommaIndex = metaFlagInstanceString.find(',', currentCommaIndex); while (nextCommaIndex != eastl::string::npos) { eastl::string flagValueString = metaFlagInstanceString.substr(currentCommaIndex, (nextCommaIndex - currentCommaIndex)); metaFlagSubstrings.emplace_back(flagValueString); currentCommaIndex = nextCommaIndex + 1; nextCommaIndex = metaFlagInstanceString.find(',', currentCommaIndex); if (nextCommaIndex == eastl::string::npos) { eastl::string lastFlagValueString = metaFlagInstanceString.substr(currentCommaIndex, (nextCommaIndex - currentCommaIndex)); // On the last iteration, we need to add the last string metaFlagSubstrings.emplace_back(lastFlagValueString); } } // Flag string count sanity check if (metaFlagSubstrings.size() == 0) { LOG(LogProgramPermutor, Warning, "Warning: Shader usage instance #%d has more than one separation commas!", outMetaFlagInstances.size()); return; } // First substring is the flag type currentMetaFlagInstance.MetaFlagType = ConvertStringToFlagType(metaFlagSubstrings.front()); if (currentMetaFlagInstance.MetaFlagType == EMetaFlagType::EMetaFlagType_Invalid) { LOG(LogProgramPermutor, Warning, "Warning: Shader usage instance #%d has an invalid meta flag type!", outMetaFlagInstances.size()); return; } // Rest of the substrings are the parameter values (if applicable) for (size_t i = 1; i < metaFlagSubstrings.size(); ++i) { currentMetaFlagInstance.MetaFlagValues.emplace_back(metaFlagSubstrings[i]); } outMetaFlagInstances.emplace_back(currentMetaFlagInstance); currentFindIndex = inShaderBufferString.find(UProgramPermutor::s_shaderMetaFlagString, currentFindIndex); } }
void UProgramPermutor::GeneratePermutations(const eastl::string& inShaderFilePath, const eastl::vector<SShaderUsageDescription>& inUsageDescriptions, const eastl::vector<SShaderPermuteDescription>& inPermuteOptions, ProgramPermutations_t& outPermutations, bool inShouldGenPermutationFiles) { UGraphicsDriver& graphicsDriver = gEngine->GetRenderer().GetGraphicsDriver(); const size_t numPermuteOptions = inPermuteOptions.size(); if (numPermuteOptions >= 0) { const size_t totalNumPermutations = 0x1ULL << numPermuteOptions; for (size_t i = 0; i < totalNumPermutations; ++i) { ProgramId_t currentProgramId = 0; eastl::vector<D3D_SHADER_MACRO> programMacroDefines; eastl::vector<char> compiledProgramByteCode; eastl::string currentProgramIdString; programMacroDefines.reserve(inPermuteOptions.size()); // Find the bits that are set and mask the associated bit mask with the program ID if (numPermuteOptions > 0) { for (size_t j = 0; j < numPermuteOptions; ++j) { const eastl::string& permuteIdString = UProgramPermutor::ConvertPIDMaskToString(inPermuteOptions[j].PermuteIdMask); currentProgramIdString += '['; if ((i & (0x1ULL << j)) != 0) { currentProgramId |= static_cast<ProgramId_t>(inPermuteOptions[j].PermuteIdMask); currentProgramIdString += '+'; programMacroDefines.push_back({ permuteIdString.c_str(), "1" }); } else { currentProgramIdString += "-"; } currentProgramIdString += permuteIdString; currentProgramIdString += ']'; } } else { currentProgramIdString += "[NO PERMUTE OPTIONS]"; } programMacroDefines.push_back({ nullptr, nullptr }); // Sentinel value necessary to determine when we are at end of macro define list // For each set of usage descriptions, we need to create a new entry within the output shader permutations outPermutations[currentProgramId] = eastl::make_shared<UPassProgram>(); for (const auto& currentUsageDescription : inUsageDescriptions) { compiledProgramByteCode.clear(); // To limit EProgramShaderType to string conversions, we convert at the very last moment // Draw back, we potentially do more than we should to find out its invalid at the end, but that's okay since this will be a pre-build step eventually //auto shaderTypeFindIter = URenderPassProgram::s_entryPointToShaderTypeMap.find(currentUsageDescription.ShaderEntryName); EProgramShaderType usageShaderType = URenderPassProgram::ConvertStringToShaderType(currentUsageDescription.ShaderEntryName); if (usageShaderType != EProgramShaderType::EProgramShaderType_Invalid) { if (graphicsDriver.CompileShaderFromFile(inShaderFilePath, currentUsageDescription.ShaderEntryName, currentUsageDescription.ShaderModelName, compiledProgramByteCode, (programMacroDefines.size() > 1) ? programMacroDefines.data() : nullptr)) { eastl::shared_ptr<UPassProgram> currentPassProgram = outPermutations[currentProgramId]; // Compilation successful (check what type of shader it is so we can set it properly in the program ID entry) switch (usageShaderType) { case EProgramShaderType::EProgramShaderType_VS: currentPassProgram->SetVS(graphicsDriver.CreateVertexShader(compiledProgramByteCode)); break; case EProgramShaderType::EProgramShaderType_GS: currentPassProgram->SetGS(graphicsDriver.CreateGeometryShader(compiledProgramByteCode)); break; case EProgramShaderType::EProgramShaderType_PS: currentPassProgram->SetPS(graphicsDriver.CreatePixelShader(compiledProgramByteCode)); break; } //LOG(LogProgramPermutor, Log, "Log: Size of compiled byte code: %d\n", compiledProgramByteCode.size()); if (inShouldGenPermutationFiles) { // Stores the generated shader permutation file in the same directory as the shader file that it is permuting eastl::string shaderFilePath = inShaderFilePath; size_t shaderFileNameBeginIndex = shaderFilePath.find_last_of('\\') + 1; size_t shaderFileNameEndIndex = shaderFilePath.find_last_of('.'); eastl::string shaderFileName(shaderFilePath.substr(shaderFileNameBeginIndex, shaderFileNameEndIndex - shaderFileNameBeginIndex)); shaderFilePath.erase(shaderFilePath.find_last_of('\\'), eastl::string::npos); GenerateProgramPermutationFile(shaderFilePath, shaderFileName, compiledProgramByteCode, currentUsageDescription, currentProgramId, currentProgramIdString); } } else { LOG(LogProgramPermutor, Error, "Error: Couldn't compile shader for usage of (%s-%s) and program ID of %d\n", currentUsageDescription.ShaderEntryName.c_str(), currentUsageDescription.ShaderModelName.c_str(), currentProgramId); } } else { LOG(LogProgramPermutor, Error, "Error: Invalid or unsupported shader usage meta flag (%s, %s)\n", currentUsageDescription.ShaderEntryName.c_str(), currentUsageDescription.ShaderModelName.c_str()); } } } } }