File: webgl_sample_query.cpp

package info (click to toggle)
emscripten 3.1.6~dfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 114,112 kB
  • sloc: ansic: 583,052; cpp: 391,943; javascript: 79,361; python: 54,180; sh: 49,997; pascal: 4,658; makefile: 3,426; asm: 2,191; lisp: 1,869; ruby: 488; cs: 142
file content (139 lines) | stat: -rw-r--r-- 3,951 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright 2021 The Emscripten Authors.  All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License.  Both these licenses can be
// found in the LICENSE file.

#include <stdlib.h>
#include <cassert>
#include <cstdio>
#include <emscripten.h>
#include <emscripten/html5.h>

#define GL_GLEXT_PROTOTYPES
#include <GLES3/gl3.h>

int result = 0;
GLuint sampleQuery = 0;

#define GL_CALL( x ) \
    { \
        x; \
        GLenum error = glGetError(); \
        if( error != GL_NO_ERROR ) { \
            printf( "GL ERROR: %d,  %s\n", (int)error, #x ); \
            result = 1; \
        } \
    } \

void getQueryResult()
{
  /* Get the result. It should be nonzero. */
  GLuint any;
  GL_CALL(glGetQueryObjectuiv(sampleQuery, GL_QUERY_RESULT, &any));

  if (!any) return;

  printf("queried any samples passed: %u\n", any);
  emscripten_cancel_main_loop();

  GL_CALL(glDeleteQueries(1, &sampleQuery));

  // result == 0 signals success
  exit(result);
}

GLuint compile_shader(GLenum shaderType, const char *src)
{
  GLuint shader = glCreateShader(shaderType);
  GL_CALL(glShaderSource(shader, 1, &src, NULL));
  GL_CALL(glCompileShader(shader));

  GLint isCompiled = 0;
  GL_CALL(glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled));
  assert(isCompiled);
  return shader;
}

GLuint create_program(GLuint vert, GLuint frag)
{
   GLuint program = glCreateProgram();
   GL_CALL(glAttachShader(program, vert));
   GL_CALL(glAttachShader(program, frag));
   GL_CALL(glBindAttribLocation(program, 0, "position"));
   GL_CALL(glLinkProgram(program));
   return program;
}

int main() {
  EmscriptenWebGLContextAttributes attrs;
  emscripten_webgl_init_context_attributes(&attrs);

  attrs.enableExtensionsByDefault = 1;
  attrs.majorVersion = 2;
  attrs.minorVersion = 0;

  /* Skip WebGL 2 tests if not supported */
  EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context("#canvas", &attrs);
  if (!context) {
    printf("Skipped: WebGL 2 is not supported.\n");
    return 0;
  }
  emscripten_webgl_make_context_current(context);

  /* Generate a query */
  GL_CALL(glGenQueries(2, &sampleQuery));
  assert(sampleQuery);

  /* Begin it */
  GL_CALL(glBeginQuery(GL_ANY_SAMPLES_PASSED, sampleQuery));

  /* Now, `sampleQuery` should be a query */
  bool isQuery = false;
  GL_CALL(isQuery = glIsQuery(sampleQuery));
  assert(isQuery);

  /* Do a draw to actually have something in the queue */
  GLuint vert = compile_shader(GL_VERTEX_SHADER,
    "#version 300 es\n"
    "in vec4 position;\n"
    "void main() {\n"
    "  gl_Position = position;\n"
    "}\n");
  GLuint frag = compile_shader(GL_FRAGMENT_SHADER,
    "#version 300 es\n"
    "precision lowp float;\n"
    "out vec4 color;\n"
    "void main() {\n"
    "  color = vec4(1.0, 0.3, 0.1, 1.0);\n"
    "}\n");
  GLuint program = create_program(vert, frag);
  GL_CALL(glUseProgram(program));
  const float positions[]{
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
  };
  GLuint vertices;
  GL_CALL(glGenBuffers(1, &vertices));
  GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vertices));
  GL_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW));
  GL_CALL(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, 0));
  GL_CALL(glEnableVertexAttribArray(0));
  GL_CALL(glClearColor(0.5f, 0.7f, 0.9f, 1.0f));
  GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
  GL_CALL(glDrawArrays(GL_TRIANGLES, 0, 3));

  /* End the query after the draw */
  GL_CALL(glEndQuery(GL_ANY_SAMPLES_PASSED));

  /* In WebGL, query results are available only in the next event loop
     iteration, so this should return false */
  GLuint isAvailable;
  GL_CALL(glGetQueryObjectuiv(sampleQuery, GL_QUERY_RESULT_AVAILABLE, &isAvailable));
  assert(!isAvailable);

  /* Run the main loop to get the result */
  emscripten_set_main_loop(getQueryResult, 0, 0);

  return 99;
}