#!/usr/bin/env python3 # Copyright (C) 2023 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from python.generators.diff_tests.testing import Path, DataPath, Metric from python.generators.diff_tests.testing import Csv, Json, TextProto from python.generators.diff_tests.testing import DiffTestBlueprint, TraceInjector from python.generators.diff_tests.testing import TestSuite class GraphicsParser(TestSuite): # Contains tests for graphics related events and tables. Graphics frame # trace tests. def test_graphics_frame_events(self): return DiffTestBlueprint( trace=Path('graphics_frame_events.py'), query=""" SELECT ts, gpu_track.name AS track_name, dur, frame_slice.name AS slice_name, frame_number, layer_name FROM gpu_track LEFT JOIN frame_slice ON gpu_track.id = frame_slice.track_id WHERE scope = 'graphics_frame_event' ORDER BY ts; """, out=Csv(''' "ts","track_name","dur","slice_name","frame_number","layer_name" 1,"Buffer: 1 layer1",0,"Dequeue",11,"layer1" 1,"APP_1 layer1",3,"11",11,"layer1" 4,"Buffer: 1 layer1",0,"Queue",11,"layer1" 4,"GPU_1 layer1",2,"11",11,"layer1" 6,"Buffer: 1 layer1",0,"AcquireFenceSignaled",11,"layer1" 6,"Buffer: 2 layer2",0,"Dequeue",12,"layer2" 6,"APP_2 layer2",3,"12",12,"layer2" 7,"Buffer: 7 layer7",0,"unknown_event",15,"layer7" 8,"Buffer: 1 layer1",0,"Latch",11,"layer1" 8,"Buffer: 2 layer2",0,"AcquireFenceSignaled",12,"layer2" 8,"SF_1 layer1",6,"11",11,"layer1" 9,"Buffer: 2 layer2",0,"Queue",12,"layer2" 11,"Buffer: 2 layer2",0,"Latch",12,"layer2" 11,"SF_2 layer2",5,"12",12,"layer2" 14,"Buffer: 1 layer1",0,"PresentFenceSignaled",11,"layer1" 14,"Display_layer1",10,"11",11,"layer1" 16,"Buffer: 2 layer2",0,"PresentFenceSignaled",12,"layer2" 16,"Display_layer2",-1,"12",12,"layer2" 24,"Buffer: 1 layer1",0,"PresentFenceSignaled",13,"layer1" 24,"Display_layer1",-1,"13",13,"layer1" 31,"Buffer: 1 layer1",0,"Dequeue",21,"layer1" 31,"APP_1 layer1",3,"21",21,"layer1" 34,"Buffer: 1 layer1",0,"Queue",21,"layer1" 34,"GPU_1 layer1",-1,"21",21,"layer1" 37,"Buffer: 1 layer1",0,"Dequeue",22,"layer1" 37,"APP_1 layer1",4,"22",22,"layer1" 41,"Buffer: 1 layer1",0,"Queue",22,"layer1" 41,"GPU_1 layer1",5,"22",22,"layer1" 46,"Buffer: 1 layer1",0,"AcquireFenceSignaled",22,"layer1" 53,"Buffer: 2 layer2",0,"Dequeue",24,"layer2" 53,"APP_2 layer2",-1,"0",0,"layer2" 59,"Buffer: 2 layer2",0,"AcquireFenceSignaled",24,"layer2" 61,"Buffer: 2 layer2",0,"Latch",24,"layer2" 61,"SF_2 layer2",-1,"24",24,"layer2" 63,"Buffer: 1 layer1",0,"Dequeue",25,"layer1" 63,"APP_1 layer1",-1,"0",0,"layer1" 73,"Buffer: 1 layer1",0,"Dequeue",26,"layer1" 73,"APP_1 layer1",2,"26",26,"layer1" 75,"Buffer: 1 layer1",0,"Queue",26,"layer1" 75,"GPU_1 layer1",4,"26",26,"layer1" 79,"Buffer: 1 layer1",0,"AcquireFenceSignaled",26,"layer1" 81,"Buffer: 1 layer1",0,"Dequeue",30,"layer1" 81,"APP_1 layer1",2,"30",30,"layer1" 83,"Buffer: 1 layer1",0,"Queue",30,"layer1" 83,"GPU_1 layer1",-1,"30",30,"layer1" 90,"Buffer: 1 layer2",0,"Dequeue",35,"layer2" 90,"APP_1 layer2",2,"35",35,"layer2" 92,"Buffer: 1 layer2",0,"Queue",35,"layer2" 92,"GPU_1 layer2",-1,"35",35,"layer2" ''')) # GPU Memory ftrace packets def test_gpu_mem_total(self): return DiffTestBlueprint( trace=Path('gpu_mem_total.py'), query=''' SELECT ct.name, ct.unit, extract_arg(ct.dimension_arg_set_id, 'gpu') AS gpu_id, c.ts, p.pid, cast_int!(c.value) AS value FROM counter_track ct LEFT JOIN process_counter_track pct USING (id) LEFT JOIN process p USING (upid) LEFT JOIN counter c ON c.track_id = ct.id ORDER BY gpu_id, ts, pid; ''', out=Csv(""" "name","unit","gpu_id","ts","pid","value" "GPU Memory","bytes",0,0,"[NULL]",123 "GPU Memory","bytes",0,0,1,100 "GPU Memory","bytes",0,5,"[NULL]",256 "GPU Memory","bytes",0,5,1,233 "GPU Memory","bytes",0,10,"[NULL]",123 "GPU Memory","bytes",0,10,1,0 "GPU Memory","bytes",1,0,"[NULL]",456 "GPU Memory","bytes",1,5,"[NULL]",512 """)) def test_gpu_mem_total_after_free_gpu_mem_total(self): return DiffTestBlueprint( trace=Path('gpu_mem_total_after_free.py'), query=''' SELECT ct.name, ct.unit, extract_arg(ct.dimension_arg_set_id, 'gpu') AS gpu_id, c.ts, p.pid, cast_int!(c.value) AS value FROM counter_track ct LEFT JOIN process_counter_track pct USING (id) LEFT JOIN process p USING (upid) LEFT JOIN counter c ON c.track_id = ct.id ORDER BY gpu_id, ts; ''', out=Csv(""" "name","unit","gpu_id","ts","pid","value" "GPU Memory","bytes",0,0,1,100 "GPU Memory","bytes",0,5,1,233 "GPU Memory","bytes",0,10,1,50 """)) # Clock sync def test_clock_sync(self): return DiffTestBlueprint( trace=Path('clock_sync.py'), query=""" SELECT ts, cast(value AS integer) AS int_value FROM counters WHERE name GLOB 'gpu_counter*'; """, out=Csv(""" "ts","int_value" 1,5 102,7 1003,9 1005,11 2006,12 2010,13 2013,14 3007,15 3010,0 """)) # Frame Timeline event trace tests def test_expected_frame_timeline_events(self): return DiffTestBlueprint( trace=Path('frame_timeline_events.py'), query=Path('expected_frame_timeline_events_test.sql'), out=Csv(""" "ts","dur","pid","display_frame_token","surface_frame_token","layer_name" 20,6,666,2,"[NULL]","[NULL]" 21,15,1000,4,1,"Layer1" 40,6,666,4,"[NULL]","[NULL]" 41,15,1000,6,5,"Layer1" 80,6,666,6,"[NULL]","[NULL]" 90,16,1000,8,7,"Layer1" 120,6,666,8,"[NULL]","[NULL]" 140,6,666,12,"[NULL]","[NULL]" 150,20,1000,15,14,"Layer1" 170,6,666,15,"[NULL]","[NULL]" 200,6,666,17,"[NULL]","[NULL]" 220,-1,666,18,"[NULL]","[NULL]" 220,10,666,18,"[NULL]","[NULL]" """)) def test_actual_frame_timeline_events(self): return DiffTestBlueprint( trace=Path('frame_timeline_events.py'), query=''' SELECT ts, dur, process.pid, display_frame_token, surface_frame_token, layer_name, present_type, on_time_finish, gpu_composition, jank_type, prediction_type, jank_tag, jank_severity_type FROM (SELECT t.*, process_track.name AS track_name FROM process_track LEFT JOIN actual_frame_timeline_slice t ON process_track.id = t.track_id) s JOIN process USING(upid) WHERE s.track_name = 'Actual Timeline' ORDER BY ts; ''', out=Csv(""" "ts","dur","pid","display_frame_token","surface_frame_token","layer_name","present_type","on_time_finish","gpu_composition","jank_type","prediction_type","jank_tag","jank_severity_type" 20,6,666,2,"[NULL]","[NULL]","On-time Present",1,0,"None","Valid Prediction","No Jank","None" 21,16,1000,4,1,"Layer1","On-time Present",1,0,"None","Valid Prediction","No Jank","None" 41,33,1000,6,5,"Layer1","Late Present",0,0,"App Deadline Missed","Valid Prediction","Self Jank","Full" 42,5,666,4,"[NULL]","[NULL]","On-time Present",1,0,"None","Valid Prediction","No Jank","None" 80,110,1000,17,16,"Layer1","Unknown Present",0,0,"Unknown Jank","Expired Prediction","Self Jank","Partial" 81,7,666,6,"[NULL]","[NULL]","On-time Present",1,0,"None","Valid Prediction","No Jank","None" 90,16,1000,8,7,"Layer1","Early Present",1,0,"SurfaceFlinger Scheduling","Valid Prediction","Other Jank","Unknown" 108,4,666,8,"[NULL]","[NULL]","Early Present",1,0,"SurfaceFlinger Scheduling","Valid Prediction","Self Jank","Unknown" 148,8,666,12,"[NULL]","[NULL]","Late Present",0,0,"SurfaceFlinger Scheduling, SurfaceFlinger CPU Deadline Missed","Valid Prediction","Self Jank","Unknown" 150,17,1000,15,14,"Layer1","On-time Present",1,0,"None","Valid Prediction","No Jank","None" 150,17,1000,15,14,"Layer2","On-time Present",1,0,"None","Valid Prediction","No Jank","None" 170,6,666,15,"[NULL]","[NULL]","On-time Present",1,0,"None","Valid Prediction","No Jank","None" 200,6,666,17,"[NULL]","[NULL]","On-time Present",1,0,"None","Valid Prediction","No Jank","None" 245,-1,666,18,"[NULL]","[NULL]","Late Present",0,0,"SurfaceFlinger Stuffing","Valid Prediction","SurfaceFlinger Stuffing","Unknown" 245,15,666,18,"[NULL]","[NULL]","Dropped Frame",0,0,"Dropped Frame","Unspecified Prediction","Dropped Frame","Unknown" """)) def test_display_power_mode_change(self): return DiffTestBlueprint( trace=Path('frame_timeline_power_mode.py'), query=''' SELECT ts, dur, process.pid, display_frame_token, surface_frame_token, layer_name, present_type, on_time_finish, gpu_composition, jank_type, prediction_type, jank_tag, jank_severity_type FROM (SELECT t.*, process_track.name AS track_name FROM process_track LEFT JOIN actual_frame_timeline_slice t ON process_track.id = t.track_id) s JOIN process USING(upid) WHERE s.track_name = 'Actual Timeline' ORDER BY ts; ''', out=Csv(""" "ts","dur","pid","display_frame_token","surface_frame_token","layer_name","present_type","on_time_finish","gpu_composition","jank_type","prediction_type","jank_tag","jank_severity_type" 100,10,666,1,"[NULL]","[NULL]","On-time Present",1,0,"PowerModeChange in progress","Valid Prediction","Non-perceivable Jank","Unknown" 120,15,1000,1,2,"Layer1","On-time Present",1,0,"PowerModeChange in progress","Valid Prediction","Non-perceivable Jank","Unknown" 140,10,666,3,"[NULL]","[NULL]","On-time Present",1,0,"Non Animating","Valid Prediction","Non-perceivable Jank","Unknown" 160,10,666,4,"[NULL]","[NULL]","On-time Present",1,0,"Display not ON","Valid Prediction","Non-perceivable Jank","Unknown" """)) # Video 4 Linux 2 related tests def test_v4l2_vidioc_slice(self): return DiffTestBlueprint( trace=Path('v4l2_vidioc.textproto'), query=""" SELECT ts, dur, name FROM slice WHERE category = 'Video 4 Linux 2'; """, out=Csv(""" "ts","dur","name" 593268475912,0,"VIDIOC_QBUF minor=0 seq=0 type=9 index=19" 593268603800,0,"VIDIOC_QBUF minor=0 seq=0 type=9 index=20" 593528238295,0,"VIDIOC_DQBUF minor=0 seq=0 type=9 index=19" 593544028229,0,"VIDIOC_DQBUF minor=0 seq=0 type=9 index=20" """)) def test_v4l2_vidioc_flow(self): return DiffTestBlueprint( trace=Path('v4l2_vidioc.textproto'), query=""" SELECT qbuf.ts, qbuf.dur, qbuf.name, dqbuf.ts, dqbuf.dur, dqbuf.name FROM flow JOIN slice qbuf ON flow.slice_out = qbuf.id JOIN slice dqbuf ON flow.slice_in = dqbuf.id; """, out=Path('v4l2_vidioc_flow.out')) def test_virtio_video_slice(self): return DiffTestBlueprint( trace=Path('virtio_video.textproto'), query=""" SELECT slice.ts, slice.dur, slice.name, track.name FROM slice JOIN track ON slice.track_id = track.id; """, out=Csv(""" "ts","dur","name","name" 593125003271,84500592,"Resource #102","virtio_video stream #4 OUTPUT" 593125003785,100000,"RESOURCE_QUEUE","virtio_video stream #4 Requests" 593125084611,709696,"Resource #62","virtio_video stream #3 OUTPUT" 593125084935,100000,"RESOURCE_QUEUE","virtio_video stream #3 Requests" 593125794194,100000,"RESOURCE_QUEUE","virtio_video stream #3 Responses" 593209502603,100000,"RESOURCE_QUEUE","virtio_video stream #4 Responses" """)) # virtgpu (drm/virtio) related tests def test_virtio_gpu(self): return DiffTestBlueprint( trace=Path('virtio_gpu.textproto'), query=""" SELECT ts, dur, name FROM slice ORDER BY ts; """, out=Csv(""" "ts","dur","name" 1345090723759,1180312,"SUBMIT_3D" 1345090746311,1167135,"CTX_DETACH_RESOURCE" """)) # Tests gpu_track with machine_id ID. def test_graphics_frame_events_machine_id(self): return DiffTestBlueprint( trace=Path('graphics_frame_events.py'), trace_modifier=TraceInjector(['graphics_frame_event'], {'machine_id': 1001}), query=""" SELECT ts, gpu_track.name AS track_name, dur, frame_slice.name AS slice_name, frame_number, layer_name FROM gpu_track LEFT JOIN frame_slice ON gpu_track.id = frame_slice.track_id WHERE scope = 'graphics_frame_event' AND gpu_track.machine_id IS NOT NULL ORDER BY ts; """, out=Csv(''' "ts","track_name","dur","slice_name","frame_number","layer_name" 1,"Buffer: 1 layer1",0,"Dequeue",11,"layer1" 1,"APP_1 layer1",3,"11",11,"layer1" 4,"Buffer: 1 layer1",0,"Queue",11,"layer1" 4,"GPU_1 layer1",2,"11",11,"layer1" 6,"Buffer: 1 layer1",0,"AcquireFenceSignaled",11,"layer1" 6,"Buffer: 2 layer2",0,"Dequeue",12,"layer2" 6,"APP_2 layer2",3,"12",12,"layer2" 7,"Buffer: 7 layer7",0,"unknown_event",15,"layer7" 8,"Buffer: 1 layer1",0,"Latch",11,"layer1" 8,"Buffer: 2 layer2",0,"AcquireFenceSignaled",12,"layer2" 8,"SF_1 layer1",6,"11",11,"layer1" 9,"Buffer: 2 layer2",0,"Queue",12,"layer2" 11,"Buffer: 2 layer2",0,"Latch",12,"layer2" 11,"SF_2 layer2",5,"12",12,"layer2" 14,"Buffer: 1 layer1",0,"PresentFenceSignaled",11,"layer1" 14,"Display_layer1",10,"11",11,"layer1" 16,"Buffer: 2 layer2",0,"PresentFenceSignaled",12,"layer2" 16,"Display_layer2",-1,"12",12,"layer2" 24,"Buffer: 1 layer1",0,"PresentFenceSignaled",13,"layer1" 24,"Display_layer1",-1,"13",13,"layer1" 31,"Buffer: 1 layer1",0,"Dequeue",21,"layer1" 31,"APP_1 layer1",3,"21",21,"layer1" 34,"Buffer: 1 layer1",0,"Queue",21,"layer1" 34,"GPU_1 layer1",-1,"21",21,"layer1" 37,"Buffer: 1 layer1",0,"Dequeue",22,"layer1" 37,"APP_1 layer1",4,"22",22,"layer1" 41,"Buffer: 1 layer1",0,"Queue",22,"layer1" 41,"GPU_1 layer1",5,"22",22,"layer1" 46,"Buffer: 1 layer1",0,"AcquireFenceSignaled",22,"layer1" 53,"Buffer: 2 layer2",0,"Dequeue",24,"layer2" 53,"APP_2 layer2",-1,"0",0,"layer2" 59,"Buffer: 2 layer2",0,"AcquireFenceSignaled",24,"layer2" 61,"Buffer: 2 layer2",0,"Latch",24,"layer2" 61,"SF_2 layer2",-1,"24",24,"layer2" 63,"Buffer: 1 layer1",0,"Dequeue",25,"layer1" 63,"APP_1 layer1",-1,"0",0,"layer1" 73,"Buffer: 1 layer1",0,"Dequeue",26,"layer1" 73,"APP_1 layer1",2,"26",26,"layer1" 75,"Buffer: 1 layer1",0,"Queue",26,"layer1" 75,"GPU_1 layer1",4,"26",26,"layer1" 79,"Buffer: 1 layer1",0,"AcquireFenceSignaled",26,"layer1" 81,"Buffer: 1 layer1",0,"Dequeue",30,"layer1" 81,"APP_1 layer1",2,"30",30,"layer1" 83,"Buffer: 1 layer1",0,"Queue",30,"layer1" 83,"GPU_1 layer1",-1,"30",30,"layer1" 90,"Buffer: 1 layer2",0,"Dequeue",35,"layer2" 90,"APP_1 layer2",2,"35",35,"layer2" 92,"Buffer: 1 layer2",0,"Queue",35,"layer2" 92,"GPU_1 layer2",-1,"35",35,"layer2" '''))