DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (2cd3752963fc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "ContextStateTracker.h"
#include "GLContext.h"
#include "GeckoProfiler.h"
#include "ProfilerMarkerPayload.h"

namespace mozilla {

void
ContextStateTrackerOGL::PushOGLSection(GLContext* aGL, const char* aSectionName)
{
  if (!profiler_feature_active(ProfilerFeature::GPU)) {
    return;
  }

  if (!aGL->IsSupported(gl::GLFeature::query_objects)) {
    return;
  }

  if (mSectionStack.Length() > 0) {
    // We need to end the query since we're starting a new section and restore it
    // when this section is finished.
    aGL->fEndQuery(LOCAL_GL_TIME_ELAPSED);
    Top().mCpuTimeEnd = TimeStamp::Now();
  }

  ContextState newSection(aSectionName);

  GLuint queryObject;
  aGL->fGenQueries(1, &queryObject);
  newSection.mStartQueryHandle = queryObject;
  newSection.mCpuTimeStart = TimeStamp::Now();

  aGL->fBeginQuery(LOCAL_GL_TIME_ELAPSED_EXT, queryObject);

  mSectionStack.AppendElement(newSection);
}

void
ContextStateTrackerOGL::PopOGLSection(GLContext* aGL, const char* aSectionName)
{
  // We might have ignored a section start if we started profiling
  // in the middle section. If so we will ignore this unmatched end.
  if (mSectionStack.Length() == 0) {
    return;
  }

  int i = mSectionStack.Length() - 1;
  MOZ_ASSERT(strcmp(mSectionStack[i].mSectionName, aSectionName) == 0);
  aGL->fEndQuery(LOCAL_GL_TIME_ELAPSED);
  mSectionStack[i].mCpuTimeEnd = TimeStamp::Now();
  mCompletedSections.AppendElement(mSectionStack[i]);
  mSectionStack.RemoveElementAt(i);

  if (i - 1 >= 0) {
    const char* sectionToRestore = Top().mSectionName;

    // We need to restore the outer section
    // Well do this by completing this section and adding a new
    // one with the same name
    mCompletedSections.AppendElement(Top());
    mSectionStack.RemoveElementAt(i - 1);

    ContextState newSection(sectionToRestore);

    GLuint queryObject;
    aGL->fGenQueries(1, &queryObject);
    newSection.mStartQueryHandle = queryObject;
    newSection.mCpuTimeStart = TimeStamp::Now();

    aGL->fBeginQuery(LOCAL_GL_TIME_ELAPSED_EXT, queryObject);

    mSectionStack.AppendElement(newSection);
  }

  Flush(aGL);
}

void
ContextStateTrackerOGL::Flush(GLContext* aGL)
{
  TimeStamp now = TimeStamp::Now();

  while (mCompletedSections.Length() != 0) {
    // On mac we see QUERY_RESULT_AVAILABLE cause a GL flush if we query it
    // too early. For profiling we rather have the last 200ms of data missing
    // while causing let's measurement distortions.
    if (mCompletedSections[0].mCpuTimeEnd + TimeDuration::FromMilliseconds(200) > now) {
      break;
    }

    GLuint handle = mCompletedSections[0].mStartQueryHandle;

    // We've waiting 200ms, content rendering at > 20 FPS will be ready. We
    // shouldn't see any flushes now.
    GLuint returned = 0;
    aGL->fGetQueryObjectuiv(handle, LOCAL_GL_QUERY_RESULT_AVAILABLE, &returned);

    if (!returned) {
      break;
    }

    GLuint gpuTime = 0;
    aGL->fGetQueryObjectuiv(handle, LOCAL_GL_QUERY_RESULT, &gpuTime);

    aGL->fDeleteQueries(1, &handle);

    if (profiler_is_active()) {
      profiler_add_marker(
        "gpu_timer_query",
        MakeUnique<GPUMarkerPayload>(mCompletedSections[0].mCpuTimeStart,
                                     mCompletedSections[0].mCpuTimeEnd,
                                     0, gpuTime));
    }

    mCompletedSections.RemoveElementAt(0);
  }
}

void
ContextStateTrackerOGL::DestroyOGL(GLContext* aGL)
{
  while (mCompletedSections.Length() != 0) {
    GLuint handle = (GLuint)mCompletedSections[0].mStartQueryHandle;
    aGL->fDeleteQueries(1, &handle);
    mCompletedSections.RemoveElementAt(0);
  }
}

} // namespace mozilla