]> git.cworth.org Git - apitrace/blob - common/trace_profiler.cpp
0f90ee2766318c54f790fc110efd772b8126f309
[apitrace] / common / trace_profiler.cpp
1 /**************************************************************************
2  *
3  * Copyright 2012 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 #include "trace_profiler.hpp"
27 #include "os_time.hpp"
28 #include <iostream>
29 #include <string.h>
30 #include <sstream>
31
32 namespace trace {
33 Profiler::Profiler()
34     : baseGpuTime(0),
35       baseCpuTime(0),
36       minCpuTime(1000),
37       cpuTimes(false),
38       gpuTimes(true),
39       pixelsDrawn(false)
40 {
41 }
42
43 Profiler::~Profiler()
44 {
45 }
46
47 void Profiler::setup(bool cpuTimes_, bool gpuTimes_, bool pixelsDrawn_)
48 {
49     cpuTimes = cpuTimes_;
50     gpuTimes = gpuTimes_;
51     pixelsDrawn = pixelsDrawn_;
52
53     std::cout << "# call no gpu_start gpu_dura cpu_start cpu_dura pixels program name" << std::endl;
54 }
55
56 int64_t Profiler::getBaseCpuTime()
57 {
58     return baseCpuTime;
59 }
60
61 int64_t Profiler::getBaseGpuTime()
62 {
63     return baseGpuTime;
64 }
65
66 void Profiler::setBaseCpuTime(int64_t cpuStart)
67 {
68     baseCpuTime = cpuStart;
69 }
70
71 void Profiler::setBaseGpuTime(int64_t gpuStart)
72 {
73     baseGpuTime = gpuStart;
74 }
75
76 bool Profiler::hasBaseTimes()
77 {
78     return baseCpuTime != 0 || baseGpuTime != 0;
79 }
80
81 void Profiler::addCall(unsigned no,
82                        const char *name,
83                        unsigned program,
84                        int64_t pixels,
85                        int64_t gpuStart, int64_t gpuDuration,
86                        int64_t cpuStart, int64_t cpuDuration)
87 {
88     if (gpuTimes && gpuStart) {
89         gpuStart -= baseGpuTime;
90     } else {
91         gpuStart = 0;
92         gpuDuration = 0;
93     }
94
95     if (cpuTimes && cpuStart) {
96         double cpuTimeScale = 1.0E9 / os::timeFrequency;
97         cpuStart = (cpuStart - baseCpuTime) * cpuTimeScale;
98         cpuDuration = cpuDuration * cpuTimeScale;
99
100         if (cpuDuration < minCpuTime) {
101             return;
102         }
103     } else {
104         cpuStart = 0;
105         cpuDuration = 0;
106     }
107
108     if (!pixelsDrawn) {
109         pixels = 0;
110     }
111
112     std::cout << "call"
113               << " " << no
114               << " " << gpuStart
115               << " " << gpuDuration
116               << " " << cpuStart
117               << " " << cpuDuration
118               << " " << pixels
119               << " " << program
120               << " " << name
121               << std::endl;
122 }
123
124 void Profiler::addFrameEnd()
125 {
126     std::cout << "frame_end" << std::endl;
127 }
128
129 void Profiler::parseLine(const char* in, Profile* profile)
130 {
131     std::stringstream line(in, std::ios_base::in);
132     std::string type;
133     static int64_t lastGpuTime;
134     static int64_t lastCpuTime;
135
136     if (in[0] == '#' || strlen(in) < 4)
137         return;
138
139     if (profile->programs.size() == 0 && profile->calls.size() == 0 && profile->frames.size() == 0) {
140         lastGpuTime = 0;
141         lastCpuTime = 0;
142     }
143
144     line >> type;
145
146     if (type.compare("call") == 0) {
147         Profile::Call call;
148
149         line >> call.no
150              >> call.gpuStart
151              >> call.gpuDuration
152              >> call.cpuStart
153              >> call.cpuDuration
154              >> call.pixels
155              >> call.program
156              >> call.name;
157
158         if (lastGpuTime < call.gpuStart + call.gpuDuration) {
159             lastGpuTime = call.gpuStart + call.gpuDuration;
160         }
161
162         if (lastCpuTime < call.cpuStart + call.cpuDuration) {
163             lastCpuTime = call.cpuStart + call.cpuDuration;
164         }
165
166         profile->calls.push_back(call);
167
168         if (call.pixels >= 0) {
169             if (profile->programs.size() <= call.program) {
170                 profile->programs.resize(call.program + 1);
171             }
172
173             Profile::Program& program = profile->programs[call.program];
174             program.cpuTotal += call.cpuDuration;
175             program.gpuTotal += call.gpuDuration;
176             program.pixelTotal += call.pixels;
177             program.calls.push_back(profile->calls.size() - 1);
178         }
179     } else if (type.compare("frame_end") == 0) {
180         Profile::Frame frame;
181         frame.no = profile->frames.size();
182
183         if (frame.no == 0) {
184             frame.gpuStart = 0;
185             frame.cpuStart = 0;
186             frame.calls.begin = 0;
187         } else {
188             frame.gpuStart = profile->frames.back().gpuStart + profile->frames.back().gpuDuration;
189             frame.cpuStart = profile->frames.back().cpuStart + profile->frames.back().cpuDuration;
190             frame.calls.begin = profile->frames.back().calls.end + 1;
191         }
192
193         frame.gpuDuration = lastGpuTime - frame.gpuStart;
194         frame.cpuDuration = lastCpuTime - frame.cpuStart;
195         frame.calls.end = profile->calls.size() - 1;
196
197         profile->frames.push_back(frame);
198     }
199 }
200 }