blob: 5b5ce3f05e306df56a47b4ba047c1e3147e93c3e [file] [log] [blame]
bsalomon@google.com373a6632011-10-19 20:43:20 +00001/*
robertphillips@google.com6177e692013-02-28 20:16:25 +00002 * Copyright 2013 Google Inc.
bsalomon@google.com373a6632011-10-19 20:43:20 +00003 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
bsalomon18a2f9d2016-05-11 10:09:18 -07007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "tools/gpu/gl/GLTestContext.h"
csmartdaltonc6618dd2016-10-05 08:42:03 -07009
Robert Phillipsf4f80112020-07-13 16:13:31 -040010#include "include/gpu/GrDirectContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/gpu/gl/GrGLUtil.h"
12#include "tools/gpu/GpuTimer.h"
bsalomon@google.com373a6632011-10-19 20:43:20 +000013
csmartdalton421a3c12016-10-04 11:08:45 -070014namespace {
cdaltond416a5b2015-06-23 13:23:44 -070015
csmartdaltonc6618dd2016-10-05 08:42:03 -070016class GLGpuTimer : public sk_gpu_test::GpuTimer {
17public:
Ben Wagner145dbcd2016-11-03 14:40:50 -040018 static std::unique_ptr<GLGpuTimer> MakeIfSupported(const sk_gpu_test::GLTestContext*);
csmartdaltonc6618dd2016-10-05 08:42:03 -070019
20 QueryStatus checkQueryStatus(sk_gpu_test::PlatformTimerQuery) override;
21 std::chrono::nanoseconds getTimeElapsed(sk_gpu_test::PlatformTimerQuery) override;
22 void deleteQuery(sk_gpu_test::PlatformTimerQuery) override;
23
24private:
25 GLGpuTimer(bool disjointSupport, const sk_gpu_test::GLTestContext*, const char* ext = "");
26
27 bool validate() const;
28
29 sk_gpu_test::PlatformTimerQuery onQueueTimerStart() const override;
30 void onQueueTimerStop(sk_gpu_test::PlatformTimerQuery) const override;
31
32 static constexpr GrGLenum GL_QUERY_RESULT = 0x8866;
33 static constexpr GrGLenum GL_QUERY_RESULT_AVAILABLE = 0x8867;
34 static constexpr GrGLenum GL_TIME_ELAPSED = 0x88bf;
35 static constexpr GrGLenum GL_GPU_DISJOINT = 0x8fbb;
36
37 typedef void (GR_GL_FUNCTION_TYPE* GLGetIntegervProc) (GrGLenum, GrGLint*);
38 typedef void (GR_GL_FUNCTION_TYPE* GLGenQueriesProc) (GrGLsizei, GrGLuint*);
39 typedef void (GR_GL_FUNCTION_TYPE* GLDeleteQueriesProc) (GrGLsizei, const GrGLuint*);
40 typedef void (GR_GL_FUNCTION_TYPE* GLBeginQueryProc) (GrGLenum, GrGLuint);
41 typedef void (GR_GL_FUNCTION_TYPE* GLEndQueryProc) (GrGLenum);
42 typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectuivProc) (GrGLuint, GrGLenum, GrGLuint*);
43 typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectui64vProc) (GrGLuint, GrGLenum, GrGLuint64*);
44
45 GLGetIntegervProc fGLGetIntegerv;
46 GLGenQueriesProc fGLGenQueries;
47 GLDeleteQueriesProc fGLDeleteQueries;
48 GLBeginQueryProc fGLBeginQuery;
49 GLEndQueryProc fGLEndQuery;
50 GLGetQueryObjectuivProc fGLGetQueryObjectuiv;
51 GLGetQueryObjectui64vProc fGLGetQueryObjectui64v;
52
53
54 typedef sk_gpu_test::GpuTimer INHERITED;
55};
56
Ben Wagner145dbcd2016-11-03 14:40:50 -040057std::unique_ptr<GLGpuTimer> GLGpuTimer::MakeIfSupported(const sk_gpu_test::GLTestContext* ctx) {
Brian Salomonf4ba4ec2020-03-19 15:54:28 -040058#ifdef SK_GL
Ben Wagner145dbcd2016-11-03 14:40:50 -040059 std::unique_ptr<GLGpuTimer> ret;
csmartdaltonc6618dd2016-10-05 08:42:03 -070060 const GrGLInterface* gl = ctx->gl();
61 if (gl->fExtensions.has("GL_EXT_disjoint_timer_query")) {
62 ret.reset(new GLGpuTimer(true, ctx, "EXT"));
63 } else if (kGL_GrGLStandard == gl->fStandard &&
64 (GrGLGetVersion(gl) > GR_GL_VER(3,3) || gl->fExtensions.has("GL_ARB_timer_query"))) {
65 ret.reset(new GLGpuTimer(false, ctx));
66 } else if (gl->fExtensions.has("GL_EXT_timer_query")) {
67 ret.reset(new GLGpuTimer(false, ctx, "EXT"));
68 }
Ben Wagner145dbcd2016-11-03 14:40:50 -040069 if (ret && !ret->validate()) {
70 ret = nullptr;
71 }
72 return ret;
Brian Salomonf4ba4ec2020-03-19 15:54:28 -040073#else
74 return nullptr;
75#endif
csmartdaltonc6618dd2016-10-05 08:42:03 -070076}
77
78GLGpuTimer::GLGpuTimer(bool disjointSupport, const sk_gpu_test::GLTestContext* ctx, const char* ext)
79 : INHERITED(disjointSupport) {
80 ctx->getGLProcAddress(&fGLGetIntegerv, "glGetIntegerv");
81 ctx->getGLProcAddress(&fGLGenQueries, "glGenQueries", ext);
82 ctx->getGLProcAddress(&fGLDeleteQueries, "glDeleteQueries", ext);
83 ctx->getGLProcAddress(&fGLBeginQuery, "glBeginQuery", ext);
84 ctx->getGLProcAddress(&fGLEndQuery, "glEndQuery", ext);
85 ctx->getGLProcAddress(&fGLGetQueryObjectuiv, "glGetQueryObjectuiv", ext);
86 ctx->getGLProcAddress(&fGLGetQueryObjectui64v, "glGetQueryObjectui64v", ext);
87}
88
89bool GLGpuTimer::validate() const {
90 return fGLGetIntegerv && fGLGenQueries && fGLDeleteQueries && fGLBeginQuery && fGLEndQuery &&
91 fGLGetQueryObjectuiv && fGLGetQueryObjectui64v;
92}
93
94sk_gpu_test::PlatformTimerQuery GLGpuTimer::onQueueTimerStart() const {
95 GrGLuint queryID;
96 fGLGenQueries(1, &queryID);
97 if (!queryID) {
98 return sk_gpu_test::kInvalidTimerQuery;
99 }
100 if (this->disjointSupport()) {
101 // Clear the disjoint flag.
102 GrGLint disjoint;
103 fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint);
104 }
105 fGLBeginQuery(GL_TIME_ELAPSED, queryID);
106 return static_cast<sk_gpu_test::PlatformTimerQuery>(queryID);
107}
108
109void GLGpuTimer::onQueueTimerStop(sk_gpu_test::PlatformTimerQuery platformTimer) const {
110 if (sk_gpu_test::kInvalidTimerQuery == platformTimer) {
111 return;
112 }
113 fGLEndQuery(GL_TIME_ELAPSED);
114}
115
116sk_gpu_test::GpuTimer::QueryStatus
117GLGpuTimer::checkQueryStatus(sk_gpu_test::PlatformTimerQuery platformTimer) {
118 const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
119 if (!queryID) {
120 return QueryStatus::kInvalid;
121 }
122 GrGLuint available = 0;
123 fGLGetQueryObjectuiv(queryID, GL_QUERY_RESULT_AVAILABLE, &available);
124 if (!available) {
125 return QueryStatus::kPending;
126 }
127 if (this->disjointSupport()) {
128 GrGLint disjoint = 1;
129 fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint);
130 if (disjoint) {
131 return QueryStatus::kDisjoint;
132 }
133 }
134 return QueryStatus::kAccurate;
135}
136
137std::chrono::nanoseconds GLGpuTimer::getTimeElapsed(sk_gpu_test::PlatformTimerQuery platformTimer) {
138 SkASSERT(this->checkQueryStatus(platformTimer) >= QueryStatus::kDisjoint);
139 const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
140 GrGLuint64 nanoseconds;
141 fGLGetQueryObjectui64v(queryID, GL_QUERY_RESULT, &nanoseconds);
142 return std::chrono::nanoseconds(nanoseconds);
143}
144
145void GLGpuTimer::deleteQuery(sk_gpu_test::PlatformTimerQuery platformTimer) {
146 const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
147 fGLDeleteQueries(1, &queryID);
148}
149
Brian Salomon4dea72a2019-12-18 10:43:10 -0500150static_assert(sizeof(GrGLuint) <= sizeof(sk_gpu_test::PlatformTimerQuery));
csmartdaltonc6618dd2016-10-05 08:42:03 -0700151
csmartdalton421a3c12016-10-04 11:08:45 -0700152} // anonymous namespace
153
154namespace sk_gpu_test {
155
bsalomon18a2f9d2016-05-11 10:09:18 -0700156GLTestContext::GLTestContext() : TestContext() {}
bsalomon@google.com373a6632011-10-19 20:43:20 +0000157
bsalomon273c0f52016-03-31 10:59:06 -0700158GLTestContext::~GLTestContext() {
halcanary96fcdcc2015-08-27 07:41:13 -0700159 SkASSERT(nullptr == fGL.get());
cdaltond416a5b2015-06-23 13:23:44 -0700160}
161
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400162bool GLTestContext::isValid() const {
163#ifdef SK_GL
164 return SkToBool(this->gl());
165#else
166 return fWasInitialized;
167#endif
168}
169
Greg Daniel02497d42020-02-21 15:46:27 -0500170static bool fence_is_supported(const GLTestContext* ctx) {
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400171#ifdef SK_GL
Greg Daniel02497d42020-02-21 15:46:27 -0500172 if (kGL_GrGLStandard == ctx->gl()->fStandard) {
173 if (GrGLGetVersion(ctx->gl()) < GR_GL_VER(3, 2) &&
174 !ctx->gl()->hasExtension("GL_ARB_sync")) {
175 return false;
176 }
177 return true;
178 } else {
179 if (ctx->gl()->hasExtension("GL_APPLE_sync")) {
180 return true;
181 } else if (ctx->gl()->hasExtension("GL_NV_fence")) {
182 return true;
183 } else if (GrGLGetVersion(ctx->gl()) >= GR_GL_VER(3, 0)) {
184 return true;
185 } else {
186 return false;
187 }
188 }
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400189#else
190 return false;
191#endif
Greg Daniel02497d42020-02-21 15:46:27 -0500192}
193
194void GLTestContext::init(sk_sp<const GrGLInterface> gl) {
Brian Salomon3d6801e2017-12-11 10:06:31 -0500195 fGL = std::move(gl);
Greg Daniel02497d42020-02-21 15:46:27 -0500196 fFenceSupport = fence_is_supported(this);
Ben Wagner145dbcd2016-11-03 14:40:50 -0400197 fGpuTimer = GLGpuTimer::MakeIfSupported(this);
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400198#ifndef SK_GL
199 fWasInitialized = true;
200#endif
cdaltond416a5b2015-06-23 13:23:44 -0700201}
202
bsalomon273c0f52016-03-31 10:59:06 -0700203void GLTestContext::teardown() {
halcanary96fcdcc2015-08-27 07:41:13 -0700204 fGL.reset(nullptr);
bsalomon18a2f9d2016-05-11 10:09:18 -0700205 INHERITED::teardown();
bsalomon@google.com373a6632011-10-19 20:43:20 +0000206}
bsalomon944bcf02014-07-29 08:01:52 -0700207
bsalomon273c0f52016-03-31 10:59:06 -0700208void GLTestContext::testAbandon() {
bsalomon18a2f9d2016-05-11 10:09:18 -0700209 INHERITED::testAbandon();
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400210#ifdef SK_GL
bsalomon49f085d2014-09-05 13:34:00 -0700211 if (fGL) {
bsalomon944bcf02014-07-29 08:01:52 -0700212 fGL->abandon();
213 }
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400214#endif
cdaltond416a5b2015-06-23 13:23:44 -0700215}
216
bsalomonc8699322016-05-11 11:55:36 -0700217void GLTestContext::finish() {
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400218#ifdef SK_GL
bsalomonc8699322016-05-11 11:55:36 -0700219 if (fGL) {
220 GR_GL_CALL(fGL.get(), Finish());
221 }
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400222#endif
bsalomonc8699322016-05-11 11:55:36 -0700223}
224
Robert Phillipsf4f80112020-07-13 16:13:31 -0400225sk_sp<GrDirectContext> GLTestContext::makeContext(const GrContextOptions& options) {
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400226#ifdef SK_GL
Robert Phillipsf4f80112020-07-13 16:13:31 -0400227 return GrDirectContext::MakeGL(fGL, options);
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400228#else
229 return nullptr;
230#endif
Greg Daniel02611d92017-07-25 10:05:01 -0400231}
232
bsalomon3724e572016-03-30 18:56:19 -0700233} // namespace sk_gpu_test