Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Depends on #8344] Implement ApiHandler functions and add JsonWriter #8379

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5ec4de6
Introduce FrameGraphInfo class
show50726 Dec 23, 2024
6eb7196
Move the assignment into pimpl
show50726 Dec 23, 2024
04afaa9
Make ctors explicit
show50726 Jan 1, 2025
1cd1d70
Add ctors to fg info structs
show50726 Jan 1, 2025
e59b111
Revert the macro change to align with existing
show50726 Jan 1, 2025
c02d231
Address the comments
show50726 Jan 8, 2025
41ee934
Merge branch 'main' into dev/framegraph-info
show50726 Jan 10, 2025
077e841
Merge branch 'main' into dev/framegraph-info
show50726 Jan 15, 2025
e6a3af6
Remove pimpl and move func def to .cc
show50726 Jan 17, 2025
a7f8176
Fix
show50726 Jan 17, 2025
1b41bf8
Convert the FrameGraph to FrameGraphInfo
show50726 Jan 1, 2025
ccc4f8a
Initialize and update debug server on engine side
show50726 Jan 10, 2025
802531c
Merge branch 'main' into dev/fginfo-conversion
show50726 Jan 18, 2025
4618bf5
Fix compile error
show50726 Jan 18, 2025
0429512
Address the comments
show50726 Jan 18, 2025
cfafbaf
Update
show50726 Jan 18, 2025
262f594
Use camelCase
show50726 Jan 18, 2025
91dc91e
Use camelCase
show50726 Jan 18, 2025
f05400c
Update
show50726 Jan 18, 2025
6dcfbb7
Add JsonWriter to convert fginfo to json
show50726 Jan 15, 2025
96a4675
Add getStatus api and implement it
show50726 Jan 15, 2025
482a7f1
Add increment
show50726 Jan 15, 2025
1ccf6b5
Implement GET apis
show50726 Jan 15, 2025
17aa06c
Fix compile error
show50726 Jan 17, 2025
4fe894c
Update
show50726 Jan 22, 2025
14ea247
Use c_str_safe
show50726 Jan 26, 2025
afb9987
Merge branch 'main' into dev/api-handling
show50726 Feb 2, 2025
57502a4
Add operator== for FrameGraphInfo
show50726 Feb 3, 2025
0e4cfc2
Call updateFrameGraph in appropriate locations
show50726 Feb 3, 2025
8715fc5
Address the comments
show50726 Feb 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions filament/src/details/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,25 @@ int FEngine::loop() {
}
#endif

#if FILAMENT_ENABLE_FGVIEWER
#ifdef __ANDROID__
const char* fgviewerPortString = "8085";
#else
const char* fgviewerPortString = getenv("FILAMENT_FGVIEWER_PORT");
#endif
if (fgviewerPortString != nullptr) {
const int fgviewerPort = atoi(fgviewerPortString);
debug.fgviewerServer = new fgviewer::DebugServer(fgviewerPort);

// Sometimes the server can fail to spin up (e.g. if the above port is already in use).
// When this occurs, carry onward, developers can look at civetweb.txt for details.
if (!debug.fgviewerServer->isReady()) {
delete debug.fgviewerServer;
debug.fgviewerServer = nullptr;
}
}
#endif

JobSystem::setThreadName("FEngine::loop");
JobSystem::setThreadPriority(JobSystem::Priority::DISPLAY);

Expand Down
9 changes: 9 additions & 0 deletions filament/src/details/Engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ using MaterialKey = uint32_t;
} // namespace filament::matdbg
#endif

#if FILAMENT_ENABLE_FGVIEWER
#include <fgviewer/DebugServer.h>
#else
namespace filament::fgviewer {
class DebugServer;
} // namespace filament::fgviewer
#endif

namespace filament {

class Renderer;
Expand Down Expand Up @@ -680,6 +688,7 @@ class FEngine : public Engine {
bool combine_multiview_images = false;
} stereo;
matdbg::DebugServer* server = nullptr;
fgviewer::DebugServer* fgviewerServer = nullptr;
} debug;

struct {
Expand Down
7 changes: 7 additions & 0 deletions filament/src/details/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1437,6 +1437,13 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {

fg.compile();

#if FILAMENT_ENABLE_FGVIEWER
fgviewer::DebugServer* fgviewerServer = engine.debug.fgviewerServer;
if (UTILS_LIKELY(fgviewerServer)) {
fgviewerServer->update(view.getViewHandle(), fg.getFrameGraphInfo(view.getName()));
}
#endif

//fg.export_graphviz(slog.d, view.getName());

fg.execute(driver);
Expand Down
15 changes: 15 additions & 0 deletions filament/src/details/View.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ FView::FView(FEngine& engine)
}
#endif

#if FILAMENT_ENABLE_FGVIEWER
fgviewer::DebugServer* fgviewerServer = engine.debug.fgviewerServer;
if (UTILS_LIKELY(fgviewerServer)) {
mFrameGraphViewerViewHandle =
fgviewerServer->createView(utils::CString(getName()));
}
#endif

// allocate UBOs
mLightUbh = driver.createBufferObject(CONFIG_MAX_LIGHT_COUNT * sizeof(LightsUib),
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
Expand Down Expand Up @@ -153,6 +161,13 @@ void FView::terminate(FEngine& engine) {
engine.getDebugRegistry().unregisterDataSource("d.view.frame_info");
}
#endif

#if FILAMENT_ENABLE_FGVIEWER
fgviewer::DebugServer* fgviewerServer = engine.debug.fgviewerServer;
if (UTILS_LIKELY(fgviewerServer)) {
fgviewerServer->destroyView(mFrameGraphViewerViewHandle);
}
#endif
}

void FView::setViewport(filament::Viewport const& viewport) noexcept {
Expand Down
14 changes: 14 additions & 0 deletions filament/src/details/View.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@
#include <utils/Range.h>
#include <utils/Slice.h>

#if FILAMENT_ENABLE_FGVIEWER
#include <fgviewer/DebugServer.h>
#else
namespace filament::fgviewer {
using ViewHandle = uint32_t;
}
#endif

#include <math/scalar.h>
#include <math/mat4.h>

Expand Down Expand Up @@ -467,6 +475,10 @@ class FView : public View {
return mUniforms;
}

fgviewer::ViewHandle getViewHandle() const noexcept {
return mFrameGraphViewerViewHandle;
}

private:
struct FPickingQuery : public PickingQuery {
private:
Expand Down Expand Up @@ -600,6 +612,8 @@ class FView : public View {
{ 0, 0, 0, 1 },
}};

fgviewer::ViewHandle mFrameGraphViewerViewHandle;

#ifndef NDEBUG
struct DebugState {
std::unique_ptr<std::array<DebugRegistry::FrameHistory, 5*60>> debugFrameHistory{};
Expand Down
55 changes: 55 additions & 0 deletions filament/src/fg/FrameGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,61 @@ void FrameGraph::export_graphviz(utils::io::ostream& out, char const* name) {
mGraph.export_graphviz(out, name);
}

fgviewer::FrameGraphInfo FrameGraph::getFrameGraphInfo(const char *viewName) const {
#if FILAMENT_ENABLE_FGVIEWER
fgviewer::FrameGraphInfo info{utils::CString(viewName)};
std::vector<fgviewer::FrameGraphInfo::Pass> passes;

auto first = mPassNodes.begin();
const auto activePassNodesEnd = mActivePassNodesEnd;
while (first != activePassNodesEnd) {
PassNode *const pass = *first;
first++;

assert_invariant(!pass->isCulled());
std::vector<fgviewer::ResourceId> reads;
auto const &readEdges = mGraph.getIncomingEdges(pass);
for (auto const &edge: readEdges) {
// all incoming edges should be valid by construction
assert_invariant(mGraph.isEdgeValid(edge));
reads.push_back(edge->from);
}

std::vector<fgviewer::ResourceId> writes;
auto const &writeEdges = mGraph.getOutgoingEdges(pass);
for (auto const &edge: writeEdges) {
// It is possible that the node we're writing to has been culled.
// In this case we'd like to ignore the edge.
if (!mGraph.isEdgeValid(edge)) {
continue;
}
writes.push_back(edge->to);
}
passes.emplace_back(utils::CString(pass->getName()),
std::move(reads), std::move(writes));
}

std::unordered_map<fgviewer::ResourceId, fgviewer::FrameGraphInfo::Resource> resources;
for (const auto &resource: mResourceNodes) {
std::vector<fgviewer::FrameGraphInfo::Resource::Property> resourceProps;
// TODO: Fill in resource properties
fgviewer::ResourceId id = resource->getId();
resources.emplace(id, fgviewer::FrameGraphInfo::Resource(
id, utils::CString(resource->getName()),
std::move(resourceProps))
);
}

info.setResources(std::move(resources));
info.setPasses(std::move(passes));

return info;
#else
return fgviewer::FrameGraphInfo();
#endif
}


// ------------------------------------------------------------------------------------------------

/*
Expand Down
14 changes: 14 additions & 0 deletions filament/src/fg/FrameGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@

#include <functional>

#if FILAMENT_ENABLE_FGVIEWER
#include <fgviewer/FrameGraphInfo.h>
#else
namespace filament::fgviewer {
class FrameGraphInfo{};
} // namespace filament::fgviewer
#endif

namespace filament {

class ResourceAllocatorInterface;
Expand Down Expand Up @@ -434,6 +442,12 @@ class FrameGraph {
//! export a graphviz view of the graph
void export_graphviz(utils::io::ostream& out, const char* name = nullptr);

/**
* Export a fgviewer::FrameGraphInfo for current graph.
* Note that this function should be called after FrameGraph::compile().
*/
fgviewer::FrameGraphInfo getFrameGraphInfo(const char *viewName) const;

private:
friend class FrameGraphResources;
friend class PassNode;
Expand Down
1 change: 1 addition & 0 deletions libs/fgviewer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ set(SRCS
src/ApiHandler.h
src/DebugServer.cpp
src/FrameGraphInfo.cpp
src/JsonWriter.cpp
show50726 marked this conversation as resolved.
Show resolved Hide resolved
)

# ==================================================================================================
Expand Down
2 changes: 0 additions & 2 deletions libs/fgviewer/include/fgviewer/DebugServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ namespace filament::fgviewer {

using ViewHandle = uint32_t;



/**
* Server-side frame graph debugger.
*
Expand Down
8 changes: 7 additions & 1 deletion libs/fgviewer/include/fgviewer/FrameGraphInfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024 The Android Open Source Project
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -70,6 +70,12 @@ class FrameGraphInfo {
// The incoming passes should be sorted by the execution order.
void setPasses(std::vector<Pass> sortedPasses);

const char* getViewName() const;

const std::vector<Pass>& getPasses() const;

const std::unordered_map<ResourceId, Resource>& getResources() const;

private:
utils::CString viewName;
// The order of the passes in the vector indicates the execution
Expand Down
100 changes: 84 additions & 16 deletions libs/fgviewer/src/ApiHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "ApiHandler.h"

#include <fgviewer/DebugServer.h>
#include <fgviewer/JsonWriter.h>

#include <utils/FixedCapacityVector.h>
#include <utils/Log.h>
Expand All @@ -40,29 +41,96 @@ auto const error = [](int line, std::string const& uri) {

} // anonymous

bool ApiHandler::handleGetApiFgInfo(struct mg_connection* conn,
struct mg_request_info const* request) {
auto const softError = [conn, request](char const* msg) {
utils::slog.e << "[fgviewer] DebugServer: " << msg << ": " << request->query_string << utils::io::endl;
mg_printf(conn, kErrorHeader.data(), "application/txt");
mg_write(conn, msg, strlen(msg));
bool ApiHandler::handleGet(CivetServer* server, struct mg_connection* conn) {
struct mg_request_info const* request = mg_get_request_info(conn);
std::string const& uri = request->local_uri;

if (uri.find("/api/status") == 0) {
return handleGetStatus(conn, request);
}

if (uri == "/api/framegraphs") {
std::unique_lock const lock(mServer->mViewsMutex);
mg_printf(conn, kSuccessHeader.data(), "application/json");
mg_printf(conn, "[");
int index = 0;
for (auto const& view: mServer->mViews) {
bool const last = (++index) == mServer->mViews.size();

JsonWriter writer;
if (!writer.writeFrameGraphInfo(view.second)) {
return error(__LINE__, uri);
}

mg_printf(conn, "{ \"fgid\": \"%8.8x\", %s } %s", view.first, writer.getJsonString(),
last ? "" : ",");
}
mg_printf(conn, "]");
return true;
}

if (uri == "/api/framegraph") {
const FrameGraphInfo* result = getFrameGraphInfo(conn, request);
if (!result) {
return error(__LINE__, uri);
}

JsonWriter writer;
if (!writer.writeFrameGraphInfo(*result)) {
return error(__LINE__, uri);
}
mg_printf(conn, kSuccessHeader.data(), "application/json");
mg_printf(conn, "{ %s }", writer.getJsonString());
return true;
};
}

// TODO: Implement the method
return true;
return error(__LINE__, uri);
}

void ApiHandler::addFrameGraph(FrameGraphInfo const* framegraph) {
// TODO: Implement the method
void ApiHandler::addFrameGraph(ViewHandle view_handle) {
std::unique_lock const lock(mStatusMutex);
snprintf(statusFrameGraphId, sizeof(statusFrameGraphId), "%8.8x", view_handle);
mStatusCondition.notify_all();
}

const FrameGraphInfo* ApiHandler::getFrameGraphInfo(struct mg_connection* conn,
show50726 marked this conversation as resolved.
Show resolved Hide resolved
struct mg_request_info const* request) {
size_t const qlength = strlen(request->query_string);
char fgid[9] = {};
if (mg_get_var(request->query_string, qlength, "fgid", fgid, sizeof(fgid)) < 0) {
return nullptr;
}
uint32_t const id = strtoul(fgid, nullptr, 16);
std::unique_lock const lock(mServer->mViewsMutex);
const auto it = mServer->mViews.find(id);
return it == mServer->mViews.end()
? nullptr
: &(it->second);
}

bool ApiHandler::handleGet(CivetServer* server, struct mg_connection* conn) {
struct mg_request_info const* request = mg_get_request_info(conn);
std::string const& uri = request->local_uri;

// TODO: Implement the method
bool ApiHandler::handleGetStatus(struct mg_connection* conn,
struct mg_request_info const* request) {
char const* qstr = request->query_string;
if (qstr && strcmp(qstr, "firstTime") == 0) {
mg_printf(conn, kSuccessHeader.data(), "application/txt");
mg_write(conn, "0", 1);
return true;
}

std::unique_lock<std::mutex> lock(mStatusMutex);
uint64_t const currentStatusCount = mCurrentStatus;
if (mStatusCondition.wait_for(lock, 10s,
[this, currentStatusCount] {
return currentStatusCount < mCurrentStatus;
})) {
mg_printf(conn, kSuccessHeader.data(), "application/txt");
mg_write(conn, statusFrameGraphId, 8);
} else {
mg_printf(conn, kSuccessHeader.data(), "application/txt");
// Use '1' to indicate a no-op. This ensures that we don't block forever if the client is
// gone.
mg_write(conn, "1", 1);
}
return true;
}

Expand Down
Loading
Loading