From 8c46e6de9b73f98d974cba9713341dda298fb4fd Mon Sep 17 00:00:00 2001 From: Philip Rideout Date: Wed, 2 Mar 2022 10:57:12 -0800 Subject: [PATCH] matdbg: repair invalid JSON and display of active variants. The JSON response to /api/active became malformed after #4465 because raw hex strings need to be enclosed by quotes. This commit changes the variant format in the /api/materials response to be consistent with one used for /api/active. By using integers instead of strings, we're avoiding the need to parse integers at run time. The JSON error did not appear in the Chrome console because it was being silenced as a hack to appease "matinfo --web-server". I fix this by removing the hack and simply emitting a valid response when there's no live backend. Also fixed the display of materials, which were always being marked as active even when they had no active variants. --- filament/src/details/Material.h | 7 +++++-- libs/matdbg/README.md | 6 ++++-- libs/matdbg/src/DebugServer.cpp | 10 +++++++++- libs/matdbg/src/JsonWriter.cpp | 4 +--- libs/matdbg/web/script.js | 17 +++++++++++------ 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/filament/src/details/Material.h b/filament/src/details/Material.h index ace927d7f7..c97142dea9 100644 --- a/filament/src/details/Material.h +++ b/filament/src/details/Material.h @@ -79,6 +79,7 @@ public: backend::Handle getProgram(Variant variant) const noexcept { #if FILAMENT_ENABLE_MATDBG + assert_invariant(variant.key < VARIANT_COUNT); mActivePrograms.set(variant.key); if (UTILS_UNLIKELY(mPendingEdits.load())) { const_cast(this)->applyPendingEdits(); @@ -89,8 +90,6 @@ public: } backend::Program getProgramBuilderWithVariants(Variant variant, Variant vertexVariant, Variant fragmentVariant) const noexcept; - backend::Handle createAndCacheProgram(backend::Program&& p, - Variant variant) const noexcept; bool isVariantLit() const noexcept { return mIsVariantLit; } @@ -168,10 +167,14 @@ private: backend::Handle getSurfaceProgramSlow(Variant variant) const noexcept; backend::Handle getPostProcessProgramSlow(Variant variant) const noexcept; + backend::Handle createAndCacheProgram(backend::Program&& p, + Variant variant) const noexcept; + // try to order by frequency of use mutable std::array, VARIANT_COUNT> mCachedPrograms; #if FILAMENT_ENABLE_MATDBG + // TODO: this should be protected with a mutex mutable VariantList mActivePrograms; #endif diff --git a/libs/matdbg/README.md b/libs/matdbg/README.md index cde88e0275..bc71188e35 100644 --- a/libs/matdbg/README.md +++ b/libs/matdbg/README.md @@ -167,8 +167,8 @@ Returns an array with all information (except shader source) for all known mater "shading": { "model": "unlit", "vertex_domain": "object", ... }, "raster": { "blending": "transparent", "color_write": "true", ... }, "opengl": [ - { "index": " 0", "shaderModel": "gl41", "pipelineStage": "vertex ", "variantString": "", "variant": "0" }, - { "index": " 1", "shaderModel": "gl41", "pipelineStage": "fragment", "variantString": "", "variant": "0" }, + { "index": " 0", "shaderModel": "gl41", "pipelineStage": "vertex ", "variantString": "", "variant": 0 }, + { "index": " 1", "shaderModel": "gl41", "pipelineStage": "fragment", "variantString": "", "variant": 0 }, ], "vulkan": [], "metal": [], @@ -184,6 +184,8 @@ Some of the returned data may seem redundant (e.g. the `index` and `variantStrin these allow the client to be very simple by passing the raw JSON into [mustache][4] templates. Moreover it helps prevent duplication of knowledge between C++ and JavaScript. +This format of this message is also used for the in-browser "database" of materials. + --- `/api/material?matid={id}` diff --git a/libs/matdbg/src/DebugServer.cpp b/libs/matdbg/src/DebugServer.cpp index d9e867a9f6..8e93275a3f 100644 --- a/libs/matdbg/src/DebugServer.cpp +++ b/libs/matdbg/src/DebugServer.cpp @@ -144,7 +144,7 @@ public: std::string uri(request->local_uri); const auto error = [request](int line) { - slog.e << "DebugServer: 404 at line " << line << ": " << request->query_string + slog.e << "DebugServer: 404 at line " << line << ": " << request->local_uri << io::endl; return false; }; @@ -160,6 +160,14 @@ public: mServer->updateActiveVariants(); mg_printf(conn, kSuccessHeader.c_str(), "application/json"); mg_printf(conn, "{"); + + // If the backend has not been resolved to Vulkan, Metal, etc, then return an empty + // list. This can occur if the server is matinfo rather than an actual Filament session. + if (mServer->mBackend == backend::Backend::DEFAULT) { + mg_printf(conn, "}"); + return true; + } + int index = 0; for (const auto& pair : mServer->mMaterialRecords) { const auto& record = pair.second; diff --git a/libs/matdbg/src/JsonWriter.cpp b/libs/matdbg/src/JsonWriter.cpp index 16d19fc22e..a7114cda71 100644 --- a/libs/matdbg/src/JsonWriter.cpp +++ b/libs/matdbg/src/JsonWriter.cpp @@ -128,7 +128,7 @@ static void printShaderInfo(ostream& json, const vector& info, const << "\"shaderModel\": \"" << toString(item.shaderModel) << "\", " << "\"pipelineStage\": \"" << ps << "\", " << "\"variantString\": \"" << variantString << "\", " - << "\"variant\": \"" << std::hex << +item.variant.key << std::dec << "\" }" + << "\"variant\": " << +item.variant.key << " }" << ((i == info.size() - 1) ? "\n" : ",\n"); } } @@ -241,13 +241,11 @@ bool JsonWriter::writeActiveInfo(const filaflat::ChunkContainer& package, return false; } json << "\""; - json << std::hex; for (size_t variant = 0; variant < activeVariants.size(); variant++) { if (activeVariants[variant]) { json << ", " << variant; } } - json << std::dec; json << "]"; mJsonString = CString(json.str().c_str()); return true; diff --git a/libs/matdbg/web/script.js b/libs/matdbg/web/script.js index 79d997e6c3..4c22e94dc0 100644 --- a/libs/matdbg/web/script.js +++ b/libs/matdbg/web/script.js @@ -171,25 +171,26 @@ function queryActiveShaders() { fetch("api/active").then(function(response) { return response.json(); }).then(function(activeMaterials) { + // The only active materials are the ones with active variants. for (matid in gMaterialDatabase) { const material = gMaterialDatabase[matid]; - material.active = matid in activeMaterials; + material.active = false; } for (matid in activeMaterials) { const material = gMaterialDatabase[matid]; const activeBackend = activeMaterials[matid][0]; const activeShaders = activeMaterials[matid].slice(1); for (const shader of material[activeBackend]) { - const variant = parseInt(shader.variant); - shader.active = activeShaders.indexOf(variant) > -1; + shader.active = activeShaders.indexOf(shader.variant) > -1; + material.active = material.active || shader.active; } } renderMaterialList(); renderMaterialDetail(); }) - .catch((error) => { - // This is expected to fail when the server is hosted from matinfo instead of Engine, since - // there are no active shaders in that situation. + .catch(error => { + // This can occur if the JSON is invalid. + console.error(error); }); } @@ -488,6 +489,10 @@ function init() { Mustache.parse(matListTemplate.innerHTML); startSocket(); + + // Poll for active shaders once every second. + // Take care not to poll more frequently than the frame rate. Active variants are determined + // by the list of variants that were fetched between this query and the previous query. setInterval(queryActiveShaders, 1000); }