diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index eed353e..2892be4 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -289,12 +289,12 @@ Known local toolchain state: sampler-state binding, texture-upload byte counts, readback bounds, frame-capture sources, destination buffer sizes, and render-target blit regions, records render/scissor/depth/blend/texture-bind/sampler-bind/upload/ - readback/frame-capture/blit commands, and records trace markers without a - window or GL context. + readback/frame-capture/blit commands, draw mesh inputs, and records trace + markers without a window or GL context. - `pano_cli record-render` exposes the recording renderer through JSON automation, including scissor/depth/blend/texture-bind/sampler-bind/upload/ - readback/frame-capture/blit command and byte totals, and is covered by - `pano_cli_record_render_smoke` plus + readback/frame-capture/blit command and byte totals plus draw vertex/index + totals, and is covered by `pano_cli_record_render_smoke` plus `pano_cli_record_render_rejects_oversized_target`. - `pano_cli simulate-document-history` exposes `pp_document::DocumentHistory` apply/undo/redo state through JSON automation and is covered by diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 6e7fb11..eedf591 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -725,7 +725,7 @@ Results: command-order validation, render-target blit validation, texture-slot binding validation, blend-state validation, scissor-state validation, recording scissor/depth/blend/texture/sampler-bind/upload/readback/frame-capture/blit - command capture, and invalid catalog rejection. + command capture, draw mesh-input capture, and invalid catalog rejection. - `pp_paint_renderer_compositor_tests` passed. - `pp_ui_core_color_tests` passed. - `pp_ui_core_layout_value_tests` passed. @@ -822,14 +822,14 @@ Results: command-order/scissor-state/depth-state/blend-state/texture-bind/ sampler-bind/texture-upload/readback/frame-capture/blit validation; it records commands, trace markers, scissor state, depth state, blend state, - texture/sampler binds, uploads/readbacks, frame captures, and render-target - blits, giving automation a backend-neutral render path that does not require - a window or GL context. + texture/sampler binds, draw mesh inputs, uploads/readbacks, frame captures, + and render-target blits, giving automation a backend-neutral render path that + does not require a window or GL context. - `pano_cli record-render` exercises that headless recording renderer and emits JSON command counts, target dimensions, backend name, trace/draw summary, and - scissor/depth/blend-state plus texture/sampler-bind/upload/readback/ - frame-capture/blit command/byte totals for agent automation, with an - expected-failure smoke for oversized render/readback targets. + draw vertex/index totals, scissor/depth/blend-state plus texture/sampler-bind/ + upload/readback/frame-capture/blit command/byte totals for agent automation, + with an expected-failure smoke for oversized render/readback targets. - `pano_cli simulate-document-history` exercises pure document history apply/undo/redo behavior and emits JSON layer/frame/history state for agent automation. diff --git a/src/renderer_api/recording_renderer.cpp b/src/renderer_api/recording_renderer.cpp index 73b6f4e..60ee32d 100644 --- a/src/renderer_api/recording_renderer.cpp +++ b/src/renderer_api/recording_renderer.cpp @@ -96,6 +96,7 @@ pp::foundation::Status RecordingCommandContext::begin_render_pass( in_render_pass_ = true; shader_bound_ = false; mesh_bound_ = false; + active_mesh_ = MeshDesc {}; push_command(commands_, RecordedRenderCommand { .kind = RecordedRenderCommandKind::begin_render_pass, .target_desc = active_target_, @@ -256,6 +257,7 @@ pp::foundation::Status RecordingCommandContext::bind_mesh(IMesh& mesh) noexcept } mesh_bound_ = true; + active_mesh_ = desc; push_command(commands_, RecordedRenderCommand { .kind = RecordedRenderCommandKind::bind_mesh, .mesh_desc = desc, @@ -277,6 +279,7 @@ pp::foundation::Status RecordingCommandContext::draw() noexcept push_command(commands_, RecordedRenderCommand { .kind = RecordedRenderCommandKind::draw, + .mesh_desc = active_mesh_, }); return pp::foundation::Status::success(); } @@ -421,6 +424,7 @@ void RecordingCommandContext::end_render_pass() noexcept in_render_pass_ = false; shader_bound_ = false; mesh_bound_ = false; + active_mesh_ = MeshDesc {}; } bool RecordingCommandContext::in_render_pass() const noexcept diff --git a/src/renderer_api/recording_renderer.h b/src/renderer_api/recording_renderer.h index c9aec34..b35b3f6 100644 --- a/src/renderer_api/recording_renderer.h +++ b/src/renderer_api/recording_renderer.h @@ -143,6 +143,7 @@ public: private: std::vector* commands_ = nullptr; TextureDesc active_target_ {}; + MeshDesc active_mesh_ {}; bool in_render_pass_ = false; bool shader_bound_ = false; bool mesh_bound_ = false; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9ec5308..e7be721 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -365,7 +365,7 @@ if(TARGET pano_cli) COMMAND pano_cli record-render --width 32 --height 16) set_tests_properties(pano_cli_record_render_smoke PROPERTIES LABELS "renderer;integration;desktop-fast" - PASS_REGULAR_EXPRESSION "\"backend\":\"recording\".*\"width\":32.*\"height\":16.*\"commands\":16.*\"drawCommands\":1.*\"scissorCommands\":1.*\"blendCommands\":1.*\"depthCommands\":1.*\"bindTextureCommands\":1.*\"bindSamplerCommands\":1.*\"boundTextureBytes\":2048.*\"uploadCommands\":1.*\"uploadBytes\":4.*\"readbackCommands\":1.*\"readbackBytes\":2048.*\"captureCommands\":1.*\"captureBytes\":2048.*\"blitCommands\":1.*\"blitSourceBytes\":2048.*\"blitDestinationBytes\":2048") + PASS_REGULAR_EXPRESSION "\"backend\":\"recording\".*\"width\":32.*\"height\":16.*\"commands\":16.*\"drawCommands\":1.*\"drawVertices\":3.*\"drawIndices\":3.*\"scissorCommands\":1.*\"blendCommands\":1.*\"depthCommands\":1.*\"bindTextureCommands\":1.*\"bindSamplerCommands\":1.*\"boundTextureBytes\":2048.*\"uploadCommands\":1.*\"uploadBytes\":4.*\"readbackCommands\":1.*\"readbackBytes\":2048.*\"captureCommands\":1.*\"captureBytes\":2048.*\"blitCommands\":1.*\"blitSourceBytes\":2048.*\"blitDestinationBytes\":2048") add_test(NAME pano_cli_record_render_rejects_oversized_target COMMAND "${CMAKE_COMMAND}" diff --git a/tests/renderer_api/renderer_api_tests.cpp b/tests/renderer_api/renderer_api_tests.cpp index 1fa2853..7bef042 100644 --- a/tests/renderer_api/renderer_api_tests.cpp +++ b/tests/renderer_api/renderer_api_tests.cpp @@ -878,7 +878,7 @@ void recording_renderer_records_valid_command_sequences(pp::tests::Harness& h) .render_target = true, }); RecordingShaderProgram shader("recorded-shader"); - RecordingMesh mesh(MeshDesc { .vertex_count = 3, .index_count = 0, .topology = PrimitiveTopology::triangles }); + RecordingMesh mesh(MeshDesc { .vertex_count = 3, .index_count = 3, .topology = PrimitiveTopology::triangles }); PP_EXPECT(h, device.backend_name() == std::string_view("recording")); device.trace()->marker("renderer", "frame"); @@ -952,7 +952,11 @@ void recording_renderer_records_valid_command_sequences(pp::tests::Harness& h) PP_EXPECT(h, recorded_render_command_kind_name(commands[8].kind) == std::string_view("bind_sampler")); PP_EXPECT(h, commands[9].kind == RecordedRenderCommandKind::bind_mesh); PP_EXPECT(h, commands[9].mesh_desc.vertex_count == 3U); + PP_EXPECT(h, commands[9].mesh_desc.index_count == 3U); PP_EXPECT(h, commands[10].kind == RecordedRenderCommandKind::draw); + PP_EXPECT(h, commands[10].mesh_desc.vertex_count == 3U); + PP_EXPECT(h, commands[10].mesh_desc.index_count == 3U); + PP_EXPECT(h, commands[10].mesh_desc.topology == PrimitiveTopology::triangles); PP_EXPECT(h, commands[11].kind == RecordedRenderCommandKind::end_render_pass); PP_EXPECT(h, recorded_render_command_kind_name(commands[10].kind) == std::string_view("draw")); diff --git a/tools/pano_cli/main.cpp b/tools/pano_cli/main.cpp index a863ba6..77fd978 100644 --- a/tools/pano_cli/main.cpp +++ b/tools/pano_cli/main.cpp @@ -2237,7 +2237,7 @@ int record_render(int argc, char** argv) pp::renderer::RecordingShaderProgram shader("pano-cli-record-render"); pp::renderer::RecordingMesh mesh(pp::renderer::MeshDesc { .vertex_count = 3, - .index_count = 0, + .index_count = 3, .topology = pp::renderer::PrimitiveTopology::triangles, }); @@ -2391,6 +2391,8 @@ int record_render(int argc, char** argv) std::size_t capture_commands = 0; std::size_t blit_commands = 0; std::size_t trace_markers = 0; + std::uint64_t draw_vertices = 0; + std::uint64_t draw_indices = 0; std::uint64_t upload_bytes = 0; std::uint64_t bound_texture_bytes = 0; std::uint64_t readback_bytes = 0; @@ -2401,6 +2403,8 @@ int record_render(int argc, char** argv) for (const auto& command : commands) { if (command.kind == pp::renderer::RecordedRenderCommandKind::draw) { ++draw_commands; + draw_vertices += command.mesh_desc.vertex_count; + draw_indices += command.mesh_desc.index_count; } else if (command.kind == pp::renderer::RecordedRenderCommandKind::set_scissor) { ++scissor_commands; } else if (command.kind == pp::renderer::RecordedRenderCommandKind::set_blend_state) { @@ -2440,6 +2444,8 @@ int record_render(int argc, char** argv) << ",\"format\":\"rgba8\"}" << ",\"commands\":" << commands.size() << ",\"drawCommands\":" << draw_commands + << ",\"drawVertices\":" << draw_vertices + << ",\"drawIndices\":" << draw_indices << ",\"scissorCommands\":" << scissor_commands << ",\"blendCommands\":" << blend_commands << ",\"depthCommands\":" << depth_commands