2 * Copyright (c) 2015 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
26 * Test rendering with SSBOs. We draw four squares with different positions,
27 * sizes, rotations and colors where those parameters come from SSBOs.
29 * Based on GL_ARB_uniform_buffer_object's rendering.c
32 #include "piglit-util-gl.h"
34 PIGLIT_GL_TEST_CONFIG_BEGIN
36 config
.supports_gl_compat_version
= 32;
37 config
.supports_gl_core_version
= 32;
38 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
39 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
41 PIGLIT_GL_TEST_CONFIG_END
43 static const char vert_shader_text
[] =
45 "#extension GL_ARB_shader_storage_buffer_object : require\n"
47 "buffer ssbo_pos_size { vec2 pos; float size; };\n"
48 "buffer ssbo_rot {float rotation; };\n"
49 "in vec4 piglit_vertex;\n"
54 " m[0][0] = m[1][1] = cos(rotation); \n"
55 " m[0][1] = sin(rotation); \n"
56 " m[1][0] = -m[0][1]; \n"
57 " gl_Position.xy = m * piglit_vertex.xy * vec2(size) + pos;\n"
58 " gl_Position.zw = vec2(0, 1);\n"
61 static const char vert_shader_no_ssbo_text
[] =
63 "#extension GL_ARB_uniform_buffer_object : require\n"
65 "layout(std140) uniform;\n"
66 "uniform ub_pos_size { vec2 pos; float size; };\n"
67 "uniform ub_rot {float rotation; };\n"
68 "in vec4 piglit_vertex;\n"
73 " m[0][0] = m[1][1] = cos(rotation); \n"
74 " m[0][1] = sin(rotation); \n"
75 " m[1][0] = -m[0][1]; \n"
76 " gl_Position.xy = m * piglit_vertex.xy * vec2(size) + pos;\n"
77 " gl_Position.zw = vec2(0, 1);\n"
80 static const char frag_shader_text
[] =
82 "#extension GL_ARB_shader_storage_buffer_object : require\n"
84 "buffer ssbo_color { vec4 color; float color_scale; };\n"
88 " gl_FragColor = color * color_scale;\n"
94 /* Square positions and sizes */
95 static const float pos_size
[NUM_SQUARES
][3] = {
102 /* Square color and color_scales */
103 static const float color
[NUM_SQUARES
][8] = {
104 { 2.0, 0.0, 0.0, 1.0, 0.50, 0.0, 0.0, 0.0 },
105 { 0.0, 4.0, 0.0, 1.0, 0.25, 0.0, 0.0, 0.0 },
106 { 0.0, 0.0, 5.0, 1.0, 0.20, 0.0, 0.0, 0.0 },
107 { 0.2, 0.2, 0.2, 0.2, 5.00, 0.0, 0.0, 0.0 }
110 /* Square rotations */
111 static const float rotation
[NUM_SQUARES
] = {
119 static GLuint buffers
[NUM_SSBOS
];
120 static GLint alignment
, ubo_alignment
;
121 static bool test_buffer_offset
= false;
122 static bool vertex_ssbo
= false;
127 static const char *names
[NUM_SSBOS
] = {
132 static const char *ubo_names
[NUM_SSBOS
] = {
138 bool vs_ubo
[NUM_SSBOS
] = {true, false, true};
139 static GLubyte zeros
[1000] = {0};
142 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT
, &alignment
);
143 printf("GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT = %d\n", alignment
);
146 glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
, &ubo_alignment
);
147 printf("GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = %d\n", ubo_alignment
);
149 if (test_buffer_offset
) {
150 printf("Testing buffer offset %d\n", alignment
);
153 /* we use alignment as the offset */
157 glGenBuffers(NUM_SSBOS
, buffers
);
159 for (i
= 0; i
< NUM_SSBOS
; i
++) {
162 if (!vertex_ssbo
&& vs_ubo
[i
]) {
163 /* query UBO index */
164 index
= glGetUniformBlockIndex(prog
, ubo_names
[i
]);
167 glGetActiveUniformBlockiv(prog
, index
,
168 GL_UNIFORM_BLOCK_DATA_SIZE
, &size
);
169 printf("UBO %s: index = %d, size = %d\n",
170 ubo_names
[i
], index
, size
);
173 /* XXX for some reason, this test doesn't work at all with
174 * nvidia if we pass NULL instead of zeros here. The UBO data
175 * is set/overwritten in the piglit_display() function so this
176 * really shouldn't matter.
178 glBindBuffer(GL_UNIFORM_BUFFER
, buffers
[i
]);
179 glBufferData(GL_UNIFORM_BUFFER
, size
+ alignment
,
180 zeros
, GL_DYNAMIC_DRAW
);
183 glBindBufferRange(GL_UNIFORM_BUFFER
, i
, buffers
[i
],
184 alignment
, /* offset */
186 glUniformBlockBinding(prog
, index
, i
);
188 /* query SSBO index */
189 index
= glGetProgramResourceIndex(prog
,
190 GL_SHADER_STORAGE_BLOCK
,
193 GLenum prop
= GL_BUFFER_DATA_SIZE
;
194 /* query SSBO size */
195 glGetProgramResourceiv(prog
, GL_SHADER_STORAGE_BLOCK
, index
,
196 1, &prop
, 1, NULL
, &size
);
197 printf("SSBO %s: index = %d, size = %d\n",
198 names
[i
], index
, size
);
201 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, buffers
[i
]);
202 glBufferData(GL_SHADER_STORAGE_BUFFER
, size
+ alignment
,
203 zeros
, GL_DYNAMIC_DRAW
);
206 glBindBufferRange(GL_SHADER_STORAGE_BUFFER
, i
, buffers
[i
],
207 alignment
, /* offset */
209 glShaderStorageBlockBinding(prog
, index
, i
);
212 if (!piglit_check_gl_error(GL_NO_ERROR
))
213 piglit_report_result(PIGLIT_FAIL
);
219 piglit_init(int argc
, char **argv
)
221 int num_vertex_ssbo
= 0;
223 piglit_require_extension("GL_ARB_shader_storage_buffer_object");
224 piglit_require_extension("GL_ARB_program_interface_query");
226 if (argc
> 1 && strcmp(argv
[1], "offset") == 0) {
227 test_buffer_offset
= true;
230 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS
, &num_vertex_ssbo
);
232 if (num_vertex_ssbo
== 0)
235 glViewport(0, 0, piglit_width
, piglit_height
);
237 prog
= piglit_build_simple_program(vertex_ssbo
? vert_shader_text
: vert_shader_no_ssbo_text
, frag_shader_text
);
243 glClearColor(0.2, 0.2, 0.2, 0.2);
248 probe(int x
, int y
, int color_index
)
252 /* mul color by color_scale */
253 expected
[0] = color
[color_index
][0] * color
[color_index
][4];
254 expected
[1] = color
[color_index
][1] * color
[color_index
][4];
255 expected
[2] = color
[color_index
][2] * color
[color_index
][4];
256 expected
[3] = color
[color_index
][3] * color
[color_index
][4];
258 return piglit_probe_pixel_rgba(x
, y
, expected
);
266 int x0
= piglit_width
/ 4;
267 int x1
= piglit_width
* 3 / 4;
268 int y0
= piglit_height
/ 4;
269 int y1
= piglit_height
* 3 / 4;
272 glViewport(0, 0, piglit_width
, piglit_height
);
274 glClear(GL_COLOR_BUFFER_BIT
);
276 for (i
= 0; i
< NUM_SQUARES
; i
++) {
277 /* Load UBO data, at offset=alignment */
279 glBindBuffer(GL_UNIFORM_BUFFER
, buffers
[0]);
280 glBufferSubData(GL_UNIFORM_BUFFER
, alignment
, sizeof(pos_size
[0]),
283 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, buffers
[0]);
284 glBufferSubData(GL_SHADER_STORAGE_BUFFER
, alignment
,
285 sizeof(pos_size
[0]), pos_size
[i
]);
287 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, buffers
[1]);
288 glBufferSubData(GL_SHADER_STORAGE_BUFFER
, alignment
,
289 sizeof(color
[0]), color
[i
]);
291 glBindBuffer(GL_UNIFORM_BUFFER
, buffers
[2]);
292 glBufferSubData(GL_UNIFORM_BUFFER
, alignment
, sizeof(rotation
[0]),
295 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, buffers
[2]);
296 glBufferSubData(GL_SHADER_STORAGE_BUFFER
, alignment
,
297 sizeof(rotation
[0]), &rotation
[i
]);
300 if (!piglit_check_gl_error(GL_NO_ERROR
))
303 piglit_draw_rect(-1, -1, 2, 2);
306 pass
= probe(x0
, y0
, 0) && pass
;
307 pass
= probe(x1
, y0
, 1) && pass
;
308 pass
= probe(x0
, y1
, 2) && pass
;
309 pass
= probe(x1
, y1
, 3) && pass
;
311 piglit_present_results();
313 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;