1cb93a386Sopenharmony_ciSkQP Render Test Algorithm 2cb93a386Sopenharmony_ci========================== 3cb93a386Sopenharmony_ci 4cb93a386Sopenharmony_ciThe following is a description of the render test validation algorithm that 5cb93a386Sopenharmony_ciwill be used by the version of SkQP that will be released for Android Q-release. 6cb93a386Sopenharmony_ci 7cb93a386Sopenharmony_ciThere is a global macro constant: `SK_SKQP_GLOBAL_ERROR_TOLERANCE`, which 8cb93a386Sopenharmony_cireflects the `gn` variable `skia_skqp_global_error_tolerance`. This is usually 9cb93a386Sopenharmony_ciset to 8. 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ciFirst, look for a file named `skqp/rendertests.txt` in the 12cb93a386Sopenharmony_ci`platform_tools/android/apps/skqp/src/main/assets` directory. The format of 13cb93a386Sopenharmony_cithis file is: each line contains one render test name, followed by a comma, 14cb93a386Sopenharmony_cifollowed by an integer. The integer is the `passing_threshold` for that test. 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ciFor each test, we have a `max_image` and a `min_image`. These are PNG-encoded 17cb93a386Sopenharmony_ciimages stored in SkQP's APK's asset directory (in the paths `gmkb/${TEST}/min.png` 18cb93a386Sopenharmony_ciand `gmkb/${TEST}/max.png`). 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ciThe test input is a rendered image. This will be produced by running one of 21cb93a386Sopenharmony_cithe render tests against the either the `vk` (Vulkan) or `gles` (OpenGL ES) 22cb93a386Sopenharmony_ciSkia backend. 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ciHere is psuedocode for the error calculation: 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ci function calculate_pixel_error(pixel_value, pixel_max, pixel_min): 27cb93a386Sopenharmony_ci pixel_error = 0 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci for color_channel in { red, green, blue, alpha }: 30cb93a386Sopenharmony_ci value = get_color(pixel_value, color_channel) 31cb93a386Sopenharmony_ci v_max = get_color(pixel_max, color_channel) 32cb93a386Sopenharmony_ci v_min = get_color(pixel_min, color_channel) 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci if value > v_max: 35cb93a386Sopenharmony_ci channel_error = value - v_max 36cb93a386Sopenharmony_ci elif value < v_min: 37cb93a386Sopenharmony_ci channel_error = v_min - value 38cb93a386Sopenharmony_ci else: 39cb93a386Sopenharmony_ci channel_error = 0 40cb93a386Sopenharmony_ci pixel_error = max(pixel_error, channel_error) 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci return max(0, pixel_error - SK_SKQP_GLOBAL_ERROR_TOLERANCE); 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci function get_error(rendered_image, max_image, min_image): 45cb93a386Sopenharmony_ci assert(dimensions(rendered_image) == dimensions(max_image)) 46cb93a386Sopenharmony_ci assert(dimensions(rendered_image) == dimensions(min_image)) 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci max_error = 0 49cb93a386Sopenharmony_ci bad_pixels = 0 50cb93a386Sopenharmony_ci total_error = 0 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci error_image = allocate_bitmap(dimensions(rendered_image)) 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci for xy in list_all_pixel_coordinates(rendered_image): 55cb93a386Sopenharmony_ci pixel_error = calculate_pixel_error(rendered_image(xy), 56cb93a386Sopenharmony_ci max_image(xy), 57cb93a386Sopenharmony_ci min_image(xy)) 58cb93a386Sopenharmony_ci if pixel_error > 0: 59cb93a386Sopenharmony_ci for neighboring_xy in find_neighbors(xy): 60cb93a386Sopenharmony_ci if not inside(neighboring_xy, dimensions(rendered_image)): 61cb93a386Sopenharmony_ci continue 62cb93a386Sopenharmony_ci pixel_error = min(pixel_error, 63cb93a386Sopenharmony_ci calculate_pixel_error(rendered_image(xy), 64cb93a386Sopenharmony_ci max_image(neighboring_xy), 65cb93a386Sopenharmony_ci min_image(neighboring_xy))) 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci if pixel_error > 0: 68cb93a386Sopenharmony_ci max_error = max(max_error, pixel_error) 69cb93a386Sopenharmony_ci bad_pixels += 1 70cb93a386Sopenharmony_ci total_error += pixel_error 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci error_image(xy) = linear_interpolation(black, red, pixel_error) 73cb93a386Sopenharmony_ci else: 74cb93a386Sopenharmony_ci error_image(xy) = white 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci return ((total_error, max_error, bad_pixels), error_image) 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ciFor each render test, there is a threshold value for `total_error`, : 79cb93a386Sopenharmony_ci`passing_threshold`. 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ciIf `passing_threshold >= 0 && total_error > passing_threshold`, then the test 82cb93a386Sopenharmony_ciis a failure and is included in the report. if `passing_threshold == -1`, then 83cb93a386Sopenharmony_cithe test always passes, but we do execute the test to verify that the driver 84cb93a386Sopenharmony_cidoes not crash. 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ciWe generate a report with the following information for each test: 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci backend_name,render_test_name,max_error,bad_pixels,total_error 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ciin CSV format in the file `out.csv`. A HTML report of just the failing tests 91cb93a386Sopenharmony_ciis written to the file `report.html`. This version includes four images for 92cb93a386Sopenharmony_cieach test: `rendered_image`, `max_image`, `min_image`, and `error_image`, as 93cb93a386Sopenharmony_ciwell as the three metrics: `max_error`, `bad_pixels`, and `total_error`. 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci 97