#ifndef _GLCVIEWPORTARRAYTESTS_HPP #define _GLCVIEWPORTARRAYTESTS_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 */ /*-------------------------------------------------------------------*/ /** * \file glcViewportArrayTests.hpp * \brief Declares test classes for "Viewport Array" functionality. */ /*-------------------------------------------------------------------*/ #include "glcTestCase.hpp" #include "glwDefs.hpp" #include "esextcTestCaseBase.hpp" namespace tcu { class MessageBuilder; } /* namespace tcu */ namespace glcts { namespace ViewportArray { class Utils { public: enum SHADER_STAGES { COMPUTE_SHADER = 0, VERTEX_SHADER, TESS_CTRL_SHADER, TESS_EVAL_SHADER, GEOMETRY_SHADER, FRAGMENT_SHADER, /* */ SHADER_STAGES_MAX }; /* Public types */ struct buffer { buffer(deqp::Context& context); ~buffer(); void bind() const; void bindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size); void generate(glw::GLenum target); void* map(glw::GLenum access) const; void unmap() const; void update(glw::GLsizeiptr size, glw::GLvoid* data, glw::GLenum usage); glw::GLuint m_id; private: deqp::Context& m_context; glw::GLenum m_target; }; struct framebuffer { framebuffer(deqp::Context& context); ~framebuffer(); void attachTexture(glw::GLenum attachment, glw::GLuint texture_id, glw::GLuint width, glw::GLuint height); void bind(); void clear(glw::GLenum mask); void clearColor(glw::GLfloat red, glw::GLfloat green, glw::GLfloat blue, glw::GLfloat alpha); void generate(); glw::GLuint m_id; private: deqp::Context& m_context; }; class shaderCompilationException : public std::exception { public: shaderCompilationException(const glw::GLchar* source, const glw::GLchar* message); virtual ~shaderCompilationException() throw() { } virtual const char* what() const throw(); std::string m_shader_source; std::string m_error_message; }; class programLinkageException : public std::exception { public: programLinkageException(const glw::GLchar* error_message); virtual ~programLinkageException() throw() { } virtual const char* what() const throw(); std::string m_error_message; }; /** Store information about program object * **/ struct program { program(deqp::Context& context); ~program(); void build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code, const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code, const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code, const glw::GLchar* const* varying_names, glw::GLuint n_varying_names, bool is_separable = false); void compile(glw::GLuint shader_id, const glw::GLchar* source) const; glw::GLint getAttribLocation(const glw::GLchar* name) const; glw::GLuint getSubroutineIndex(const glw::GLchar* subroutine_name, glw::GLenum shader_stage) const; glw::GLint getSubroutineUniformLocation(const glw::GLchar* uniform_name, glw::GLenum shader_stage) const; glw::GLint getUniformLocation(const glw::GLchar* uniform_name) const; void link() const; void remove(); void use() const; /* */ static void printShaderSource(const glw::GLchar* source, tcu::MessageBuilder& log); static const glw::GLenum ARB_COMPUTE_SHADER; glw::GLuint m_compute_shader_id; glw::GLuint m_fragment_shader_id; glw::GLuint m_geometry_shader_id; glw::GLuint m_program_object_id; glw::GLuint m_tesselation_control_shader_id; glw::GLuint m_tesselation_evaluation_shader_id; glw::GLuint m_vertex_shader_id; private: deqp::Context& m_context; }; struct texture { texture(deqp::Context& context); ~texture(); void bind() const; void create(glw::GLuint width, glw::GLuint height, glw::GLenum internal_format); void create(glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum internal_format); void get(glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data) const; void release(); void update(glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type, glw::GLvoid* data); glw::GLuint m_id; glw::GLuint m_width; glw::GLuint m_height; glw::GLuint m_depth; private: deqp::Context& m_context; bool m_is_array; }; struct vertexArray { vertexArray(deqp::Context& Context); ~vertexArray(); void generate(); void bind(); glw::GLuint m_id; private: deqp::Context& m_context; }; class DepthFuncWrapper { public: DepthFuncWrapper(deqp::Context& context) : m_gl(context.getRenderContext().getFunctions()){} ~DepthFuncWrapper(){} void depthRangeArray(glw::GLuint first, glw::GLsizei count, const glw::GLfloat* v) { m_gl.depthRangeArrayfvOES(first, count, v); } void depthRangeArray(glw::GLuint first, glw::GLsizei count, const glw::GLdouble* v) { m_gl.depthRangeArrayv(first, count, v); } void depthRangeIndexed(glw::GLuint index, glw::GLfloat n, glw::GLfloat f) { m_gl.depthRangeIndexedfOES(index, n, f); } void depthRangeIndexed(glw::GLuint index, glw::GLdouble n, glw::GLdouble f) { m_gl.depthRangeIndexed(index, n, f); } void depthRange(glw::GLfloat near, glw::GLfloat far) { m_gl.depthRangef(near, far); } void depthRange(glw::GLdouble near, glw::GLdouble far) { m_gl.depthRange(near, far); } void getDepthi_v(glw::GLenum target, glw::GLuint index, glw::GLfloat* data) { m_gl.getFloati_v(target, index, data); } void getDepthi_v(glw::GLenum target, glw::GLuint index, glw::GLdouble* data) { m_gl.getDoublei_v(target, index, data); } const glw::Functions& getFunctions() { return m_gl; } private: const glw::Functions& m_gl; }; }; /** Implements test APIErrors, description follows: * * Verify that API generate errors as specified. Check that: * * DepthRangeArrayv generates INVALID_VALUE when + is greater * than or equal to the value of MAX_VIEWPORTS; * * DepthRangeIndexed generates INVALID_VALUE when is greater than or * equal to the value of MAX_VIEWPORTS; * * ViewportArrayv generates INVALID_VALUE when + is greater * than or equal to the value of MAX_VIEWPORTS; * * ViewportIndexedf and ViewportIndexedfv generate INVALID_VALUE when * is greater than or equal to the value of MAX_VIEWPORTS; * * ViewportArrayv, Viewport, ViewportIndexedf and ViewportIndexedfv generate * INVALID_VALUE when or values are negative; * * ScissorArrayv generates INVALID_VALUE when + is greater * than or equal to the value of MAX_VIEWPORTS; * * ScissorIndexed and ScissorIndexedv generate INVALID_VALUE when is * greater than or equal to the value of MAX_VIEWPORTS; * * ScissorArrayv, ScissorIndexed, ScissorIndexedv and Scissor generate * INVALID_VALUE when or values are negative; * * Disablei, Enablei and IsEnabledi generate INVALID_VALUE when is * SCISSOR_TEST and is greater than or equal to the * value of MAX_VIEWPORTS; * * GetIntegeri_v generates INVALID_VALUE when is SCISSOR_BOX and * is greater than or equal to the value of MAX_VIEWPORTS; * * GetFloati_v generates INVALID_VALUE when is VIEWPORT and * is greater than or equal to the value of MAX_VIEWPORTS; * * GetDoublei_v generates INVALID_VALUE when is DEPTH_RANGE and * is greater than or equal to the value of MAX_VIEWPORTS; **/ class APIErrors : public glcts::TestCaseBase { public: /* Public methods */ APIErrors(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~APIErrors() { } /* Public methods inherited from TestCaseBase */ virtual IterateResult iterate(void); private: template void depthRangeArrayHelper(Utils::DepthFuncWrapper& depthFunc, glw::GLint max_viewports, bool& test_result, T* data = NULL); template void depthRangeIndexedHelper(Utils::DepthFuncWrapper& depthFunc, glw::GLint max_viewports, bool& test_result, T* data = NULL); template void getDepthHelper(Utils::DepthFuncWrapper& depthFunc, glw::GLint max_viewports, bool& test_result, T* data = NULL); void checkGLError(glw::GLenum expected_error, const glw::GLchar* description, bool& out_result); }; /** Implements test Queries, description follows: * * Verify that: * * Initial dimensions of VIEWPORT returned by GetFloati_v match dimensions of * the window into which GL is rendering; * * Initial values of DEPTH_RANGE returned by GetDoublei_v are [0, 1]; * * Initial state of SCISSOR_TEST returned by IsEnabledi is FALSE; * * Initial dimensions of SCISSOR_BOX returned by GetIntegeri_v are either * zeros or match dimensions of the window into which GL is rendering; * * Dimensions of MAX_VIEWPORT_DIMS returned by GetFloati_v are at least * as big as supported dimensions of render buffers, see MAX_RENDERBUFFER_SIZE; * * Value of MAX_VIEWPORTS returned by GetIntegeri_v is at least 16; * * Value of VIEWPORT_SUBPIXEL_BITS returned by GetIntegeri_v is at least 0; * * Values of VIEWPORT_BOUNDS_RANGE returned by GetFloatv are * at least [-32768, 32767]; * * Values of LAYER_PROVOKING_VERTEX and VIEWPORT_INDEX_PROVOKING_VERTEX * returned by GetIntegerv are located in the following set * { FIRST_VERTEX_CONVENTION, LAST_VERTEX_CONVENTION, PROVOKING_VERTEX, * UNDEFINED_VERTEX }; **/ class Queries : public glcts::TestCaseBase { public: /* Public methods */ Queries(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~Queries() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); private: template void depthRangeInitialValuesHelper(Utils::DepthFuncWrapper& depthFunc, glw::GLint max_viewports, bool& test_result, T* data = NULL); }; /** Implements test ViewportAPI, description follows: * * Verify that VIEWPORT can be set and queried. * Steps: * - get initial dimensions of VIEWPORT for all MAX_VIEWPORTS indices; * - change location and dimensions of all indices at once with * ViewportArrayv; * - get VIEWPORT for all MAX_VIEWPORTS indices and verify results; * - for each index: * * modify with ViewportIndexedf, * * get VIEWPORT for all MAX_VIEWPORTS indices and verify results; * * modify with ViewportIndexedfv, * * get VIEWPORT for all MAX_VIEWPORTS indices and verify results; * - for each index: * * modify all indices before and after current one with ViewportArrayv, * * get VIEWPORT for all MAX_VIEWPORTS indices and verify results; * - change location and dimensions of all indices at once with Viewport; * - get VIEWPORT for all MAX_VIEWPORTS indices and verify results; **/ class ViewportAPI : public glcts::TestCaseBase { public: /* Public methods */ ViewportAPI(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~ViewportAPI() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); private: /* Private methods */ void compareViewports(std::vector& left, std::vector& right, const glw::GLchar* description, bool& out_result); void getViewports(glw::GLint max_viewports, std::vector& out_data); /* Private constants */ static const glw::GLuint m_n_elements; }; /** Implements test ScissorAPI, description follows: * * Verify that SCISSOR_BOX can be set and queried. * Steps: * - get initial dimensions of SCISSOR_BOX for all MAX_VIEWPORTS indices; * - change location and dimensions of all indices at once with * ScissorArrayv; * - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results; * - for each index: * * modify with ScissorIndexed, * * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results; * * modify with ScissorIndexedv, * * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results; * - for each index: * * modify all indices before and after current one with ScissorArrayv, * * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results; * - change location and dimensions of all indices at once with Scissor; * - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results; **/ class ScissorAPI : public glcts::TestCaseBase { public: /* Public methods */ ScissorAPI(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~ScissorAPI() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); private: /* Private methods */ void compareScissorBoxes(std::vector& left, std::vector& right, const glw::GLchar* description, bool& out_result); void getScissorBoxes(glw::GLint max_viewports, std::vector& out_data); /* Private constants */ static const glw::GLuint m_n_elements; }; /** Implements test DepthRangeAPI, description follows: * * Verify that DEPTH_RANGE can be set and queried. * Steps: * - get initial values of DEPTH_RANGE for all MAX_VIEWPORTS indices; * - change values of all indices at once with DepthRangeArrayv; * - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results; * - for each index: * * modify with DepthRangeIndexed, * * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results; * - for each index: * * modify all indices before and after current one with DepthRangeArrayv, * * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results; * - change values of all indices at once with DepthRange; * - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results; **/ class DepthRangeAPI : public glcts::TestCaseBase { public: /* Public methods */ DepthRangeAPI(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~DepthRangeAPI() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); private: /* Private methods */ template void compareDepthRanges(std::vector& left, std::vector& right, const glw::GLchar* description, bool& out_result); template void getDepthRanges(Utils::DepthFuncWrapper& depthFunc, glw::GLint max_viewports, std::vector& out_data); template bool iterateHelper(T* data = NULL); /* Private constants */ static const glw::GLuint m_n_elements; }; /** Implements test ScissorTestStateAPI, description follows: * * Verify that state of SCISSOR_TEST can be set and queried. * Steps: * - get initial state of SCISSOR_TEST for all MAX_VIEWPORTS indices; * - for each index: * * toggle SCISSOR_TEST, * * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify; * - for each index: * * toggle SCISSOR_TEST, * * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify; * - enable SCISSOR_TEST for all indices at once with Enable; * - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify; * - disable SCISSOR_TEST for all indices at once with Disable; * - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify; * - enable SCISSOR_TEST for all indices at once with Enable; * - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify; **/ class ScissorTestStateAPI : public glcts::TestCaseBase { public: /* Public methods */ ScissorTestStateAPI(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~ScissorTestStateAPI() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); private: /* Private methods */ void compareScissorTestStates(std::vector& left, std::vector& right, const glw::GLchar* description, bool& out_result); void getScissorTestStates(glw::GLint max_viewports, std::vector& out_data); }; class DrawTestBase : public glcts::TestCaseBase { public: /* Public methods */ DrawTestBase(deqp::Context& context, const glcts::ExtParameters& extParams, const glw::GLchar* test_name, const glw::GLchar* test_description); virtual ~DrawTestBase() { } /* Public methods inherited from TestCase */ virtual tcu::TestNode::IterateResult iterate(void); protected: /* Protected enums */ enum VIEWPORT_METHOD { VIEWPORTARRAYV = 0, VIEWPORTINDEXEDF, VIEWPORTINDEXEDF_V, }; enum SCISSOR_METHOD { SCISSORARRAYV = 0, SCISSORINDEXEDF, SCISSORINDEXEDF_V, }; enum DEPTH_RANGE_METHOD { DEPTHRANGEARRAYV = 0, DEPTHRANGEINDEXED, }; enum PROVOKING_VERTEX { FIRST, LAST, }; enum TEST_TYPE { VIEWPORT, SCISSOR, DEPTHRANGE, PROVOKING, }; /* Protected methods to be implemented by child class */ virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index); virtual void getClearSettings(bool& clear_depth_before_draw, glw::GLuint iteration_index, glw::GLfloat& depth_value); virtual glw::GLuint getDrawCallsNumber(); virtual std::string getFragmentShader() = 0; virtual std::string getGeometryShader() = 0; virtual TEST_TYPE getTestType(); virtual bool isClearTest(); virtual void prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1); virtual void prepareUniforms(Utils::program& program, glw::GLuint draw_call_index); virtual void setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0, Utils::texture& texture_1); virtual void setupViewports(TEST_TYPE type, glw::GLuint iteration_index); /* Methods available for child class */ bool checkRegionR32I(glw::GLuint x, glw::GLuint y, glw::GLint expected_value, glw::GLint* data); bool checkRegionR32I(glw::GLuint x, glw::GLuint y, glw::GLuint width, glw::GLuint height, glw::GLint expected_value, glw::GLint* data); void prepareTextureR32I(Utils::texture& texture); void prepareTextureR32Ix4(Utils::texture& texture); void prepareTextureArrayR32I(Utils::texture& texture); void prepareTextureR32F(Utils::texture& texture); void prepareTextureD32F(Utils::texture& texture); void setup16x2Depths(DEPTH_RANGE_METHOD method); void setup4x4Scissor(SCISSOR_METHOD method, bool set_zeros); void setup4x4Viewport(VIEWPORT_METHOD method); void setup2x2Viewport(PROVOKING_VERTEX provoking); /* Constants available to child class */ static const glw::GLuint m_depth; static const glw::GLuint m_height; static const glw::GLuint m_width; static const glw::GLuint m_r32f_height; static const glw::GLuint m_r32f_width; static const glw::GLuint m_r32ix4_depth; private: /* Private methods */ std::string getVertexShader(); template void setup16x2DepthsHelper(DEPTH_RANGE_METHOD method, T* data = NULL); }; /** Implements test DrawToSingleLayerWithMultipleViewports, description follows: * * Verify that multiple viewports can be used to draw to single image. * Steps: * - prepare 2D R32I 128x128 texture filled with value -1 and set it up as * COLOR_ATTACHMENT_0; * - prepare program that consist of: * * boilerplate vertex shader, * * geometry shader, * * fragment shaders; * Geometry shader should output a quad (-1,-1 : 1,1) made of * triangle_strip; gl_ViewportIndex and declared integer varying "color" * should be assigned the value of gl_InvocationID; Amount of geometry shader * invocations should be set to 16; Fragment shader should output value of * varying "color" to attachment 0. * - set up first 16 viewports with following code snippet: * * index = 0; * for (y = 0; y < 4; ++y) * for (x = 0; x < 4; ++x) * ViewportIndexedf(index++, * x * 32 x offset, * y * 32 y offset, * 32 width , * 32 height ); * - draw single vertex; * - inspect contents of COLOR_ATTACHMENT_0; * - test pass if image is filled with the following pattern: * * 0 1 2 3 * 4 5 6 7 * 8 9 10 11 * 12 13 14 15; * * Each area should be 32x32 pixels rectangle; * - repeat test with functions ViewportIndexedf_v and ViewportArrayv; **/ class DrawToSingleLayerWithMultipleViewports : public DrawTestBase { public: /* Public methods */ DrawToSingleLayerWithMultipleViewports(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~DrawToSingleLayerWithMultipleViewports() { } protected: /* Protected methods inherited from DrawTestBase */ virtual std::string getFragmentShader(); virtual std::string getGeometryShader(); }; /** Implements test DynamicViewportIndex, description follows: * * Verify that gl_ViewportIndex can be set in dynamic manner. * Modify DrawToSingleLayerWithMultipleViewports in the following aspects: * - geometry shader should declare unsigned integer uniform "index"; * - geometry shader should assign a value of "index" to gl_ViewportIndex and * "color"; * - amount of geometry shader invocations should be set to 1; * - 16 times: * * set "index" to unique value from range <0:15>; * * draw single vertex; * * verify that only area of viewport at "index" has been updated; * - test pass if correct pixels were modified in each draw; **/ class DynamicViewportIndex : public DrawTestBase { public: /* Public methods */ DynamicViewportIndex(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~DynamicViewportIndex() { } protected: /* Protected methods inherited from DrawTestBase */ virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index); virtual std::string getFragmentShader(); virtual std::string getGeometryShader(); virtual glw::GLuint getDrawCallsNumber(); virtual void prepareUniforms(Utils::program& program, glw::GLuint draw_call_index); }; /** Implements test DrawMulitpleViewportsWithSingleInvocation, description follows: * * Verify that multiple viewports can be affected by single invocation of * geometry shader. * Modify DrawToSingleLayerWithMultipleViewports in the following aspects: * - geometry shader should output 16 quads, as separate primitives; * - instead of gl_InvocationID, geometry shader should use predefined values * from range <0:15>, unique per quad; * - amount of geometry shader invocations should be set to 1; **/ class DrawMulitpleViewportsWithSingleInvocation : public DrawTestBase { public: /* Public methods */ DrawMulitpleViewportsWithSingleInvocation(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~DrawMulitpleViewportsWithSingleInvocation() { } protected: /* Protected methods inherited from DrawTestBase */ virtual std::string getFragmentShader(); virtual std::string getGeometryShader(); }; /** Implements test ViewportIndexSubroutine, description follows: * * Verify that gl_ViewportIndex can be assigned by subroutine. * Depends on: ARB_shader_subroutine. * Modify DynamicViewportIndex in the following aspects: * - geometry shader should define two subroutines and single subroutine * uniform; First subroutine should assign value 4 to gl_ViewportIndex and * "color"; Second subroutine should assign value 5 to gl_ViewportIndex and * "color"; subroutine should be called once per emitted vertex; * - uniform "index" should be removed; * - viewport 4 should be configured to span over left half of image; viewport * 5 should span over right half of image; * - set up first subroutine and draw single vertex; * - set up second subroutine and draw single vertex; * - test pass if left half of image is filled with value 4 and right one with * 5; **/ class ViewportIndexSubroutine : public DrawTestBase { public: /* Public methods */ ViewportIndexSubroutine(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~ViewportIndexSubroutine() { } /* Public methods inherited from TestCase/DrawTestBase */ virtual tcu::TestNode::IterateResult iterate(void); protected: /* Protected methods inherited from DrawTestBase */ virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index); virtual std::string getFragmentShader(); virtual std::string getGeometryShader(); virtual glw::GLuint getDrawCallsNumber(); virtual void prepareUniforms(Utils::program& program, glw::GLuint draw_call_index); virtual void setupViewports(TEST_TYPE type, glw::GLuint iteration_index); }; /** Implements test DrawMultipleLayers, description follows: * * Verify that single viewport affects multiple layers in the same way. * Modify DynamicViewportIndex in the following aspects: * - texture should be 2D array with 16 layers; * - geometry shader should assign a value of gl_InvocationId to gl_Layer; * - amount of geometry shader invocations should be set to 16; * - verification should be applied to all 16 layers; **/ class DrawMultipleLayers : public DrawTestBase { public: /* Public methods */ DrawMultipleLayers(deqp::Context& context, const glcts::ExtParameters& extParams); DrawMultipleLayers(deqp::Context& context, const glcts::ExtParameters& extParams, const glw::GLchar* test_name, const glw::GLchar* test_description); virtual ~DrawMultipleLayers() { } protected: /* Protected methods inherited from DrawTestBase */ virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index); virtual std::string getFragmentShader(); virtual std::string getGeometryShader(); virtual void prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1); }; /** Implements test Scissor, description follows: * * Verify that scissor test is applied as expected. * Modify DrawMultipleLayers in the following aspects: * - set all viewports to location 0,0 and dimensions 128x128; * - set up first 16 scissor boxes with following code snippet: * * index = 0; * for (y = 0; y < 4; ++y) * for (x = 0; x < 4; ++x) * ScissorIndexed(index++, * x * 32 x offset, * y * 32 y offset, * 32 width , * 32 height ); * * - enable SCISSORT_TEST for first 16 indices; * - verification should be concerned with areas of the scissor boxes not * viewports; * - repeat test with functions ScissorIndexedv and ScissorArrayv; **/ class Scissor : public DrawMultipleLayers { public: /* Public methods */ Scissor(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~Scissor() { } protected: /* Protected methods inherited from DrawTestBase */ virtual TEST_TYPE getTestType(); }; /** Implements test ScissorZeroDimension, description follows: * * Verify that scissor test discard all fragments when width and height is set * to zero. * Modify Scissor to set up width and height of scissor boxes to 0. * Test pass if no pixel is modified. **/ class ScissorZeroDimension : public DrawMultipleLayers { public: /* Public methods */ ScissorZeroDimension(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~ScissorZeroDimension() { } protected: /* Protected methods inherited from DrawTestBase */ virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index); virtual TEST_TYPE getTestType(); virtual void setupViewports(TEST_TYPE type, glw::GLuint iteration_index); }; /** Implements test ScissorClear, description follows: * * Verify that Clear is affected only by settings of scissor test in first * viewport. * Steps: * - prepare 2D 128x128 R32I texture, filled with value -1 and set it as * COLOR_ATTACHMENT_0; * - configure first 16 viewports as in Scissor; * - enable SCISSOR_TEST for first 16 indices; * - clear framebuffer to (0, 0, 0, 0); * - inspect image; * - test pass if only area corresponding with first SCISSOR_BOX was filled * with 0, while rest of image remain filled with value -1; **/ class ScissorClear : public DrawMultipleLayers { public: /* Public methods */ ScissorClear(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~ScissorClear() { } protected: /* Protected methods inherited from DrawTestBase */ virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index); virtual TEST_TYPE getTestType(); virtual bool isClearTest(); }; /** Implements test DepthRange, description follows: * * Verify that depth range is applied as expected. * Steps: * - prepate 2D 16x2 R32F texture filled with value -1.0 and set it up as * COLOR_ATTACHMENT_0; * - prepare program that consist of: * * boilerplate vertex shader, * * geometry shader, * * fragment shader; * Geometry shader should emit two quads: * * -1,0 : 1,1 with z equal -1.0, * * -1,-1 : 1,0 with z equal 1.0, * made of triangle_strip; gl_ViewportIndex should be assigned an value of * gl_InvocationId; Amount of geometry shader invocations should be set to 16; * Fragment shader should output value of gl_FragCoord.z to attachment 0. * - set up first 16 viewports with the following code snippet: * * const double step = 1.0 / 16.0; * for (index = 0; index < 16; ++index) * { * const double near = ((double) i) * step; * VieportIndexed (i, (float) i, 0.0, 1.0, 2.0); * DepthRangeIndexed(i, near, 1.0 - near); * } * * - draw single vertex; * - inspect contents of COLOR_ATTACHMENT_0; * - test pass if: * * top row of image is filled with increasing values, starting at 0 with * step 1/16; * * bottom row of image is filled with decreasing values, starting at 1 with * step 1/16; * - repeat test with function DepthRangeArrayv; **/ class DepthRange : public DrawTestBase { public: /* Public methods */ DepthRange(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~DepthRange() { } protected: /* Protected methods inherited from DrawTestBase */ virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index); virtual std::string getFragmentShader(); virtual std::string getGeometryShader(); virtual TEST_TYPE getTestType(); virtual void prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1); }; /** Implements test DepthRangeDepthTest, description follows: * * Verify that depth test work as expected with multiple viewports. * Modify DepthRange test in the following aspect: * - add second 2D 16x2 DEPTH_COMPONENT32F texture and set it up as * DEPTH_ATTACHMENT; * - enable DEPTH_TEST; * - DepthFunc should be set to LESS (initial value); * - 18 times: * * set ClearDepth to "i" * 1/16, starting at 0 up to 17/16, * * draw single vertex * * verify contents of color attachment; * - test pass when color attachment is filled only with values lower than * current ClearDepth value; **/ class DepthRangeDepthTest : public DrawTestBase { public: /* Public methods */ DepthRangeDepthTest(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~DepthRangeDepthTest() { } protected: /* Protected methods inherited from DrawTestBase */ virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index); virtual void getClearSettings(bool& clear_depth_before_draw, glw::GLuint iteration_index, glw::GLfloat& depth_value); virtual glw::GLuint getDrawCallsNumber(); virtual std::string getFragmentShader(); virtual std::string getGeometryShader(); virtual TEST_TYPE getTestType(); virtual void prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1); virtual void setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0, Utils::texture& texture_1); virtual void setupViewports(TEST_TYPE type, glw::GLuint iteration_index); }; /** Implements test ProvokingVertex, description follows: * * Verify that provoking vertex work as expected. * Steps: * - prepare 2D array R32I 128x128x4 texture and configure it as * COLOR_ATTACHMENT_0; * - prepare program consisting of: * * boilerplate vertex shader, * * geometry shader, * * fragment shader; * Geometry shader should output a quad (-1,-1 : 1,1); Each vertex should * receive different gl_ViewportIndex value, first vertex should be assigned an * 0, second 1, third 2, fourth 3; gl_Layer should be set in the same way as * gl_ViewportIndex; Fragment shader should output integer of value 1; * - configure first four viewports to form 2x2 grid, spanning whole image; * - for each combination of LAYER_PROVOKING_VERTEX and * VIEWPORT_INDEX_PROVOKING_VERTEX: * * clear framebuffer to (0,0,0,0), * * draw single vertex * * inspect image; * - test pass if correct area of correct layer is filled with value 1, while * rest of image remains "clean"; * Notes: * - for UNDEFINED_VERTEX any selection is correct; * - for PROVOKING_VERTEX convention is selected by function ProvokingVertex; * Test all possible combinations; **/ class ProvokingVertex : public DrawTestBase { public: /* Public methods */ ProvokingVertex(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~ProvokingVertex() { } protected: /* Protected methods inherited from DrawTestBase */ virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index); virtual std::string getFragmentShader(); virtual std::string getGeometryShader(); virtual TEST_TYPE getTestType(); virtual void prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1); }; } /* ViewportArray namespace */ /** Group class for Shader Language 420Pack conformance tests */ class ViewportArrayTests : public glcts::TestCaseGroupBase { public: /* Public methods */ ViewportArrayTests(deqp::Context& context, const glcts::ExtParameters& extParams); virtual ~ViewportArrayTests(void) { } virtual void init(void); private: /* Private methods */ ViewportArrayTests(const ViewportArrayTests& other); ViewportArrayTests& operator=(const ViewportArrayTests& other); }; } // glcts #endif // _GLCVIEWPORTARRAYTESTS_HPP