blob: 9291f86a8837f05287493cd3928a51d4417b9da9 [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() {
Brian Salomonb2b7f802020-08-26 15:27:03 -0400159 SkASSERT(!fGLInterface);
160 SkASSERT(!fOriginalGLInterface);
cdaltond416a5b2015-06-23 13:23:44 -0700161}
162
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400163bool GLTestContext::isValid() const {
164#ifdef SK_GL
165 return SkToBool(this->gl());
166#else
167 return fWasInitialized;
168#endif
169}
170
Greg Daniel02497d42020-02-21 15:46:27 -0500171static bool fence_is_supported(const GLTestContext* ctx) {
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400172#ifdef SK_GL
Greg Daniel02497d42020-02-21 15:46:27 -0500173 if (kGL_GrGLStandard == ctx->gl()->fStandard) {
174 if (GrGLGetVersion(ctx->gl()) < GR_GL_VER(3, 2) &&
175 !ctx->gl()->hasExtension("GL_ARB_sync")) {
176 return false;
177 }
178 return true;
179 } else {
180 if (ctx->gl()->hasExtension("GL_APPLE_sync")) {
181 return true;
182 } else if (ctx->gl()->hasExtension("GL_NV_fence")) {
183 return true;
184 } else if (GrGLGetVersion(ctx->gl()) >= GR_GL_VER(3, 0)) {
185 return true;
186 } else {
187 return false;
188 }
189 }
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400190#else
191 return false;
192#endif
Greg Daniel02497d42020-02-21 15:46:27 -0500193}
194
195void GLTestContext::init(sk_sp<const GrGLInterface> gl) {
Brian Salomonb2b7f802020-08-26 15:27:03 -0400196 fGLInterface = std::move(gl);
197 fOriginalGLInterface = fGLInterface;
Greg Daniel02497d42020-02-21 15:46:27 -0500198 fFenceSupport = fence_is_supported(this);
Ben Wagner145dbcd2016-11-03 14:40:50 -0400199 fGpuTimer = GLGpuTimer::MakeIfSupported(this);
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400200#ifndef SK_GL
201 fWasInitialized = true;
202#endif
cdaltond416a5b2015-06-23 13:23:44 -0700203}
204
bsalomon273c0f52016-03-31 10:59:06 -0700205void GLTestContext::teardown() {
Brian Salomonb2b7f802020-08-26 15:27:03 -0400206 fGLInterface.reset();
207 fOriginalGLInterface.reset();
bsalomon18a2f9d2016-05-11 10:09:18 -0700208 INHERITED::teardown();
bsalomon@google.com373a6632011-10-19 20:43:20 +0000209}
bsalomon944bcf02014-07-29 08:01:52 -0700210
bsalomon273c0f52016-03-31 10:59:06 -0700211void GLTestContext::testAbandon() {
bsalomon18a2f9d2016-05-11 10:09:18 -0700212 INHERITED::testAbandon();
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400213#ifdef SK_GL
Brian Salomonb2b7f802020-08-26 15:27:03 -0400214 if (fGLInterface) {
215 fGLInterface->abandon();
216 fOriginalGLInterface->abandon();
bsalomon944bcf02014-07-29 08:01:52 -0700217 }
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400218#endif
cdaltond416a5b2015-06-23 13:23:44 -0700219}
220
bsalomonc8699322016-05-11 11:55:36 -0700221void GLTestContext::finish() {
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400222#ifdef SK_GL
Brian Salomonb2b7f802020-08-26 15:27:03 -0400223 if (fGLInterface) {
224 GR_GL_CALL(fGLInterface.get(), Finish());
bsalomonc8699322016-05-11 11:55:36 -0700225 }
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400226#endif
bsalomonc8699322016-05-11 11:55:36 -0700227}
228
Brian Salomonb2b7f802020-08-26 15:27:03 -0400229void GLTestContext::overrideVersion(const char* version, const char* shadingLanguageVersion) {
230#ifdef SK_GL
231 // GrGLFunction has both a limited capture size and doesn't call a destructor when it is
232 // initialized with a lambda. So here we're trusting fOriginalGLInterface will be kept alive.
233 auto getString = [wrapped = &fOriginalGLInterface->fFunctions.fGetString,
234 version,
235 shadingLanguageVersion](GrGLenum name) {
236 if (name == GR_GL_VERSION) {
237 return reinterpret_cast<const GrGLubyte*>(version);
238 } else if (name == GR_GL_SHADING_LANGUAGE_VERSION) {
239 return reinterpret_cast<const GrGLubyte*>(shadingLanguageVersion);
240 }
241 return (*wrapped)(name);
242 };
243 auto newInterface = sk_make_sp<GrGLInterface>(*fOriginalGLInterface);
244 newInterface->fFunctions.fGetString = getString;
245 fGLInterface = std::move(newInterface);
246#endif
247};
248
Robert Phillipsf4f80112020-07-13 16:13:31 -0400249sk_sp<GrDirectContext> GLTestContext::makeContext(const GrContextOptions& options) {
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400250#ifdef SK_GL
Brian Salomonb2b7f802020-08-26 15:27:03 -0400251 return GrDirectContext::MakeGL(fGLInterface, options);
Brian Salomonf4ba4ec2020-03-19 15:54:28 -0400252#else
253 return nullptr;
254#endif
Greg Daniel02611d92017-07-25 10:05:01 -0400255}
256
bsalomon3724e572016-03-30 18:56:19 -0700257} // namespace sk_gpu_test