blob: 78466658b9b6540a996b14f76064933afc01fe80 [file] [log] [blame]
#ifndef _ESEXTCGEOMETRYSHADERPRIMITIVECOUNTER_HPP
#define _ESEXTCGEOMETRYSHADERPRIMITIVECOUNTER_HPP
/*-------------------------------------------------------------------------
* OpenGL Conformance Test Suite
* -----------------------------
*
* Copyright (c) 2014-2016 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/ /*!
* \file
* \brief
*/ /*-------------------------------------------------------------------*/
#include "../esextcTestCaseBase.hpp"
#include <string.h>
namespace glcts
{
struct DataPrimitiveIDInCounter
{
glw::GLenum m_drawMode;
std::string m_emitVertexCodeForGeometryShader;
glw::GLenum m_feedbackMode;
std::string m_layoutIn;
std::string m_layoutOut;
glw::GLuint m_numberOfVerticesPerOneOutputPrimitive;
glw::GLuint m_numberOfVerticesPerOneInputPrimitive;
glw::GLuint m_numberOfDrawnPrimitives;
};
/** Implementation of "Group 6" from CTS_EXT_geometry_shader.
* Test Group for "Group 6" tests, storing configuration data and initializing the tests.
* All tests from "Group 6" and children of GeometryShaderPrimitiveCounterTestGroup.
*/
class GeometryShaderPrimitiveCounterTestGroup : public TestCaseGroupBase
{
public:
/* Public methods */
GeometryShaderPrimitiveCounterTestGroup(Context& context, const ExtParameters& extParams, const char* name,
const char* description);
virtual ~GeometryShaderPrimitiveCounterTestGroup()
{
}
virtual void init(void);
};
/**
* 1. Make sure that a built-in geometry shader's input variable
* gl_PrimitiveIDIn increments correctly for all valid <draw call mode,
* input primitive type, output primitive type> tuples.
"
* Category: API;
* Functional Test.
*
* Let N_VERTICES represent amount of vertices that must be emitted, given
* active geometry shader's output primitive type, to form a single
* primitive that can be passed to rasterization stage
*
* Use Transform Feedback functionality to capture gl_PrimitiveIDIn value
* as read in the geometry shader:
*
* - The shader should emit:
*
* floor(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT / N_VERTICES) / (4 + 1)
*
* primitives. It should call EndPrimitive() every N_VERTICES vertices
* emitted.
*
* - The draw call should be made for 1024 primitives.
*
* Test should fail if the result data for any of the tuples is determined
* to be incorrect.
*/
class GeometryShaderPrimitiveCounter : public TestCaseBase
{
public:
/* Public methods */
GeometryShaderPrimitiveCounter(Context& context, const ExtParameters& extParams, const char* name,
const char* description, const DataPrimitiveIDInCounter& testConfiguration);
virtual ~GeometryShaderPrimitiveCounter(void)
{
}
virtual void deinit(void);
virtual IterateResult iterate(void);
protected:
/* Protected methods */
bool checkResult(const glw::GLint* feedbackResult);
void createAndBuildProgramWithFeedback(void);
void drawAndGetFeedback(glw::GLint* feedbackResult);
void prepareBufferObjects();
/* Protected virtual methods */
virtual void drawFunction();
/* Protected members */
DataPrimitiveIDInCounter m_testConfiguration;
glw::GLuint m_nrVaryings;
glw::GLuint m_sizeOfDataArray;
glw::GLuint m_sizeOfFeedbackBuffer;
const glw::GLuint m_n_components;
private:
/* Private functions */
std::string GetGeometryShaderCode(const std::string& max_vertices, const std::string& layout_in,
const std::string& layout_out, const std::string& emit_vertices,
const std::string& n_iterations);
/* Private variables */
static const char* m_fragment_shader_code;
static const char* m_vertex_shader_code;
glw::GLint m_maxGeometryOutputVertices;
glw::GLuint m_fragment_shader_id;
glw::GLuint m_geometry_shader_id;
glw::GLuint m_vertex_shader_id;
glw::GLuint m_program_id;
glw::GLuint m_tbo;
glw::GLuint m_vao;
glw::GLuint m_vbo;
};
/** 2. Make sure that restarting a primitive topology with a primitive restart
* index does not affect primitive ID counter, when a element-driven draw
* call is made.
*
* Category: API;
* Functional Test.
*
* Modify test case 6.1 so that it uses element-sourced data. Insert the
* restart primitive index right after first primitive is rendered but
* before indices for the second one start.
*/
class GeometryShaderPrimitiveCounterRestartingPrimitive : public GeometryShaderPrimitiveCounter
{
public:
/* Public methods */
GeometryShaderPrimitiveCounterRestartingPrimitive(Context& context, const ExtParameters& extParams,
const char* name, const char* description,
const DataPrimitiveIDInCounter& testConfiguration);
virtual ~GeometryShaderPrimitiveCounterRestartingPrimitive(void)
{
}
virtual void deinit(void);
virtual IterateResult iterate(void);
protected:
/* Protected functions */
virtual void drawFunction();
void setUpVertexAttributeArrays();
private:
/* Private fields */
glw::GLuint m_bo_id;
glw::GLuint m_numberOfRestarts;
};
/** 3. Make sure that gl_PrimitiveID built-in variable can be read correctly
* from a fragment shader, assuming geometry shader writes to it in
* previous stage.
*
* Category: API;
* Functional Test.
*
* Vertex shader should output an int variable called vs_vertex_id, to which
* gl_VertexID has been saved.
*
* Geometry shader should take points and output a triangle strip. It will
* emit up to 4 vertices. The geometry shader should define an input int
* variable called vs_vertex_id. Let:
*
* int column = vs_vertex_id % 64;
* int row = floor(vs_vertex_id / 64);
*
* The shader should emit the following vertices:
*
* 1) (-1.0 + (column+1) / 32.0, -1.0 + (row + 1) / 32.0, 0, 1)
* 2) (-1.0 + (column+1) / 32.0, -1.0 + (row) / 32.0, 0, 1)
* 3) (-1.0 + (column) / 32.0, -1.0 + (row + 1) / 32.0, 0, 1)
* 4) (-1.0 + (column) / 32.0, -1.0 + (row) / 32.0, 0, 1)
*
* Finally, the geometry shader should set gl_PrimitiveID for each of the
* vertices to vs_vertex_id.
*
* Fragment shader should set output variable's result value as follows: (*)
*
* result[0] = (gl_PrimitiveID % 64) / 64.0;
* result[1] = floor(gl_PrimitiveID / 64) / 64.0;
* result[2] = gl_PrimitiveID / 4096.0;
* result[3] = ((gl_PrimitiveID % 2) == 0) ? 1.0 : 0.0;
*
* Using a program object built of these shader, the test should issue
* a draw call for 4096 points. The test is considered to have passed
* successfully if the rendered data consists of 4096 rectangles of edge
* equal to 1/64th of the output resolution, centers of which have values
* as described in (*).
*
* Texture object used as color attachment should be at least of 1024x1024
* resolution, in which case quad edge will be 4px long.
*/
class GeometryShaderPrimitiveIDFromFragmentShader : public TestCaseBase
{
public:
/* Publi methods */
GeometryShaderPrimitiveIDFromFragmentShader(Context& context, const ExtParameters& extParams, const char* name,
const char* description);
virtual ~GeometryShaderPrimitiveIDFromFragmentShader(void)
{
}
void deinit(void);
IterateResult iterate(void);
private:
/* Private fields */
static const char* m_fragment_shader_code;
static const char* m_geometry_shader_code;
static const char* m_vertex_shader_code;
const glw::GLuint m_n_drawn_vertices;
const glw::GLuint m_squareEdgeSize;
const glw::GLuint m_texture_height;
const glw::GLuint m_texture_n_components;
const glw::GLuint m_texture_n_levels;
const glw::GLuint m_texture_width;
glw::GLuint m_fbo_id;
glw::GLuint m_fragment_shader_id;
glw::GLuint m_geometry_shader_id;
glw::GLuint m_program_id;
glw::GLuint m_texture_id;
glw::GLuint m_vao_id;
glw::GLuint m_vbo_id;
glw::GLuint m_vertex_shader_id;
};
} // namespace glcts
#endif // _ESEXTCGEOMETRYSHADERPRIMITIVECOUNTER_HPP