• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  #ifndef _GL3CCLIPDISTANCE_HPP
2  #define _GL3CCLIPDISTANCE_HPP
3  /*-------------------------------------------------------------------------
4   * OpenGL Conformance Test Suite
5   * -----------------------------
6   *
7   * Copyright (c) 2015-2016 The Khronos Group Inc.
8   *
9   * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   *
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   *
21   */ /*!
22   * \file
23   * \brief
24   */ /*-------------------------------------------------------------------*/
25  
26  /**
27   */ /*!
28   * \file  gl3cClipDistance.hpp
29   * \brief Conformance tests for Clip Distance feature functionality.
30   */ /*-------------------------------------------------------------------*/
31  
32  #include "glcTestCase.hpp"
33  #include "gluDefs.hpp"
34  #include "glwDefs.hpp"
35  #include "tcuDefs.hpp"
36  
37  /* Includes. */
38  #include <cstring>
39  #include <map>
40  #include <typeinfo>
41  #include <vector>
42  
43  #include "glwEnums.hpp"
44  #include "glwFunctions.hpp"
45  
46  namespace gl3cts
47  {
48  namespace ClipDistance
49  {
50  namespace Utility
51  {
52  /** @class Program
53   *
54   *  @brief GLSL program encapsulation class.
55   */
56  class Program
57  {
58  public:
59  	/* Public type definitions */
60  
61  	/** @struct CompilationStatus
62  	 *
63  	 *  @brief GLSL shader encapsulation class.
64  	 */
65  	struct CompilationStatus
66  	{
67  		glw::GLuint shader_id;
68  		glw::GLint  shader_compilation_status;
69  		std::string shader_log;
70  	};
71  
72  	/** @struct CompilationStatus
73  	 *
74  	 *  @brief GLSL shader encapsulation class.
75  	 */
76  	struct LinkageStatus
77  	{
78  		glw::GLuint program_id;
79  		glw::GLint  program_linkage_status;
80  		std::string program_linkage_log;
81  	};
82  
83  	/* Public member variables */
84  	Program(const glw::Functions& gl, const std::string& vertex_shader_code, const std::string& fragment_shader_code,
85  			std::vector<std::string> transform_feedback_varyings = std::vector<std::string>());
86  
87  	~Program();
88  
89  	const CompilationStatus& VertexShaderStatus() const;
90  	const CompilationStatus& FragmentShaderStatus() const;
91  	const LinkageStatus&	 ProgramStatus() const;
92  
93  	void UseProgram() const;
94  
95  private:
96  	/* Private member variables */
97  	CompilationStatus m_vertex_shader_status;
98  	CompilationStatus m_fragment_shader_status;
99  	LinkageStatus	 m_program_status;
100  
101  	const glw::Functions& m_gl;
102  
103  	/* Private member functions */
104  	CompilationStatus compileShader(const glw::GLenum shader_type, const glw::GLchar* const* shader_code);
105  
106  	LinkageStatus linkShaders(const CompilationStatus& vertex_shader, const CompilationStatus& fragment_shader,
107  							  std::vector<std::string>& transform_feedback_varyings);
108  };
109  /* Program class */
110  
111  /** @class Framebuffer
112   *
113   *  @brief OpenGL's Framebuffer encapsulation class.
114   *
115   *  @note Created framebuffer is red-color-only and float type.
116   */
117  class Framebuffer
118  {
119  public:
120  	Framebuffer(const glw::Functions& gl, const glw::GLsizei size_x, const glw::GLsizei size_y);
121  	~Framebuffer();
122  
123  	bool					  isValid();
124  	void					  bind();
125  	std::vector<glw::GLfloat> readPixels();
126  	void					  clear();
127  
128  private:
129  	const glw::Functions& m_gl;
130  	const glw::GLsizei	m_size_x;
131  	const glw::GLsizei	m_size_y;
132  	glw::GLuint			  m_framebuffer_id;
133  	glw::GLuint			  m_renderbuffer_id;
134  };
135  /* Framebuffer class */
136  
137  /** @class Vertex Array Object
138   *
139   *  @brief OpenGL's Vertex Array Object encapsulation class.
140   */
141  class VertexArrayObject
142  {
143  public:
144  	VertexArrayObject(const glw::Functions& gl, const glw::GLenum primitive_type); // create empty vao
145  	~VertexArrayObject();
146  
147  	void bind();
148  	void draw(glw::GLuint first, glw::GLuint count);
149  	void drawWithTransformFeedback(glw::GLuint first, glw::GLuint count, bool discard_rasterizer);
150  
151  private:
152  	const glw::Functions& m_gl;
153  	glw::GLuint			  m_vertex_array_object_id;
154  	glw::GLenum			  m_primitive_type;
155  };
156  /* VertexArrayObject class */
157  
158  /** @class Vertex Buffer Object
159   *
160   *  @brief OpenGL's Vertex Buffer Object encapsulation template class.
161   *
162   *  @note Input data type is a template parameter.
163   */
164  template <class T>
165  class VertexBufferObject
166  {
167  public:
168  	VertexBufferObject(const glw::Functions& gl, const glw::GLenum target, std::vector<T> data);
169  	~VertexBufferObject();
170  
171  	bool bind();
172  	bool useAsShaderInput(Program program, std::string input_attribute_name, glw::GLint number_of_components);
173  	std::vector<T> readBuffer();
174  
175  private:
176  	const glw::Functions& m_gl;
177  	glw::GLuint			  m_vertex_buffer_object_id;
178  	glw::GLenum			  m_target;
179  	glw::GLsizei		  m_size;
180  
181  	std::vector<glw::GLint> m_enabled_arrays;
182  };
183  /* VertexBufferObject template class */
184  
185  std::string preprocessCode(std::string source, std::string key, std::string value);
186  std::string itoa(glw::GLint i);
187  } /* Utility namespace */
188  
189  /** @class Tests
190   *
191   *  @brief Clip distance test group.
192   */
193  class Tests : public deqp::TestCaseGroup
194  {
195  public:
196  	/* Public member functions */
197  	Tests(deqp::Context& context);
198  
199  	void init();
200  
201  private:
202  	/* Private member functions */
203  	Tests(const Tests& other);
204  	Tests& operator=(const Tests& other);
205  };
206  
207  /** @class CoverageTest
208   *
209   *  @brief Clip distance API Coverage test cases.
210   */
211  class CoverageTest : public deqp::TestCase
212  {
213  public:
214  	/* Public member functions */
215  	CoverageTest(deqp::Context& context);
216  
217  	virtual tcu::TestNode::IterateResult iterate();
218  
219  private:
220  	/* Private member functions */
221  	CoverageTest(const CoverageTest& other);
222  	CoverageTest& operator=(const CoverageTest& other);
223  
224  	bool MaxClipDistancesValueTest(const glw::Functions& gl);
225  	bool EnableDisableTest(const glw::Functions& gl);
226  	bool MaxClipDistancesValueInVertexShaderTest(const glw::Functions& gl);
227  	bool MaxClipDistancesValueInFragmentShaderTest(const glw::Functions& gl);
228  	bool ClipDistancesValuePassing(const glw::Functions& gl);
229  
230  	/* Private member variables */
231  	glw::GLint m_gl_max_clip_distances_value;
232  
233  	/* Private static constants */
234  	static const glw::GLchar* m_vertex_shader_code_case_0;
235  	static const glw::GLchar* m_fragment_shader_code_case_0;
236  
237  	static const glw::GLchar* m_vertex_shader_code_case_1;
238  	static const glw::GLchar* m_fragment_shader_code_case_1;
239  
240  	static const glw::GLchar* m_vertex_shader_code_case_2;
241  	static const glw::GLchar* m_fragment_shader_code_case_2;
242  };
243  
244  /** @class FunctionalTest
245   *
246   *  @brief Clip distance Functional test cases.
247   */
248  class FunctionalTest : public deqp::TestCase
249  {
250  public:
251  	/* Public member functions */
252  	FunctionalTest(deqp::Context& context);
253  
254  	virtual void						 init();
255  	virtual tcu::TestNode::IterateResult iterate();
256  
257  private:
258  	/* Private member functions */
259  	FunctionalTest(const FunctionalTest& other);
260  	FunctionalTest& operator=(const FunctionalTest& other);
261  
262  	std::string prepareVertexShaderCode(bool explicit_redeclaration, bool dynamic_setter, glw::GLuint clip_count,
263  										glw::GLuint clip_function, glw::GLenum primitive_type);
264  
265  	gl3cts::ClipDistance::Utility::VertexBufferObject<glw::GLfloat>* prepareGeometry(const glw::Functions& gl,
266  																					 const glw::GLenum primitive_type);
267  
268  	bool checkResults(glw::GLenum primitive_type, glw::GLuint clip_function, std::vector<glw::GLfloat>& results);
269  
270  	/* Private member variables */
271  	glw::GLint m_gl_max_clip_distances_value;
272  
273  	/* Private static constants */
274  	static const glw::GLchar* m_vertex_shader_code;
275  	static const glw::GLchar* m_fragment_shader_code;
276  	static const glw::GLchar* m_dynamic_array_setter;
277  	static const glw::GLchar* m_static_array_setter;
278  	static const glw::GLchar* m_explicit_redeclaration;
279  	static const glw::GLchar* m_clip_function[];
280  	static const glw::GLuint  m_clip_function_count;
281  
282  	static const glw::GLenum m_primitive_types[];
283  	static const glw::GLenum m_primitive_indices[];
284  	static const glw::GLuint m_primitive_types_count;
285  
286  	static const glw::GLfloat m_expected_integral[];
287  };
288  
289  /** @class NegativeTest
290   *
291   *  @brief Clip distance API Negative test cases.
292   */
293  class NegativeTest : public deqp::TestCase
294  {
295  public:
296  	/* Public member functions */
297  	NegativeTest(deqp::Context& context);
298  
299  	virtual tcu::TestNode::IterateResult iterate();
300  
301  private:
302  	/* Private member functions */
303  	NegativeTest(const NegativeTest& other);
304  	NegativeTest& operator=(const NegativeTest& other);
305  
306  	bool testClipVertexBuildingErrors(const glw::Functions& gl);
307  	bool testMaxClipDistancesBuildingErrors(const glw::Functions& gl);
308  	bool testClipDistancesRedeclarationBuildingErrors(const glw::Functions& gl);
309  
310  	/* Private static constants */
311  	static const glw::GLchar* m_vertex_shader_code_case_0;
312  	static const glw::GLchar* m_vertex_shader_code_case_1;
313  	static const glw::GLchar* m_vertex_shader_code_case_2;
314  	static const glw::GLchar* m_fragment_shader_code;
315  };
316  } /* ClipDistance namespace */
317  } /* gl3cts namespace */
318  
319  /* Template classes' implementation */
320  
321  /** @brief Vertex Buffer Object constructor.
322   *
323   *  @note It silently binds VAO to OpenGL.
324   *
325   *  @param [in] gl               OpenGL functions access.
326   *  @param [in] target           Binding target of the VBO.
327   *  @param [in] data             Data of the buffer (may be empty).
328   */
329  template <class T>
VertexBufferObject(const glw::Functions & gl,const glw::GLenum target,std::vector<T> data)330  gl3cts::ClipDistance::Utility::VertexBufferObject<T>::VertexBufferObject(const glw::Functions& gl,
331  																		 const glw::GLenum target, std::vector<T> data)
332  	: m_gl(gl), m_vertex_buffer_object_id(0), m_target(target), m_size(0)
333  {
334  	m_gl.genBuffers(1, &m_vertex_buffer_object_id);
335  	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers call failed.");
336  
337  	if (m_vertex_buffer_object_id)
338  	{
339  		m_size = (glw::GLsizei)(sizeof(T) * data.size());
340  
341  		bind();
342  
343  		m_gl.bufferData(m_target, m_size, &data[0], GL_STATIC_DRAW);
344  		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferData call failed.");
345  	}
346  }
347  
348  /** @brief Vertex Buffer Object destructor. */
349  template <class T>
~VertexBufferObject()350  gl3cts::ClipDistance::Utility::VertexBufferObject<T>::~VertexBufferObject()
351  {
352  	m_gl.deleteBuffers(1, &m_vertex_buffer_object_id); /* Delete silently unbinds the buffer. */
353  	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteBuffers call failed.");
354  
355  	for (std::vector<glw::GLint>::iterator i_enabled_array = m_enabled_arrays.begin();
356  		 i_enabled_array != m_enabled_arrays.end(); ++i_enabled_array)
357  	{
358  		m_gl.disableVertexAttribArray(*i_enabled_array);
359  	}
360  }
361  
362  /** @brief Bind Vertex Buffer Object to its target.
363   *
364   *  @note It binds also to indexed binding point for GL_TRANSFORM_FEEDBACK_BUFFER target.
365   */
366  template <class T>
bind()367  bool gl3cts::ClipDistance::Utility::VertexBufferObject<T>::bind()
368  {
369  	if (m_vertex_buffer_object_id)
370  	{
371  		m_gl.bindBuffer(m_target, m_vertex_buffer_object_id);
372  		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer call failed.");
373  
374  		if (m_target == GL_TRANSFORM_FEEDBACK_BUFFER)
375  		{
376  			m_gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_vertex_buffer_object_id);
377  			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBufferBase call failed.");
378  		}
379  
380  		return true;
381  	}
382  
383  	return false;
384  }
385  
386  /** @brief Use VBO as attribute vertex array.
387   *
388   *  @note It silently binds VBO.
389   *
390   *  @param [in] program                 GLSL Program to which VBO shall be bound.
391   *  @param [in] input_attribute_name    Name of GLSL asttribute.
392   *  @param [in] number_of_components    Number of attribute's components.
393   *
394   *  @return True on success, false otherwise.
395   */
396  template <class T>
useAsShaderInput(Program program,std::string input_attribute_name,glw::GLint number_of_components)397  bool gl3cts::ClipDistance::Utility::VertexBufferObject<T>::useAsShaderInput(Program		program,
398  																			std::string input_attribute_name,
399  																			glw::GLint  number_of_components)
400  {
401  	if (program.ProgramStatus().program_id)
402  	{
403  		glw::GLint location = m_gl.getAttribLocation(program.ProgramStatus().program_id, input_attribute_name.c_str());
404  		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetAttribLocation call failed.");
405  
406  		if (location >= 0)
407  		{
408  			const std::type_info& buffer_type = typeid(T);
409  			const std::type_info& float_type  = typeid(glw::GLfloat);
410  			const std::type_info& int_type	= typeid(glw::GLint);
411  
412  			m_gl.enableVertexAttribArray(location);
413  			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glEnableVertexAttribArray call failed.");
414  			m_enabled_arrays.push_back(location);
415  
416  			bind();
417  
418  			if (buffer_type == float_type)
419  			{
420  				m_gl.vertexAttribPointer(location, number_of_components, GL_FLOAT, false, 0, NULL);
421  				GLU_EXPECT_NO_ERROR(m_gl.getError(), "glVertexAttribPointer call failed.");
422  			}
423  			else if (buffer_type == int_type)
424  			{
425  				m_gl.vertexAttribIPointer(location, number_of_components, GL_FLOAT, 0, NULL);
426  				GLU_EXPECT_NO_ERROR(m_gl.getError(), "glVertexAttribIPointer call failed.");
427  			}
428  			else
429  			{
430  				return false;
431  			}
432  
433  			return true;
434  		}
435  	}
436  
437  	return false;
438  }
439  
440  /** @brief Read VBO content (potentially set by transform feedback).
441   *
442   *  @return Content of VBO.
443   */
444  template <class T>
readBuffer()445  std::vector<T> gl3cts::ClipDistance::Utility::VertexBufferObject<T>::readBuffer()
446  {
447  	std::vector<T> buffer_data(m_size / sizeof(T));
448  
449  	bind();
450  
451  	glw::GLvoid* results = m_gl.mapBuffer(m_target, GL_READ_ONLY);
452  
453  	if (results)
454  	{
455  		memcpy(&buffer_data[0], results, m_size);
456  	}
457  
458  	m_gl.unmapBuffer(m_target);
459  
460  	return buffer_data;
461  }
462  #endif // _GL3CCLIPDISTANCE_HPP
463