flutter3d_testing 0.8.0
flutter3d_testing: ^0.8.0 copied to clipboard
Renders a flutter3d scene with no GPU and compares it against a reference image, so a game gets pixel regression tests on a machine with no display.
0.8.0 #
- Two pictures can be compared the way an eye would.
fliptakes two 8-bit sRGB frames andflipLineartwo in linear light, and both return aFlipResult: the per-pixel error map and its mean, nought for identical and one for as different as green is from blue. It is LDR-FLIP (Andersson, Nilsson, Akenine-Möller, Oskarsson, Åström and Fairchild, HPG 2020), ported line for line from the reference C++ so a value here is the value there, and a test holds it to the error maps that implementation publishes. The viewing condition defaults todefaultFlipPpd, about 67 pixels per degree. A count of moved pixels cannot say how much worse a frame looks: a lower render scale moves nearly every pixel a little and looks almost the same. The reference code's BSD licence is kept inthird_party/flip. expectMatchesGoldentakesflipBudget. Null, the default, compares as before. Given, the mean FLIP error replaces the share of differing pixels, for a frame meant to differ a little everywhere, such as a lower render scale or a stochastic effect against its sorted reference.measureQualityTablemeasures the tableAdaptiveQualityinflutter3d_corechooses from. It renders eachQualitySceneat every setting ofQualitySetting.gridon the device it is handed, gives each setting its own renderer andsettleframes, then takes the fastest ofsamplesinterleaved frames, and returns aQualityMeasurementper setting: its cost relative to full quality and its mean FLIP against it. The time is the passes' GPU time where the device reports it and the renderer's wall clock where it does not.qualityTablesSourcewrites the source offlutter3d_core'stables/quality_tables.dartfrom a full grid perDeviceClass, with a flag for whether each was measured on that class. It is an offline tool: it draws every scene at every setting many times over.replayPacingplays a recorded run a frame at a time and times every frame. A frame is one step of the tape throughonStepand onedrawFrame, back to back with the CPU and GPU halves serialised, which errs long and pins each spike to the frame that caused it.gpuSettledcloses a frame and waits for the device'sonFrameComplete, so the GPU's share is counted. The result,FramePacing, keeps the median, the 99th percentile, the worst frame and its index, and every frame overlimitMillis(50 by default); a frame rate would hide the one stop a player notices.repeats,rewindandwarmUpFramesplay a tape several times from its start or skip a level's first frames.
Its flutter3d_* dependencies ask for ^0.8.0.
0.7.1 #
- A zero tolerance was never byte for byte, and now the README says so.
toleranceis the share of pixels allowed to differ, but a pixel only counted as differing when red, green or blue moved by more than 8 steps, and alpha was not compared at all. The README called that "zero". The defaults stay as they were, andexpectMatchesGoldentakeschannelandalpha, so a test with byte-exact references passeschannel: 0, alpha: true.
Its flutter3d_* dependencies ask for ^0.7.1, and it asks for vector_math ^2.4.3.
0.7.0 #
- Breaking for code that builds a
RenderedFrameby hand. The record gained a fourth field,drawCalls, read off theFrameResultevery render already produced.renderFramefills it, and a test can now assert how many draws a scene cost as well as what it looked like. Code that only readspixels,widthandheightis unaffected; a literal(pixels:, width:, height:)passed where aRenderedFrameis wanted no longer has the type. replayGolden: a recorded run, replayed to one step, held to a picture. It drives anInputStatefrom aDemo's tape, calls the caller'sonSteponce per entry, draws the caller'sframeatatStepthroughrenderFrameand compares withexpectMatchesGolden. ADigestTracealready says whether a replay reached the same numbers; this is for a renderer that changed under numbers that did not. The step is the caller's because a genre's simulation is not this package's to know. A tape that ends beforeatStepthrowsStateError, so a short recording is not reported as a wrong picture.flutter3d_sim^0.7.0is a dependency for it.MaterialProgramStagedraws a material written as source on the software backend. It implementsflutter3d_cpu'sCpuFragmentShaderover aMaterialProgramfrompackage:flutter3d_core/formats.dartthat has been throughspecialiseMaterial, and evaluates the same tree the GLSL emitter writes from. It lives here becauseflutter3d_cpu'slib/may not reach the engine and the engine may not reach a backend.flutter3d_core^0.7.0is a dependency for it.- The archive carries a skill for a coding agent,
skills/flutter3d-testing-pixel-regression/, which a project depending on this package installs withdart run skills@ get. - The floors on
flutter3d,flutter3d_cpuandflutter3d_hardwareare^0.7.0.renderFrame,expectMatchesGoldenand the tolerance of zero are unchanged.
0.6.0 #
- Floors, and no code. Drawing a frame through the software backend and
holding it to a reference image works exactly as it did in 0.5.2. The floors
on
flutter3d,flutter3d_cpuandflutter3d_hardwareare^0.6.0— and they matter more here than in most places, because a golden helper resolved against a different engine than the game under test compares two different renderers and calls the difference a regression.
0.5.2 #
^0.5.2on both halves. This package is the one place the engine and the software backend are named together, so it is where "these two move as a pair" can be written at all — seeflutter3d_backend0.5.2 for what a mismatched pair does with morph targets.
0.5.1 #
- Its floors move to
flutter3dandflutter3d_cpuat 0.5.1, both of them. This package pairs the engine with the software backend, and 0.5.1 changed a contract they share: what the surface buffer's alpha holds, and the members of theFogInfoblock. Either half at 0.5.0 against the other at 0.5.1 draws a picture that is quietly the old one — the software backend reads a missing uniform member as zeros rather than refusing, so nothing says anything. Naming both floors is what closes it in both directions, whichflutter3d_backendcannot do because it does not depend on the engine.
0.5.0 #
Breaking. The frame builder takes one object.
FrameBuilderisFrameSubject Function(FrameRequest), so telling a builder the size it is drawing at, or which backend it is on, does not break every builder anybody has written.
0.4.0 #
- No changes of its own; the version moves with the workspace, whose sibling constraints name a single release. The README's closing section now says what the engine around this package is.
0.3.0 #
- First release.
renderFramedraws a scene through the software backend, with no GPU, no driver and no display;expectMatchesGoldenholds the result to a reference image, recording one when there is none. - The tolerance defaults to zero, because a software rasteriser draws the same scene the same way twice and a test that allows drift has stopped watching it.