Plan renderer diagnostics in app status
This commit is contained in:
@@ -17,6 +17,7 @@ and validation command.
|
||||
| Version metadata | `scripts/pre-build.py`, `version.*` | build system, `pp_foundation` | Generated header smoke test, missing-tag behavior |
|
||||
| Thumbnail generation/read | `Canvas`, `Image` | `pp_assets`, `pp_paint_renderer` | Golden thumbnail, corrupt input, destination-feedback copy/fetch gate |
|
||||
| Save-as, overwrite prompts | App/dialogs | `pp_app_core`, `pp_panopainter_ui`, `pp_platform_*` | Decision tests, UI automation, and platform smoke |
|
||||
| App status and renderer diagnostics | App title/status widgets, extension indicators | `pp_app_core`, `pp_renderer_api`, `pp_panopainter_ui` | Title/status text tests, renderer diagnostic indicator tests, CLI status smoke, live layout adapter smoke |
|
||||
|
||||
## Image And Export
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -182,9 +182,11 @@ the live tools/options menu and `pano_cli plan-app-preferences` consume those
|
||||
contracts while legacy widgets and settings persistence execute them.
|
||||
It also owns tested app status/display plans for document title text,
|
||||
resolution mapping/labels, DPI text, history-memory text, and recording-frame
|
||||
status text; `App::title_update`, `App::update_memory_usage`,
|
||||
`App::update_rec_frames`, resolution helpers, and `pano_cli plan-app-status`
|
||||
consume those contracts while legacy UI nodes still render the strings.
|
||||
status text, plus renderer diagnostic indicator labels for framebuffer fetch
|
||||
and floating-point render targets; `App::title_update`,
|
||||
`App::update_memory_usage`, `App::update_rec_frames`, resolution helpers,
|
||||
`App::initLayout`, and `pano_cli plan-app-status` consume those contracts while
|
||||
legacy UI nodes still render the strings and status lights.
|
||||
`panopainter_app` is now a real static target that owns app orchestration
|
||||
sources, app version metadata, and version-header generation.
|
||||
`pp_panopainter_ui` now owns app-specific modal, dialog, panel, canvas,
|
||||
|
||||
@@ -33,6 +33,23 @@ struct RecordingFrameLabel {
|
||||
std::string text;
|
||||
};
|
||||
|
||||
struct RendererDiagnosticsInput {
|
||||
bool framebuffer_fetch = false;
|
||||
bool float32_render_targets = false;
|
||||
bool float32_linear_filtering = false;
|
||||
bool float16_render_targets = false;
|
||||
};
|
||||
|
||||
struct RendererDiagnosticIndicator {
|
||||
bool supported = false;
|
||||
std::string_view label;
|
||||
};
|
||||
|
||||
struct RendererDiagnosticsPlan {
|
||||
RendererDiagnosticIndicator framebuffer_fetch;
|
||||
RendererDiagnosticIndicator floating_point_targets;
|
||||
};
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<int> display_resolution_from_index(int index)
|
||||
{
|
||||
if (index < 0 || static_cast<std::size_t>(index) >= document_resolution_values.size()) {
|
||||
@@ -116,4 +133,38 @@ struct RecordingFrameLabel {
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] inline RendererDiagnosticsPlan plan_renderer_diagnostics(
|
||||
RendererDiagnosticsInput input) noexcept
|
||||
{
|
||||
RendererDiagnosticsPlan plan;
|
||||
plan.framebuffer_fetch = {
|
||||
input.framebuffer_fetch,
|
||||
"FBF",
|
||||
};
|
||||
|
||||
if (input.float32_linear_filtering) {
|
||||
plan.floating_point_targets = {
|
||||
true,
|
||||
"F32L",
|
||||
};
|
||||
} else if (input.float32_render_targets) {
|
||||
plan.floating_point_targets = {
|
||||
true,
|
||||
"F32",
|
||||
};
|
||||
} else if (input.float16_render_targets) {
|
||||
plan.floating_point_targets = {
|
||||
true,
|
||||
"F16",
|
||||
};
|
||||
} else {
|
||||
plan.floating_point_targets = {
|
||||
false,
|
||||
"",
|
||||
};
|
||||
}
|
||||
|
||||
return plan;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2179,23 +2179,28 @@ void App::initLayout()
|
||||
version_label->set_text(g_version);
|
||||
}
|
||||
|
||||
const auto renderer_features = ShaderManager::render_device_features();
|
||||
const auto renderer_diagnostics = pp::app::plan_renderer_diagnostics({
|
||||
.framebuffer_fetch = renderer_features.framebuffer_fetch,
|
||||
.float32_render_targets = renderer_features.float32_render_targets,
|
||||
.float32_linear_filtering = ShaderManager::ext_float32_linear,
|
||||
.float16_render_targets = renderer_features.float16_render_targets,
|
||||
});
|
||||
|
||||
if (auto x = layout[main_id]->find<NodeBorder>("ext-fbf"))
|
||||
{
|
||||
x->m_color = ShaderManager::ext_framebuffer_fetch ? glm::vec4(0, 1, 0, 1) : glm::vec4(1, 0, 0, 1);
|
||||
x->m_color = renderer_diagnostics.framebuffer_fetch.supported ?
|
||||
glm::vec4(0, 1, 0, 1) :
|
||||
glm::vec4(1, 0, 0, 1);
|
||||
}
|
||||
|
||||
if (auto x = layout[main_id]->find<NodeBorder>("ext-flt"))
|
||||
{
|
||||
if (ShaderManager::ext_float32 || ShaderManager::ext_float16)
|
||||
if (renderer_diagnostics.floating_point_targets.supported)
|
||||
{
|
||||
if (auto t = x->find<NodeText>("ext-flt-text"))
|
||||
{
|
||||
if (ShaderManager::ext_float32_linear)
|
||||
t->set_text("F32L");
|
||||
else if (ShaderManager::ext_float32)
|
||||
t->set_text("F32");
|
||||
else if (ShaderManager::ext_float16)
|
||||
t->set_text("F16");
|
||||
t->set_text(std::string(renderer_diagnostics.floating_point_targets.label));
|
||||
}
|
||||
x->m_color = glm::vec4(0, 1, 0, 1);
|
||||
}
|
||||
|
||||
@@ -905,16 +905,20 @@ if(TARGET pano_cli)
|
||||
--history-bytes 1572864
|
||||
--recording-running
|
||||
--encoder-available
|
||||
--encoded-frames 12)
|
||||
--encoded-frames 12
|
||||
--framebuffer-fetch
|
||||
--float32
|
||||
--float32-linear
|
||||
--float16)
|
||||
set_tests_properties(pano_cli_plan_app_status_smoke PROPERTIES
|
||||
LABELS "app;integration;desktop-fast"
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-status\".*\"title\":\"Panodoc: demo\\* \\(8K\\)\".*\"dpi\":\"1.3x-dpi\".*\"memory\":\"History memory: 1.50 Mb\".*\"recording\":\\{\"visible\":true,\"text\":\"Recorded 12 frames\"\\}.*\"fromIndexValid\":true.*\"fromIndex\":2048.*\"toIndexValid\":true.*\"toIndex\":3.*\"labelValid\":true.*\"label\":\"8K\"")
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-status\".*\"title\":\"Panodoc: demo\\* \\(8K\\)\".*\"dpi\":\"1.3x-dpi\".*\"memory\":\"History memory: 1.50 Mb\".*\"recording\":\\{\"visible\":true,\"text\":\"Recorded 12 frames\"\\}.*\"rendererDiagnostics\":\\{\"framebufferFetch\":\\{\"supported\":true,\"label\":\"FBF\"\\},\"floatingPointTargets\":\\{\"supported\":true,\"label\":\"F32L\"\\}\\}.*\"fromIndexValid\":true.*\"fromIndex\":2048.*\"toIndexValid\":true.*\"toIndex\":3.*\"labelValid\":true.*\"label\":\"8K\"")
|
||||
|
||||
add_test(NAME pano_cli_plan_app_status_unknown_resolution_smoke
|
||||
COMMAND pano_cli plan-app-status --doc-name demo --resolution 1234 --resolution-index 9 --recording-running)
|
||||
set_tests_properties(pano_cli_plan_app_status_unknown_resolution_smoke PROPERTIES
|
||||
LABELS "app;integration;desktop-fast;fuzz"
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-status\".*\"title\":\"Panodoc: demo \\(unknown\\)\".*\"recording\":\\{\"visible\":false,\"text\":\"\"\\}.*\"fromIndexValid\":false.*\"toIndexValid\":false.*\"labelValid\":false.*\"label\":\"\"")
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-status\".*\"title\":\"Panodoc: demo \\(unknown\\)\".*\"recording\":\\{\"visible\":false,\"text\":\"\"\\}.*\"rendererDiagnostics\":\\{\"framebufferFetch\":\\{\"supported\":false,\"label\":\"FBF\"\\},\"floatingPointTargets\":\\{\"supported\":false,\"label\":\"\"\\}\\}.*\"fromIndexValid\":false.*\"toIndexValid\":false.*\"labelValid\":false.*\"label\":\"\"")
|
||||
|
||||
add_test(NAME pano_cli_plan_document_resize_smoke
|
||||
COMMAND pano_cli plan-document-resize --current-resolution 2048 --selected-resolution-index 4)
|
||||
|
||||
@@ -71,6 +71,47 @@ void recording_label_only_shows_when_recording_with_encoder(pp::tests::Harness&
|
||||
PP_EXPECT(harness, active.text == "Recorded 12 frames");
|
||||
}
|
||||
|
||||
void renderer_diagnostics_report_framebuffer_fetch(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto unsupported = pp::app::plan_renderer_diagnostics({});
|
||||
PP_EXPECT(harness, !unsupported.framebuffer_fetch.supported);
|
||||
PP_EXPECT(harness, unsupported.framebuffer_fetch.label == "FBF");
|
||||
|
||||
const auto supported = pp::app::plan_renderer_diagnostics({
|
||||
.framebuffer_fetch = true,
|
||||
});
|
||||
PP_EXPECT(harness, supported.framebuffer_fetch.supported);
|
||||
PP_EXPECT(harness, supported.framebuffer_fetch.label == "FBF");
|
||||
}
|
||||
|
||||
void renderer_diagnostics_prefer_highest_float_capability_label(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto none = pp::app::plan_renderer_diagnostics({});
|
||||
PP_EXPECT(harness, !none.floating_point_targets.supported);
|
||||
PP_EXPECT(harness, none.floating_point_targets.label.empty());
|
||||
|
||||
const auto float16 = pp::app::plan_renderer_diagnostics({
|
||||
.float16_render_targets = true,
|
||||
});
|
||||
PP_EXPECT(harness, float16.floating_point_targets.supported);
|
||||
PP_EXPECT(harness, float16.floating_point_targets.label == "F16");
|
||||
|
||||
const auto float32 = pp::app::plan_renderer_diagnostics({
|
||||
.float32_render_targets = true,
|
||||
.float16_render_targets = true,
|
||||
});
|
||||
PP_EXPECT(harness, float32.floating_point_targets.supported);
|
||||
PP_EXPECT(harness, float32.floating_point_targets.label == "F32");
|
||||
|
||||
const auto float32_linear = pp::app::plan_renderer_diagnostics({
|
||||
.float32_render_targets = true,
|
||||
.float32_linear_filtering = true,
|
||||
.float16_render_targets = true,
|
||||
});
|
||||
PP_EXPECT(harness, float32_linear.floating_point_targets.supported);
|
||||
PP_EXPECT(harness, float32_linear.floating_point_targets.label == "F32L");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -82,5 +123,7 @@ int main()
|
||||
harness.run("document title survives unknown resolution", document_title_survives_unknown_resolution);
|
||||
harness.run("status labels match legacy text", status_labels_match_legacy_text);
|
||||
harness.run("recording label only shows when recording with encoder", recording_label_only_shows_when_recording_with_encoder);
|
||||
harness.run("renderer diagnostics report framebuffer fetch", renderer_diagnostics_report_framebuffer_fetch);
|
||||
harness.run("renderer diagnostics prefer highest float capability label", renderer_diagnostics_prefer_highest_float_capability_label);
|
||||
return harness.finish();
|
||||
}
|
||||
|
||||
@@ -236,6 +236,10 @@ struct PlanAppStatusArgs {
|
||||
bool recording_running = false;
|
||||
bool encoder_available = false;
|
||||
std::uint32_t encoded_frames = 0;
|
||||
bool framebuffer_fetch = false;
|
||||
bool float32_render_targets = false;
|
||||
bool float32_linear_filtering = false;
|
||||
bool float16_render_targets = false;
|
||||
};
|
||||
|
||||
struct PlanDocumentResizeArgs {
|
||||
@@ -1766,7 +1770,7 @@ void print_help()
|
||||
<< " plan-cloud-upload-all [--file-count N] [--no-progress-ui]\n"
|
||||
<< " plan-recording-session [--running] [--frame-count N] [--platform-deletes-recorded-files]\n"
|
||||
<< " plan-app-preferences [--ui-scale N] [--display-density N] [--current-scale N] [--scale-option N] [--viewport-scale N] [--rtl] [--timelapse-disabled] [--recording-running] [--vr-controllers-disabled] [--cursor-mode N]\n"
|
||||
<< " plan-app-status [--doc-name NAME] [--unsaved] [--resolution N] [--resolution-index N] [--zoom N] [--history-bytes N] [--recording-running] [--encoder-available] [--encoded-frames N]\n"
|
||||
<< " plan-app-status [--doc-name NAME] [--unsaved] [--resolution N] [--resolution-index N] [--zoom N] [--history-bytes N] [--recording-running] [--encoder-available] [--encoded-frames N] [--framebuffer-fetch] [--float32] [--float32-linear] [--float16]\n"
|
||||
<< " plan-tools-menu --command panels|options|clear-grids|reset-camera|shortcuts|sonarpen [--sonarpen-available]\n"
|
||||
<< " plan-tools-panel --panel presets|color|color-advanced|layers|brush|grids|animation [--already-visible]\n"
|
||||
<< " plan-about-menu --command help|about|news|crash|performance [--version-major N] [--version-minor N] [--version-fix N] [--no-diagnostics] [--no-canvas]\n"
|
||||
@@ -3558,6 +3562,14 @@ pp::foundation::Status parse_plan_app_status_args(
|
||||
args.recording_running = true;
|
||||
} else if (key == "--encoder-available") {
|
||||
args.encoder_available = true;
|
||||
} else if (key == "--framebuffer-fetch") {
|
||||
args.framebuffer_fetch = true;
|
||||
} else if (key == "--float32") {
|
||||
args.float32_render_targets = true;
|
||||
} else if (key == "--float32-linear") {
|
||||
args.float32_linear_filtering = true;
|
||||
} else if (key == "--float16") {
|
||||
args.float16_render_targets = true;
|
||||
} else {
|
||||
return pp::foundation::Status::invalid_argument("unknown option");
|
||||
}
|
||||
@@ -3582,6 +3594,12 @@ int plan_app_status(int argc, char** argv)
|
||||
args.recording_running,
|
||||
args.encoder_available,
|
||||
static_cast<int>(args.encoded_frames));
|
||||
const auto diagnostics = pp::app::plan_renderer_diagnostics({
|
||||
.framebuffer_fetch = args.framebuffer_fetch,
|
||||
.float32_render_targets = args.float32_render_targets,
|
||||
.float32_linear_filtering = args.float32_linear_filtering,
|
||||
.float16_render_targets = args.float16_render_targets,
|
||||
});
|
||||
|
||||
std::cout << "{\"ok\":true,\"command\":\"plan-app-status\""
|
||||
<< ",\"state\":{\"documentName\":\"" << json_escape(args.document_name)
|
||||
@@ -3593,6 +3611,10 @@ int plan_app_status(int argc, char** argv)
|
||||
<< ",\"recordingRunning\":" << json_bool(args.recording_running)
|
||||
<< ",\"encoderAvailable\":" << json_bool(args.encoder_available)
|
||||
<< ",\"encodedFrames\":" << args.encoded_frames
|
||||
<< ",\"framebufferFetch\":" << json_bool(args.framebuffer_fetch)
|
||||
<< ",\"float32\":" << json_bool(args.float32_render_targets)
|
||||
<< ",\"float32Linear\":" << json_bool(args.float32_linear_filtering)
|
||||
<< ",\"float16\":" << json_bool(args.float16_render_targets)
|
||||
<< "},\"title\":\"" << json_escape(pp::app::make_document_title(
|
||||
args.document_name,
|
||||
args.unsaved,
|
||||
@@ -3601,7 +3623,13 @@ int plan_app_status(int argc, char** argv)
|
||||
<< "\",\"memory\":\"" << json_escape(pp::app::make_history_memory_label(args.history_bytes))
|
||||
<< "\",\"recording\":{\"visible\":" << json_bool(recording_label.visible)
|
||||
<< ",\"text\":\"" << json_escape(recording_label.text)
|
||||
<< "\"},\"resolutionMap\":{\"fromIndexValid\":" << json_bool(static_cast<bool>(resolution_from_index))
|
||||
<< "\"},\"rendererDiagnostics\":{\"framebufferFetch\":{\"supported\":"
|
||||
<< json_bool(diagnostics.framebuffer_fetch.supported)
|
||||
<< ",\"label\":\"" << json_escape(std::string(diagnostics.framebuffer_fetch.label))
|
||||
<< "\"},\"floatingPointTargets\":{\"supported\":"
|
||||
<< json_bool(diagnostics.floating_point_targets.supported)
|
||||
<< ",\"label\":\"" << json_escape(std::string(diagnostics.floating_point_targets.label))
|
||||
<< "\"}},\"resolutionMap\":{\"fromIndexValid\":" << json_bool(static_cast<bool>(resolution_from_index))
|
||||
<< ",\"fromIndex\":" << (resolution_from_index ? resolution_from_index.value() : 0)
|
||||
<< ",\"toIndexValid\":" << json_bool(static_cast<bool>(resolution_index))
|
||||
<< ",\"toIndex\":" << (resolution_index ? resolution_index.value() : 0)
|
||||
|
||||
Reference in New Issue
Block a user