1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2013 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/gl/GLTestContext.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/gl/GrGLDirectContext.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/gl/GrGLUtil.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/GpuTimer.h"
14*c8dee2aaSAndroid Build Coastguard Worker
15*c8dee2aaSAndroid Build Coastguard Worker namespace {
16*c8dee2aaSAndroid Build Coastguard Worker
17*c8dee2aaSAndroid Build Coastguard Worker class GLGpuTimer : public sk_gpu_test::GpuTimer {
18*c8dee2aaSAndroid Build Coastguard Worker public:
19*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<GLGpuTimer> MakeIfSupported(const sk_gpu_test::GLTestContext*);
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Worker QueryStatus checkQueryStatus(sk_gpu_test::PlatformTimerQuery) override;
22*c8dee2aaSAndroid Build Coastguard Worker std::chrono::nanoseconds getTimeElapsed(sk_gpu_test::PlatformTimerQuery) override;
23*c8dee2aaSAndroid Build Coastguard Worker void deleteQuery(sk_gpu_test::PlatformTimerQuery) override;
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker private:
26*c8dee2aaSAndroid Build Coastguard Worker GLGpuTimer(bool disjointSupport, const sk_gpu_test::GLTestContext*, const char* ext = "");
27*c8dee2aaSAndroid Build Coastguard Worker bool validate() const;
28*c8dee2aaSAndroid Build Coastguard Worker
29*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::PlatformTimerQuery onQueueTimerStart() const override;
30*c8dee2aaSAndroid Build Coastguard Worker void onQueueTimerStop(sk_gpu_test::PlatformTimerQuery) const override;
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr GrGLenum GL_QUERY_RESULT = 0x8866;
33*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr GrGLenum GL_QUERY_RESULT_AVAILABLE = 0x8867;
34*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr GrGLenum GL_TIME_ELAPSED = 0x88bf;
35*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr GrGLenum GL_GPU_DISJOINT = 0x8fbb;
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker typedef void (GR_GL_FUNCTION_TYPE* GLGetIntegervProc) (GrGLenum, GrGLint*);
38*c8dee2aaSAndroid Build Coastguard Worker typedef void (GR_GL_FUNCTION_TYPE* GLGenQueriesProc) (GrGLsizei, GrGLuint*);
39*c8dee2aaSAndroid Build Coastguard Worker typedef void (GR_GL_FUNCTION_TYPE* GLDeleteQueriesProc) (GrGLsizei, const GrGLuint*);
40*c8dee2aaSAndroid Build Coastguard Worker typedef void (GR_GL_FUNCTION_TYPE* GLBeginQueryProc) (GrGLenum, GrGLuint);
41*c8dee2aaSAndroid Build Coastguard Worker typedef void (GR_GL_FUNCTION_TYPE* GLEndQueryProc) (GrGLenum);
42*c8dee2aaSAndroid Build Coastguard Worker typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectuivProc) (GrGLuint, GrGLenum, GrGLuint*);
43*c8dee2aaSAndroid Build Coastguard Worker typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectui64vProc) (GrGLuint, GrGLenum, GrGLuint64*);
44*c8dee2aaSAndroid Build Coastguard Worker
45*c8dee2aaSAndroid Build Coastguard Worker GLGetIntegervProc fGLGetIntegerv;
46*c8dee2aaSAndroid Build Coastguard Worker GLGenQueriesProc fGLGenQueries;
47*c8dee2aaSAndroid Build Coastguard Worker GLDeleteQueriesProc fGLDeleteQueries;
48*c8dee2aaSAndroid Build Coastguard Worker GLBeginQueryProc fGLBeginQuery;
49*c8dee2aaSAndroid Build Coastguard Worker GLEndQueryProc fGLEndQuery;
50*c8dee2aaSAndroid Build Coastguard Worker GLGetQueryObjectuivProc fGLGetQueryObjectuiv;
51*c8dee2aaSAndroid Build Coastguard Worker GLGetQueryObjectui64vProc fGLGetQueryObjectui64v;
52*c8dee2aaSAndroid Build Coastguard Worker
53*c8dee2aaSAndroid Build Coastguard Worker
54*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = sk_gpu_test::GpuTimer;
55*c8dee2aaSAndroid Build Coastguard Worker };
56*c8dee2aaSAndroid Build Coastguard Worker
MakeIfSupported(const sk_gpu_test::GLTestContext * ctx)57*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GLGpuTimer> GLGpuTimer::MakeIfSupported(const sk_gpu_test::GLTestContext* ctx) {
58*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GLGpuTimer> ret;
59*c8dee2aaSAndroid Build Coastguard Worker const GrGLInterface* gl = ctx->gl();
60*c8dee2aaSAndroid Build Coastguard Worker if (gl->fExtensions.has("GL_EXT_disjoint_timer_query")) {
61*c8dee2aaSAndroid Build Coastguard Worker ret.reset(new GLGpuTimer(true, ctx, "EXT"));
62*c8dee2aaSAndroid Build Coastguard Worker } else if (kGL_GrGLStandard == gl->fStandard &&
63*c8dee2aaSAndroid Build Coastguard Worker (GrGLGetVersion(gl) > GR_GL_VER(3,3) || gl->fExtensions.has("GL_ARB_timer_query"))) {
64*c8dee2aaSAndroid Build Coastguard Worker ret.reset(new GLGpuTimer(false, ctx));
65*c8dee2aaSAndroid Build Coastguard Worker } else if (gl->fExtensions.has("GL_EXT_timer_query")) {
66*c8dee2aaSAndroid Build Coastguard Worker ret.reset(new GLGpuTimer(false, ctx, "EXT"));
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker if (ret && !ret->validate()) {
69*c8dee2aaSAndroid Build Coastguard Worker ret = nullptr;
70*c8dee2aaSAndroid Build Coastguard Worker }
71*c8dee2aaSAndroid Build Coastguard Worker return ret;
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker
GLGpuTimer(bool disjointSupport,const sk_gpu_test::GLTestContext * ctx,const char * ext)74*c8dee2aaSAndroid Build Coastguard Worker GLGpuTimer::GLGpuTimer(bool disjointSupport, const sk_gpu_test::GLTestContext* ctx, const char* ext)
75*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(disjointSupport) {
76*c8dee2aaSAndroid Build Coastguard Worker ctx->getGLProcAddress(&fGLGetIntegerv, "glGetIntegerv");
77*c8dee2aaSAndroid Build Coastguard Worker ctx->getGLProcAddress(&fGLGenQueries, "glGenQueries", ext);
78*c8dee2aaSAndroid Build Coastguard Worker ctx->getGLProcAddress(&fGLDeleteQueries, "glDeleteQueries", ext);
79*c8dee2aaSAndroid Build Coastguard Worker ctx->getGLProcAddress(&fGLBeginQuery, "glBeginQuery", ext);
80*c8dee2aaSAndroid Build Coastguard Worker ctx->getGLProcAddress(&fGLEndQuery, "glEndQuery", ext);
81*c8dee2aaSAndroid Build Coastguard Worker ctx->getGLProcAddress(&fGLGetQueryObjectuiv, "glGetQueryObjectuiv", ext);
82*c8dee2aaSAndroid Build Coastguard Worker ctx->getGLProcAddress(&fGLGetQueryObjectui64v, "glGetQueryObjectui64v", ext);
83*c8dee2aaSAndroid Build Coastguard Worker }
84*c8dee2aaSAndroid Build Coastguard Worker
validate() const85*c8dee2aaSAndroid Build Coastguard Worker bool GLGpuTimer::validate() const {
86*c8dee2aaSAndroid Build Coastguard Worker return fGLGetIntegerv && fGLGenQueries && fGLDeleteQueries && fGLBeginQuery && fGLEndQuery &&
87*c8dee2aaSAndroid Build Coastguard Worker fGLGetQueryObjectuiv && fGLGetQueryObjectui64v;
88*c8dee2aaSAndroid Build Coastguard Worker }
89*c8dee2aaSAndroid Build Coastguard Worker
onQueueTimerStart() const90*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::PlatformTimerQuery GLGpuTimer::onQueueTimerStart() const {
91*c8dee2aaSAndroid Build Coastguard Worker GrGLuint queryID;
92*c8dee2aaSAndroid Build Coastguard Worker fGLGenQueries(1, &queryID);
93*c8dee2aaSAndroid Build Coastguard Worker if (!queryID) {
94*c8dee2aaSAndroid Build Coastguard Worker return sk_gpu_test::kInvalidTimerQuery;
95*c8dee2aaSAndroid Build Coastguard Worker }
96*c8dee2aaSAndroid Build Coastguard Worker if (this->disjointSupport()) {
97*c8dee2aaSAndroid Build Coastguard Worker // Clear the disjoint flag.
98*c8dee2aaSAndroid Build Coastguard Worker GrGLint disjoint;
99*c8dee2aaSAndroid Build Coastguard Worker fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint);
100*c8dee2aaSAndroid Build Coastguard Worker }
101*c8dee2aaSAndroid Build Coastguard Worker fGLBeginQuery(GL_TIME_ELAPSED, queryID);
102*c8dee2aaSAndroid Build Coastguard Worker return static_cast<sk_gpu_test::PlatformTimerQuery>(queryID);
103*c8dee2aaSAndroid Build Coastguard Worker }
104*c8dee2aaSAndroid Build Coastguard Worker
onQueueTimerStop(sk_gpu_test::PlatformTimerQuery platformTimer) const105*c8dee2aaSAndroid Build Coastguard Worker void GLGpuTimer::onQueueTimerStop(sk_gpu_test::PlatformTimerQuery platformTimer) const {
106*c8dee2aaSAndroid Build Coastguard Worker if (sk_gpu_test::kInvalidTimerQuery == platformTimer) {
107*c8dee2aaSAndroid Build Coastguard Worker return;
108*c8dee2aaSAndroid Build Coastguard Worker }
109*c8dee2aaSAndroid Build Coastguard Worker fGLEndQuery(GL_TIME_ELAPSED);
110*c8dee2aaSAndroid Build Coastguard Worker }
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::GpuTimer::QueryStatus
checkQueryStatus(sk_gpu_test::PlatformTimerQuery platformTimer)113*c8dee2aaSAndroid Build Coastguard Worker GLGpuTimer::checkQueryStatus(sk_gpu_test::PlatformTimerQuery platformTimer) {
114*c8dee2aaSAndroid Build Coastguard Worker const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
115*c8dee2aaSAndroid Build Coastguard Worker if (!queryID) {
116*c8dee2aaSAndroid Build Coastguard Worker return QueryStatus::kInvalid;
117*c8dee2aaSAndroid Build Coastguard Worker }
118*c8dee2aaSAndroid Build Coastguard Worker GrGLuint available = 0;
119*c8dee2aaSAndroid Build Coastguard Worker fGLGetQueryObjectuiv(queryID, GL_QUERY_RESULT_AVAILABLE, &available);
120*c8dee2aaSAndroid Build Coastguard Worker if (!available) {
121*c8dee2aaSAndroid Build Coastguard Worker return QueryStatus::kPending;
122*c8dee2aaSAndroid Build Coastguard Worker }
123*c8dee2aaSAndroid Build Coastguard Worker if (this->disjointSupport()) {
124*c8dee2aaSAndroid Build Coastguard Worker GrGLint disjoint = 1;
125*c8dee2aaSAndroid Build Coastguard Worker fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint);
126*c8dee2aaSAndroid Build Coastguard Worker if (disjoint) {
127*c8dee2aaSAndroid Build Coastguard Worker return QueryStatus::kDisjoint;
128*c8dee2aaSAndroid Build Coastguard Worker }
129*c8dee2aaSAndroid Build Coastguard Worker }
130*c8dee2aaSAndroid Build Coastguard Worker return QueryStatus::kAccurate;
131*c8dee2aaSAndroid Build Coastguard Worker }
132*c8dee2aaSAndroid Build Coastguard Worker
getTimeElapsed(sk_gpu_test::PlatformTimerQuery platformTimer)133*c8dee2aaSAndroid Build Coastguard Worker std::chrono::nanoseconds GLGpuTimer::getTimeElapsed(sk_gpu_test::PlatformTimerQuery platformTimer) {
134*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(this->checkQueryStatus(platformTimer) >= QueryStatus::kDisjoint);
135*c8dee2aaSAndroid Build Coastguard Worker const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
136*c8dee2aaSAndroid Build Coastguard Worker GrGLuint64 nanoseconds;
137*c8dee2aaSAndroid Build Coastguard Worker fGLGetQueryObjectui64v(queryID, GL_QUERY_RESULT, &nanoseconds);
138*c8dee2aaSAndroid Build Coastguard Worker return std::chrono::nanoseconds(nanoseconds);
139*c8dee2aaSAndroid Build Coastguard Worker }
140*c8dee2aaSAndroid Build Coastguard Worker
deleteQuery(sk_gpu_test::PlatformTimerQuery platformTimer)141*c8dee2aaSAndroid Build Coastguard Worker void GLGpuTimer::deleteQuery(sk_gpu_test::PlatformTimerQuery platformTimer) {
142*c8dee2aaSAndroid Build Coastguard Worker const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
143*c8dee2aaSAndroid Build Coastguard Worker fGLDeleteQueries(1, &queryID);
144*c8dee2aaSAndroid Build Coastguard Worker }
145*c8dee2aaSAndroid Build Coastguard Worker
146*c8dee2aaSAndroid Build Coastguard Worker static_assert(sizeof(GrGLuint) <= sizeof(sk_gpu_test::PlatformTimerQuery));
147*c8dee2aaSAndroid Build Coastguard Worker
148*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
149*c8dee2aaSAndroid Build Coastguard Worker
150*c8dee2aaSAndroid Build Coastguard Worker namespace sk_gpu_test {
151*c8dee2aaSAndroid Build Coastguard Worker
GLTestContext()152*c8dee2aaSAndroid Build Coastguard Worker GLTestContext::GLTestContext() : TestContext() {}
153*c8dee2aaSAndroid Build Coastguard Worker
~GLTestContext()154*c8dee2aaSAndroid Build Coastguard Worker GLTestContext::~GLTestContext() {
155*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fGLInterface);
156*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fOriginalGLInterface);
157*c8dee2aaSAndroid Build Coastguard Worker }
158*c8dee2aaSAndroid Build Coastguard Worker
isValid() const159*c8dee2aaSAndroid Build Coastguard Worker bool GLTestContext::isValid() const {
160*c8dee2aaSAndroid Build Coastguard Worker return SkToBool(this->gl());
161*c8dee2aaSAndroid Build Coastguard Worker }
162*c8dee2aaSAndroid Build Coastguard Worker
fence_is_supported(const GLTestContext * ctx)163*c8dee2aaSAndroid Build Coastguard Worker static bool fence_is_supported(const GLTestContext* ctx) {
164*c8dee2aaSAndroid Build Coastguard Worker if (kGL_GrGLStandard == ctx->gl()->fStandard) {
165*c8dee2aaSAndroid Build Coastguard Worker if (GrGLGetVersion(ctx->gl()) < GR_GL_VER(3, 2) &&
166*c8dee2aaSAndroid Build Coastguard Worker !ctx->gl()->hasExtension("GL_ARB_sync")) {
167*c8dee2aaSAndroid Build Coastguard Worker return false;
168*c8dee2aaSAndroid Build Coastguard Worker }
169*c8dee2aaSAndroid Build Coastguard Worker return true;
170*c8dee2aaSAndroid Build Coastguard Worker } else {
171*c8dee2aaSAndroid Build Coastguard Worker if (ctx->gl()->hasExtension("GL_APPLE_sync")) {
172*c8dee2aaSAndroid Build Coastguard Worker return true;
173*c8dee2aaSAndroid Build Coastguard Worker } else if (ctx->gl()->hasExtension("GL_NV_fence")) {
174*c8dee2aaSAndroid Build Coastguard Worker return true;
175*c8dee2aaSAndroid Build Coastguard Worker } else if (GrGLGetVersion(ctx->gl()) >= GR_GL_VER(3, 0)) {
176*c8dee2aaSAndroid Build Coastguard Worker return true;
177*c8dee2aaSAndroid Build Coastguard Worker } else {
178*c8dee2aaSAndroid Build Coastguard Worker return false;
179*c8dee2aaSAndroid Build Coastguard Worker }
180*c8dee2aaSAndroid Build Coastguard Worker }
181*c8dee2aaSAndroid Build Coastguard Worker }
182*c8dee2aaSAndroid Build Coastguard Worker
init(sk_sp<const GrGLInterface> gl)183*c8dee2aaSAndroid Build Coastguard Worker void GLTestContext::init(sk_sp<const GrGLInterface> gl) {
184*c8dee2aaSAndroid Build Coastguard Worker fGLInterface = std::move(gl);
185*c8dee2aaSAndroid Build Coastguard Worker fOriginalGLInterface = fGLInterface;
186*c8dee2aaSAndroid Build Coastguard Worker fFenceSupport = fence_is_supported(this);
187*c8dee2aaSAndroid Build Coastguard Worker fGpuTimer = GLGpuTimer::MakeIfSupported(this);
188*c8dee2aaSAndroid Build Coastguard Worker }
189*c8dee2aaSAndroid Build Coastguard Worker
teardown()190*c8dee2aaSAndroid Build Coastguard Worker void GLTestContext::teardown() {
191*c8dee2aaSAndroid Build Coastguard Worker fGLInterface.reset();
192*c8dee2aaSAndroid Build Coastguard Worker fOriginalGLInterface.reset();
193*c8dee2aaSAndroid Build Coastguard Worker INHERITED::teardown();
194*c8dee2aaSAndroid Build Coastguard Worker }
195*c8dee2aaSAndroid Build Coastguard Worker
testAbandon()196*c8dee2aaSAndroid Build Coastguard Worker void GLTestContext::testAbandon() {
197*c8dee2aaSAndroid Build Coastguard Worker INHERITED::testAbandon();
198*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
199*c8dee2aaSAndroid Build Coastguard Worker if (fGLInterface) {
200*c8dee2aaSAndroid Build Coastguard Worker fGLInterface->abandon();
201*c8dee2aaSAndroid Build Coastguard Worker fOriginalGLInterface->abandon();
202*c8dee2aaSAndroid Build Coastguard Worker }
203*c8dee2aaSAndroid Build Coastguard Worker #endif
204*c8dee2aaSAndroid Build Coastguard Worker }
205*c8dee2aaSAndroid Build Coastguard Worker
overrideVersion(const char * version,const char * shadingLanguageVersion)206*c8dee2aaSAndroid Build Coastguard Worker void GLTestContext::overrideVersion(const char* version, const char* shadingLanguageVersion) {
207*c8dee2aaSAndroid Build Coastguard Worker // GrGLFunction has both a limited capture size and doesn't call a destructor when it is
208*c8dee2aaSAndroid Build Coastguard Worker // initialized with a lambda. So here we're trusting fOriginalGLInterface will be kept alive.
209*c8dee2aaSAndroid Build Coastguard Worker auto getString = [wrapped = &fOriginalGLInterface->fFunctions.fGetString,
210*c8dee2aaSAndroid Build Coastguard Worker version,
211*c8dee2aaSAndroid Build Coastguard Worker shadingLanguageVersion](GrGLenum name) {
212*c8dee2aaSAndroid Build Coastguard Worker if (name == GR_GL_VERSION) {
213*c8dee2aaSAndroid Build Coastguard Worker return reinterpret_cast<const GrGLubyte*>(version);
214*c8dee2aaSAndroid Build Coastguard Worker } else if (name == GR_GL_SHADING_LANGUAGE_VERSION) {
215*c8dee2aaSAndroid Build Coastguard Worker return reinterpret_cast<const GrGLubyte*>(shadingLanguageVersion);
216*c8dee2aaSAndroid Build Coastguard Worker }
217*c8dee2aaSAndroid Build Coastguard Worker return (*wrapped)(name);
218*c8dee2aaSAndroid Build Coastguard Worker };
219*c8dee2aaSAndroid Build Coastguard Worker auto newInterface = sk_make_sp<GrGLInterface>(*fOriginalGLInterface);
220*c8dee2aaSAndroid Build Coastguard Worker newInterface->fFunctions.fGetString = getString;
221*c8dee2aaSAndroid Build Coastguard Worker fGLInterface = std::move(newInterface);
222*c8dee2aaSAndroid Build Coastguard Worker }
223*c8dee2aaSAndroid Build Coastguard Worker
makeContext(const GrContextOptions & options)224*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrDirectContext> GLTestContext::makeContext(const GrContextOptions& options) {
225*c8dee2aaSAndroid Build Coastguard Worker return GrDirectContexts::MakeGL(fGLInterface, options);
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker
228*c8dee2aaSAndroid Build Coastguard Worker } // namespace sk_gpu_test
229