3.9 KiB
SkQP Render Test Algorithm
The following is a description of the render test validation algorithm that will be used by the version of SkQP that will be released for Android Q-release.
There is a global macro constant: SK_SKQP_GLOBAL_ERROR_TOLERANCE
, which
reflects the gn
variable skia_skqp_global_error_tolerance
. This is usually
set to 8.
First, look for a file named skqp/rendertests.txt
in the
platform_tools/android/apps/skqp/src/main/assets
directory. The format of
this file is: each line contains one render test name, followed by a comma,
followed by an integer. The integer is the passing_threshold
for that test.
For each test, we have a max_image
and a min_image
. These are PNG-encoded
images stored in SkQP's APK's asset directory (in the paths gmkb/${TEST}/min.png
and gmkb/${TEST}/max.png
).
The test input is a rendered image. This will be produced by running one of
the render tests against the either the vk
(Vulkan) or gles
(OpenGL ES)
Skia backend.
Here is psuedocode for the error calculation:
function calculate_pixel_error(pixel_value, pixel_max, pixel_min):
pixel_error = 0
for color_channel in { red, green, blue, alpha }:
value = get_color(pixel_value, color_channel)
v_max = get_color(pixel_max, color_channel)
v_min = get_color(pixel_min, color_channel)
if value > v_max:
channel_error = value - v_max
elif value < v_min:
channel_error = v_min - value
else:
channel_error = 0
pixel_error = max(pixel_error, channel_error)
return max(0, pixel_error - SK_SKQP_GLOBAL_ERROR_TOLERANCE);
function get_error(rendered_image, max_image, min_image):
assert(dimensions(rendered_image) == dimensions(max_image))
assert(dimensions(rendered_image) == dimensions(min_image))
max_error = 0
bad_pixels = 0
total_error = 0
error_image = allocate_bitmap(dimensions(rendered_image))
for xy in list_all_pixel_coordinates(rendered_image):
pixel_error = calculate_pixel_error(rendered_image(xy),
max_image(xy),
min_image(xy))
if pixel_error > 0:
for neighboring_xy in find_neighbors(xy):
if not inside(neighboring_xy, dimensions(rendered_image)):
continue
pixel_error = min(pixel_error,
calculate_pixel_error(rendered_image(xy),
max_image(neighboring_xy),
min_image(neighboring_xy)))
if pixel_error > 0:
max_error = max(max_error, pixel_error)
bad_pixels += 1
total_error += pixel_error
error_image(xy) = linear_interpolation(black, red, pixel_error)
else:
error_image(xy) = white
return ((total_error, max_error, bad_pixels), error_image)
For each render test, there is a threshold value for total_error
, :
passing_threshold
.
If passing_threshold >= 0 && total_error > passing_threshold
, then the test
is a failure and is included in the report. if passing_threshold == -1
, then
the test always passes, but we do execute the test to verify that the driver
does not crash.
We generate a report with the following information for each test:
backend_name,render_test_name,max_error,bad_pixels,total_error
in CSV format in the file out.csv
. A HTML report of just the failing tests
is written to the file report.html
. This version includes four images for
each test: rendered_image
, max_image
, min_image
, and error_image
, as
well as the three metrics: max_error
, bad_pixels
, and total_error
.