blob: 9126799f93d97e965f91cb24d90f591d0bd5bef6 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/gpu/GrContext.h"
11#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) {
58 std::unique_ptr<GLGpuTimer> ret;
csmartdaltonc6618dd2016-10-05 08:42:03 -070059 const GrGLInterface* gl = ctx->gl();
60 if (gl->fExtensions.has("GL_EXT_disjoint_timer_query")) {
61 ret.reset(new GLGpuTimer(true, ctx, "EXT"));
62 } else if (kGL_GrGLStandard == gl->fStandard &&
63 (GrGLGetVersion(gl) > GR_GL_VER(3,3) || gl->fExtensions.has("GL_ARB_timer_query"))) {
64 ret.reset(new GLGpuTimer(false, ctx));
65 } else if (gl->fExtensions.has("GL_EXT_timer_query")) {
66 ret.reset(new GLGpuTimer(false, ctx, "EXT"));
67 }
Ben Wagner145dbcd2016-11-03 14:40:50 -040068 if (ret && !ret->validate()) {
69 ret = nullptr;
70 }
71 return ret;
csmartdaltonc6618dd2016-10-05 08:42:03 -070072}
73
74GLGpuTimer::GLGpuTimer(bool disjointSupport, const sk_gpu_test::GLTestContext* ctx, const char* ext)
75 : INHERITED(disjointSupport) {
76 ctx->getGLProcAddress(&fGLGetIntegerv, "glGetIntegerv");
77 ctx->getGLProcAddress(&fGLGenQueries, "glGenQueries", ext);
78 ctx->getGLProcAddress(&fGLDeleteQueries, "glDeleteQueries", ext);
79 ctx->getGLProcAddress(&fGLBeginQuery, "glBeginQuery", ext);
80 ctx->getGLProcAddress(&fGLEndQuery, "glEndQuery", ext);
81 ctx->getGLProcAddress(&fGLGetQueryObjectuiv, "glGetQueryObjectuiv", ext);
82 ctx->getGLProcAddress(&fGLGetQueryObjectui64v, "glGetQueryObjectui64v", ext);
83}
84
85bool GLGpuTimer::validate() const {
86 return fGLGetIntegerv && fGLGenQueries && fGLDeleteQueries && fGLBeginQuery && fGLEndQuery &&
87 fGLGetQueryObjectuiv && fGLGetQueryObjectui64v;
88}
89
90sk_gpu_test::PlatformTimerQuery GLGpuTimer::onQueueTimerStart() const {
91 GrGLuint queryID;
92 fGLGenQueries(1, &queryID);
93 if (!queryID) {
94 return sk_gpu_test::kInvalidTimerQuery;
95 }
96 if (this->disjointSupport()) {
97 // Clear the disjoint flag.
98 GrGLint disjoint;
99 fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint);
100 }
101 fGLBeginQuery(GL_TIME_ELAPSED, queryID);
102 return static_cast<sk_gpu_test::PlatformTimerQuery>(queryID);
103}
104
105void GLGpuTimer::onQueueTimerStop(sk_gpu_test::PlatformTimerQuery platformTimer) const {
106 if (sk_gpu_test::kInvalidTimerQuery == platformTimer) {
107 return;
108 }
109 fGLEndQuery(GL_TIME_ELAPSED);
110}
111
112sk_gpu_test::GpuTimer::QueryStatus
113GLGpuTimer::checkQueryStatus(sk_gpu_test::PlatformTimerQuery platformTimer) {
114 const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
115 if (!queryID) {
116 return QueryStatus::kInvalid;
117 }
118 GrGLuint available = 0;
119 fGLGetQueryObjectuiv(queryID, GL_QUERY_RESULT_AVAILABLE, &available);
120 if (!available) {
121 return QueryStatus::kPending;
122 }
123 if (this->disjointSupport()) {
124 GrGLint disjoint = 1;
125 fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint);
126 if (disjoint) {
127 return QueryStatus::kDisjoint;
128 }
129 }
130 return QueryStatus::kAccurate;
131}
132
133std::chrono::nanoseconds GLGpuTimer::getTimeElapsed(sk_gpu_test::PlatformTimerQuery platformTimer) {
134 SkASSERT(this->checkQueryStatus(platformTimer) >= QueryStatus::kDisjoint);
135 const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
136 GrGLuint64 nanoseconds;
137 fGLGetQueryObjectui64v(queryID, GL_QUERY_RESULT, &nanoseconds);
138 return std::chrono::nanoseconds(nanoseconds);
139}
140
141void GLGpuTimer::deleteQuery(sk_gpu_test::PlatformTimerQuery platformTimer) {
142 const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
143 fGLDeleteQueries(1, &queryID);
144}
145
Brian Salomon4dea72a2019-12-18 10:43:10 -0500146static_assert(sizeof(GrGLuint) <= sizeof(sk_gpu_test::PlatformTimerQuery));
csmartdaltonc6618dd2016-10-05 08:42:03 -0700147
csmartdalton421a3c12016-10-04 11:08:45 -0700148} // anonymous namespace
149
150namespace sk_gpu_test {
151
bsalomon18a2f9d2016-05-11 10:09:18 -0700152GLTestContext::GLTestContext() : TestContext() {}
bsalomon@google.com373a6632011-10-19 20:43:20 +0000153
bsalomon273c0f52016-03-31 10:59:06 -0700154GLTestContext::~GLTestContext() {
halcanary96fcdcc2015-08-27 07:41:13 -0700155 SkASSERT(nullptr == fGL.get());
cdaltond416a5b2015-06-23 13:23:44 -0700156}
157
Greg Daniel02497d42020-02-21 15:46:27 -0500158static bool fence_is_supported(const GLTestContext* ctx) {
159 if (kGL_GrGLStandard == ctx->gl()->fStandard) {
160 if (GrGLGetVersion(ctx->gl()) < GR_GL_VER(3, 2) &&
161 !ctx->gl()->hasExtension("GL_ARB_sync")) {
162 return false;
163 }
164 return true;
165 } else {
166 if (ctx->gl()->hasExtension("GL_APPLE_sync")) {
167 return true;
168 } else if (ctx->gl()->hasExtension("GL_NV_fence")) {
169 return true;
170 } else if (GrGLGetVersion(ctx->gl()) >= GR_GL_VER(3, 0)) {
171 return true;
172 } else {
173 return false;
174 }
175 }
176}
177
178void GLTestContext::init(sk_sp<const GrGLInterface> gl) {
Brian Salomon3d6801e2017-12-11 10:06:31 -0500179 fGL = std::move(gl);
Greg Daniel02497d42020-02-21 15:46:27 -0500180 fFenceSupport = fence_is_supported(this);
Ben Wagner145dbcd2016-11-03 14:40:50 -0400181 fGpuTimer = GLGpuTimer::MakeIfSupported(this);
cdaltond416a5b2015-06-23 13:23:44 -0700182}
183
bsalomon273c0f52016-03-31 10:59:06 -0700184void GLTestContext::teardown() {
halcanary96fcdcc2015-08-27 07:41:13 -0700185 fGL.reset(nullptr);
bsalomon18a2f9d2016-05-11 10:09:18 -0700186 INHERITED::teardown();
bsalomon@google.com373a6632011-10-19 20:43:20 +0000187}
bsalomon944bcf02014-07-29 08:01:52 -0700188
bsalomon273c0f52016-03-31 10:59:06 -0700189void GLTestContext::testAbandon() {
bsalomon18a2f9d2016-05-11 10:09:18 -0700190 INHERITED::testAbandon();
bsalomon49f085d2014-09-05 13:34:00 -0700191 if (fGL) {
bsalomon944bcf02014-07-29 08:01:52 -0700192 fGL->abandon();
193 }
cdaltond416a5b2015-06-23 13:23:44 -0700194}
195
bsalomonc8699322016-05-11 11:55:36 -0700196void GLTestContext::finish() {
197 if (fGL) {
198 GR_GL_CALL(fGL.get(), Finish());
199 }
200}
201
Brian Salomon1f05d452019-02-08 12:33:08 -0500202GrGLuint GLTestContext::createTextureRectangle(int width, int height, GrGLenum internalFormat,
203 GrGLenum externalFormat, GrGLenum externalType,
204 GrGLvoid* data) {
Weiliang Chen1e04b362018-07-12 17:13:35 -0400205 // Should match GrGLCaps check for fRectangleTextureSupport.
206 if (kGL_GrGLStandard != fGL->fStandard ||
207 (GrGLGetVersion(fGL.get()) < GR_GL_VER(3, 1) &&
208 !fGL->fExtensions.has("GL_ARB_texture_rectangle") &&
209 !fGL->fExtensions.has("GL_ANGLE_texture_rectangle"))) {
bsalomone5286e02016-01-14 09:24:09 -0800210 return 0;
211 }
bsalomone179a912016-01-20 06:18:10 -0800212
Hal Canary1b612a82016-11-03 16:26:13 -0400213 if (GrGLGetGLSLVersion(fGL.get()) < GR_GLSL_VER(1, 40)) {
bsalomone179a912016-01-20 06:18:10 -0800214 return 0;
215 }
216
bsalomone5286e02016-01-14 09:24:09 -0800217 GrGLuint id;
Hal Canary1b612a82016-11-03 16:26:13 -0400218 GR_GL_CALL(fGL.get(), GenTextures(1, &id));
219 GR_GL_CALL(fGL.get(), BindTexture(GR_GL_TEXTURE_RECTANGLE, id));
220 GR_GL_CALL(fGL.get(), TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_MAG_FILTER,
221 GR_GL_NEAREST));
222 GR_GL_CALL(fGL.get(), TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_MIN_FILTER,
223 GR_GL_NEAREST));
224 GR_GL_CALL(fGL.get(), TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_WRAP_S,
225 GR_GL_CLAMP_TO_EDGE));
226 GR_GL_CALL(fGL.get(), TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_WRAP_T,
227 GR_GL_CLAMP_TO_EDGE));
228 GR_GL_CALL(fGL.get(), TexImage2D(GR_GL_TEXTURE_RECTANGLE, 0, internalFormat, width, height, 0,
229 externalFormat, externalType, data));
bsalomone5286e02016-01-14 09:24:09 -0800230 return id;
231}
Greg Daniel02611d92017-07-25 10:05:01 -0400232
233sk_sp<GrContext> GLTestContext::makeGrContext(const GrContextOptions& options) {
Brian Salomon384fab42017-12-07 12:33:05 -0500234 return GrContext::MakeGL(fGL, options);
Greg Daniel02611d92017-07-25 10:05:01 -0400235}
236
bsalomon3724e572016-03-30 18:56:19 -0700237} // namespace sk_gpu_test