mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-04 14:20:58 +00:00
94 lines
5.5 KiB
Markdown
94 lines
5.5 KiB
Markdown
# 3D Scene Benchmark: High Level Design
|
|
|
|
## Why it exists
|
|
|
|
Rendering changes, such as the realistic view, shadows or SSAO, need a number to compare
|
|
before and after, and user reports of a slow viewport need a way to say how slow. The FPS
|
|
overlay and the render timings overlay show live values while someone drags the camera,
|
|
which varies from run to run with the model, the path of the mouse and the view.
|
|
|
|
The benchmark renders a fixed model along a fixed camera path in both 3D views, so two
|
|
runs on the same machine differ only by the code or the settings, and prints a report that
|
|
can be pasted into an issue.
|
|
|
|
## What it does
|
|
|
|
`run_scene_benchmark()` in `src/slic3r/GUI/SceneBenchmark.cpp` is reached from Help >
|
|
Benchmark 3D Scene, the command palette and Preferences > Graphics. After a confirmation
|
|
it starts a new project, which asks to save the current one if needed, loads the
|
|
OrcaSliced Combo handy model and arranges it. A small dialog in a corner of the 3D view
|
|
then shows the progress; every other window is disabled until the run ends, so a click
|
|
cannot change the scene being measured. Cancel or Esc stops the run.
|
|
|
|
The run goes through these stages, driven by a timer while it waits and by idle events
|
|
while it renders:
|
|
|
|
1. Loading: waits until the UI job worker is idle, so the arrange job has moved the
|
|
objects. The orbit target is the center of the objects on the current plate, and the
|
|
base zoom fits their bounding box in the viewport.
|
|
2. Prepare: renders the scene in the Prepare view.
|
|
3. Slicing: slices the plate and switches to Preview, then waits for the G-code preview
|
|
to load. If slicing fails, the report holds Prepare alone.
|
|
4. Preview: renders the scene in the Preview view, with the slicing progress notification
|
|
hidden.
|
|
5. Layers: renders the Preview view again while the layer slider moves, which is what
|
|
makes dragging it feel slow on large prints.
|
|
|
|
The dialog then shows the report, with a button to copy it. A scene cut short, because its
|
|
view was hidden, is left out of the report.
|
|
|
|
## Rendering a scene
|
|
|
|
Each scene renders 30 warm-up frames, then the camera path twice, 360 frames each time.
|
|
|
|
- The first pass times the frames. A frame's time is the interval between the starts of
|
|
consecutive benchmark frames, so it includes the event loop between them.
|
|
- The second pass averages the render timings. The frame profiler flushes the GL command
|
|
queue after each section, which slows a frame down, so it only runs in this pass.
|
|
`FrameProfiler::start_averaging()` flags every frame begun afterwards, and
|
|
`finish_averaging()` waits for the flagged frames still on the GPU and returns the mean
|
|
CPU and GPU time of each section per profiled frame.
|
|
- A section's GPU time is taken between a timestamp before its commands and one after
|
|
them. The first is only sent along with those commands, so when the GPU finishes a
|
|
section before the CPU has issued the next one, the wait counts in neither.
|
|
|
|
The dialog renders one frame per idle event by calling `GLCanvas3D::render()`, which
|
|
redraws the whole scene. While `GLCanvas3D::set_benchmarking()` is on, the canvas does not
|
|
render from its own idle handler, so no other frame is drawn in between, and it skips the
|
|
picking pass and the FPS and render timings overlays, which depend on the mouse and on
|
|
preferences. The FPS cap does not apply, since it only paces idle redraws.
|
|
|
|
VSync is turned off for the scene through `wxGLCanvas::SetSwapInterval(0)`, so the frame
|
|
rate is what the GPU and CPU can reach rather than the display's refresh rate, and the
|
|
previous interval is restored afterwards. When the platform cannot report the current
|
|
interval (EGL), it is left as it is and the report says so.
|
|
|
|
The camera path makes two turns around the target while the view rises three times from
|
|
25 degrees below the plate to 85 degrees above it and the zoom goes twice between 0.6 and
|
|
1.4 times the base zoom. The camera stays at the default distance, so the perspective is
|
|
the same in every run. The camera the scene started with is restored at its end.
|
|
|
|
The Layers scene holds the camera at the start of that path and moves the top of the layer
|
|
slider instead, from the last layer down to the first and back up in each pass. It goes
|
|
through `IMSlider::SetHigherValue()`, as a drag does, so every frame applies a new layer
|
|
range to the toolpaths and the objects before drawing them, including a new shadow map when
|
|
the shadows are static. Its warm-up frames lead into the start of the path, so the slider
|
|
moves in every frame. The slider position it started from is restored at its end.
|
|
|
|
## The report
|
|
|
|
The report is plain English text, so it reads the same in every language:
|
|
|
|
- The version and build commit, the GPU and OpenGL version, the viewport size and camera
|
|
type, and the graphics settings that change the cost of a frame: MSAA samples as read
|
|
from the framebuffer, FXAA, the scene cache, VSync and the realistic view options.
|
|
- The printer and process presets the model was sliced with, marked when they have
|
|
unsaved changes, and the toolpath vertices and layers they produced, since the Preview
|
|
scenes cost more with more toolpaths.
|
|
- For each scene, the average FPS and the average, median, 95th percentile, 99th
|
|
percentile and maximum frame time. Percentiles are nearest-rank, so each is a measured
|
|
frame (`frame_time_stats()`).
|
|
- For each scene, the render timings table: the CPU and GPU milliseconds of each section
|
|
of a frame, and their total. Without timer queries (OpenGL 3.3 or `ARB_timer_query`) the
|
|
table says that the driver does not support them.
|