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 all 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
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
)

# ==================================================================================================
Expand Down
16 changes: 15 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 @@ -36,17 +36,25 @@ class FrameGraphInfo {

FrameGraphInfo(FrameGraphInfo const &) = delete;

bool operator==(const FrameGraphInfo& rhs) const;

struct Pass {
Pass(utils::CString name, std::vector<ResourceId> reads,
std::vector<ResourceId> writes);

bool operator==(const Pass& rhs) const;

utils::CString name;
std::vector<ResourceId> reads;
std::vector<ResourceId> writes;
};

struct Resource {
bool operator==(const Resource& rhs) const;

struct Property {
bool operator==(const Property& rhs) const;

utils::CString name;
utils::CString value;
};
Expand All @@ -70,6 +78,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(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::updateFrameGraph(ViewHandle view_handle) {
std::unique_lock const lock(mStatusMutex);
snprintf(statusFrameGraphId, sizeof(statusFrameGraphId), "%8.8x", view_handle);
mCurrentStatus++;
mStatusCondition.notify_all();
}

const FrameGraphInfo* ApiHandler::getFrameGraphInfo(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
22 changes: 19 additions & 3 deletions libs/fgviewer/src/ApiHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#ifndef FGVIEWER_APIHANDLER_H
#define FGVIEWER_APIHANDLER_H

#include <fgviewer/DebugServer.h>

#include <CivetServer.h>

namespace filament::fgviewer {
Expand All @@ -27,7 +29,8 @@ struct FrameGraphInfo;
// Handles the following REST requests, where {id} is an 8-digit hex string.
//
// GET /api/framegraphs
// GET /api/framegraph?fg={viewname}
// GET /api/framegraph?fg={fgid}
// GET /api/status
//
class ApiHandler : public CivetHandler {
public:
Expand All @@ -36,12 +39,25 @@ class ApiHandler : public CivetHandler {
~ApiHandler() = default;

bool handleGet(CivetServer* server, struct mg_connection* conn);
void addFrameGraph(FrameGraphInfo const* frameGraph);

void updateFrameGraph(ViewHandle view_handle);

private:
bool handleGetApiFgInfo(struct mg_connection* conn, struct mg_request_info const* request);
const FrameGraphInfo* getFrameGraphInfo(struct mg_request_info const* request);

bool handleGetStatus(struct mg_connection* conn,
struct mg_request_info const* request);

DebugServer* mServer;

std::mutex mStatusMutex;
std::condition_variable mStatusCondition;
char statusFrameGraphId[9] = {};

// This variable is to implement a *hanging* effect for /api/status. The call to /api/status
// will always block until statusMaterialId is updated again. The client is expected to keep
// calling /api/status (a constant "pull" to simulate a push).
uint64_t mCurrentStatus = 0;
};

} // filament::fgviewer
Expand Down
12 changes: 12 additions & 0 deletions libs/fgviewer/src/DebugServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ ViewHandle DebugServer::createView(utils::CString name) {
std::unique_lock<utils::Mutex> lock(mViewsMutex);
ViewHandle handle = mViewCounter++;
mViews.emplace(handle, FrameGraphInfo(std::move(name)));
mApiHandler->updateFrameGraph(handle);

return handle;
}
Expand All @@ -121,8 +122,19 @@ void DebugServer::destroyView(ViewHandle h) {

void DebugServer::update(ViewHandle h, FrameGraphInfo info) {
std::unique_lock<utils::Mutex> lock(mViewsMutex);
const auto it = mViews.find(h);
if (it == mViews.end()) {
slog.w << "[fgviewer] Received update for unknown handle " << h;
return;
}

bool has_changed = !(it->second == info);
if (!has_changed)
return;

mViews.erase(h);
mViews.emplace(h, std::move(info));
mApiHandler->updateFrameGraph(h);
}

} // namespace filament::fgviewer
33 changes: 32 additions & 1 deletion libs/fgviewer/src/FrameGraphInfo.cpp
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 All @@ -25,15 +25,33 @@ FrameGraphInfo::~FrameGraphInfo() = default;

FrameGraphInfo::FrameGraphInfo(FrameGraphInfo&& rhs) noexcept = default;

bool FrameGraphInfo::operator==(const FrameGraphInfo& rhs) const {
return viewName == rhs.viewName
&& passes == rhs.passes
&& resources == rhs.resources;
}

FrameGraphInfo::Pass::Pass(utils::CString name, std::vector<ResourceId> reads,
std::vector<ResourceId> writes): name(std::move(name)),
reads(std::move(reads)),
writes(std::move(writes)) {}

bool FrameGraphInfo::Pass::operator==(const Pass& rhs) const {
return name == rhs.name && reads == rhs.reads && writes == rhs.writes;
}

FrameGraphInfo::Resource::Resource(ResourceId id, utils::CString name,
std::vector<Property> properties): id(id),
name(std::move(name)), properties(std::move(properties)) {}

bool FrameGraphInfo::Resource::operator==(const Resource& rhs) const {
return id == rhs.id && name == rhs.name && properties == rhs.properties;
}

bool FrameGraphInfo::Resource::Property::operator==(const Property &rhs) const {
return name == rhs.name && value == rhs.value;
}

void FrameGraphInfo::setResources(
std::unordered_map<ResourceId, Resource> resources) {
this->resources = std::move(resources);
Expand All @@ -43,4 +61,17 @@ void FrameGraphInfo::setPasses(std::vector<Pass> sortedPasses) {
passes = std::move(sortedPasses);
}

const char* FrameGraphInfo::getViewName() const {
return viewName.c_str_safe();
}

const std::vector<FrameGraphInfo::Pass>& FrameGraphInfo::getPasses() const {
return passes;
}

const std::unordered_map<ResourceId, FrameGraphInfo::Resource>&
FrameGraphInfo::getResources() const {
return resources;
}

} // namespace filament::fgviewer
Loading