Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "ContextStateTracker.h"
7 : #include "GLContext.h"
8 : #include "GeckoProfiler.h"
9 : #include "ProfilerMarkerPayload.h"
10 :
11 : namespace mozilla {
12 :
13 : void
14 0 : ContextStateTrackerOGL::PushOGLSection(GLContext* aGL, const char* aSectionName)
15 : {
16 0 : if (!profiler_feature_active(ProfilerFeature::GPU)) {
17 0 : return;
18 : }
19 :
20 0 : if (!aGL->IsSupported(gl::GLFeature::query_objects)) {
21 0 : return;
22 : }
23 :
24 0 : if (mSectionStack.Length() > 0) {
25 : // We need to end the query since we're starting a new section and restore it
26 : // when this section is finished.
27 0 : aGL->fEndQuery(LOCAL_GL_TIME_ELAPSED);
28 0 : Top().mCpuTimeEnd = TimeStamp::Now();
29 : }
30 :
31 0 : ContextState newSection(aSectionName);
32 :
33 : GLuint queryObject;
34 0 : aGL->fGenQueries(1, &queryObject);
35 0 : newSection.mStartQueryHandle = queryObject;
36 0 : newSection.mCpuTimeStart = TimeStamp::Now();
37 :
38 0 : aGL->fBeginQuery(LOCAL_GL_TIME_ELAPSED_EXT, queryObject);
39 :
40 0 : mSectionStack.AppendElement(newSection);
41 : }
42 :
43 : void
44 0 : ContextStateTrackerOGL::PopOGLSection(GLContext* aGL, const char* aSectionName)
45 : {
46 : // We might have ignored a section start if we started profiling
47 : // in the middle section. If so we will ignore this unmatched end.
48 0 : if (mSectionStack.Length() == 0) {
49 0 : return;
50 : }
51 :
52 0 : int i = mSectionStack.Length() - 1;
53 0 : MOZ_ASSERT(strcmp(mSectionStack[i].mSectionName, aSectionName) == 0);
54 0 : aGL->fEndQuery(LOCAL_GL_TIME_ELAPSED);
55 0 : mSectionStack[i].mCpuTimeEnd = TimeStamp::Now();
56 0 : mCompletedSections.AppendElement(mSectionStack[i]);
57 0 : mSectionStack.RemoveElementAt(i);
58 :
59 0 : if (i - 1 >= 0) {
60 0 : const char* sectionToRestore = Top().mSectionName;
61 :
62 : // We need to restore the outer section
63 : // Well do this by completing this section and adding a new
64 : // one with the same name
65 0 : mCompletedSections.AppendElement(Top());
66 0 : mSectionStack.RemoveElementAt(i - 1);
67 :
68 0 : ContextState newSection(sectionToRestore);
69 :
70 : GLuint queryObject;
71 0 : aGL->fGenQueries(1, &queryObject);
72 0 : newSection.mStartQueryHandle = queryObject;
73 0 : newSection.mCpuTimeStart = TimeStamp::Now();
74 :
75 0 : aGL->fBeginQuery(LOCAL_GL_TIME_ELAPSED_EXT, queryObject);
76 :
77 0 : mSectionStack.AppendElement(newSection);
78 : }
79 :
80 0 : Flush(aGL);
81 : }
82 :
83 : void
84 0 : ContextStateTrackerOGL::Flush(GLContext* aGL)
85 : {
86 0 : TimeStamp now = TimeStamp::Now();
87 :
88 0 : while (mCompletedSections.Length() != 0) {
89 : // On mac we see QUERY_RESULT_AVAILABLE cause a GL flush if we query it
90 : // too early. For profiling we rather have the last 200ms of data missing
91 : // while causing let's measurement distortions.
92 0 : if (mCompletedSections[0].mCpuTimeEnd + TimeDuration::FromMilliseconds(200) > now) {
93 0 : break;
94 : }
95 :
96 0 : GLuint handle = mCompletedSections[0].mStartQueryHandle;
97 :
98 : // We've waiting 200ms, content rendering at > 20 FPS will be ready. We
99 : // shouldn't see any flushes now.
100 0 : GLuint returned = 0;
101 0 : aGL->fGetQueryObjectuiv(handle, LOCAL_GL_QUERY_RESULT_AVAILABLE, &returned);
102 :
103 0 : if (!returned) {
104 0 : break;
105 : }
106 :
107 0 : GLuint gpuTime = 0;
108 0 : aGL->fGetQueryObjectuiv(handle, LOCAL_GL_QUERY_RESULT, &gpuTime);
109 :
110 0 : aGL->fDeleteQueries(1, &handle);
111 :
112 0 : if (profiler_is_active()) {
113 0 : profiler_add_marker(
114 : "gpu_timer_query",
115 0 : MakeUnique<GPUMarkerPayload>(mCompletedSections[0].mCpuTimeStart,
116 0 : mCompletedSections[0].mCpuTimeEnd,
117 0 : 0, gpuTime));
118 : }
119 :
120 0 : mCompletedSections.RemoveElementAt(0);
121 : }
122 0 : }
123 :
124 : void
125 0 : ContextStateTrackerOGL::DestroyOGL(GLContext* aGL)
126 : {
127 0 : while (mCompletedSections.Length() != 0) {
128 0 : GLuint handle = (GLuint)mCompletedSections[0].mStartQueryHandle;
129 0 : aGL->fDeleteQueries(1, &handle);
130 0 : mCompletedSections.RemoveElementAt(0);
131 : }
132 0 : }
133 :
134 : } // namespace mozilla
135 :
|