blob: 22a5293014dd41ec41b5fd229fe8a24b5f91a723 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright 2018 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/tracing/core/test_utils.html">
<link rel="import" href="/tracing/metrics/rendering/pipeline.html">
<link rel="import" href="/tracing/model/user_model/segment.html">
<link rel="import" href="/tracing/value/histogram_set.html">
<script>
'use strict';
tr.b.unittest.testSuite(function() {
function addPipelineForOneFrame(compositor, renderer, id, frame,
displayTrace) {
const EVENT_NAME = 'Graphics.Pipeline';
if (frame.IssueBeginFrame) {
compositor.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
{ title: EVENT_NAME,
start: frame.IssueBeginFrame, duration: 1, bindId: id,
args: {step: 'IssueBeginFrame'}}));
}
if (frame.ReceiveBeginFrame) {
renderer.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
{ title: EVENT_NAME,
start: frame.ReceiveBeginFrame, duration: 1, bindId: id,
args: {step: 'ReceiveBeginFrame'}}));
}
renderer.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
{ title: EVENT_NAME,
start: frame.GenerateRenderPass, duration: 1, bindId: id,
args: {step: 'GenerateRenderPass'}}));
renderer.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
{ title: EVENT_NAME,
start: frame.GenerateCompositorFrame, duration: 1, bindId: id,
args: {step: 'GenerateCompositorFrame'}}));
renderer.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
{ title: EVENT_NAME,
start: frame.SubmitCompositorFrame, duration: 1, bindId: id,
args: {step: 'SubmitCompositorFrame'}}));
compositor.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
{ title: EVENT_NAME,
start: frame.ReceiveCompositorFrame, duration: 1, bindId: id,
args: {step: 'ReceiveCompositorFrame'}}));
compositor.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
{ title: EVENT_NAME,
start: frame.SurfaceAggregation, duration: 1, bindId: id,
args: {step: 'SurfaceAggregation', display_trace: displayTrace}}));
}
function addDrawSlice(compositor, displayTrace, start, steps, opt_args) {
const EVENT_NAME = 'Graphics.Pipeline.DrawAndSwap';
let totalDuration = 0;
for (const duration of Object.values(steps)) {
totalDuration += duration;
}
const slice = tr.c.TestUtils.newAsyncSliceNamed(
EVENT_NAME, start, totalDuration);
slice.id = ':ptr:' + displayTrace;
slice.args = opt_args;
compositor.sliceGroup.pushSlice(slice);
totalDuration = 0;
for (const step in steps) {
slice.subSlices.push(tr.c.TestUtils.newAsyncSliceNamed(
step, start + totalDuration, steps[step]));
totalDuration += steps[step];
}
}
test('graphicsPipeline', function() {
const model = tr.c.TestUtils.newModel((model) => {
const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
browserMain.name = 'CrBrowserMain';
const rendererCompositor =
model.getOrCreateProcess(1).getOrCreateThread(1);
rendererCompositor.name = 'Compositor';
addPipelineForOneFrame(browserMain, rendererCompositor, 1, {
IssueBeginFrame: 1, ReceiveBeginFrame: 2, GenerateRenderPass: 3,
GenerateCompositorFrame: 4, SubmitCompositorFrame: 5,
ReceiveCompositorFrame: 6, SurfaceAggregation: 10
});
addPipelineForOneFrame(browserMain, rendererCompositor, 2, {
IssueBeginFrame: 15, ReceiveBeginFrame: 16, GenerateRenderPass: 17,
GenerateCompositorFrame: 18, SubmitCompositorFrame: 19,
ReceiveCompositorFrame: 20, SurfaceAggregation: 21
});
addPipelineForOneFrame(browserMain, rendererCompositor, 3, {
IssueBeginFrame: 32, ReceiveBeginFrame: 34, GenerateRenderPass: 35,
GenerateCompositorFrame: 36, SubmitCompositorFrame: 37,
SubmitCompositorFrame: 38, ReceiveCompositorFrame: 41,
SurfaceAggregation: 44
});
});
const histograms = new tr.v.HistogramSet();
tr.metrics.rendering.addPipelineHistograms(
histograms, model, [new tr.model.um.Segment(0, 50)]);
const beginFrameTransport = histograms.getHistogramNamed(
'pipeline:begin_frame_transport');
const frameSubmission = histograms.getHistogramNamed(
'pipeline:begin_frame_to_frame_submission');
const surfaceAggregation = histograms.getHistogramNamed(
'pipeline:frame_submission_to_display');
assert.closeTo(beginFrameTransport.average, 4 / 3, 1e-6);
assert.closeTo(frameSubmission.average, 13 / 3, 1e-6);
assert.closeTo(surfaceAggregation.average, 13 / 3, 1e-6);
});
test('graphicsPipeline_duplicateSteps', function() {
const model = tr.c.TestUtils.newModel((model) => {
const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
browserMain.name = 'CrBrowserMain';
const rendererCompositor =
model.getOrCreateProcess(1).getOrCreateThread(1);
rendererCompositor.name = 'Compositor';
addPipelineForOneFrame(browserMain, rendererCompositor, 1, {
IssueBeginFrame: 1, ReceiveBeginFrame: 2, GenerateRenderPass: 3,
GenerateCompositorFrame: 4, SubmitCompositorFrame: 5,
ReceiveCompositorFrame: 6, SurfaceAggregation: 9
});
// Add duplicate steps for SubmitCompositorFrame and the subsequent
// steps for the same trace-id.
addPipelineForOneFrame(browserMain, rendererCompositor, 1, {
GenerateRenderPass: 10, GenerateCompositorFrame: 11,
SubmitCompositorFrame: 12, ReceiveCompositorFrame: 15,
SurfaceAggregation: 18
});
});
const histograms = new tr.v.HistogramSet();
tr.metrics.rendering.addPipelineHistograms(
histograms, model,
[new tr.model.um.Segment(0, 50), new tr.model.um.Segment(0, 20)]);
const beginFrameTransport = histograms.getHistogramNamed(
'pipeline:begin_frame_transport');
const frameSubmission = histograms.getHistogramNamed(
'pipeline:begin_frame_to_frame_submission');
const surfaceAggregation = histograms.getHistogramNamed(
'pipeline:frame_submission_to_display');
assert.strictEqual(beginFrameTransport.average, 1);
assert.strictEqual(frameSubmission.average, 4);
assert.strictEqual(surfaceAggregation.average, 4);
});
test('graphicsPipeline_drawSteps', function() {
const model = tr.c.TestUtils.newModel((model) => {
const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
browserMain.name = 'CrBrowserMain';
const rendererCompositor =
model.getOrCreateProcess(1).getOrCreateThread(1);
rendererCompositor.name = 'Compositor';
const displayTrace = '1';
addPipelineForOneFrame(browserMain, rendererCompositor, 1, {
IssueBeginFrame: 1, ReceiveBeginFrame: 2, GenerateRenderPass: 3,
GenerateCompositorFrame: 4, SubmitCompositorFrame: 5,
ReceiveCompositorFrame: 6, SurfaceAggregation: 9
}, displayTrace);
addDrawSlice(browserMain, displayTrace, 10,
{Draw: 2, Swap: 1, WaitForAck: 5}, {});
});
const histograms = new tr.v.HistogramSet();
tr.metrics.rendering.addPipelineHistograms(
histograms, model, [new tr.model.um.Segment(0, 50)]);
const drawHistogram = histograms.getHistogramNamed('pipeline:draw');
assert.strictEqual(drawHistogram.average, 8);
});
test('graphicsPipeline_drawCanceled', function() {
const model = tr.c.TestUtils.newModel((model) => {
const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
browserMain.name = 'CrBrowserMain';
const rendererCompositor =
model.getOrCreateProcess(1).getOrCreateThread(1);
rendererCompositor.name = 'Compositor';
const displayTrace = '1';
addPipelineForOneFrame(browserMain, rendererCompositor, 1, {
IssueBeginFrame: 1, ReceiveBeginFrame: 2, GenerateRenderPass: 3,
GenerateCompositorFrame: 4, SubmitCompositorFrame: 5,
ReceiveCompositorFrame: 6, SurfaceAggregation: 9
}, displayTrace);
addDrawSlice(browserMain, displayTrace, 10,
{Draw: 2, Swap: 1, WaitForAck: 5}, {status: 'canceled'});
addDrawSlice(browserMain, displayTrace, 15,
{Draw: 2, Swap: 1, WaitForAck: 5});
});
const histograms = new tr.v.HistogramSet();
tr.metrics.rendering.addPipelineHistograms(
histograms, model, [new tr.model.um.Segment(0, 50)]);
const drawHistogram = histograms.getHistogramNamed('pipeline:draw');
assert.strictEqual(drawHistogram.average, 8);
});
});
</script>