]> git.cworth.org Git - apitrace/blob - common/trace_profiler.cpp
Synchronise gpuStart and cpuStart for profiling.
[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 <iostream>
28 #include <string.h>
29 #include <assert.h>
30 #include <sstream>
31 #include "os_time.hpp"
32
33 namespace trace {
34 Profiler::Profiler()
35     : baseGpuTime(0),
36       baseCpuTime(0),
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 << "# frame_begin no gpu_start cpu_start" << std::endl;
54     std::cout << "# frame_end no gpu_end gpu_dura cpu_end cpu_dura" << std::endl;
55     std::cout << "# call no gpu_start gpu_dura cpu_start cpu_dura pixels program name" << std::endl;
56 }
57
58 void Profiler::setBaseTimes(uint64_t gpuStart, uint64_t cpuStart)
59 {
60     baseCpuTime = cpuStart;
61     baseGpuTime = gpuStart;
62 }
63
64 void Profiler::addCall(unsigned no,
65                        const char *name,
66                        unsigned program,
67                        uint64_t pixels,
68                        uint64_t gpuStart, uint64_t gpuDuration,
69                        uint64_t cpuStart, uint64_t cpuDuration)
70 {
71     if (gpuTimes) {
72         gpuStart -= baseGpuTime;
73     } else {
74         gpuStart = 0;
75         gpuDuration = 0;
76     }
77
78     if (cpuTimes) {
79         double cpuTimeScale = 1.0E9 / os::timeFrequency;
80         cpuStart = (cpuStart - baseCpuTime) * cpuTimeScale;
81         cpuDuration = cpuDuration * cpuTimeScale;
82     } else {
83         cpuStart = 0;
84         cpuDuration = 0;
85     }
86
87     if (!pixelsDrawn) {
88         pixels = 0;
89     }
90
91     std::cout << "call"
92               << " " << no
93               << " " << gpuStart
94               << " " << gpuDuration
95               << " " << cpuStart
96               << " " << cpuDuration
97               << " " << pixels
98               << " " << program
99               << " " << name
100               << std::endl;
101 }
102
103 void Profiler::addFrameStart(unsigned no, uint64_t gpuStart, uint64_t cpuStart)
104 {
105     lastFrame.no = no;
106     lastFrame.gpuStart = gpuStart;
107     lastFrame.cpuStart = cpuStart;
108
109     if (gpuTimes) {
110         gpuStart = gpuStart - baseGpuTime;
111     } else {
112         gpuStart = 0;
113     }
114
115     if (cpuTimes) {
116         double cpuTimeScale = 1.0E9 / os::timeFrequency;
117         cpuStart = (cpuStart - baseCpuTime) * cpuTimeScale;
118     } else {
119         cpuStart = 0;
120     }
121
122     std::cout << "frame_begin"
123               << " " << no
124               << " " << gpuStart
125               << " " << cpuStart
126               << std::endl;
127 }
128
129 void Profiler::addFrameEnd(uint64_t gpuEnd, uint64_t cpuEnd)
130 {
131     uint64_t gpuDuration, cpuDuration;
132
133     if (gpuTimes) {
134         gpuDuration = gpuEnd - lastFrame.gpuStart;
135         gpuEnd = gpuEnd - baseGpuTime;
136     } else {
137         gpuEnd = 0;
138         gpuDuration = 0;
139     }
140
141     if (cpuTimes) {
142         double cpuTimeScale = 1.0E9 / os::timeFrequency;
143         cpuDuration = (cpuEnd - lastFrame.cpuStart) * cpuTimeScale;
144         cpuEnd = (cpuEnd - baseCpuTime) * cpuTimeScale;
145     } else {
146         cpuEnd = 0;
147         cpuDuration = 0;
148     }
149
150     std::cout << "frame_end"
151               << " " << lastFrame.no
152               << " " << gpuEnd
153               << " " << gpuDuration
154               << " " << cpuEnd
155               << " " << cpuDuration
156               << std::endl;
157 }
158
159 void Profiler::parseLine(const char* in, Profile* profile)
160 {
161     std::stringstream line(in, std::ios_base::in);
162     std::string type;
163
164     if (in[0] == '#' || strlen(in) < 12)
165         return;
166
167     line >> type;
168
169     if (type.compare("call") == 0) {
170         assert(profile->frames.size());
171         Profile::Call call;
172
173         line >> call.no
174              >> call.gpuStart
175              >> call.gpuDuration
176              >> call.cpuStart
177              >> call.cpuDuration
178              >> call.pixels
179              >> call.program
180              >> call.name;
181
182         profile->frames.back().calls.push_back(call);
183     } else if (type.compare("frame_begin") == 0) {
184         Profile::Frame frame;
185         frame.gpuDuration = 0;
186         frame.cpuDuration = 0;
187
188         line >> frame.no
189              >> frame.gpuStart
190              >> frame.cpuStart;
191
192         profile->frames.push_back(frame);
193     } else if (type.compare("frame_end") == 0) {
194         assert(profile->frames.size());
195         Profile::Frame& frame = profile->frames.back();
196         int64_t skipi64;
197
198         line >> frame.no
199              >> skipi64
200              >> frame.gpuDuration
201              >> skipi64
202              >> frame.cpuDuration;
203     }
204 }
205 }