1 /*
2 * Copyright © 2020 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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.
22 *
23 * Author:
24 * Eleni Maria Stea <estea@igalia.com>
25 * Juan A. Suarez Romero <jasuarez@igalia.com>
26 */
27
28 #include <piglit-util-gl.h>
29 #include "interop.h"
30 #include "params.h"
31 #include "helpers.h"
32
33 PIGLIT_GL_TEST_CONFIG_BEGIN
34
35 config.supports_gl_compat_version = 30;
36 config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
37 config.khr_no_error_support = PIGLIT_HAS_ERRORS;
38
39 PIGLIT_GL_TEST_CONFIG_END
40
41 static GLenum gl_target = GL_TEXTURE_2D;
42
43 static struct vk_ctx vk_core;
44 static struct vk_image_props vk_img_props;
45 static struct vk_image_obj vk_img_obj;
46 static GLuint gl_mem_obj;
47 static GLuint gl_tex;
48 static GLuint gl_fbo;
49 static GLuint gl_rbo;
50
51 static int gl_prog_flt;
52 static int gl_prog_int;
53 static int gl_prog_uint;
54
55 static const char vs[] =
56 "#version 130\n"
57 "in vec4 piglit_vertex;\n"
58 "in vec2 piglit_texcoord;\n"
59 "out vec2 tex_coords;\n"
60 "void main()\n"
61 "{\n"
62 " gl_Position = piglit_vertex;\n"
63 " tex_coords = piglit_texcoord;\n" "}\n";
64
65 /* we want this shader to work with most color formats
66 * so we subtract the expected and the sampled color
67 * if the colors match, all the components will be 0
68 * and their sum (res.x) will be 0. We pass the negative
69 * of the subtraction result to step that is going to
70 * return 0 or non 0 depending on the result (edge = 0)
71 * and we use mix to select between red if there's no match
72 * and green if there's match for the output color */
73
74 #define MAKE_FS(SAMPLER, VEC4) \
75 "#version 130\n" \
76 "in vec2 tex_coords;\n" \
77 "uniform " #SAMPLER " tex; \n" \
78 "uniform " #VEC4 " expected_color;\n" \
79 "out vec4 color;\n" \
80 "void main() \n" \
81 "{\n" \
82 " " #VEC4 " sampled_color = texture(tex, tex_coords);\n" \
83 " " #VEC4 " res = " #VEC4 " (abs(expected_color - sampled_color));\n" \
84 " res.x += res.y + res.z + res.w;\n" \
85 " color = mix(vec4(1.0, 0.0, 0.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0), step(0, -float(res.x)));\n" \
86 "}\n"
87
88 static const char *fs[] = {
89 MAKE_FS(sampler2D, vec4),
90 MAKE_FS(isampler2D, ivec4),
91 MAKE_FS(usampler2D, uvec4),
92 };
93
94 #undef MAKE_FS
95
96 static float exp_color_flt[4];
97 static int exp_color_int[4];
98 static unsigned int exp_color_uint[4];
99
100 static enum piglit_result
101 run_subtest(int case_num);
102
103 static bool
104 vk_init(void);
105
106 static bool
107 gl_init(void);
108
109 static bool
110 vk_set_image_props(uint32_t w, uint32_t h,
111 uint32_t depth,
112 uint32_t num_samples,
113 uint32_t num_levels, VkFormat format,
114 VkImageTiling tiling, VkImageUsageFlagBits usage);
115
116 static bool
117 gl_draw_texture(enum fragment_type fs_type, uint32_t w, uint32_t h);
118
119 static void
120 gl_cleanup(void);
121
122 static void
123 cleanup(void);
124
125 void
piglit_init(int argc,char ** argv)126 piglit_init(int argc, char **argv)
127 {
128 /* From the EXT_external_objects spec:
129 *
130 * "GL_EXT_memory_object requires ARB_texture_storage or a
131 * version of OpenGL or OpenGL ES that incorporates it."
132 */
133 piglit_require_extension("GL_ARB_texture_storage");
134 piglit_require_extension("GL_EXT_memory_object");
135 piglit_require_extension("GL_EXT_memory_object_fd");
136
137 atexit(cleanup);
138
139 if (!vk_init())
140 piglit_report_result(PIGLIT_SKIP);
141
142 if (!gl_init())
143 piglit_report_result(PIGLIT_SKIP);
144 }
145
146 enum piglit_result
piglit_display()147 piglit_display()
148 {
149 enum piglit_result piglit_test_state = PIGLIT_SKIP;
150 enum piglit_result piglit_subtest_state;
151 int c;
152
153 for (c = 0; c < ARRAY_SIZE(vk_gl_format); c++) {
154 piglit_subtest_state = run_subtest(c);
155 piglit_merge_result(&piglit_test_state, piglit_subtest_state);
156 }
157
158 return piglit_test_state;
159 }
160
161 /* static functions */
162
163 static enum piglit_result
run_subtest(int case_num)164 run_subtest(int case_num)
165 {
166 bool result = false;
167 enum piglit_result subtest_result;
168 const float color_prb[] = { 0.0, 1.0, 0.0, 1.0 };
169 GLint loc = -1;
170
171 /* We don't set the usage flags as the purpose of this test is to test different formats
172 * We will check different combinations of usage/tiling mode in another test */
173 if (!vk_set_image_props(piglit_width, piglit_height, d,
174 num_samples, num_levels,
175 vk_gl_format[case_num].vkformat,
176 vk_gl_format[case_num].tiling, 0)) {
177 piglit_report_subtest_result(PIGLIT_SKIP,
178 "%s: Unsupported image format.",
179 vk_gl_format[case_num].name);
180 return PIGLIT_SKIP;
181 }
182
183 if (!vk_create_ext_image(&vk_core, &vk_img_props, &vk_img_obj)) {
184 piglit_report_subtest_result(PIGLIT_FAIL,
185 "%s: Failed to create external Vulkan image.",
186 vk_gl_format[case_num].name);
187 return PIGLIT_FAIL;
188 }
189
190 /* call function that generates a texture in image props */
191 if (!gl_create_mem_obj_from_vk_mem(&vk_core, &vk_img_obj.mobj,
192 &gl_mem_obj)) {
193 piglit_report_subtest_result(PIGLIT_FAIL,
194 "%s: Failed to create GL memory object from Vulkan memory.",
195 vk_gl_format[case_num].name);
196 vk_destroy_ext_image(&vk_core, &vk_img_obj);
197 return PIGLIT_FAIL;
198 }
199
200 if (!gl_gen_tex_from_mem_obj(&vk_img_props, vk_gl_format[case_num].glformat,
201 gl_mem_obj, 0,
202 &gl_tex)) {
203 piglit_report_subtest_result(PIGLIT_FAIL,
204 "%s: Failed to create texture from GL memory object.",
205 vk_gl_format[case_num].name);
206 vk_destroy_ext_image(&vk_core, &vk_img_obj);
207 gl_cleanup();
208 return PIGLIT_FAIL;
209 }
210
211 if (!gl_draw_texture(vk_gl_format[case_num].fs_type, vk_img_props.w, vk_img_props.h)) {
212 piglit_report_subtest_result(PIGLIT_FAIL,
213 "%s: Failed to initialize OpenGL FBO/RBO",
214 vk_gl_format[case_num].name);
215 vk_destroy_ext_image(&vk_core, &vk_img_obj);
216 gl_cleanup();
217 return PIGLIT_FAIL;
218 }
219
220 switch(vk_gl_format[case_num].fs_type) {
221 case INT_FS:
222 {
223 glUseProgram(gl_prog_int);
224
225 if ((loc = glGetUniformLocation(gl_prog_int, "expected_color")) == -1) {
226 fprintf(stderr, "Failed to get int expected color location.\n");
227 vk_destroy_ext_image(&vk_core, &vk_img_obj);
228 return PIGLIT_FAIL;
229 }
230
231 exp_color_int[0] = pow(2, vk_gl_format[case_num].rbits) / 2 - 1;
232 exp_color_int[1] = pow(2, vk_gl_format[case_num].gbits) / 2 - 1;
233 exp_color_int[2] = 0;
234 exp_color_int[3] = pow(2, vk_gl_format[case_num].abits) / 2 - 1;
235
236 glUniform4iv(loc, 1, exp_color_int);
237 } break;
238 case UINT_FS:
239 {
240 glUseProgram(gl_prog_uint);
241
242 if ((loc = glGetUniformLocation(gl_prog_uint, "expected_color")) == -1) {
243 fprintf(stderr, "Failed to get uint expected color location.\n");
244 vk_destroy_ext_image(&vk_core, &vk_img_obj);
245 return PIGLIT_FAIL;
246 }
247
248 exp_color_uint[0] = pow(2, vk_gl_format[case_num].rbits) - 1;
249 exp_color_uint[1] = pow(2, vk_gl_format[case_num].gbits) - 1;
250 exp_color_uint[2] = 0;
251 exp_color_uint[3] = pow(2, vk_gl_format[case_num].abits) - 1;
252
253 glUniform4uiv(loc, 1, exp_color_uint);
254 } break;
255 case FLOAT_FS:
256 {
257 glUseProgram(gl_prog_flt);
258
259 if ((loc = glGetUniformLocation(gl_prog_flt, "expected_color")) == -1) {
260 fprintf(stderr, "Failed to get float expected color location.\n");
261 vk_destroy_ext_image(&vk_core, &vk_img_obj);
262 return PIGLIT_FAIL;
263 }
264
265 exp_color_flt[0] = 1.0;
266 exp_color_flt[1] = 1.0;
267 exp_color_flt[2] = 0.0;
268 exp_color_flt[3] = 1.0;
269
270 glUniform4fv(loc, 1, exp_color_flt);
271 } break;
272 default:
273 fprintf(stderr, "Invalid format. Shouldn't reach.\n");
274 vk_destroy_ext_image(&vk_core, &vk_img_obj);
275 gl_cleanup();
276 return PIGLIT_FAIL;
277 };
278
279
280 glClear(GL_COLOR_BUFFER_BIT);
281 glBindTexture(gl_target, gl_tex);
282
283 piglit_draw_rect_tex(-1, -1,
284 2.0 * vk_img_props.w / piglit_width,
285 2.0 * vk_img_props.h / piglit_height,
286 0, 0, 1, 1);
287
288 result = piglit_probe_pixel_rgba((float)piglit_width / 2.0,
289 (float)piglit_height / 2.0,
290 color_prb);
291
292 subtest_result = result ? PIGLIT_PASS : PIGLIT_FAIL;
293
294 piglit_report_subtest_result(subtest_result, "%s", vk_gl_format[case_num].name);
295
296 piglit_present_results();
297
298 vk_destroy_ext_image(&vk_core, &vk_img_obj);
299 gl_cleanup();
300
301 return subtest_result;
302 }
303
304 static bool
vk_init(void)305 vk_init(void)
306 {
307 if (!vk_init_ctx(&vk_core)) {
308 fprintf(stderr, "Failed to initialize Vulkan\n");
309 return false;
310 }
311
312 if (!vk_check_gl_compatibility(&vk_core)) {
313 fprintf(stderr, "Mismatch in driver/device UUID\n");
314 return false;
315 }
316
317 return true;
318 }
319
320 static bool
vk_set_image_props(uint32_t w,uint32_t h,uint32_t d,uint32_t num_samples,uint32_t num_levels,VkFormat format,VkImageTiling tiling,VkImageUsageFlagBits usage)321 vk_set_image_props(uint32_t w, uint32_t h, uint32_t d,
322 uint32_t num_samples, uint32_t num_levels,
323 VkFormat format, VkImageTiling tiling,
324 VkImageUsageFlagBits usage)
325 {
326 VkImageLayout in_layout = VK_IMAGE_LAYOUT_UNDEFINED;
327 VkImageLayout end_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
328 uint32_t num_layers = 1;
329
330 return vk_fill_ext_image_props(&vk_core, w, h, d,
331 num_samples, num_levels,
332 num_layers,
333 format, tiling, usage,
334 in_layout, end_layout,
335 &vk_img_props);
336 }
337
338 static bool
gl_draw_texture(enum fragment_type fs_type,uint32_t w,uint32_t h)339 gl_draw_texture(enum fragment_type fs_type, uint32_t w, uint32_t h)
340 {
341 glBindTexture(gl_target, gl_tex);
342
343 glBindFramebuffer(GL_FRAMEBUFFER, gl_fbo);
344 glBindRenderbuffer(GL_RENDERBUFFER, gl_rbo);
345
346 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
347 w, h);
348 glBindRenderbuffer(GL_RENDERBUFFER, 0);
349 glFramebufferRenderbuffer(GL_FRAMEBUFFER,
350 GL_DEPTH_STENCIL_ATTACHMENT,
351 GL_RENDERBUFFER, gl_rbo);
352
353 glFramebufferTexture2D(GL_FRAMEBUFFER,
354 GL_COLOR_ATTACHMENT0,
355 gl_target, gl_tex, 0);
356
357 if (!check_bound_fbo_status())
358 return false;
359
360 glClearColor(1.0, 1.0, 0.0, 1.0);
361 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
362 glEnable(GL_DEPTH_TEST);
363
364 glBindFramebuffer(GL_FRAMEBUFFER, 0);
365
366 glDisable(GL_DEPTH_TEST);
367 glClearColor(0.0, 0.0, 1.0, 1.0);
368 glClear(GL_COLOR_BUFFER_BIT);
369
370 return glGetError() == GL_NO_ERROR;
371 }
372
373 static void
gl_cleanup(void)374 gl_cleanup(void)
375 {
376 glBindTexture(gl_get_target(&vk_img_props), 0);
377 glBindFramebuffer(GL_FRAMEBUFFER, 0);
378 glUseProgram(0);
379
380 glDeleteTextures(1, &gl_tex);
381 glDeleteMemoryObjectsEXT(1, &gl_mem_obj);
382 }
383
384 static void
cleanup(void)385 cleanup(void)
386 {
387 vk_cleanup_ctx(&vk_core);
388 gl_cleanup();
389
390 glDeleteRenderbuffers(1, &gl_rbo);
391 glDeleteFramebuffers(1, &gl_fbo);
392
393 glDeleteProgram(gl_prog_flt);
394 glDeleteProgram(gl_prog_int);
395 glDeleteProgram(gl_prog_uint);
396 }
397
398 static bool
gl_init(void)399 gl_init(void)
400 {
401 gl_prog_flt = piglit_build_simple_program(vs, fs[0]);
402 gl_prog_int = piglit_build_simple_program(vs, fs[1]);
403 gl_prog_uint = piglit_build_simple_program(vs, fs[2]);
404
405 glGenFramebuffers(1, &gl_fbo);
406 glGenRenderbuffers(1, &gl_rbo);
407
408 glUseProgram(0);
409
410 return glGetError() == GL_NO_ERROR;
411 }
412