blob: 9862a29d8cd1cf7511d96479d3c03a91aa02821b [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:
Ben Wagnera3f996c2021-08-05 10:14:23 -040025#ifdef SK_GL
csmartdaltonc6618dd2016-10-05 08:42:03 -070026 GLGpuTimer(bool disjointSupport, const sk_gpu_test::GLTestContext*, const char* ext = "");
csmartdaltonc6618dd2016-10-05 08:42:03 -070027 bool validate() const;
Ben Wagnera3f996c2021-08-05 10:14:23 -040028#endif
csmartdaltonc6618dd2016-10-05 08:42:03 -070029
30 sk_gpu_test::PlatformTimerQuery onQueueTimerStart() const override;
31 void onQueueTimerStop(sk_gpu_test::PlatformTimerQuery) const override;
32
33 static constexpr GrGLenum GL_QUERY_RESULT = 0x8866;
34 static constexpr GrGLenum GL_QUERY_RESULT_AVAILABLE = 0x8867;
35 static constexpr GrGLenum GL_TIME_ELAPSED = 0x88bf;
36 static constexpr GrGLenum GL_GPU_DISJOINT = 0x8fbb;
37
38 typedef void (GR_GL_FUNCTION_TYPE* GLGetIntegervProc) (GrGLenum, GrGLint*);
39 typedef void (GR_GL_FUNCTION_TYPE* GLGenQueriesProc) (GrGLsizei, GrGLuint*);
40 typedef void (GR_GL_FUNCTION_TYPE* GLDeleteQueriesProc) (GrGLsizei, const GrGLuint*);
41 typedef void (GR_GL_FUNCTION_TYPE* GLBeginQueryProc) (GrGLenum, GrGLuint);
42 typedef void (GR_GL_FUNCTION_TYPE* GLEndQueryProc) (GrGLenum);
43 typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectuivProc) (GrGLuint, GrGLenum, GrGLuint*);
44 typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectui64vProc) (GrGLuint, GrGLenum, GrGLuint64*);
45
46 GLGetIntegervProc fGLGetIntegerv;
47 GLGenQueriesProc fGLGenQueries;
48 GLDeleteQueriesProc fGLDeleteQueries;
49 GLBeginQueryProc fGLBeginQuery;
50 GLEndQueryProc fGLEndQuery;
51 GLGetQueryObjectuivProc fGLGetQueryObjectuiv;
52 GLGetQueryObjectui64vProc fGLGetQueryObjectui64v;
53
54
John Stiles7571f9e2020-09-02 22:42:33 -040055 using INHERITED = sk_gpu_test::GpuTimer;
csmartdaltonc6618dd2016-10-05 08:42:03 -070056};
57
Ben Wagner145dbcd2016-11-03 14:40:50 -040058std::unique_ptr<GLGpuTimer> GLGpuTimer::MakeIfSupported(const sk_gpu_test::GLTestContext* ctx) {
Brian Salomonf4ba4ec2020-03-19 15:54:28 -040059#ifdef SK_GL
Ben Wagner145dbcd2016-11-03 14:40:50 -040060 std::unique_ptr<GLGpuTimer> ret;
csmartdaltonc6618dd2016-10-05 08:42:03 -070061 const GrGLInterface* gl = ctx->gl();
62 if (gl->fExtensions.has("GL_EXT_disjoint_timer_query")) {
63 ret.reset(new GLGpuTimer(true, ctx, "EXT"));
64 } else if (kGL_GrGLStandard == gl->fStandard &&
65 (GrGLGetVersion(gl) > GR_GL_VER(3,3) || gl->fExtensions.has("GL_ARB_timer_query"))) {
66 ret.reset(new GLGpuTimer(false, ctx));
67 } else if (gl->fExtensions.has("GL_EXT_timer_query")) {
68 ret.reset(new GLGpuTimer(false, ctx, "EXT"));
69 }
Ben Wagner145dbcd2016-11-03 14:40:50 -040070 if (ret && !ret->validate()) {
71 ret = nullptr;
72 }
73 return ret;
Brian Salomonf4ba4ec2020-03-19 15:54:28 -040074#else
75 return nullptr;
76#endif
csmartdaltonc6618dd2016-10-05 08:42:03 -070077}
78
Ben Wagnera3f996c2021-08-05 10:14:23 -040079#ifdef SK_GL
csmartdaltonc6618dd2016-10-05 08:42:03 -070080GLGpuTimer::GLGpuTimer(bool disjointSupport, const sk_gpu_test::GLTestContext* ctx, const char* ext)
81 : INHERITED(disjointSupport) {
82 ctx->getGLProcAddress(&fGLGetIntegerv, "glGetIntegerv");
83 ctx->getGLProcAddress(&fGLGenQueries, "glGenQueries", ext);
84 ctx->getGLProcAddress(&fGLDeleteQueries, "glDeleteQueries", ext);
85 ctx->getGLProcAddress(&fGLBeginQuery, "glBeginQuery", ext);
86 ctx->getGLProcAddress(&fGLEndQuery, "glEndQuery", ext);
87 ctx->getGLProcAddress(&fGLGetQueryObjectuiv, "glGetQueryObjectuiv", ext);
88 ctx->getGLProcAddress(&fGLGetQueryObjectui64v, "glGetQueryObjectui64v", ext);
89}
90
91bool GLGpuTimer::validate() const {
92 return fGLGetIntegerv && fGLGenQueries && fGLDeleteQueries && fGLBeginQuery && fGLEndQuery &&
93 fGLGetQueryObjectuiv && fGLGetQueryObjectui64v;
94}
Ben Wagnera3f996c2021-08-05 10:14:23 -040095#endif
csmartdaltonc6618dd2016-10-05 08:42:03 -070096
97sk_gpu_test::PlatformTimerQuery GLGpuTimer::onQueueTimerStart() const {
98 GrGLuint queryID;
99 fGLGenQueries(1, &queryID);
100 if (!queryID) {
101 return sk_gpu_test::kInvalidTimerQuery;
102 }
103 if (this->disjointSupport()) {
104 // Clear the disjoint flag.
105 GrGLint disjoint;
106 fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint);
107 }
108 fGLBeginQuery(GL_TIME_ELAPSED, queryID);
109 return static_cast<sk_gpu_test::PlatformTimerQuery>(queryID);
110}
111
112void GLGpuTimer::onQueueTimerStop(sk_gpu_test::PlatformTimerQuery platformTimer) const {
113 if (sk_gpu_test::kInvalidTimerQuery == platformTimer) {
114 return;
115 }
116 fGLEndQuery(GL_TIME_ELAPSED);
117}
118
119sk_gpu_test::GpuTimer::QueryStatus
120GLGpuTimer::checkQueryStatus(sk_gpu_test::PlatformTimerQuery platformTimer) {
121 const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
122 if (!queryID) {
123 return QueryStatus::kInvalid;
124 }
125 GrGLuint available = 0;
126 fGLGetQueryObjectuiv(queryID, GL_QUERY_RESULT_AVAILABLE, &available);
127 if (!available) {
128 return QueryStatus::kPending;
129 }
130 if (this->disjointSupport()) {
131 GrGLint disjoint = 1;
132 fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint);
133 if (disjoint) {
134 return QueryStatus::kDisjoint;
135 }
136 }
137 return QueryStatus::kAccurate;
138}
139
140std::chrono::nanoseconds GLGpuTimer::getTimeElapsed(sk_gpu_test::PlatformTimerQuery platformTimer) {
141 SkASSERT(this->checkQueryStatus(platformTimer) >= QueryStatus::kDisjoint);
142 const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
143 GrGLuint64 nanoseconds;
144 fGLGetQueryObjectui64v(queryID, GL_QUERY_RESULT, &nanoseconds);
145 return std::chrono::nanoseconds(nanoseconds);
146}
147
148void GLGpuTimer::deleteQuery(sk_gpu_test::PlatformTimerQuery platformTimer) {
149 const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
150 fGLDeleteQueries(1, &queryID);
151}
152
Brian Salomon4dea72a2019-12-18 10:43:10 -0500153static_assert(sizeof(GrGLuint) <= sizeof(sk_gpu_test::PlatformTimerQuery));
csmartdaltonc6618dd2016-10-05 08:42:03 -0700154
csmartdalton421a3c12016-10-04 11:08:45 -0700155} // anonymous namespace
156
157namespace sk_gpu_test {
158
bsalomon18a2f9d2016-05-11 10:09:18 -0700159GLTestContext::GLTestContext() : TestContext() {}
bsalomon@google.com373a6632011-10-19 20:43:20 +0000160
bsalomon273c0f52016-03-31 10:59:06 -0700161GLTestContext::~GLTestContext() {
Brian Salomonb2b7f802020-08-26 15:27:03 -0400162 SkASSERT(!fGLInterface);
163 SkASSERT(!fOriginalGLInterface);
cdaltond416a5b2015-06-23 13:23:44 -0700164}
165
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400166bool GLTestContext::isValid() const {
167#ifdef SK_GL
168 return SkToBool(this->gl());
169#else
170 return fWasInitialized;
171#endif
172}
173
Greg Daniel02497d42020-02-21 15:46:27 -0500174static bool fence_is_supported(const GLTestContext* ctx) {
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400175#ifdef SK_GL
Greg Daniel02497d42020-02-21 15:46:27 -0500176 if (kGL_GrGLStandard == ctx->gl()->fStandard) {
177 if (GrGLGetVersion(ctx->gl()) < GR_GL_VER(3, 2) &&
178 !ctx->gl()->hasExtension("GL_ARB_sync")) {
179 return false;
180 }
181 return true;
182 } else {
183 if (ctx->gl()->hasExtension("GL_APPLE_sync")) {
184 return true;
185 } else if (ctx->gl()->hasExtension("GL_NV_fence")) {
186 return true;
187 } else if (GrGLGetVersion(ctx->gl()) >= GR_GL_VER(3, 0)) {
188 return true;
189 } else {
190 return false;
191 }
192 }
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400193#else
194 return false;
195#endif
Greg Daniel02497d42020-02-21 15:46:27 -0500196}
197
198void GLTestContext::init(sk_sp<const GrGLInterface> gl) {
Brian Salomonb2b7f802020-08-26 15:27:03 -0400199 fGLInterface = std::move(gl);
200 fOriginalGLInterface = fGLInterface;
Greg Daniel02497d42020-02-21 15:46:27 -0500201 fFenceSupport = fence_is_supported(this);
Ben Wagner145dbcd2016-11-03 14:40:50 -0400202 fGpuTimer = GLGpuTimer::MakeIfSupported(this);
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400203#ifndef SK_GL
204 fWasInitialized = true;
205#endif
cdaltond416a5b2015-06-23 13:23:44 -0700206}
207
bsalomon273c0f52016-03-31 10:59:06 -0700208void GLTestContext::teardown() {
Brian Salomonb2b7f802020-08-26 15:27:03 -0400209 fGLInterface.reset();
210 fOriginalGLInterface.reset();
bsalomon18a2f9d2016-05-11 10:09:18 -0700211 INHERITED::teardown();
bsalomon@google.com373a6632011-10-19 20:43:20 +0000212}
bsalomon944bcf02014-07-29 08:01:52 -0700213
bsalomon273c0f52016-03-31 10:59:06 -0700214void GLTestContext::testAbandon() {
bsalomon18a2f9d2016-05-11 10:09:18 -0700215 INHERITED::testAbandon();
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400216#ifdef SK_GL
Brian Salomonb2b7f802020-08-26 15:27:03 -0400217 if (fGLInterface) {
218 fGLInterface->abandon();
219 fOriginalGLInterface->abandon();
bsalomon944bcf02014-07-29 08:01:52 -0700220 }
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400221#endif
cdaltond416a5b2015-06-23 13:23:44 -0700222}
223
bsalomonc8699322016-05-11 11:55:36 -0700224void GLTestContext::finish() {
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400225#ifdef SK_GL
Brian Salomonb2b7f802020-08-26 15:27:03 -0400226 if (fGLInterface) {
227 GR_GL_CALL(fGLInterface.get(), Finish());
bsalomonc8699322016-05-11 11:55:36 -0700228 }
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400229#endif
bsalomonc8699322016-05-11 11:55:36 -0700230}
231
Brian Salomonb2b7f802020-08-26 15:27:03 -0400232void GLTestContext::overrideVersion(const char* version, const char* shadingLanguageVersion) {
233#ifdef SK_GL
234 // GrGLFunction has both a limited capture size and doesn't call a destructor when it is
235 // initialized with a lambda. So here we're trusting fOriginalGLInterface will be kept alive.
236 auto getString = [wrapped = &fOriginalGLInterface->fFunctions.fGetString,
237 version,
238 shadingLanguageVersion](GrGLenum name) {
239 if (name == GR_GL_VERSION) {
240 return reinterpret_cast<const GrGLubyte*>(version);
241 } else if (name == GR_GL_SHADING_LANGUAGE_VERSION) {
242 return reinterpret_cast<const GrGLubyte*>(shadingLanguageVersion);
243 }
244 return (*wrapped)(name);
245 };
246 auto newInterface = sk_make_sp<GrGLInterface>(*fOriginalGLInterface);
247 newInterface->fFunctions.fGetString = getString;
248 fGLInterface = std::move(newInterface);
249#endif
250};
251
Robert Phillipsf4f80112020-07-13 16:13:31 -0400252sk_sp<GrDirectContext> GLTestContext::makeContext(const GrContextOptions& options) {
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400253#ifdef SK_GL
Brian Salomonb2b7f802020-08-26 15:27:03 -0400254 return GrDirectContext::MakeGL(fGLInterface, options);
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400255#else
256 return nullptr;
257#endif
Greg Daniel02611d92017-07-25 10:05:01 -0400258}
259
bsalomon3724e572016-03-30 18:56:19 -0700260} // namespace sk_gpu_test