[04/15] adj-prims: beef up the test to tease out what nvidia hardware does

Submitted by Marek Olšák on March 26, 2018, 11:32 p.m.

Details

Message ID 20180326233255.18529-4-maraeo@gmail.com
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Piglit

Not browsing as part of any series.

Commit Message

Marek Olšák March 26, 2018, 11:32 p.m.
From: Nicolai Hähnle <nicolai.haehnle@amd.com>

---
 tests/spec/gl-3.2/adj-prims.c | 144 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 128 insertions(+), 16 deletions(-)

Patch hide | download patch | download mbox

diff --git a/tests/spec/gl-3.2/adj-prims.c b/tests/spec/gl-3.2/adj-prims.c
index f4479c708..6faff74d2 100644
--- a/tests/spec/gl-3.2/adj-prims.c
+++ b/tests/spec/gl-3.2/adj-prims.c
@@ -135,25 +135,28 @@  static GLuint triangles_adj_vao;
 static GLuint triangle_strip_adj_vao;
 
 static GLenum polygon_mode = GL_FILL;
 static GLenum cull_mode = GL_NONE;
 static GLenum provoking_vertex = GL_LAST_VERTEX_CONVENTION;
 
 static GLuint gs_lines_program;
 static GLuint gs_line_strip_program;
 static GLuint gs_triangles_program;
 static GLuint gs_triangle_strip_program;
+static GLuint xfb_buf;
+static GLuint element_buf;
 static GLuint ref_program;
 static GLint colorUniform, modelViewProjUniform;
 
 // if false, draw without GS, also draw the 'extra' lines/tris.  For debugging.
 static bool draw_with_gs = true;
+static bool draw_elements = false;
 
 
 /**
  * Given a primitive type (adjacency type only), and the first/last provoking
  * vertex mode, and a primitive (line, triangle) index, return the index of
  * the vertex which will specify the primitive's flat-shaded color.
  */
 static unsigned
 provoking_vertex_index(GLenum prim_mode, GLenum pv_mode, unsigned prim_index)
 {
@@ -304,42 +307,47 @@  num_gs_prims(GLenum prim_mode, unsigned num_verts)
 static bool
 probe_prims(GLenum prim_mode, const float verts[][2], unsigned num_verts,
 	    unsigned vp_pos)
 {
 	const int vp_w = piglit_width / 4;
 	const unsigned num_prims = num_gs_prims(prim_mode, num_verts);
 	unsigned prim;
 
 	for (prim = 0; prim < num_prims; prim++) {
 		bool pass = false;
-		const float *expected_color = NULL;
-		float bad_color[4];
+		float expected_color[4];
+		float bad_color[4] = { -1 };
 		bool bad_color_found = false;
 		int x, y, i;
 
 		compute_probe_location(prim_mode, prim, verts,
 				       vp_pos * vp_w, 0, &x, &y);
 
 		if (cull_mode == GL_FRONT &&
 		    (prim_mode == GL_TRIANGLES_ADJACENCY ||
 		     prim_mode == GL_TRIANGLE_STRIP_ADJACENCY)) {
 			// All triangles should be front facing.
 			// With front culling, all should be discarded.
 			// Region should be black.
 			if (piglit_probe_rect_rgba(x-1, y-1, 3, 3, black)) {
 				pass = true;
 			}
 		} else {
 			GLfloat buf[9][4];
 			unsigned pvi = provoking_vertex_index(prim_mode,
 						     provoking_vertex, prim);
-			expected_color = colors[pvi];
+			memcpy(&expected_color, colors[pvi], sizeof(expected_color));
+			if (prim_mode == GL_TRIANGLES_ADJACENCY ||
+			    prim_mode == GL_TRIANGLE_STRIP_ADJACENCY) {
+				expected_color[2] = pvi * (1.0 / 255);
+				expected_color[3] = provoking_vertex == GL_FIRST_VERTEX_CONVENTION ? 0.0 : 1.0;
+			}
 
 			// Read a 3x3 region for line probing
 			glReadPixels(x-1, y-1, 3, 3, GL_RGBA, GL_FLOAT, buf);
 
 			// look for non-black pixel
 			for (i = 0; i < 9; i++) {
 				if (buf[i][0] != 0 || buf[i][1] != 0 ||
 				    buf[i][2] != 0 || buf[i][3] != 0) {
 					// check for expected color
 					if (colors_match(expected_color, buf[i]))
@@ -352,57 +360,100 @@  probe_prims(GLenum prim_mode, const float verts[][2], unsigned num_verts,
 						bad_color[3] = buf[i][3];
 					}
 				}
 			}
 		}
 
 		if (!pass) {
 			printf("Failure for %s, "
 			       "prim %u wrong color at (%d,%d)\n",
 			       piglit_get_prim_name(prim_mode), prim, x, y);
-			if (expected_color && bad_color_found) {
-				printf("Expected %.1g, %.1g, %.1g, %.1g\n",
+			if (bad_color_found) {
+				printf("Expected %g, %g, %g, %g\n",
 				       expected_color[0],
 				       expected_color[1],
 				       expected_color[2],
 				       expected_color[3]);
-				printf("Found %.1g, %.1g, %.1g, %.1g\n",
+				printf("Found %g, %g, %g, %g\n",
 				       bad_color[0],
 				       bad_color[1],
 				       bad_color[2],
 				       bad_color[3]);
 			}
 
 			return false;
 		}
 	}
 
 	return true;
 }
 
+static bool
+probe_xfb(GLenum prim_mode, unsigned num_verts)
+{
+	bool pass = true;
+	const unsigned num_prims = num_gs_prims(prim_mode, num_verts);
+	const float *xfb_data = glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
+
+	for (unsigned prim = 0; prim < num_prims; prim++) {
+		const float *found_color;
+		float expected_color[4];
+		unsigned pvi = provoking_vertex_index(prim_mode,
+						provoking_vertex, prim);
+
+		memcpy(&expected_color, colors[pvi], sizeof(expected_color));
+		expected_color[2] = pvi * (1.0 / 255);
+		expected_color[3] = provoking_vertex == GL_FIRST_VERTEX_CONVENTION ? 0.0 : 1.0;
+
+		found_color = xfb_data + 4 * (3 * prim + (provoking_vertex == GL_FIRST_VERTEX_CONVENTION ? 0 : 2));
+
+		if (!colors_match(expected_color, found_color)) {
+			printf("Transform Feedback Failure for %s, prim %u wrong color\n",
+			       piglit_get_prim_name(prim_mode), prim);
+			printf("Expected %g, %g, %g, %g\n",
+			       expected_color[0],
+			       expected_color[1],
+			       expected_color[2],
+			       expected_color[3]);
+			printf("Found %g, %g, %g, %g\n",
+			       found_color[0],
+			       found_color[1],
+			       found_color[2],
+			       found_color[3]);
+
+			pass = false;
+		}
+	}
+
+	glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
+
+	return pass;
+}
 
 
 static GLuint
 make_gs_program(GLenum input_prim)
 {
 	static const char *vs_text =
 		"#version 150 \n"
 		"in vec4 vertex; \n"
 		"in vec4 color; \n"
 		"uniform mat4 modelViewProj; \n"
 		"out vec4 pos;\n"
 		"out vec4 vs_gs_color; \n"
+		"out int vs_gs_vertex_id; \n"
 		"void main() \n"
 		"{ \n"
 		"   gl_Position = vertex * modelViewProj; \n"
 		"   pos = vertex * modelViewProj; \n"
 		"   vs_gs_color = color; \n"
+		"   vs_gs_vertex_id = gl_VertexID; \n"
 		"} \n";
 	static const char *gs_text_lines =
 		"#version 150 \n"
 		"layout(lines_adjacency) in;\n"
 		"layout(line_strip, max_vertices = 2) out;\n"
 		"in vec4 pos[]; \n"
 		"in vec4 vs_gs_color[4]; \n"
 		"flat out vec4 gs_fs_color; \n"
 		"void main() \n"
 		"{ \n"
@@ -413,41 +464,49 @@  make_gs_program(GLenum input_prim)
 		"   gl_Position = pos[2]; \n"
 		"   EmitVertex(); \n"
 		"   EndPrimitive(); \n"
 		"} \n";
 	static const char *gs_text_triangles =
 		"#version 150 \n"
 		"layout(triangles_adjacency) in;\n"
 		"layout(triangle_strip, max_vertices = 3) out;\n"
 		"in vec4 pos[]; \n"
 		"in vec4 vs_gs_color[6]; \n"
+		"in int vs_gs_vertex_id[6]; \n"
 		"flat out vec4 gs_fs_color; \n"
 		"void main() \n"
 		"{ \n"
 		"   gs_fs_color = vs_gs_color[0]; \n"
+		"   gs_fs_color.b = vs_gs_vertex_id[0] * (1. / 255.); \n"
+		"   gs_fs_color.a = 0.0; \n"
 		"   gl_Position = pos[0]; \n"
 		"   EmitVertex(); \n"
 		"   gs_fs_color = vs_gs_color[2]; \n"
+		"   gs_fs_color.b = vs_gs_vertex_id[2] * (1. / 255.); \n"
+		"   gs_fs_color.a = 0.5; \n"
 		"   gl_Position = pos[2]; \n"
 		"   EmitVertex(); \n"
 		"   gs_fs_color = vs_gs_color[4]; \n"
+		"   gs_fs_color.b = vs_gs_vertex_id[4] * (1. / 255.); \n"
+		"   gs_fs_color.a = 1.0; \n"
 		"   gl_Position = pos[4]; \n"
 		"   EmitVertex(); \n"
 		"   //EndPrimitive(); \n"
 		"} \n";
 	static const char *fs_text =
 		"#version 150 \n"
 		"flat in vec4 gs_fs_color; \n"
 		"void main() \n"
 		"{ \n"
 		"   gl_FragColor = gs_fs_color; \n"
 		"} \n";
+	static const char *gs_xfb_varyings[] = { "gs_fs_color" };
 	const char *gs_text;
 	GLuint program;
 
 	switch (input_prim) {
 	case GL_LINES_ADJACENCY:
 	case GL_LINE_STRIP_ADJACENCY:
 		gs_text = gs_text_lines;
 		break;
 	case GL_TRIANGLES_ADJACENCY:
 	case GL_TRIANGLE_STRIP_ADJACENCY:
@@ -462,20 +521,23 @@  make_gs_program(GLenum input_prim)
 		GL_VERTEX_SHADER, vs_text,
 		GL_GEOMETRY_SHADER, gs_text,
 		GL_FRAGMENT_SHADER, fs_text,
 		0);
 
 	assert(program);
 
 	glBindAttribLocation(program, 0, "vertex");
 	glBindAttribLocation(program, 1, "color");
 
+	glTransformFeedbackVaryings(program, 1, &gs_xfb_varyings[0],
+				    GL_INTERLEAVED_ATTRIBS);
+
 	glLinkProgram(program);
 
 	return program;
 }
 
 
 static GLuint
 make_ref_program(void)
 {
 	static const char *vs_text =
@@ -661,51 +723,96 @@  use_program(GLuint program)
 
 static void
 set_viewport(unsigned pos)
 {
 	int vp_w = piglit_width / 4;
 	assert(pos < 4);
 	glViewport(pos * vp_w, 0, vp_w, piglit_height);
 }
 
 
+static void
+draw_gs_triangles(GLenum prim_mode, GLuint vao, unsigned num_verts,
+		  unsigned vp_pos)
+{
+	size_t buffer_size;
+	void *zeros;
+
+	use_program(gs_triangles_program);
+	set_viewport(vp_pos);
+	glBindVertexArray(vao);
+
+	buffer_size =
+		12 * sizeof(float) *
+		num_gs_prims(prim_mode, num_verts);
+	zeros = calloc(1, buffer_size);
+
+	glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buf);
+	glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, buffer_size,
+			zeros, GL_STREAM_READ);
+
+	free(zeros);
+
+	glBeginTransformFeedback(GL_TRIANGLES);
+
+	if (draw_elements) {
+		GLushort* elements;
+
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buf);
+		glBufferData(GL_ELEMENT_ARRAY_BUFFER,
+			sizeof(GLushort) * num_verts, NULL,
+			GL_STATIC_DRAW);
+		elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
+		for (unsigned i = 0; i < num_verts; i++) {
+			elements[i] = i;
+		}
+		glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+
+		glDrawElements(prim_mode, num_verts, GL_UNSIGNED_SHORT, NULL);
+	} else {
+		glDrawArrays(prim_mode, 0, num_verts);
+	}
+
+	glEndTransformFeedback();
+}
+
 enum piglit_result
 piglit_display(void)
 {
 	bool pass = true;
 
 	glClear(GL_COLOR_BUFFER_BIT);
 
 	if (draw_with_gs) {
 		use_program(gs_lines_program);
 		set_viewport(0);
 		glBindVertexArray(lines_adj_vao);
 		glDrawArrays(GL_LINES_ADJACENCY, 0,
 			     NUM_VERTS(lines_adj_verts));
 
 		use_program(gs_line_strip_program);
 		set_viewport(1);
 		glBindVertexArray(line_strip_adj_vao);
 		glDrawArrays(GL_LINE_STRIP_ADJACENCY, 0,
 			     NUM_VERTS(line_strip_adj_verts));
 
-		use_program(gs_triangles_program);
-		set_viewport(2);
-		glBindVertexArray(triangles_adj_vao);
-		glDrawArrays(GL_TRIANGLES_ADJACENCY, 0,
-			     NUM_VERTS(triangles_adj_verts));
+		draw_gs_triangles(GL_TRIANGLES_ADJACENCY, triangles_adj_vao,
+				  NUM_VERTS(triangles_adj_verts), 2);
 
-		use_program(gs_triangle_strip_program);
-		set_viewport(3);
-		glBindVertexArray(triangle_strip_adj_vao);
-		glDrawArrays(GL_TRIANGLE_STRIP_ADJACENCY, 0,
-			     NUM_VERTS(triangle_strip_adj_verts));
+		pass = probe_xfb(GL_TRIANGLES_ADJACENCY,
+				 NUM_VERTS(triangles_adj_verts)) && pass;
+
+		draw_gs_triangles(GL_TRIANGLE_STRIP_ADJACENCY, triangle_strip_adj_vao,
+				  NUM_VERTS(triangle_strip_adj_verts), 3);
+
+		pass = probe_xfb(GL_TRIANGLE_STRIP_ADJACENCY,
+				 NUM_VERTS(triangle_strip_adj_verts)) && pass;
 	}
 	else {
 		/* This path is basically for debugging and visualizing the
 		 * "extra" lines and tris in adjacency primitives.
 		 */
 		use_program(ref_program);
 
 		set_viewport(0);
 		draw_lines_adj(lines_adj_vao, 8);
 
@@ -780,32 +887,37 @@  piglit_init(int argc, char **argv)
 		else if (strcmp(argv[i], "cull-back") == 0)
 			cull_mode = GL_BACK;
 		else if (strcmp(argv[i], "cull-front") == 0)
 			cull_mode = GL_FRONT;
 		else if (strcmp(argv[i], "ref") == 0)
 			draw_with_gs = GL_FALSE;
 		else if (strcmp(argv[i], "pv-last") == 0)
 			provoking_vertex = GL_LAST_VERTEX_CONVENTION;
 		else if (strcmp(argv[i], "pv-first") == 0)
 			provoking_vertex = GL_FIRST_VERTEX_CONVENTION;
+		else if (strcmp(argv[i], "elements") == 0)
+			draw_elements = true;
 		else
 			printf("Unexpected %s argument\n", argv[i]);
 	}
 
 	glPolygonMode(GL_FRONT_AND_BACK, polygon_mode);
 	if (cull_mode != GL_NONE) {
 		glCullFace(cull_mode);
 		glEnable(GL_CULL_FACE);
 		glFrontFace(GL_CW);
 	}
 	glProvokingVertex(provoking_vertex);
 
+	glGenBuffers(1, &xfb_buf);
+	glGenBuffers(1, &element_buf);
+
 	lines_adj_vao = create_vao(lines_adj_verts,
 				   NUM_VERTS(lines_adj_verts));
 
 	line_strip_adj_vao = create_vao(line_strip_adj_verts,
 					NUM_VERTS(line_strip_adj_verts));
 
 	triangles_adj_vao = create_vao(triangles_adj_verts,
 				       NUM_VERTS(triangles_adj_verts));
 
 	triangle_strip_adj_vao = create_vao(triangle_strip_adj_verts,