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