13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Tessellation and geometry shader interaction tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fTessellationGeometryInteractionTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRenderTarget.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuSurface.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageCompare.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluStrUtil.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluObjectWrapper.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deUniquePtr.hpp"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sstream>
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm>
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <iterator>
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* const s_positionVertexShader =		"#version 310 es\n"
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"in highp vec4 a_position;\n"
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"void main (void)\n"
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"{\n"
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	gl_Position = a_position;\n"
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"}\n";
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* const s_whiteOutputFragmentShader =	"#version 310 es\n"
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"layout(location = 0) out mediump vec4 fragColor;\n"
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"void main (void)\n"
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"{\n"
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"	fragColor = vec4(1.0);\n"
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														"}\n";
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool isBlack (const tcu::RGBA& c)
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return c.getRed() == 0 && c.getGreen() == 0 && c.getBlue() == 0;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IdentityShaderCase : public TestCase
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					IdentityShaderCase	(Context& context, const char* name, const char* description);
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		getVertexSource		(void) const;
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		getFragmentSource	(void) const;
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
843c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIdentityShaderCase::IdentityShaderCase (Context& context, const char* name, const char* description)
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase(context, name, description)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* IdentityShaderCase::getVertexSource (void) const
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return	"#version 310 es\n"
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in highp vec4 a_position;\n"
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 v_vertex_color;\n"
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_Position = a_position;\n"
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	v_vertex_color = vec4(a_position.x * 0.5 + 0.5, a_position.y * 0.5 + 0.5, 1.0, 0.4);\n"
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* IdentityShaderCase::getFragmentSource (void) const
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return	"#version 310 es\n"
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in mediump vec4 v_fragment_color;\n"
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(location = 0) out mediump vec4 fragColor;\n"
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	fragColor = v_fragment_color;\n"
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IdentityGeometryShaderCase : public IdentityShaderCase
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum CaseType
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASE_TRIANGLES = 0,
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASE_QUADS,
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASE_ISOLINES,
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					IdentityGeometryShaderCase			(Context& context, const char* name, const char* description, CaseType caseType);
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					~IdentityGeometryShaderCase			(void);
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			init								(void);
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			deinit								(void);
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult	iterate								(void);
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		getTessellationControlSource		(void) const;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		getTessellationEvaluationSource		(bool geometryActive) const;
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		getGeometrySource					(void) const;
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		RENDER_SIZE = 128,
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const CaseType	m_case;
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32		m_patchBuffer;
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1433c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIdentityGeometryShaderCase::IdentityGeometryShaderCase (Context& context, const char* name, const char* description, CaseType caseType)
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: IdentityShaderCase	(context, name, description)
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_case				(caseType)
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_patchBuffer			(0)
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1503c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIdentityGeometryShaderCase::~IdentityGeometryShaderCase (void)
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid IdentityGeometryShaderCase::init (void)
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Requirements
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader") ||
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader and GL_EXT_geometry_shader extensions");
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_context.getRenderTarget().getWidth() < RENDER_SIZE ||
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderTarget().getHeight() < RENDER_SIZE)
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires " + de::toString<int>(RENDER_SIZE) + "x" + de::toString<int>(RENDER_SIZE) + " or larger render target.");
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Log
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog()
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::Message
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Testing tessellating shader program output does not change when a passthrough geometry shader is attached.\n"
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Rendering two images, first with and second without a geometry shader. Expecting similar results.\n"
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Using additive blending to detect overlap.\n"
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::EndMessage;
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Resources
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const tcu::Vec4 patchBufferData[4] =
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4( -0.9f, -0.9f, 0.0f, 1.0f ),
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4( -0.9f,  0.9f, 0.0f, 1.0f ),
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4(  0.9f, -0.9f, 0.0f, 1.0f ),
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4(  0.9f,  0.9f, 0.0f, 1.0f ),
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &m_patchBuffer);
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_ARRAY_BUFFER, m_patchBuffer);
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_ARRAY_BUFFER, sizeof(patchBufferData), patchBufferData, GL_STATIC_DRAW);
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen buffer");
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid IdentityGeometryShaderCase::deinit (void)
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_patchBuffer)
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_patchBuffer);
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_patchBuffer = 0;
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2053c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIdentityGeometryShaderCase::IterateResult IdentityGeometryShaderCase::iterate (void)
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float				innerTessellationLevel	= 14.0f;
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float				outerTessellationLevel	= 14.0f;
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface			resultWithGeometry		(RENDER_SIZE, RENDER_SIZE);
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface			resultWithoutGeometry	(RENDER_SIZE, RENDER_SIZE);
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const struct
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*				name;
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*				description;
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool					containsGeometryShader;
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::PixelBufferAccess	surfaceAccess;
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} renderTargets[] =
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "RenderWithGeometryShader",		"Render with geometry shader",		true,	resultWithGeometry.getAccess()		},
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "RenderWithoutGeometryShader",	"Render without geometry shader",	false,	resultWithoutGeometry.getAccess()	},
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport(0, 0, RENDER_SIZE, RENDER_SIZE);
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "set viewport");
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.enable(GL_BLEND);
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.blendFunc(GL_SRC_ALPHA, GL_ONE);
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.blendEquation(GL_FUNC_ADD);
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "set blend");
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation level: inner " << innerTessellationLevel << ", outer " << outerTessellationLevel << tcu::TestLog::EndMessage;
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// render with and without geometry shader
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renderTargets); ++renderNdx)
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ScopedLogSection	section	(m_testCtx.getLog(), renderTargets[renderNdx].name, renderTargets[renderNdx].description);
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::ProgramSources			sources;
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources	<< glu::VertexSource(getVertexSource())
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::FragmentSource(getFragmentSource())
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::TessellationControlSource(getTessellationControlSource())
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::TessellationEvaluationSource(getTessellationEvaluationSource(renderTargets[renderNdx].containsGeometryShader));
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (renderTargets[renderNdx].containsGeometryShader)
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sources << glu::GeometrySource(getGeometrySource());
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::ShaderProgram	program					(m_context.getRenderContext(), sources);
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::VertexArray		vao						(m_context.getRenderContext());
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int					posLocation				= gl.getAttribLocation(program.getProgram(), "a_position");
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int					innerTessellationLoc	= gl.getUniformLocation(program.getProgram(), "u_innerTessellationLevel");
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int					outerTessellationLoc	= gl.getUniformLocation(program.getProgram(), "u_outerTessellationLevel");
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << program;
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!program.isOk())
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("could not build program");
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (posLocation == -1)
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("a_position location was -1");
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (outerTessellationLoc == -1)
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("u_outerTessellationLevel location was -1");
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindVertexArray(*vao);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBuffer(GL_ARRAY_BUFFER, m_patchBuffer);
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.enableVertexAttribArray(posLocation);
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "setup attribs");
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.useProgram(program.getProgram());
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.uniform1f(outerTessellationLoc, outerTessellationLevel);
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (innerTessellationLoc == -1)
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.uniform1f(innerTessellationLoc, innerTessellationLevel);
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "use program");
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.patchParameteri(GL_PATCH_VERTICES, (m_case == CASE_TRIANGLES) ? (3): (4));
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "set patch param");
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.clear(GL_COLOR_BUFFER_BIT);
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.drawArrays(GL_PATCHES, 0, 4);
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "draw patches");
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::readPixels(m_context.getRenderContext(), 0, 0, renderTargets[renderNdx].surfaceAccess);
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (tcu::intThresholdPositionDeviationCompare(m_testCtx.getLog(),
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  "ImageCompare",
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  "Image comparison",
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  resultWithoutGeometry.getAccess(),
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  resultWithGeometry.getAccess(),
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  tcu::UVec4(8, 8, 8, 255),
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  tcu::IVec3(1, 1, 0),
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  true,
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  tcu::COMPARE_LOG_RESULT))
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string IdentityGeometryShaderCase::getTessellationControlSource (void) const
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"#version 310 es\n"
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_tessellation_shader : require\n"
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(vertices = 4) out;\n"
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform highp float u_innerTessellationLevel;\n"
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform highp float u_outerTessellationLevel;\n"
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in highp vec4 v_vertex_color[];\n"
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 v_patch_color[];\n"
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	v_patch_color[gl_InvocationID] = v_vertex_color[gl_InvocationID];\n"
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n";
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_case == CASE_TRIANGLES)
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	gl_TessLevelOuter[0] = u_outerTessellationLevel;\n"
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[1] = u_outerTessellationLevel;\n"
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[2] = u_outerTessellationLevel;\n"
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelInner[0] = u_innerTessellationLevel;\n";
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_case == CASE_QUADS)
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	gl_TessLevelOuter[0] = u_outerTessellationLevel;\n"
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[1] = u_outerTessellationLevel;\n"
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[2] = u_outerTessellationLevel;\n"
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[3] = u_outerTessellationLevel;\n"
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelInner[0] = u_innerTessellationLevel;\n"
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelInner[1] = u_innerTessellationLevel;\n";
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_case == CASE_ISOLINES)
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	gl_TessLevelOuter[0] = u_outerTessellationLevel;\n"
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[1] = u_outerTessellationLevel;\n";
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"}\n";
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string IdentityGeometryShaderCase::getTessellationEvaluationSource (bool geometryActive) const
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const	colorOutputName = ((geometryActive) ? ("v_evaluated_color") : ("v_fragment_color"));
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"#version 310 es\n"
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_tessellation_shader : require\n"
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout("
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_case == CASE_TRIANGLES) ? ("triangles") : (m_case == CASE_QUADS) ? ("quads") : ("isolines"))
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ") in;\n"
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in highp vec4 v_patch_color[];\n"
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 " << colorOutputName << ";\n"
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n";
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_case == CASE_TRIANGLES)
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	vec3 weights = vec3(pow(gl_TessCoord.x, 1.3), pow(gl_TessCoord.y, 1.3), pow(gl_TessCoord.z, 1.3));\n"
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	vec3 cweights = gl_TessCoord;\n"
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_Position = vec4(weights.x * gl_in[0].gl_Position.xyz + weights.y * gl_in[1].gl_Position.xyz + weights.z * gl_in[2].gl_Position.xyz, 1.0);\n"
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	" << colorOutputName << " = cweights.x * v_patch_color[0] + cweights.y * v_patch_color[1] + cweights.z * v_patch_color[2];\n";
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_case == CASE_QUADS || m_case == CASE_ISOLINES)
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	vec2 normalizedCoord = (gl_TessCoord.xy * 2.0 - vec2(1.0));\n"
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	vec2 normalizedWeights = normalizedCoord * (vec2(1.0) - 0.3 * cos(normalizedCoord.yx * 1.57));\n"
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	vec2 weights = normalizedWeights * 0.5 + vec2(0.5);\n"
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	vec2 cweights = gl_TessCoord.xy;\n"
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_Position = mix(mix(gl_in[0].gl_Position, gl_in[1].gl_Position, weights.y), mix(gl_in[2].gl_Position, gl_in[3].gl_Position, weights.y), weights.x);\n"
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	" << colorOutputName << " = mix(mix(v_patch_color[0], v_patch_color[1], cweights.y), mix(v_patch_color[2], v_patch_color[3], cweights.y), cweights.x);\n";
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"}\n";
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string IdentityGeometryShaderCase::getGeometrySource (void) const
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const	geometryInputPrimitive			= (m_case == CASE_ISOLINES) ? ("lines") : ("triangles");
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const	geometryOutputPrimitive			= (m_case == CASE_ISOLINES) ? ("line_strip") : ("triangle_strip");
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numEmitVertices					= (m_case == CASE_ISOLINES) ? (2) : (3);
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"#version 310 es\n"
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_geometry_shader : require\n"
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(" << geometryInputPrimitive << ") in;\n"
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(" << geometryOutputPrimitive << ", max_vertices=" << numEmitVertices <<") out;\n"
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in highp vec4 v_evaluated_color[];\n"
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 v_fragment_color;\n"
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	for (int ndx = 0; ndx < gl_in.length(); ++ndx)\n"
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	{\n"
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		gl_Position = gl_in[ndx].gl_Position;\n"
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		v_fragment_color = v_evaluated_color[ndx];\n"
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		EmitVertex();\n"
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	}\n"
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IdentityTessellationShaderCase : public IdentityShaderCase
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum CaseType
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASE_TRIANGLES = 0,
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASE_ISOLINES,
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					IdentityTessellationShaderCase		(Context& context, const char* name, const char* description, CaseType caseType);
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					~IdentityTessellationShaderCase		(void);
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			init								(void);
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			deinit								(void);
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult	iterate								(void);
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		getTessellationControlSource		(void) const;
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		getTessellationEvaluationSource		(void) const;
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		getGeometrySource					(bool tessellationActive) const;
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		RENDER_SIZE = 256,
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const CaseType	m_case;
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32		m_dataBuffer;
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4463c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIdentityTessellationShaderCase::IdentityTessellationShaderCase (Context& context, const char* name, const char* description, CaseType caseType)
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: IdentityShaderCase	(context, name, description)
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_case				(caseType)
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_dataBuffer			(0)
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4533c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIdentityTessellationShaderCase::~IdentityTessellationShaderCase (void)
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid IdentityTessellationShaderCase::init (void)
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Requirements
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader") ||
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader and GL_EXT_geometry_shader extensions");
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_context.getRenderTarget().getWidth() < RENDER_SIZE ||
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderTarget().getHeight() < RENDER_SIZE)
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires " + de::toString<int>(RENDER_SIZE) + "x" + de::toString<int>(RENDER_SIZE) + " or larger render target.");
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Log
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog()
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::Message
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Testing geometry shading shader program output does not change when a passthrough tessellation shader is attached.\n"
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Rendering two images, first with and second without a tessellation shader. Expecting similar results.\n"
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Using additive blending to detect overlap.\n"
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::EndMessage;
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Resources
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const tcu::Vec4	pointData[]	=
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f ),
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4(  0.0f, -0.5f, 0.0f, 1.0f ),
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4(  0.4f,  0.4f, 0.0f, 1.0f ),
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &m_dataBuffer);
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_ARRAY_BUFFER, m_dataBuffer);
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_ARRAY_BUFFER, sizeof(pointData), pointData, GL_STATIC_DRAW);
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen buffer");
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid IdentityTessellationShaderCase::deinit (void)
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_dataBuffer)
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_dataBuffer);
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_dataBuffer = 0;
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5063c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIdentityTessellationShaderCase::IterateResult IdentityTessellationShaderCase::iterate (void)
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl							= m_context.getRenderContext().getFunctions();
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface			resultWithTessellation		(RENDER_SIZE, RENDER_SIZE);
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface			resultWithoutTessellation	(RENDER_SIZE, RENDER_SIZE);
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numPrimitiveVertices		= (m_case == CASE_TRIANGLES) ? (3) : (2);
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const struct
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*				name;
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*				description;
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool					containsTessellationShaders;
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::PixelBufferAccess	surfaceAccess;
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} renderTargets[] =
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "RenderWithTessellationShader",		"Render with tessellation shader",		true,	resultWithTessellation.getAccess()		},
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "RenderWithoutTessellationShader",	"Render without tessellation shader",	false,	resultWithoutTessellation.getAccess()	},
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport(0, 0, RENDER_SIZE, RENDER_SIZE);
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "set viewport");
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.enable(GL_BLEND);
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.blendFunc(GL_SRC_ALPHA, GL_ONE);
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.blendEquation(GL_FUNC_ADD);
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "set blend");
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// render with and without tessellation shader
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renderTargets); ++renderNdx)
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ScopedLogSection	section	(m_testCtx.getLog(), renderTargets[renderNdx].name, renderTargets[renderNdx].description);
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::ProgramSources			sources;
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources	<< glu::VertexSource(getVertexSource())
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::FragmentSource(getFragmentSource())
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::GeometrySource(getGeometrySource(renderTargets[renderNdx].containsTessellationShaders));
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (renderTargets[renderNdx].containsTessellationShaders)
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sources	<< glu::TessellationControlSource(getTessellationControlSource())
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< glu::TessellationEvaluationSource(getTessellationEvaluationSource());
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::ShaderProgram	program					(m_context.getRenderContext(), sources);
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const glu::VertexArray		vao						(m_context.getRenderContext());
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int					posLocation				= gl.getAttribLocation(program.getProgram(), "a_position");
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << program;
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!program.isOk())
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("could not build program");
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (posLocation == -1)
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw tcu::TestError("a_position location was -1");
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindVertexArray(*vao);
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBuffer(GL_ARRAY_BUFFER, m_dataBuffer);
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.enableVertexAttribArray(posLocation);
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "setup attribs");
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.useProgram(program.getProgram());
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "use program");
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.clear(GL_COLOR_BUFFER_BIT);
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (renderTargets[renderNdx].containsTessellationShaders)
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.patchParameteri(GL_PATCH_VERTICES, numPrimitiveVertices);
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				GLU_EXPECT_NO_ERROR(gl.getError(), "set patch param");
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.drawArrays(GL_PATCHES, 0, numPrimitiveVertices);
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				GLU_EXPECT_NO_ERROR(gl.getError(), "draw patches");
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.drawArrays((m_case == CASE_TRIANGLES) ? (GL_TRIANGLES) : (GL_LINES), 0, numPrimitiveVertices);
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				GLU_EXPECT_NO_ERROR(gl.getError(), "draw primitives");
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::readPixels(m_context.getRenderContext(), 0, 0, renderTargets[renderNdx].surfaceAccess);
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// compare
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool imageOk;
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_context.getRenderTarget().getNumSamples() > 1)
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			imageOk = tcu::fuzzyCompare(m_testCtx.getLog(),
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										"ImageCompare",
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										"Image comparison",
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										resultWithoutTessellation.getAccess(),
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										resultWithTessellation.getAccess(),
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										0.03f,
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										tcu::COMPARE_LOG_RESULT);
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			imageOk = tcu::intThresholdPositionDeviationCompare(m_testCtx.getLog(),
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"ImageCompare",
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"Image comparison",
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																resultWithoutTessellation.getAccess(),
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																resultWithTessellation.getAccess(),
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																tcu::UVec4(8, 8, 8, 255),				//!< threshold
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																tcu::IVec3(1, 1, 0),					//!< 3x3 search kernel
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																true,									//!< fragments may end up over the viewport, just ignore them
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																tcu::COMPARE_LOG_RESULT);
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (imageOk)
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string IdentityTessellationShaderCase::getTessellationControlSource (void) const
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"#version 310 es\n"
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_tessellation_shader : require\n"
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(vertices = " << ((m_case == CASE_TRIANGLES) ? (3) : (2)) << ") out;\n"
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in highp vec4 v_vertex_color[];\n"
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 v_control_color[];\n"
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	v_control_color[gl_InvocationID] = v_vertex_color[gl_InvocationID];\n"
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n";
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_case == CASE_TRIANGLES)
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	gl_TessLevelOuter[0] = 1.0;\n"
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[1] = 1.0;\n"
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[2] = 1.0;\n"
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelInner[0] = 1.0;\n";
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_case == CASE_ISOLINES)
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	gl_TessLevelOuter[0] = 1.0;\n"
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[1] = 1.0;\n";
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"}\n";
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string IdentityTessellationShaderCase::getTessellationEvaluationSource (void) const
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"#version 310 es\n"
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_tessellation_shader : require\n"
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout("
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_case == CASE_TRIANGLES) ? ("triangles") : ("isolines"))
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ") in;\n"
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in highp vec4 v_control_color[];\n"
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 v_evaluated_color;\n"
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n";
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_case == CASE_TRIANGLES)
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n"
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	v_evaluated_color = gl_TessCoord.x * v_control_color[0] + gl_TessCoord.y * v_control_color[1] + gl_TessCoord.z * v_control_color[2];\n";
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_case == CASE_ISOLINES)
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	v_evaluated_color = mix(v_control_color[0], v_control_color[1], gl_TessCoord.x);\n";
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"}\n";
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string IdentityTessellationShaderCase::getGeometrySource (bool tessellationActive) const
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const	colorSourceName			= (tessellationActive) ? ("v_evaluated_color") : ("v_vertex_color");
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const	geometryInputPrimitive	= (m_case == CASE_ISOLINES) ? ("lines") : ("triangles");
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const	geometryOutputPrimitive	= (m_case == CASE_ISOLINES) ? ("line_strip") : ("triangle_strip");
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numEmitVertices			= (m_case == CASE_ISOLINES) ? (11) : (8);
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"#version 310 es\n"
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_geometry_shader : require\n"
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(" << geometryInputPrimitive << ") in;\n"
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(" << geometryOutputPrimitive << ", max_vertices=" << numEmitVertices <<") out;\n"
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in highp vec4 " << colorSourceName << "[];\n"
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 v_fragment_color;\n"
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n";
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_case == CASE_TRIANGLES)
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	vec4 centerPos = (gl_in[0].gl_Position + gl_in[1].gl_Position + gl_in[2].gl_Position) / 3.0f;\n"
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	for (int ndx = 0; ndx < 4; ++ndx)\n"
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	{\n"
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = centerPos + (centerPos - gl_in[ndx % 3].gl_Position);\n"
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_fragment_color = " << colorSourceName << "[ndx % 3];\n"
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = centerPos + 0.7 * (centerPos - gl_in[ndx % 3].gl_Position);\n"
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_fragment_color = " << colorSourceName << "[ndx % 3];\n"
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	}\n";
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_case == CASE_ISOLINES)
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	vec4 mdir = vec4(gl_in[0].gl_Position.y - gl_in[1].gl_Position.y, gl_in[1].gl_Position.x - gl_in[0].gl_Position.x, 0.0, 0.0);\n"
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	for (int i = 0; i <= 10; ++i)\n"
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	{\n"
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		float xweight = cos(float(i) / 10.0 * 6.28) * 0.5 + 0.5;\n"
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		float mweight = sin(float(i) / 10.0 * 6.28) * 0.1 + 0.1;\n"
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, xweight) + mweight * mdir;\n"
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_fragment_color = mix(" << colorSourceName << "[0], " << colorSourceName << "[1], xweight);\n"
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	}\n";
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"}\n";
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FeedbackPrimitiveTypeCase : public TestCase
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum TessellationOutputType
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TESSELLATION_OUT_TRIANGLES = 0,
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TESSELLATION_OUT_QUADS,
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TESSELLATION_OUT_ISOLINES,
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TESSELLATION_OUT_LAST
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum TessellationPointMode
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TESSELLATION_POINTMODE_OFF = 0,
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TESSELLATION_POINTMODE_ON,
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TESSELLATION_POINTMODE_LAST
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum GeometryOutputType
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GEOMETRY_OUTPUT_POINTS = 0,
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GEOMETRY_OUTPUT_LINES,
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GEOMETRY_OUTPUT_TRIANGLES,
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GEOMETRY_OUTPUT_LAST
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									FeedbackPrimitiveTypeCase				(Context& context,
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			 const char* name,
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			 const char* description,
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			 TessellationOutputType tessellationOutput,
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			 TessellationPointMode tessellationPointMode,
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			 GeometryOutputType geometryOutputType);
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									~FeedbackPrimitiveTypeCase				(void);
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							init									(void);
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							deinit									(void);
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult					iterate									(void);
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							renderWithFeedback						(tcu::Surface& dst);
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							renderWithoutFeedback					(tcu::Surface& dst);
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							verifyFeedbackResults					(const std::vector<tcu::Vec4>& feedbackResult);
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							verifyRenderedImage						(const tcu::Surface& image, const std::vector<tcu::Vec4>& vertices);
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							genTransformFeedback					(void);
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int								getNumGeneratedElementsPerPrimitive		(void) const;
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int								getNumGeneratedPrimitives				(void) const;
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int								getNumTessellatedPrimitives				(void) const;
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int								getGeometryAmplification				(void) const;
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*						getVertexSource							(void) const;
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*						getFragmentSource						(void) const;
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string						getTessellationControlSource			(void) const;
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string						getTessellationEvaluationSource			(void) const;
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string						getGeometrySource						(void) const;
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char*				getTessellationOutputDescription		(TessellationOutputType tessellationOutput,
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			 TessellationPointMode tessellationPointMode);
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char*				getGeometryInputDescription				(TessellationOutputType tessellationOutput,
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																			 TessellationPointMode tessellationPointMode);
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char*				getGeometryOutputDescription			(GeometryOutputType geometryOutput);
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glw::GLenum						getOutputPrimitiveGLType				(void) const;
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		RENDER_SIZE = 128,
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessellationOutputType	m_tessellationOutput;
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TessellationPointMode		m_tessellationPointMode;
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const GeometryOutputType		m_geometryOutputType;
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*				m_feedbackProgram;
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*				m_nonFeedbackProgram;
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32						m_patchBuffer;
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32						m_feedbackID;
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32						m_feedbackBuffer;
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8203c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFeedbackPrimitiveTypeCase::FeedbackPrimitiveTypeCase (Context& context,
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  const char* name,
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  const char* description,
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  TessellationOutputType tessellationOutput,
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  TessellationPointMode tessellationPointMode,
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  GeometryOutputType geometryOutputType)
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase					(context, name, description)
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_tessellationOutput		(tessellationOutput)
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_tessellationPointMode	(tessellationPointMode)
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_geometryOutputType		(geometryOutputType)
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_feedbackProgram			(DE_NULL)
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_nonFeedbackProgram		(DE_NULL)
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_patchBuffer				(0)
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_feedbackID				(0)
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_feedbackBuffer			(0)
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(tessellationOutput < TESSELLATION_OUT_LAST);
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(tessellationPointMode < TESSELLATION_POINTMODE_LAST);
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(geometryOutputType < GEOMETRY_OUTPUT_LAST);
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8413c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFeedbackPrimitiveTypeCase::~FeedbackPrimitiveTypeCase (void)
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FeedbackPrimitiveTypeCase::init (void)
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Requirements
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader") ||
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader and GL_EXT_geometry_shader extensions");
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_context.getRenderTarget().getWidth() < RENDER_SIZE ||
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderTarget().getHeight() < RENDER_SIZE)
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires " + de::toString<int>(RENDER_SIZE) + "x" + de::toString<int>(RENDER_SIZE) + " or larger render target.");
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Log
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog()
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::Message
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Testing "
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< getTessellationOutputDescription(m_tessellationOutput, m_tessellationPointMode)
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "->"
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< getGeometryInputDescription(m_tessellationOutput, m_tessellationPointMode)
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< " primitive conversion with and without transform feedback.\n"
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Sending a patch of 4 vertices (2x2 uniform grid) to tessellation control shader.\n"
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Control shader emits a patch of 9 vertices (3x3 uniform grid).\n"
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Setting outer tessellation level = 3, inner = 3.\n"
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Primitive generator emits " << getTessellationOutputDescription(m_tessellationOutput, m_tessellationPointMode) << "\n"
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Geometry shader transforms emitted primitives to " << getGeometryOutputDescription(m_geometryOutputType) << "\n"
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Reading back vertex positions of generated primitives using transform feedback.\n"
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Verifying rendered image and feedback vertices are consistent.\n"
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Rendering scene again with identical shader program, but without setting feedback varying. Expecting similar output image."
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::EndMessage;
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Resources
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const tcu::Vec4 patchBufferData[4] =
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4( -0.9f, -0.9f, 0.0f, 1.0f ),
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4( -0.9f,  0.9f, 0.0f, 1.0f ),
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4(  0.9f, -0.9f, 0.0f, 1.0f ),
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4(  0.9f,  0.9f, 0.0f, 1.0f ),
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &m_patchBuffer);
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_ARRAY_BUFFER, m_patchBuffer);
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_ARRAY_BUFFER, sizeof(patchBufferData), patchBufferData, GL_STATIC_DRAW);
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen buffer");
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_feedbackProgram = new glu::ShaderProgram(m_context.getRenderContext(),
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											   glu::ProgramSources()
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												<< glu::VertexSource(getVertexSource())
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												<< glu::FragmentSource(getFragmentSource())
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												<< glu::TessellationControlSource(getTessellationControlSource())
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												<< glu::TessellationEvaluationSource(getTessellationEvaluationSource())
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												<< glu::GeometrySource(getGeometrySource())
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												<< glu::TransformFeedbackVarying("tf_someVertexPosition")
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												<< glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS));
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_feedbackProgram;
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_feedbackProgram->isOk())
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("failed to build program");
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_nonFeedbackProgram = new glu::ShaderProgram(m_context.getRenderContext(),
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  glu::ProgramSources()
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< glu::VertexSource(getVertexSource())
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< glu::FragmentSource(getFragmentSource())
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< glu::TessellationControlSource(getTessellationControlSource())
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< glu::TessellationEvaluationSource(getTessellationEvaluationSource())
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													<< glu::GeometrySource(getGeometrySource()));
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_nonFeedbackProgram->isOk())
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *m_nonFeedbackProgram;
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("failed to build program");
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	genTransformFeedback();
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FeedbackPrimitiveTypeCase::deinit (void)
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_patchBuffer)
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_patchBuffer);
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_patchBuffer = 0;
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_feedbackBuffer)
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_feedbackBuffer);
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_feedbackBuffer = 0;
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_feedbackID)
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteTransformFeedbacks(1, &m_feedbackID);
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_feedbackID = 0;
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_feedbackProgram)
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete m_feedbackProgram;
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_feedbackProgram = DE_NULL;
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_nonFeedbackProgram)
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete m_nonFeedbackProgram;
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_nonFeedbackProgram = DE_NULL;
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9583c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFeedbackPrimitiveTypeCase::IterateResult FeedbackPrimitiveTypeCase::iterate (void)
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface feedbackResult		(RENDER_SIZE, RENDER_SIZE);
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface nonFeedbackResult	(RENDER_SIZE, RENDER_SIZE);
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// render with and without XFB
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	renderWithFeedback(feedbackResult);
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	renderWithoutFeedback(nonFeedbackResult);
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// compare
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool imageOk;
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Comparing the image rendered with no transform feedback against the image rendered with enabled transform feedback." << tcu::TestLog::EndMessage;
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_context.getRenderTarget().getNumSamples() > 1)
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			imageOk = tcu::fuzzyCompare(m_testCtx.getLog(),
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										"ImageCompare",
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										"Image comparison",
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										feedbackResult.getAccess(),
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										nonFeedbackResult.getAccess(),
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										0.03f,
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										tcu::COMPARE_LOG_RESULT);
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			imageOk = tcu::intThresholdPositionDeviationCompare(m_testCtx.getLog(),
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"ImageCompare",
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																"Image comparison",
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																feedbackResult.getAccess(),
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																nonFeedbackResult.getAccess(),
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																tcu::UVec4(8, 8, 8, 255),						//!< threshold
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																tcu::IVec3(1, 1, 0),							//!< 3x3 search kernel
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																true,											//!< fragments may end up over the viewport, just ignore them
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																tcu::COMPARE_LOG_RESULT);
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!imageOk)
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FeedbackPrimitiveTypeCase::renderWithFeedback(tcu::Surface& dst)
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl							= m_context.getRenderContext().getFunctions();
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VertexArray			vao							(m_context.getRenderContext());
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::Query				primitivesGeneratedQuery	(m_context.getRenderContext());
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						posLocation					= gl.getAttribLocation(m_feedbackProgram->getProgram(), "a_position");
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::GLenum				feedbackPrimitiveMode		= getOutputPrimitiveGLType();
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (posLocation == -1)
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("a_position was -1");
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering with transform feedback" << tcu::TestLog::EndMessage;
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport(0, 0, dst.getWidth(), dst.getHeight());
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clear(GL_COLOR_BUFFER_BIT);
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindVertexArray(*vao);
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_ARRAY_BUFFER, m_patchBuffer);
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.enableVertexAttribArray(posLocation);
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "setup attribs");
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_feedbackProgram->getProgram());
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "use program");
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, 4);
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "set patch param");
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.beginQuery(GL_PRIMITIVES_GENERATED, *primitivesGeneratedQuery);
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "begin GL_PRIMITIVES_GENERATED query");
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Begin transform feedback with mode " << glu::getPrimitiveTypeStr(feedbackPrimitiveMode) << tcu::TestLog::EndMessage;
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.beginTransformFeedback(feedbackPrimitiveMode);
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "begin xfb");
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Calling drawArrays with mode GL_PATCHES" << tcu::TestLog::EndMessage;
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.drawArrays(GL_PATCHES, 0, 4);
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "draw patches");
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.endTransformFeedback();
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "end xfb");
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.endQuery(GL_PRIMITIVES_GENERATED);
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "end GL_PRIMITIVES_GENERATED query");
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "readPixels");
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// verify GL_PRIMITIVES_GENERATED
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glw::GLuint primitivesGeneratedResult = 0;
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.getQueryObjectuiv(*primitivesGeneratedQuery, GL_QUERY_RESULT, &primitivesGeneratedResult);
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "get GL_PRIMITIVES_GENERATED value");
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying GL_PRIMITIVES_GENERATED, expecting " << getNumGeneratedPrimitives() << tcu::TestLog::EndMessage;
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((int)primitivesGeneratedResult != getNumGeneratedPrimitives())
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Error, GL_PRIMITIVES_GENERATED was " << primitivesGeneratedResult << tcu::TestLog::EndMessage;
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected GL_PRIMITIVES_GENERATED");
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "GL_PRIMITIVES_GENERATED valid." << tcu::TestLog::EndMessage;
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// feedback
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::vector<tcu::Vec4>	feedbackResults		(getNumGeneratedElementsPerPrimitive() * getNumGeneratedPrimitives());
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const void*				mappedPtr			= gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, (glw::GLsizeiptr)(feedbackResults.size() * sizeof(tcu::Vec4)), GL_MAP_READ_BIT);
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glw::GLboolean			unmapResult;
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange");
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Reading transform feedback buffer." << tcu::TestLog::EndMessage;
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!mappedPtr)
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("mapBufferRange returned null");
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemcpy(feedbackResults[0].getPtr(), mappedPtr, (int)(feedbackResults.size() * sizeof(tcu::Vec4)));
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		unmapResult = gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "unmapBuffer");
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (unmapResult != GL_TRUE)
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("unmapBuffer failed, did not return true");
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// verify transform results
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		verifyFeedbackResults(feedbackResults);
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// verify feedback results are consistent with rendered image
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		verifyRenderedImage(dst, feedbackResults);
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FeedbackPrimitiveTypeCase::renderWithoutFeedback (tcu::Surface& dst)
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl							= m_context.getRenderContext().getFunctions();
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VertexArray			vao							(m_context.getRenderContext());
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						posLocation					= gl.getAttribLocation(m_nonFeedbackProgram->getProgram(), "a_position");
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (posLocation == -1)
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("a_position was -1");
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering without transform feedback" << tcu::TestLog::EndMessage;
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport(0, 0, dst.getWidth(), dst.getHeight());
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clear(GL_COLOR_BUFFER_BIT);
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindVertexArray(*vao);
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_ARRAY_BUFFER, m_patchBuffer);
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.enableVertexAttribArray(posLocation);
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "setup attribs");
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_nonFeedbackProgram->getProgram());
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "use program");
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, 4);
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "set patch param");
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Calling drawArrays with mode GL_PATCHES" << tcu::TestLog::EndMessage;
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.drawArrays(GL_PATCHES, 0, 4);
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "draw patches");
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "readPixels");
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FeedbackPrimitiveTypeCase::verifyFeedbackResults (const std::vector<tcu::Vec4>& feedbackResult)
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	geometryAmplification	= getGeometryAmplification();
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	elementsPerPrimitive	= getNumGeneratedElementsPerPrimitive();
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	errorFloodThreshold		= 8;
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			readNdx					= 0;
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			numErrors				= 0;
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying feedback results." << tcu::TestLog::EndMessage;
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int tessellatedPrimitiveNdx = 0; tessellatedPrimitiveNdx < getNumTessellatedPrimitives(); ++tessellatedPrimitiveNdx)
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	primitiveVertex = feedbackResult[readNdx];
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// check the generated vertices are in the proper range (range: -0.4 <-> 0.4)
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	equalThreshold	=	1.0e-6f;
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool	centroidOk		=	(primitiveVertex.x() >= -0.4f - equalThreshold) &&
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											(primitiveVertex.x() <=  0.4f + equalThreshold) &&
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											(primitiveVertex.y() >= -0.4f - equalThreshold) &&
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											(primitiveVertex.y() <=  0.4f + equalThreshold) &&
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											(de::abs(primitiveVertex.z()) < equalThreshold) &&
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											(de::abs(primitiveVertex.w() - 1.0f) < equalThreshold);
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!centroidOk && numErrors++ < errorFloodThreshold)
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog()
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::Message
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Element at index " << (readNdx) << " (tessellation invocation " << tessellatedPrimitiveNdx << ")\n"
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "\texpected vertex in range: ( [-0.4, 0.4], [-0.4, 0.4], 0.0, 1.0 )\n"
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "\tgot: " << primitiveVertex
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::EndMessage;
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid feedback output");
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				++readNdx;
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// check all other primitives generated from this tessellated primitive have the same feedback value
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int generatedPrimitiveNdx = 0; generatedPrimitiveNdx < geometryAmplification; ++generatedPrimitiveNdx)
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int primitiveVertexNdx = 0; primitiveVertexNdx < elementsPerPrimitive; ++primitiveVertexNdx)
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4 generatedElementVertex	= feedbackResult[readNdx];
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4 equalThreshold			(1.0e-6f);
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (tcu::boolAny(tcu::greaterThan(tcu::abs(primitiveVertex - generatedElementVertex), equalThreshold)))
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (numErrors++ < errorFloodThreshold)
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog()
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< tcu::TestLog::Message
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "Element at index " << (readNdx) << " (tessellation invocation " << tessellatedPrimitiveNdx << ", geometry primitive " << generatedPrimitiveNdx << ", emitted vertex " << primitiveVertexNdx << "):\n"
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "\tfeedback result was not contant over whole primitive.\n"
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "\tfirst emitted value: " << primitiveVertex << "\n"
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "\tcurrent emitted value:" << generatedElementVertex << "\n"
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< tcu::TestLog::EndMessage;
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got multiple different feedback values for a single primitive");
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			readNdx++;
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numErrors > errorFloodThreshold)
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Omitted " << (numErrors - errorFloodThreshold) << " error(s)." << tcu::TestLog::EndMessage;
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool feedbackResultCompare (const tcu::Vec4& a, const tcu::Vec4& b)
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (a.x() < b.x())
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (a.x() > b.x())
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return a.y() < b.y();
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FeedbackPrimitiveTypeCase::verifyRenderedImage (const tcu::Surface& image, const std::vector<tcu::Vec4>& tfVertices)
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<tcu::Vec4> vertices;
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Comparing result image against feedback results." << tcu::TestLog::EndMessage;
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check only unique vertices
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::unique_copy(tfVertices.begin(), tfVertices.end(), std::back_insert_iterator<std::vector<tcu::Vec4> >(vertices));
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::sort(vertices.begin(), vertices.end(), feedbackResultCompare);
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertices.erase(std::unique(vertices.begin(), vertices.end()), vertices.end());
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verifying vertices recorded with feedback actually ended up on the result image
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)vertices.size(); ++ndx)
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Rasterization (of lines) may deviate by one pixel. In addition to that, allow minimal errors in rasterized position vs. feedback result.
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// This minimal error could result in a difference in rounding => allow one additional pixel in deviation
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			rasterDeviation	= 2;
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::IVec2	rasterPos		((int)deFloatRound((vertices[ndx].x() * 0.5f + 0.5f) * image.getWidth()), (int)deFloatRound((vertices[ndx].y() * 0.5f + 0.5f) * image.getHeight()));
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Find produced rasterization results
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool				found			= false;
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int dy = -rasterDeviation; dy <= rasterDeviation && !found; ++dy)
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int dx = -rasterDeviation; dx <= rasterDeviation && !found; ++dx)
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Raster result could end up outside the viewport
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (rasterPos.x() + dx < 0 || rasterPos.x() + dx >= image.getWidth() ||
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				rasterPos.y() + dy < 0 || rasterPos.y() + dy >= image.getHeight())
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				found = true;
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::RGBA result = image.getPixel(rasterPos.x() + dx, rasterPos.y() + dy);
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if(!isBlack(result))
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					found = true;
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!found)
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog()
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< tcu::TestLog::Message
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "Vertex " << vertices[ndx] << "\n"
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "\tCould not find rasterization output for vertex.\n"
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "\tExpected non-black pixels near " << rasterPos
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< tcu::TestLog::EndMessage;
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid result image");
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FeedbackPrimitiveTypeCase::genTransformFeedback (void)
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl						= m_context.getRenderContext().getFunctions();
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						elementsPerPrimitive	= getNumGeneratedElementsPerPrimitive();
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						feedbackPrimitives		= getNumGeneratedPrimitives();
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						feedbackElements		= elementsPerPrimitive * feedbackPrimitives;
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::vector<tcu::Vec4>	initialBuffer			(feedbackElements, tcu::Vec4(-1.0f, -1.0f, -1.0f, -1.0f));
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genTransformFeedbacks(1, &m_feedbackID);
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_feedbackID);
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "gen transform feedback");
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.genBuffers(1, &m_feedbackBuffer);
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_feedbackBuffer);
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(tcu::Vec4) * initialBuffer.size(), initialBuffer[0].getPtr(), GL_STATIC_COPY);
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "gen feedback buffer");
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_feedbackBuffer);
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "bind feedback buffer");
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getTriangleNumOutputPrimitives (int tessellationLevel)
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (tessellationLevel == 1)
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 1;
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (tessellationLevel == 2)
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 6;
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 3 * (2 + 2 * (tessellationLevel - 2)) + getTriangleNumOutputPrimitives(tessellationLevel - 2);
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getTriangleNumOutputPrimitivesPoints (int tessellationLevel)
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (tessellationLevel == 0)
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 1;
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (tessellationLevel == 1)
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 3;
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 3 + 3 * (tessellationLevel - 1) + getTriangleNumOutputPrimitivesPoints(tessellationLevel - 2);
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint FeedbackPrimitiveTypeCase::getNumGeneratedElementsPerPrimitive (void) const
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_geometryOutputType == GEOMETRY_OUTPUT_TRIANGLES)
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 3;
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_geometryOutputType == GEOMETRY_OUTPUT_LINES)
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 2;
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_geometryOutputType == GEOMETRY_OUTPUT_POINTS)
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 1;
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint FeedbackPrimitiveTypeCase::getNumGeneratedPrimitives (void) const
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return getNumTessellatedPrimitives() * getGeometryAmplification();
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint FeedbackPrimitiveTypeCase::getNumTessellatedPrimitives (void) const
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int tessellationLevel = 3;
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_tessellationPointMode == TESSELLATION_POINTMODE_OFF)
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_tessellationOutput == TESSELLATION_OUT_TRIANGLES)
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return getTriangleNumOutputPrimitives(tessellationLevel);
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_tessellationOutput == TESSELLATION_OUT_QUADS)
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return tessellationLevel * tessellationLevel * 2; // tessellated as triangles
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_tessellationOutput == TESSELLATION_OUT_ISOLINES)
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return tessellationLevel * tessellationLevel;
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_tessellationPointMode == TESSELLATION_POINTMODE_ON)
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_tessellationOutput == TESSELLATION_OUT_TRIANGLES)
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return getTriangleNumOutputPrimitivesPoints(tessellationLevel);
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_tessellationOutput == TESSELLATION_OUT_QUADS)
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return (tessellationLevel + 1) * (tessellationLevel + 1);
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_tessellationOutput == TESSELLATION_OUT_ISOLINES)
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return tessellationLevel * (tessellationLevel + 1);
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(false);
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return -1;
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint FeedbackPrimitiveTypeCase::getGeometryAmplification (void) const
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int outputAmplification	= (m_geometryOutputType == GEOMETRY_OUTPUT_LINES) ? (2) : (1);
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int numInputVertices		= (m_tessellationPointMode) ? (1) : (m_tessellationOutput == TESSELLATION_OUT_ISOLINES) ? (2) : (3);
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return outputAmplification * numInputVertices;
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglw::GLenum FeedbackPrimitiveTypeCase::getOutputPrimitiveGLType (void) const
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_geometryOutputType == GEOMETRY_OUTPUT_TRIANGLES)
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return GL_TRIANGLES;
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_geometryOutputType == GEOMETRY_OUTPUT_LINES)
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return GL_LINES;
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_geometryOutputType == GEOMETRY_OUTPUT_POINTS)
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return GL_POINTS;
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* FeedbackPrimitiveTypeCase::getVertexSource (void) const
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_positionVertexShader;
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* FeedbackPrimitiveTypeCase::getFragmentSource (void) const
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_whiteOutputFragmentShader;
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string FeedbackPrimitiveTypeCase::getTessellationControlSource (void) const
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"#version 310 es\n"
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_tessellation_shader : require\n"
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(vertices = 9) out;\n"
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform highp float u_innerTessellationLevel;\n"
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform highp float u_outerTessellationLevel;\n"
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	if (gl_PatchVerticesIn != 4)\n"
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		return;\n"
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	// Convert input 2x2 grid to 3x3 grid\n"
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	float xweight = float(gl_InvocationID % 3) / 2.0f;\n"
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	float yweight = float(gl_InvocationID / 3) / 2.0f;\n"
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	vec4 y0 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, yweight);\n"
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	vec4 y1 = mix(gl_in[2].gl_Position, gl_in[3].gl_Position, yweight);\n"
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_out[gl_InvocationID].gl_Position = mix(y0, y1, xweight);\n"
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n";
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_tessellationOutput == TESSELLATION_OUT_TRIANGLES)
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	gl_TessLevelOuter[0] = 3.0;\n"
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[1] = 3.0;\n"
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[2] = 3.0;\n"
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelInner[0] = 3.0;\n";
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_tessellationOutput == TESSELLATION_OUT_QUADS)
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	gl_TessLevelOuter[0] = 3.0;\n"
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[1] = 3.0;\n"
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[2] = 3.0;\n"
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[3] = 3.0;\n"
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelInner[0] = 3.0;\n"
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelInner[1] = 3.0;\n";
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_tessellationOutput == TESSELLATION_OUT_ISOLINES)
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	gl_TessLevelOuter[0] = 3.0;\n"
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_TessLevelOuter[1] = 3.0;\n";
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"}\n";
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string FeedbackPrimitiveTypeCase::getTessellationEvaluationSource (void) const
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"#version 310 es\n"
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_tessellation_shader : require\n"
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout("
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_tessellationOutput == TESSELLATION_OUT_TRIANGLES) ? ("triangles") : (m_tessellationOutput == TESSELLATION_OUT_QUADS) ? ("quads") : ("isolines"))
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ((m_tessellationPointMode) ? (", point_mode") : (""))
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< ") in;\n"
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 v_tessellationCoords;\n"
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	if (gl_PatchVerticesIn != 9)\n"
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		return;\n"
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	vec4 patchCentroid = vec4(0.0);\n"
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	for (int ndx = 0; ndx < gl_PatchVerticesIn; ++ndx)\n"
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		patchCentroid += gl_in[ndx].gl_Position;\n"
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	patchCentroid /= patchCentroid.w;\n"
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n";
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_tessellationOutput == TESSELLATION_OUT_TRIANGLES)
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	// map barycentric coords to 2d coords\n"
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	const vec3 tessDirX = vec3( 0.4,  0.4, 0.0);\n"
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	const vec3 tessDirY = vec3( 0.0, -0.4, 0.0);\n"
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	const vec3 tessDirZ = vec3(-0.4,  0.4, 0.0);\n"
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_Position = patchCentroid + vec4(gl_TessCoord.x * tessDirX + gl_TessCoord.y * tessDirY + gl_TessCoord.z * tessDirZ, 0.0);\n";
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_tessellationOutput == TESSELLATION_OUT_QUADS || m_tessellationOutput == TESSELLATION_OUT_ISOLINES)
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	gl_Position = patchCentroid + vec4(gl_TessCoord.x * 0.8 - 0.4, gl_TessCoord.y * 0.8 - 0.4, 0.0, 0.0);\n";
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"	v_tessellationCoords = vec4(gl_TessCoord, 0.0);\n"
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string FeedbackPrimitiveTypeCase::getGeometrySource (void) const
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const	geometryInputPrimitive			= (m_tessellationPointMode) ? ("points") : (m_tessellationOutput == TESSELLATION_OUT_ISOLINES) ? ("lines") : ("triangles");
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const	geometryOutputPrimitive			= (m_geometryOutputType == GEOMETRY_OUTPUT_POINTS) ? ("points") : (m_geometryOutputType == GEOMETRY_OUTPUT_LINES) ? ("line_strip") : ("triangle_strip");
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numInputVertices				= (m_tessellationPointMode) ? (1) : (m_tessellationOutput == TESSELLATION_OUT_ISOLINES) ? (2) : (3);
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numSingleVertexOutputVertices	= (m_geometryOutputType == GEOMETRY_OUTPUT_POINTS) ? (1) : (m_geometryOutputType == GEOMETRY_OUTPUT_LINES) ? (4) : (3);
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numEmitVertices					= numInputVertices * numSingleVertexOutputVertices;
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream	buf;
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"#version 310 es\n"
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_geometry_shader : require\n"
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(" << geometryInputPrimitive << ") in;\n"
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(" << geometryOutputPrimitive << ", max_vertices=" << numEmitVertices <<") out;\n"
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in highp vec4 v_tessellationCoords[];\n"
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 tf_someVertexPosition;\n"
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	// Emit primitive\n"
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	for (int ndx = 0; ndx < gl_in.length(); ++ndx)\n"
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	{\n";
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (m_geometryOutputType)
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GEOMETRY_OUTPUT_POINTS:
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf <<	"		// Draw point on vertex\n"
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		gl_Position = gl_in[ndx].gl_Position;\n"
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		tf_someVertexPosition = gl_in[gl_in.length() - 1].gl_Position;\n"
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		EmitVertex();\n";
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GEOMETRY_OUTPUT_LINES:
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf <<	"		// Draw cross on vertex\n"
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		gl_Position = gl_in[ndx].gl_Position + vec4(-0.02, -0.02, 0.0, 0.0);\n"
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		tf_someVertexPosition = gl_in[gl_in.length() - 1].gl_Position;\n"
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		EmitVertex();\n"
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		gl_Position = gl_in[ndx].gl_Position + vec4( 0.02,  0.02, 0.0, 0.0);\n"
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		tf_someVertexPosition = gl_in[gl_in.length() - 1].gl_Position;\n"
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		EmitVertex();\n"
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		EndPrimitive();\n"
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		gl_Position = gl_in[ndx].gl_Position + vec4( 0.02, -0.02, 0.0, 0.0);\n"
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		tf_someVertexPosition = gl_in[gl_in.length() - 1].gl_Position;\n"
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		EmitVertex();\n"
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		gl_Position = gl_in[ndx].gl_Position + vec4(-0.02,  0.02, 0.0, 0.0);\n"
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		tf_someVertexPosition = gl_in[gl_in.length() - 1].gl_Position;\n"
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		EmitVertex();\n"
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		EndPrimitive();\n";
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GEOMETRY_OUTPUT_TRIANGLES:
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf <<	"		// Draw triangle on vertex\n"
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		gl_Position = gl_in[ndx].gl_Position + vec4(  0.00, -0.02, 0.0, 0.0);\n"
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		tf_someVertexPosition = gl_in[gl_in.length() - 1].gl_Position;\n"
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		EmitVertex();\n"
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		gl_Position = gl_in[ndx].gl_Position + vec4(  0.02,  0.00, 0.0, 0.0);\n"
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		tf_someVertexPosition = gl_in[gl_in.length() - 1].gl_Position;\n"
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		EmitVertex();\n"
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		gl_Position = gl_in[ndx].gl_Position + vec4( -0.02,  0.00, 0.0, 0.0);\n"
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		tf_someVertexPosition = gl_in[gl_in.length() - 1].gl_Position;\n"
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		EmitVertex();\n"
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"		EndPrimitive();\n";
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return "";
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"	}\n"
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* FeedbackPrimitiveTypeCase::getTessellationOutputDescription (TessellationOutputType tessellationOutput, TessellationPointMode pointMode)
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (tessellationOutput)
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSELLATION_OUT_TRIANGLES:	return (pointMode) ? ("points (triangles in point mode)") : ("triangles");
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSELLATION_OUT_QUADS:		return (pointMode) ? ("points (quads in point mode)")     : ("quads");
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSELLATION_OUT_ISOLINES:		return (pointMode) ? ("points (isolines in point mode)")  : ("isolines");
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* FeedbackPrimitiveTypeCase::getGeometryInputDescription (TessellationOutputType tessellationOutput, TessellationPointMode pointMode)
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (tessellationOutput)
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSELLATION_OUT_TRIANGLES:	return (pointMode) ? ("points") : ("triangles");
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSELLATION_OUT_QUADS:		return (pointMode) ? ("points") : ("triangles");
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TESSELLATION_OUT_ISOLINES:		return (pointMode) ? ("points") : ("lines");
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* FeedbackPrimitiveTypeCase::getGeometryOutputDescription (GeometryOutputType geometryOutput)
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (geometryOutput)
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GEOMETRY_OUTPUT_POINTS:		return "points";
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GEOMETRY_OUTPUT_LINES:			return "lines";
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case GEOMETRY_OUTPUT_TRIANGLES:		return "triangles";
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PointSizeCase : public TestCase
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum Flags
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_VERTEX_SET						= 0x01,		// !< set gl_PointSize in vertex shader
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_TESSELLATION_CONTROL_SET		= 0x02,		// !< set gl_PointSize in tessellation evaluation shader
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_TESSELLATION_EVALUATION_SET	= 0x04,		// !< set gl_PointSize in tessellation control shader
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_TESSELLATION_ADD				= 0x08,		// !< read and add to gl_PointSize in tessellation shader pair
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_TESSELLATION_DONT_SET			= 0x10,		// !< don't set gl_PointSize in tessellation shader
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_GEOMETRY_SET					= 0x20,		// !< set gl_PointSize in geometry shader
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_GEOMETRY_ADD					= 0x40,		// !< read and add to gl_PointSize in geometry shader
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_GEOMETRY_DONT_SET				= 0x80,		// !< don't set gl_PointSize in geometry shader
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						PointSizeCase					(Context& context, const char* name, const char* description, int flags);
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						~PointSizeCase					(void);
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static std::string	genTestCaseName					(int flags);
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static std::string	genTestCaseDescription			(int flags);
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				init							(void);
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				deinit							(void);
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult		iterate							(void);
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				checkExtensions					(void) const;
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				checkPointSizeRequirements		(void) const;
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				renderTo						(tcu::Surface& dst);
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				verifyImage						(const tcu::Surface& src);
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					getExpectedPointSize			(void) const;
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			genVertexSource					(void) const;
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			genFragmentSource				(void) const;
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			genTessellationControlSource	(void) const;
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			genTessellationEvaluationSource	(void) const;
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			genGeometrySource				(void) const;
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		RENDER_SIZE = 32,
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			m_flags;
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*	m_program;
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16423c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPointSizeCase::PointSizeCase (Context& context, const char* name, const char* description, int flags)
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase	(context, name, description)
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_flags	(flags)
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program	(DE_NULL)
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16493c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPointSizeCase::~PointSizeCase (void)
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string PointSizeCase::genTestCaseName (int flags)
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// join per-bit descriptions into a single string with '_' separator
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_VERTEX_SET)					buf																		<< "vertex_set";
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_TESSELLATION_CONTROL_SET)		buf << ((flags & (FLAG_TESSELLATION_CONTROL_SET-1))		? ("_") : (""))	<< "control_set";
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_TESSELLATION_EVALUATION_SET)	buf << ((flags & (FLAG_TESSELLATION_EVALUATION_SET-1))	? ("_") : (""))	<< "evaluation_set";
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_TESSELLATION_ADD)				buf << ((flags & (FLAG_TESSELLATION_ADD-1))				? ("_") : (""))	<< "control_pass_eval_add";
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_TESSELLATION_DONT_SET)			buf << ((flags & (FLAG_TESSELLATION_DONT_SET-1))		? ("_") : (""))	<< "eval_default";
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_GEOMETRY_SET)					buf << ((flags & (FLAG_GEOMETRY_SET-1))					? ("_") : (""))	<< "geometry_set";
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_GEOMETRY_ADD)					buf << ((flags & (FLAG_GEOMETRY_ADD-1))					? ("_") : (""))	<< "geometry_add";
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_GEOMETRY_DONT_SET)				buf << ((flags & (FLAG_GEOMETRY_DONT_SET-1))			? ("_") : (""))	<< "geometry_default";
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string PointSizeCase::genTestCaseDescription (int flags)
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// join per-bit descriptions into a single string with ", " separator
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_VERTEX_SET)					buf																			<< "set point size in vertex shader";
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_TESSELLATION_CONTROL_SET)		buf << ((flags & (FLAG_TESSELLATION_CONTROL_SET-1))		? (", ") : (""))	<< "set point size in tessellation control shader";
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_TESSELLATION_EVALUATION_SET)	buf << ((flags & (FLAG_TESSELLATION_EVALUATION_SET-1))	? (", ") : (""))	<< "set point size in tessellation evaluation shader";
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_TESSELLATION_ADD)				buf << ((flags & (FLAG_TESSELLATION_ADD-1))				? (", ") : (""))	<< "add to point size in tessellation shader";
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_TESSELLATION_DONT_SET)			buf << ((flags & (FLAG_TESSELLATION_DONT_SET-1))		? (", ") : (""))	<< "don't set point size in tessellation evaluation shader";
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_GEOMETRY_SET)					buf << ((flags & (FLAG_GEOMETRY_SET-1))					? (", ") : (""))	<< "set point size in geometry shader";
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_GEOMETRY_ADD)					buf << ((flags & (FLAG_GEOMETRY_ADD-1))					? (", ") : (""))	<< "add to point size in geometry shader";
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & FLAG_GEOMETRY_DONT_SET)				buf << ((flags & (FLAG_GEOMETRY_DONT_SET-1))			? (", ") : (""))	<< "don't set point size in geometry shader";
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PointSizeCase::init (void)
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkExtensions();
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	checkPointSizeRequirements();
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// log
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_VERTEX_SET)
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Setting point size in vertex shader to 2.0." << tcu::TestLog::EndMessage;
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_TESSELLATION_CONTROL_SET)
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Setting point size in tessellation control shader to 4.0. (And ignoring it in evaluation)." << tcu::TestLog::EndMessage;
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_TESSELLATION_EVALUATION_SET)
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Setting point size in tessellation evaluation shader to 4.0." << tcu::TestLog::EndMessage;
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_TESSELLATION_ADD)
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Reading point size in tessellation control shader and adding 2.0 to it in evaluation." << tcu::TestLog::EndMessage;
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_TESSELLATION_DONT_SET)
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Not setting point size in tessellation evaluation shader (resulting in the default point size)." << tcu::TestLog::EndMessage;
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_GEOMETRY_SET)
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Setting point size in geometry shader to 6.0." << tcu::TestLog::EndMessage;
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_GEOMETRY_ADD)
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Reading point size in geometry shader and adding 2.0." << tcu::TestLog::EndMessage;
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_GEOMETRY_DONT_SET)
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Not setting point size in geometry shader (resulting in the default point size)." << tcu::TestLog::EndMessage;
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// program
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::ProgramSources sources;
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources	<< glu::VertexSource(genVertexSource())
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::FragmentSource(genFragmentSource());
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_flags & (FLAG_TESSELLATION_CONTROL_SET | FLAG_TESSELLATION_EVALUATION_SET | FLAG_TESSELLATION_ADD | FLAG_TESSELLATION_DONT_SET))
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sources << glu::TessellationControlSource(genTessellationControlSource())
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< glu::TessellationEvaluationSource(genTessellationEvaluationSource());
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_flags & (FLAG_GEOMETRY_SET | FLAG_GEOMETRY_ADD | FLAG_GEOMETRY_DONT_SET))
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sources << glu::GeometrySource(genGeometrySource());
17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_program = new glu::ShaderProgram(m_context.getRenderContext(), sources);
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *m_program;
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_program->isOk())
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("failed to build program");
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PointSizeCase::deinit (void)
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = DE_NULL;
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17403c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPointSizeCase::IterateResult PointSizeCase::iterate (void)
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface resultImage(RENDER_SIZE, RENDER_SIZE);
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	renderTo(resultImage);
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (verifyImage(resultImage))
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PointSizeCase::checkExtensions (void) const
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<std::string>	requiredExtensions;
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool						allOk				= true;
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & (FLAG_TESSELLATION_CONTROL_SET | FLAG_TESSELLATION_EVALUATION_SET | FLAG_TESSELLATION_ADD | FLAG_TESSELLATION_DONT_SET))
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		requiredExtensions.push_back("GL_EXT_tessellation_shader");
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & (FLAG_TESSELLATION_CONTROL_SET | FLAG_TESSELLATION_EVALUATION_SET | FLAG_TESSELLATION_ADD))
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		requiredExtensions.push_back("GL_EXT_tessellation_point_size");
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & (m_flags & (FLAG_GEOMETRY_SET | FLAG_GEOMETRY_ADD | FLAG_GEOMETRY_DONT_SET)))
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		requiredExtensions.push_back("GL_EXT_geometry_shader");
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & (m_flags & (FLAG_GEOMETRY_SET | FLAG_GEOMETRY_ADD)))
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		requiredExtensions.push_back("GL_EXT_geometry_point_size");
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < (int)requiredExtensions.size(); ++ndx)
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_context.getContextInfo().isExtensionSupported(requiredExtensions[ndx].c_str()))
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			allOk = false;
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!allOk)
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::ostringstream extensionList;
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < (int)requiredExtensions.size(); ++ndx)
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (ndx != 0)
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				extensionList << ", ";
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			extensionList << requiredExtensions[ndx];
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires {" + extensionList.str() + "} extension(s)");
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PointSizeCase::checkPointSizeRequirements (void) const
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float					aliasedSizeRange[2]	= { 0.0f, 0.0f };
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				requiredSize		= getExpectedPointSize();
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, aliasedSizeRange);
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (float(requiredSize) > aliasedSizeRange[1])
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires point size " + de::toString(requiredSize));
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PointSizeCase::renderTo (tcu::Surface& dst)
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool				tessellationActive	= (m_flags & (FLAG_TESSELLATION_CONTROL_SET | FLAG_TESSELLATION_EVALUATION_SET | FLAG_TESSELLATION_ADD | FLAG_TESSELLATION_DONT_SET)) != 0;
18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				positionLocation	= gl.getAttribLocation(m_program->getProgram(), "a_position");
18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VertexArray	vao					(m_context.getRenderContext());
18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering single point." << tcu::TestLog::EndMessage;
18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (positionLocation == -1)
18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("Attribute a_position location was -1");
18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport(0, 0, RENDER_SIZE, RENDER_SIZE);
18153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
18163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clear(GL_COLOR_BUFFER_BIT);
18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
18183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindVertexArray(*vao);
18203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "bind vao");
18213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_program->getProgram());
18233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "use program");
18243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.vertexAttrib4f(positionLocation, 0.0f, 0.0f, 0.0f, 1.0f);
18263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (tessellationActive)
18283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.patchParameteri(GL_PATCH_VERTICES, 1);
18303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "set patch param");
18313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.drawArrays(GL_PATCHES, 0, 1);
18333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "draw patches");
18343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
18363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.drawArrays(GL_POINTS, 0, 1);
18383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "draw points");
18393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
18423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool PointSizeCase::verifyImage (const tcu::Surface& src)
18453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool MSAATarget	= (m_context.getRenderTarget().getNumSamples() > 1);
18473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int expectedSize	= getExpectedPointSize();
18483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying rendered point size. Expecting " << expectedSize << " pixels." << tcu::TestLog::EndMessage;
18503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Image("RenderImage", "Rendered image", src.getAccess());
18513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool		resultAreaFound	= false;
18543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::IVec4	resultArea;
18553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Find rasterization output area
18573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int y = 0; y < src.getHeight(); ++y)
18593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < src.getWidth();  ++x)
18603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!isBlack(src.getPixel(x, y)))
18623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!resultAreaFound)
18643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
18653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// first fragment
18663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					resultArea = tcu::IVec4(x, y, x + 1, y + 1);
18673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					resultAreaFound = true;
18683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
18693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
18703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
18713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// union area
18723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					resultArea.x() = de::min(resultArea.x(), x);
18733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					resultArea.y() = de::min(resultArea.y(), y);
18743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					resultArea.z() = de::max(resultArea.z(), x+1);
18753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					resultArea.w() = de::max(resultArea.w(), y+1);
18763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
18773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!resultAreaFound)
18813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << tcu::TestLog::Message << "Verification failed, could not find any point fragments." << tcu::TestLog::EndMessage;
18833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
18843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// verify area size
18873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (MSAATarget)
18883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::IVec2 pointSize = resultArea.swizzle(2,3) - resultArea.swizzle(0, 1);
18903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// MSAA: edges may be a little fuzzy
18923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (de::abs(pointSize.x() - pointSize.y()) > 1)
18933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "ERROR! Rasterized point is not a square. Detected point size was " << pointSize << tcu::TestLog::EndMessage;
18953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
18963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// MSAA may produce larger areas, allow one pixel larger
18993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (expectedSize != de::max(pointSize.x(), pointSize.y()) && (expectedSize+1) != de::max(pointSize.x(), pointSize.y()))
19003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "ERROR! Point size invalid, expected " << expectedSize << ", got " << de::max(pointSize.x(), pointSize.y()) << tcu::TestLog::EndMessage;
19023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
19033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
19063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
19073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::IVec2 pointSize = resultArea.swizzle(2,3) - resultArea.swizzle(0, 1);
19083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (pointSize.x() != pointSize.y())
19103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "ERROR! Rasterized point is not a square. Point size was " << pointSize << tcu::TestLog::EndMessage;
19123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
19133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (pointSize.x() != expectedSize)
19163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
19173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "ERROR! Point size invalid, expected " << expectedSize << ", got " << pointSize.x() << tcu::TestLog::EndMessage;
19183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
19193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
19243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint PointSizeCase::getExpectedPointSize (void) const
19273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int addition = 0;
19293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// geometry
19313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_GEOMETRY_DONT_SET)
19323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 1;
19333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_flags & FLAG_GEOMETRY_SET)
19343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 6;
19353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_flags & FLAG_GEOMETRY_ADD)
19363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addition += 2;
19373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// tessellation
19393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_TESSELLATION_EVALUATION_SET)
19403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 4 + addition;
19413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_flags & FLAG_TESSELLATION_ADD)
19423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addition += 2;
19433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_flags & (FLAG_TESSELLATION_CONTROL_SET | FLAG_TESSELLATION_DONT_SET))
19443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT((m_flags & FLAG_GEOMETRY_ADD) == 0); // reading pointSize undefined
19463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 1;
19473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// vertex
19503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_VERTEX_SET)
19513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 2 + addition;
19523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// undefined
19543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(false);
19553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return -1;
19563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string PointSizeCase::genVertexSource (void) const
19593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
19613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "#version 310 es\n"
19633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "in highp vec4 a_position;\n"
19643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main ()\n"
19653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
19663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	gl_Position = a_position;\n";
19673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_VERTEX_SET)
19693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "	gl_PointSize = 2.0;\n";
19703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "}\n";
19723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
19743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* PointSizeCase::genFragmentSource (void) const
19773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_whiteOutputFragmentShader;
19793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string PointSizeCase::genTessellationControlSource (void) const
19823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
19843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "#version 310 es\n"
19863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "#extension GL_EXT_tessellation_shader : require\n"
19873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((m_flags & FLAG_TESSELLATION_DONT_SET) ? ("") : ("#extension GL_EXT_tessellation_point_size : require\n"))
19883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout(vertices = 1) out;\n"
19893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main ()\n"
19903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
19913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	gl_TessLevelOuter[0] = 3.0;\n"
19923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	gl_TessLevelOuter[1] = 3.0;\n"
19933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	gl_TessLevelOuter[2] = 3.0;\n"
19943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	gl_TessLevelInner[0] = 3.0;\n"
19953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n";
19963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_TESSELLATION_ADD)
19983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "	// pass as is to eval\n"
19993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n";
20003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_flags & FLAG_TESSELLATION_CONTROL_SET)
20013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "	// thrown away\n"
20023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	gl_out[gl_InvocationID].gl_PointSize = 4.0;\n";
20033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "}\n";
20053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
20073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string PointSizeCase::genTessellationEvaluationSource (void) const
20103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
20123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "#version 310 es\n"
20143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "#extension GL_EXT_tessellation_shader : require\n"
20153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((m_flags & FLAG_TESSELLATION_DONT_SET) ? ("") : ("#extension GL_EXT_tessellation_point_size : require\n"))
20163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout(triangles, point_mode) in;\n"
20173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main ()\n"
20183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n"
20193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	// hide all but one vertex\n"
20203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	if (gl_TessCoord.x < 0.99)\n"
20213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "		gl_Position = vec4(-2.0, 0.0, 0.0, 1.0);\n"
20223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "	else\n"
20233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "		gl_Position = gl_in[0].gl_Position;\n";
20243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_TESSELLATION_ADD)
20263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "\n"
20273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	// add to point size\n"
20283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	gl_PointSize = gl_in[0].gl_PointSize + 2.0;\n";
20293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_flags & FLAG_TESSELLATION_EVALUATION_SET)
20303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf << "\n"
20313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	// set point size\n"
20323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	gl_PointSize = 4.0;\n";
20333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "}\n";
20353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
20373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string PointSizeCase::genGeometrySource (void) const
20403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
20423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "#version 310 es\n"
20443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "#extension GL_EXT_geometry_shader : require\n"
20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< ((m_flags & FLAG_GEOMETRY_DONT_SET) ? ("") : ("#extension GL_EXT_geometry_point_size : require\n"))
20463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (points) in;\n"
20473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "layout (points, max_vertices=1) out;\n"
20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "\n"
20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "void main ()\n"
20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "{\n";
20513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_GEOMETRY_SET)
20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf	<< "	gl_Position = gl_in[0].gl_Position;\n"
20543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	gl_PointSize = 6.0;\n";
20553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_flags & FLAG_GEOMETRY_ADD)
20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf	<< "	gl_Position = gl_in[0].gl_Position;\n"
20573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "	gl_PointSize = gl_in[0].gl_PointSize + 2.0;\n";
20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_flags & FLAG_GEOMETRY_DONT_SET)
20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf	<< "	gl_Position = gl_in[0].gl_Position;\n";
20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<< "	EmitVertex();\n"
20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "}\n";
20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AllowedRenderFailureException : public std::runtime_error
20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	AllowedRenderFailureException (const char* message) : std::runtime_error(message) { }
20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass GridRenderCase : public TestCase
20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
20753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum Flags
20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_TESSELLATION_MAX_SPEC						= 0x0001,
20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_TESSELLATION_MAX_IMPLEMENTATION			= 0x0002,
20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_GEOMETRY_MAX_SPEC							= 0x0004,
20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_GEOMETRY_MAX_IMPLEMENTATION				= 0x0008,
20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_GEOMETRY_INVOCATIONS_MAX_SPEC				= 0x0010,
20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_GEOMETRY_INVOCATIONS_MAX_IMPLEMENTATION	= 0x0020,
20843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_GEOMETRY_SCATTER_INSTANCES					= 0x0040,
20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_GEOMETRY_SCATTER_PRIMITIVES				= 0x0080,
20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_GEOMETRY_SEPARATE_PRIMITIVES				= 0x0100, //!< if set, geometry shader outputs separate grid cells and not continuous slices
20883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_GEOMETRY_SCATTER_LAYERS					= 0x0200,
20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		FLAG_ALLOW_OUT_OF_MEMORY						= 0x0400, //!< allow draw command to set GL_OUT_OF_MEMORY
20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						GridRenderCase					(Context& context, const char* name, const char* description, int flags);
20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						~GridRenderCase					(void);
20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				init							(void);
20983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				deinit							(void);
20993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult		iterate							(void);
21003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				renderTo						(std::vector<tcu::Surface>& dst);
21023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				verifyResultLayer				(int layerNdx, const tcu::Surface& dst);
21033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			getVertexSource					(void);
21053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			getFragmentSource				(void);
21063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			getTessellationControlSource	(int tessLevel);
21073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			getTessellationEvaluationSource	(int tessLevel);
21083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			getGeometryShaderSource			(int numPrimitives, int numInstances, int tessLevel);
21093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum
21113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		RENDER_SIZE = 256
21133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
21143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			m_flags;
21163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*	m_program;
21183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32			m_texture;
21193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					m_numLayers;
21203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
21213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21223c827367444ee418f129b2c238299f49d3264554Jarkko PoyryGridRenderCase::GridRenderCase (Context& context, const char* name, const char* description, int flags)
21233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase		(context, name, description)
21243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_flags		(flags)
21253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program		(DE_NULL)
21263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_texture		(0)
21273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numLayers	(1)
21283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(((m_flags & FLAG_TESSELLATION_MAX_SPEC) == 0)			|| ((m_flags & FLAG_TESSELLATION_MAX_IMPLEMENTATION) == 0));
21303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(((m_flags & FLAG_GEOMETRY_MAX_SPEC) == 0)				|| ((m_flags & FLAG_GEOMETRY_MAX_IMPLEMENTATION) == 0));
21313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(((m_flags & FLAG_GEOMETRY_INVOCATIONS_MAX_SPEC) == 0)	|| ((m_flags & FLAG_GEOMETRY_INVOCATIONS_MAX_IMPLEMENTATION) == 0));
21323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(((m_flags & (FLAG_GEOMETRY_SCATTER_PRIMITIVES | FLAG_GEOMETRY_SCATTER_LAYERS)) != 0) == ((m_flags & FLAG_GEOMETRY_SEPARATE_PRIMITIVES) != 0));
21333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21353c827367444ee418f129b2c238299f49d3264554Jarkko PoyryGridRenderCase::~GridRenderCase (void)
21363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
21383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid GridRenderCase::init (void)
21413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
21433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Requirements
21453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader") ||
21473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
21483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader and GL_EXT_geometry_shader extensions");
21493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((m_flags & FLAG_GEOMETRY_SCATTER_LAYERS) == 0)
21513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_context.getRenderTarget().getWidth() < RENDER_SIZE ||
21533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_context.getRenderTarget().getHeight() < RENDER_SIZE)
21543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::NotSupportedError("Test requires " + de::toString<int>(RENDER_SIZE) + "x" + de::toString<int>(RENDER_SIZE) + " or larger render target.");
21553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Log
21583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog()
21603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::Message
21613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "Testing tessellation and geometry shaders that output a large number of primitives.\n"
21623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< getDescription()
21633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< tcu::TestLog::EndMessage;
21643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Render target
21663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_GEOMETRY_SCATTER_LAYERS)
21673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// set limits
21693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_numLayers = 8;
21703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Rendering to 2d texture array, numLayers = " << m_numLayers << tcu::TestLog::EndMessage;
21723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genTextures(1, &m_texture);
21743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
21753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, RENDER_SIZE, RENDER_SIZE, m_numLayers);
21763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
21783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
21793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
21803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
21813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen texture");
21833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Gen program
21863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::ProgramSources	sources;
21883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int					tessGenLevel = -1;
21893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sources	<< glu::VertexSource(getVertexSource())
21913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< glu::FragmentSource(getFragmentSource());
21923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Tessellation limits
21943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
21953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_flags & FLAG_TESSELLATION_MAX_IMPLEMENTATION)
21963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
21973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.getIntegerv(GL_MAX_TESS_GEN_LEVEL, &tessGenLevel);
21983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				GLU_EXPECT_NO_ERROR(gl.getError(), "query tessellation limits");
21993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_flags & FLAG_TESSELLATION_MAX_SPEC)
22013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tessGenLevel = 64;
22033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
22053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tessGenLevel = 5;
22073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog()
22103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::Message
22113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Tessellation level: " << tessGenLevel << ", mode = quad.\n"
22123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "\tEach input patch produces " << (tessGenLevel*tessGenLevel) << " (" << (tessGenLevel*tessGenLevel*2) << " triangles)\n"
22133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::EndMessage;
22143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sources << glu::TessellationControlSource(getTessellationControlSource(tessGenLevel))
22163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< glu::TessellationEvaluationSource(getTessellationEvaluationSource(tessGenLevel));
22173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Geometry limits
22203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		geometryOutputComponents		= -1;
22223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		geometryOutputVertices			= -1;
22233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		geometryTotalOutputComponents	= -1;
22243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		geometryShaderInvocations		= -1;
22253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool	logGeometryLimits				= false;
22263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool	logInvocationLimits				= false;
22273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_flags & FLAG_GEOMETRY_MAX_IMPLEMENTATION)
22293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "Using implementation maximum geometry shader output limits." << tcu::TestLog::EndMessage;
22313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &geometryOutputComponents);
22333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &geometryOutputVertices);
22343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &geometryTotalOutputComponents);
22353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				GLU_EXPECT_NO_ERROR(gl.getError(), "query geometry limits");
22363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				logGeometryLimits = true;
22383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_flags & FLAG_GEOMETRY_MAX_SPEC)
22403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "Using geometry shader extension minimum maximum output limits." << tcu::TestLog::EndMessage;
22423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				geometryOutputComponents = 128;
22443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				geometryOutputVertices = 256;
22453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				geometryTotalOutputComponents = 1024;
22463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				logGeometryLimits = true;
22473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
22493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				geometryOutputComponents = 128;
22513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				geometryOutputVertices = 16;
22523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				geometryTotalOutputComponents = 1024;
22533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_flags & FLAG_GEOMETRY_INVOCATIONS_MAX_IMPLEMENTATION)
22563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS, &geometryShaderInvocations);
22583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				GLU_EXPECT_NO_ERROR(gl.getError(), "query geometry invocation limits");
22593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				logInvocationLimits = true;
22613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_flags & FLAG_GEOMETRY_INVOCATIONS_MAX_SPEC)
22633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				geometryShaderInvocations = 32;
22653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				logInvocationLimits = true;
22663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
22683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				geometryShaderInvocations = 4;
22703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (logGeometryLimits || logInvocationLimits)
22733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::MessageBuilder msg(&m_testCtx.getLog());
22753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				msg << "Geometry shader, targeting following limits:\n";
22773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (logGeometryLimits)
22793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					msg	<< "\tGL_MAX_GEOMETRY_OUTPUT_COMPONENTS = " << geometryOutputComponents << "\n"
22803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "\tGL_MAX_GEOMETRY_OUTPUT_VERTICES = " << geometryOutputVertices << "\n"
22813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< "\tGL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = " << geometryTotalOutputComponents << "\n";
22823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (logInvocationLimits)
22843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					msg << "\tGL_MAX_GEOMETRY_SHADER_INVOCATIONS = " << geometryShaderInvocations;
22853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				msg << tcu::TestLog::EndMessage;
22873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool	separatePrimitives			= (m_flags & FLAG_GEOMETRY_SEPARATE_PRIMITIVES) != 0;
22913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int	numComponentsPerVertex		= 8; // vec4 pos, vec4 color
22923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int			numVerticesPerInvocation;
22933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int			numPrimitivesPerInvocation;
22943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int			geometryVerticesPerPrimitive;
22953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int			geometryPrimitivesOutPerPrimitive;
22963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (separatePrimitives)
22983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
22993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int	numComponentLimit	= geometryTotalOutputComponents / (4 * numComponentsPerVertex);
23003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int	numOutputLimit		= geometryOutputVertices / 4;
23013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numPrimitivesPerInvocation		= de::min(numComponentLimit, numOutputLimit);
23033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numVerticesPerInvocation		= numPrimitivesPerInvocation * 4;
23043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
23053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
23063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
23073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// If FLAG_GEOMETRY_SEPARATE_PRIMITIVES is not set, geometry shader fills a rectangle area in slices.
23083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Each slice is a triangle strip and is generated by a single shader invocation.
23093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// One slice with 4 segment ends (nodes) and 3 segments:
23103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					//    .__.__.__.
23113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					//    |\ |\ |\ |
23123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					//    |_\|_\|_\|
23133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int	numSliceNodesComponentLimit	= geometryTotalOutputComponents / (2 * numComponentsPerVertex);			// each node 2 vertices
23153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int	numSliceNodesOutputLimit	= geometryOutputVertices / 2;											// each node 2 vertices
23163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int	numSliceNodes				= de::min(numSliceNodesComponentLimit, numSliceNodesOutputLimit);
23173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numVerticesPerInvocation				= numSliceNodes * 2;
23193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numPrimitivesPerInvocation				= (numSliceNodes - 1) * 2;
23203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
23213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				geometryVerticesPerPrimitive = numVerticesPerInvocation * geometryShaderInvocations;
23233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				geometryPrimitivesOutPerPrimitive = numPrimitivesPerInvocation * geometryShaderInvocations;
23243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog()
23263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::Message
23273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Geometry shader:\n"
23283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "\tTotal output vertex count per invocation: " << (numVerticesPerInvocation) << "\n"
23293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "\tTotal output primitive count per invocation: " << (numPrimitivesPerInvocation) << "\n"
23303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "\tNumber of invocations per primitive: " << geometryShaderInvocations << "\n"
23313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "\tTotal output vertex count per input primitive: " << (geometryVerticesPerPrimitive) << "\n"
23323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "\tTotal output primitive count per input primitive: " << (geometryPrimitivesOutPerPrimitive) << "\n"
23333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::EndMessage;
23343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				sources	<< glu::GeometrySource(getGeometryShaderSource(numPrimitivesPerInvocation, geometryShaderInvocations, tessGenLevel));
23363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog()
23383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::Message
23393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "Program:\n"
23403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "\tTotal program output vertices count per input patch: " << (tessGenLevel*tessGenLevel*2 * geometryVerticesPerPrimitive) << "\n"
23413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< "\tTotal program output primitive count per input patch: " << (tessGenLevel*tessGenLevel*2 * geometryPrimitivesOutPerPrimitive) << "\n"
23423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					<< tcu::TestLog::EndMessage;
23433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
23443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
23453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_program = new glu::ShaderProgram(m_context.getRenderContext(), sources);
23473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *m_program;
23483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!m_program->isOk())
23493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("failed to build program");
23503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
23513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
23523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid GridRenderCase::deinit (void)
23543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
23563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = DE_NULL;
23573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_texture)
23593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texture);
23613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_texture = 0;
23623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
23633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
23643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23653c827367444ee418f129b2c238299f49d3264554Jarkko PoyryGridRenderCase::IterateResult GridRenderCase::iterate (void)
23663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<tcu::Surface>	renderedLayers	(m_numLayers);
23683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool						allLayersOk		= true;
23693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_numLayers; ++ndx)
23713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		renderedLayers[ndx].setSize(RENDER_SIZE, RENDER_SIZE);
23723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering single point at the origin. Expecting yellow and green colored grid-like image. (High-frequency grid may appear unicolored)." << tcu::TestLog::EndMessage;
23743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
23763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		renderTo(renderedLayers);
23783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
23793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const AllowedRenderFailureException& ex)
23803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Got accepted failure
23823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog()
23833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Message
23843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Could not render, reason: " << ex.what() << "\n"
23853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "Failure is allowed."
23863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::EndMessage;
23873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
23893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return STOP;
23903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
23913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_numLayers; ++ndx)
23933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		allLayersOk &= verifyResultLayer(ndx, renderedLayers[ndx]);
23943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (allLayersOk)
23963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
23973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
23983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
23993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
24003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
24013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid GridRenderCase::renderTo (std::vector<tcu::Surface>& dst)
24033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl					= m_context.getRenderContext().getFunctions();
24053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						positionLocation	= gl.getAttribLocation(m_program->getProgram(), "a_position");
24063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VertexArray			vao					(m_context.getRenderContext());
24073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::MovePtr<glu::Framebuffer>	fbo;
24083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (positionLocation == -1)
24103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("Attribute a_position location was -1");
24113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport(0, 0, dst.front().getWidth(), dst.front().getHeight());
24133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
24143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
24153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindVertexArray(*vao);
24173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "bind vao");
24183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_program->getProgram());
24203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "use program");
24213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, 1);
24233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "set patch param");
24243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.vertexAttrib4f(positionLocation, 0.0f, 0.0f, 0.0f, 1.0f);
24263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_GEOMETRY_SCATTER_LAYERS)
24283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// clear texture contents
24303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
24313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::Framebuffer clearFbo(m_context.getRenderContext());
24323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindFramebuffer(GL_FRAMEBUFFER, *clearFbo);
24333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int layerNdx = 0; layerNdx < m_numLayers; ++layerNdx)
24353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
24363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.framebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture, 0, layerNdx);
24373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.clear(GL_COLOR_BUFFER_BIT);
24383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
24393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "clear tex contents");
24413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
24423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// create and bind layered fbo
24443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fbo = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
24463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindFramebuffer(GL_FRAMEBUFFER, **fbo);
24483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture, 0);
24493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen fbo");
24503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
24523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// clear viewport
24543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clear(GL_COLOR_BUFFER_BIT);
24553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// draw
24583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glw::GLenum glerror;
24603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.drawArrays(GL_PATCHES, 0, 1);
24623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glerror = gl.getError();
24643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (glerror == GL_OUT_OF_MEMORY && (m_flags & FLAG_ALLOW_OUT_OF_MEMORY))
24653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw AllowedRenderFailureException("got GL_OUT_OF_MEMORY while drawing");
24663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(glerror, "draw patches");
24683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Read layers
24713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_GEOMETRY_SCATTER_LAYERS)
24733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::Framebuffer readFbo(m_context.getRenderContext());
24753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindFramebuffer(GL_FRAMEBUFFER, *readFbo);
24763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int layerNdx = 0; layerNdx < m_numLayers; ++layerNdx)
24783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
24793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.framebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture, 0, layerNdx);
24803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::readPixels(m_context.getRenderContext(), 0, 0, dst[layerNdx].getAccess());
24813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "read pixels");
24823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
24833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
24853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::readPixels(m_context.getRenderContext(), 0, 0, dst.front().getAccess());
24873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "read pixels");
24883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
24903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool GridRenderCase::verifyResultLayer (int layerNdx, const tcu::Surface& image)
24923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask	(image.getWidth(), image.getHeight());
24943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			foundError	= false;
24953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
24973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying output layer " << layerNdx  << tcu::TestLog::EndMessage;
24993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < image.getHeight(); ++y)
25013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < image.getWidth(); ++x)
25023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		threshold	= 8;
25043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::RGBA	color		= image.getPixel(x, y);
25053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Color must be a linear combination of green and yellow
25073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (color.getGreen() < 255 - threshold || color.getBlue() > threshold)
25083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
25093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			errorMask.setPixel(x, y, tcu::RGBA::red);
25103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			foundError = true;
25113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
25123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!foundError)
25153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog()
25173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Message << "Image valid." << tcu::TestLog::EndMessage
25183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::ImageSet("ImageVerification", "Image verification")
25193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Image("Result", "Rendered result", image.getAccess())
25203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::EndImageSet;
25213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return true;
25223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
25243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog()
25263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Message << "Image verification failed, found invalid pixels." << tcu::TestLog::EndMessage
25273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::ImageSet("ImageVerification", "Image verification")
25283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Image("Result", "Rendered result", image.getAccess())
25293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask.getAccess())
25303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< tcu::TestLog::EndImageSet;
25313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
25323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* GridRenderCase::getVertexSource (void)
25363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_positionVertexShader;
25383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* GridRenderCase::getFragmentSource (void)
25413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return	"#version 310 es\n"
25433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"flat in mediump vec4 v_color;\n"
25443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(location = 0) out mediump vec4 fragColor;\n"
25453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
25463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
25473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	fragColor = v_color;\n"
25483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
25493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string GridRenderCase::getTessellationControlSource (int tessLevel)
25523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
25543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"#version 310 es\n"
25563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_tessellation_shader : require\n"
25573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(vertices=1) out;\n"
25583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
25593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main()\n"
25603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
25613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
25623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_TessLevelOuter[0] = " << tessLevel << ".0;\n"
25633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_TessLevelOuter[1] = " << tessLevel << ".0;\n"
25643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_TessLevelOuter[2] = " << tessLevel << ".0;\n"
25653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_TessLevelOuter[3] = " << tessLevel << ".0;\n"
25663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_TessLevelInner[0] = " << tessLevel << ".0;\n"
25673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_TessLevelInner[1] = " << tessLevel << ".0;\n"
25683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
25693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
25713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string GridRenderCase::getTessellationEvaluationSource (int tessLevel)
25743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
25763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"#version 310 es\n"
25783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_tessellation_shader : require\n"
25793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(quads) in;\n"
25803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
25813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out mediump ivec2 v_tessellationGridPosition;\n"
25823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
25833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
25843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n";
25853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & (FLAG_GEOMETRY_SCATTER_INSTANCES | FLAG_GEOMETRY_SCATTER_PRIMITIVES | FLAG_GEOMETRY_SCATTER_LAYERS))
25873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	// Cover only a small area in a corner. The area will be expanded in geometry shader to cover whole viewport\n"
25883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_Position = vec4(gl_TessCoord.x * 0.3 - 1.0, gl_TessCoord.y * 0.3 - 1.0, 0.0, 1.0);\n";
25893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
25903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	// Fill the whole viewport\n"
25913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_Position = vec4(gl_TessCoord.x * 2.0 - 1.0, gl_TessCoord.y * 2.0 - 1.0, 0.0, 1.0);\n";
25923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"	// Calculate position in tessellation grid\n"
25943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	v_tessellationGridPosition = ivec2(round(gl_TessCoord.xy * float(" << tessLevel << ")));\n"
25953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
25963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
25983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string GridRenderCase::getGeometryShaderSource (int numPrimitives, int numInstances, int tessLevel)
26013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
26023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ostringstream buf;
26033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf	<<	"#version 310 es\n"
26053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_geometry_shader : require\n"
26063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(triangles, invocations=" << numInstances << ") in;\n"
26073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(triangle_strip, max_vertices=" << ((m_flags & FLAG_GEOMETRY_SEPARATE_PRIMITIVES) ? (4 * numPrimitives) : (numPrimitives + 2)) << ") out;\n"
26083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
26093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in mediump ivec2 v_tessellationGridPosition[];\n"
26103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"flat out highp vec4 v_color;\n"
26113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
26123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main ()\n"
26133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
26143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	const float equalThreshold = 0.001;\n"
26153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	const float gapOffset = 0.0001; // subdivision performed by the geometry shader might produce gaps. Fill potential gaps by enlarging the output slice a little.\n"
26163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
26173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	// Input triangle is generated from an axis-aligned rectangle by splitting it in half\n"
26183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	// Original rectangle can be found by finding the bounding AABB of the triangle\n"
26193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	vec4 aabb = vec4(min(gl_in[0].gl_Position.x, min(gl_in[1].gl_Position.x, gl_in[2].gl_Position.x)),\n"
26203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	                 min(gl_in[0].gl_Position.y, min(gl_in[1].gl_Position.y, gl_in[2].gl_Position.y)),\n"
26213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	                 max(gl_in[0].gl_Position.x, max(gl_in[1].gl_Position.x, gl_in[2].gl_Position.x)),\n"
26223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	                 max(gl_in[0].gl_Position.y, max(gl_in[1].gl_Position.y, gl_in[2].gl_Position.y)));\n"
26233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
26243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	// Location in tessellation grid\n"
26253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	ivec2 gridPosition = ivec2(min(v_tessellationGridPosition[0], min(v_tessellationGridPosition[1], v_tessellationGridPosition[2])));\n"
26263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
26273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	// Which triangle of the two that split the grid cell\n"
26283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	int numVerticesOnBottomEdge = 0;\n"
26293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	for (int ndx = 0; ndx < 3; ++ndx)\n"
26303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		if (abs(gl_in[ndx].gl_Position.y - aabb.w) < equalThreshold)\n"
26313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"			++numVerticesOnBottomEdge;\n"
26323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	bool isBottomTriangle = numVerticesOnBottomEdge == 2;\n"
26333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n";
26343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_flags & FLAG_GEOMETRY_SCATTER_PRIMITIVES)
26363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// scatter primitives
26383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	// Draw grid cells\n"
26393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	int inputTriangleNdx = gl_InvocationID * 2 + ((isBottomTriangle) ? (1) : (0));\n"
26403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	for (int ndx = 0; ndx < " << numPrimitives << "; ++ndx)\n"
26413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	{\n"
26423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		ivec2 dstGridSize = ivec2(" << tessLevel << " * " << numPrimitives << ", 2 * " << tessLevel << " * " << numInstances << ");\n"
26433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		ivec2 dstGridNdx = ivec2(" << tessLevel << " * ndx + gridPosition.x, " << tessLevel << " * inputTriangleNdx + 2 * gridPosition.y + ndx * 127) % dstGridSize;\n"
26443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		vec4 dstArea;\n"
26453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		dstArea.x = float(dstGridNdx.x) / float(dstGridSize.x) * 2.0 - 1.0 - gapOffset;\n"
26463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		dstArea.y = float(dstGridNdx.y) / float(dstGridSize.y) * 2.0 - 1.0 - gapOffset;\n"
26473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		dstArea.z = float(dstGridNdx.x+1) / float(dstGridSize.x) * 2.0 - 1.0 + gapOffset;\n"
26483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		dstArea.w = float(dstGridNdx.y+1) / float(dstGridSize.y) * 2.0 - 1.0 + gapOffset;\n"
26493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
26503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
26513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
26523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		vec4 outputColor = (((dstGridNdx.y + dstGridNdx.x) % 2) == 0) ? (green) : (yellow);\n"
26533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
26543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = vec4(dstArea.x, dstArea.y, 0.0, 1.0);\n"
26553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_color = outputColor;\n"
26563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
26573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
26583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = vec4(dstArea.x, dstArea.w, 0.0, 1.0);\n"
26593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_color = outputColor;\n"
26603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
26613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
26623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = vec4(dstArea.z, dstArea.y, 0.0, 1.0);\n"
26633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_color = outputColor;\n"
26643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
26653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
26663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = vec4(dstArea.z, dstArea.w, 0.0, 1.0);\n"
26673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_color = outputColor;\n"
26683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
26693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EndPrimitive();\n"
26703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	}\n";
26713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
26723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_flags & FLAG_GEOMETRY_SCATTER_LAYERS)
26733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Number of subrectangle instances = num layers
26753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_numLayers == numInstances * 2);
26763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"	// Draw grid cells, send each primitive to a separate layer\n"
26783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	int baseLayer = gl_InvocationID * 2 + ((isBottomTriangle) ? (1) : (0));\n"
26793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	for (int ndx = 0; ndx < " << numPrimitives << "; ++ndx)\n"
26803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	{\n"
26813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		ivec2 dstGridSize = ivec2(" << tessLevel << " * " << numPrimitives << ", " << tessLevel << ");\n"
26823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		ivec2 dstGridNdx = ivec2((gridPosition.x * " << numPrimitives << " * 7 + ndx)*13, (gridPosition.y * 127 + ndx) * 19) % dstGridSize;\n"
26833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		vec4 dstArea;\n"
26843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		dstArea.x = float(dstGridNdx.x) / float(dstGridSize.x) * 2.0 - 1.0 - gapOffset;\n"
26853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		dstArea.y = float(dstGridNdx.y) / float(dstGridSize.y) * 2.0 - 1.0 - gapOffset;\n"
26863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		dstArea.z = float(dstGridNdx.x+1) / float(dstGridSize.x) * 2.0 - 1.0 + gapOffset;\n"
26873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		dstArea.w = float(dstGridNdx.y+1) / float(dstGridSize.y) * 2.0 - 1.0 + gapOffset;\n"
26883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
26893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
26903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
26913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		vec4 outputColor = (((dstGridNdx.y + dstGridNdx.x) % 2) == 0) ? (green) : (yellow);\n"
26923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
26933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = vec4(dstArea.x, dstArea.y, 0.0, 1.0);\n"
26943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_color = outputColor;\n"
26953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Layer = ((baseLayer + ndx) * 11) % " << m_numLayers << ";\n"
26963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
26973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
26983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = vec4(dstArea.x, dstArea.w, 0.0, 1.0);\n"
26993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_color = outputColor;\n"
27003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Layer = ((baseLayer + ndx) * 11) % " << m_numLayers << ";\n"
27013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
27023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
27033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = vec4(dstArea.z, dstArea.y, 0.0, 1.0);\n"
27043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_color = outputColor;\n"
27053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Layer = ((baseLayer + ndx) * 11) % " << m_numLayers << ";\n"
27063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
27073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
27083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = vec4(dstArea.z, dstArea.w, 0.0, 1.0);\n"
27093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_color = outputColor;\n"
27103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Layer = ((baseLayer + ndx) * 11) % " << m_numLayers << ";\n"
27113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
27123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EndPrimitive();\n"
27133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	}\n";
27143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
27163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
27173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_flags & FLAG_GEOMETRY_SCATTER_INSTANCES)
27183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
27193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf <<	"	// Scatter slices\n"
27203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	int inputTriangleNdx = gl_InvocationID * 2 + ((isBottomTriangle) ? (1) : (0));\n"
27213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	ivec2 srcSliceNdx = ivec2(gridPosition.x, gridPosition.y * " << (numInstances*2) << " + inputTriangleNdx);\n"
27223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	ivec2 dstSliceNdx = ivec2(7 * srcSliceNdx.x, 127 * srcSliceNdx.y) % ivec2(" << tessLevel << ", " << tessLevel << " * " << (numInstances*2) << ");\n"
27233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"\n"
27243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	// Draw slice to the dstSlice slot\n"
27253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	vec4 outputSliceArea;\n"
27263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	outputSliceArea.x = float(dstSliceNdx.x) / float(" << tessLevel << ") * 2.0 - 1.0 - gapOffset;\n"
27273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	outputSliceArea.y = float(dstSliceNdx.y) / float(" << (tessLevel * numInstances * 2) << ") * 2.0 - 1.0 - gapOffset;\n"
27283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	outputSliceArea.z = float(dstSliceNdx.x+1) / float(" << tessLevel << ") * 2.0 - 1.0 + gapOffset;\n"
27293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	outputSliceArea.w = float(dstSliceNdx.y+1) / float(" << (tessLevel * numInstances * 2) << ") * 2.0 - 1.0 + gapOffset;\n";
27303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
27313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
27323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
27333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			buf <<	"	// Fill the input area with slices\n"
27343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	// Upper triangle produces slices only to the upper half of the quad and vice-versa\n"
27353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	float triangleOffset = (isBottomTriangle) ? ((aabb.w + aabb.y) / 2.0) : (aabb.y);\n"
27363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	// Each slice is a invocation\n"
27373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	float sliceHeight = (aabb.w - aabb.y) / float(2 * " << numInstances << ");\n"
27383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	float invocationOffset = float(gl_InvocationID) * sliceHeight;\n"
27393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"\n"
27403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	vec4 outputSliceArea;\n"
27413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	outputSliceArea.x = aabb.x - gapOffset;\n"
27423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	outputSliceArea.y = triangleOffset + invocationOffset - gapOffset;\n"
27433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	outputSliceArea.z = aabb.z + gapOffset;\n"
27443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"	outputSliceArea.w = triangleOffset + invocationOffset + sliceHeight + gapOffset;\n";
27453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
27463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buf <<	"\n"
27483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	// Draw slice\n"
27493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	for (int ndx = 0; ndx < " << ((numPrimitives+2)/2) << "; ++ndx)\n"
27503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	{\n"
27513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
27523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
27533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		vec4 outputColor = (((gl_InvocationID + ndx) % 2) == 0) ? (green) : (yellow);\n"
27543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		float xpos = mix(outputSliceArea.x, outputSliceArea.z, float(ndx) / float(" << (numPrimitives/2) << "));\n"
27553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
27563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = vec4(xpos, outputSliceArea.y, 0.0, 1.0);\n"
27573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_color = outputColor;\n"
27583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
27593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"\n"
27603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		gl_Position = vec4(xpos, outputSliceArea.w, 0.0, 1.0);\n"
27613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		v_color = outputColor;\n"
27623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		EmitVertex();\n"
27633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	}\n";
27643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buf <<	"}\n";
27673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return buf.str();
27693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
27703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FeedbackRecordVariableSelectionCase : public TestCase
27723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
27733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
27743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						FeedbackRecordVariableSelectionCase		(Context& context, const char* name, const char* description);
27753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						~FeedbackRecordVariableSelectionCase	(void);
27763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
27783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				init									(void);
27793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				deinit									(void);
27803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult		iterate									(void);
27813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			getVertexSource							(void);
27833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			getFragmentSource						(void);
27843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			getTessellationControlSource			(void);
27853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			getTessellationEvaluationSource			(void);
27863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			getGeometrySource						(void);
27873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram*	m_program;
27893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32			m_xfbBuf;
27903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
27913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27923c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFeedbackRecordVariableSelectionCase::FeedbackRecordVariableSelectionCase (Context& context, const char* name, const char* description)
27933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase	(context, name, description)
27943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program	(DE_NULL)
27953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_xfbBuf	(0)
27963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
27973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
27983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27993c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFeedbackRecordVariableSelectionCase::~FeedbackRecordVariableSelectionCase (void)
28003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
28023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
28033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FeedbackRecordVariableSelectionCase::init (void)
28053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader") ||
28073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
28083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader and GL_EXT_geometry_shader extensions");
28093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Declaring multiple output variables with the same name in multiple shader stages. Capturing the value of the varying using transform feedback." << tcu::TestLog::EndMessage;
28113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// gen feedback buffer fit for 1 triangle (4 components)
28133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const tcu::Vec4 initialData[3] =
28153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
28163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4(-1.0f, -1.0f, -1.0f, -1.0f),
28173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4(-1.0f, -1.0f, -1.0f, -1.0f),
28183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4(-1.0f, -1.0f, -1.0f, -1.0f),
28193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
28203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
28223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << tcu::TestLog::Message << "Creating buffer for transform feedback. Allocating storage for one triangle. Filling with -1.0" << tcu::TestLog::EndMessage;
28243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.genBuffers(1, &m_xfbBuf);
28263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfbBuf);
28273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, (int)(sizeof(tcu::Vec4[3])), initialData, GL_DYNAMIC_READ);
28283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen xfb buf");
28293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// gen shader
28323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
28333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 << glu::VertexSource(getVertexSource())
28343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 << glu::FragmentSource(getFragmentSource())
28353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 << glu::TessellationControlSource(getTessellationControlSource())
28363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 << glu::TessellationEvaluationSource(getTessellationEvaluationSource())
28373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 << glu::GeometrySource(getGeometrySource())
28383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 << glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS)
28393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 << glu::TransformFeedbackVarying("tf_feedback"));
28403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
28413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
28433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("could not build program");
28443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
28453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FeedbackRecordVariableSelectionCase::deinit (void)
28473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
28493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = DE_NULL;
28503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_xfbBuf)
28523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_xfbBuf);
28543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_xfbBuf = 0;
28553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
28573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28583c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFeedbackRecordVariableSelectionCase::IterateResult FeedbackRecordVariableSelectionCase::iterate (void)
28593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
28613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				posLoc	= gl.getAttribLocation(m_program->getProgram(), "a_position");
28623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::VertexArray	vao		(m_context.getRenderContext());
28633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (posLoc == -1)
28653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("a_position attribute location was -1");
28663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
28683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering a patch of size 1." << tcu::TestLog::EndMessage;
28703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Render and feed back
28723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.viewport(0, 0, 1, 1);
28743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
28753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clear(GL_COLOR_BUFFER_BIT);
28763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
28773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindVertexArray(*vao);
28793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "bindVertexArray");
28803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.vertexAttrib4f(posLoc, 0.0f, 0.0f, 0.0f, 1.0f);
28823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "vertexAttrib4f");
28833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(m_program->getProgram());
28853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "use program");
28863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.patchParameteri(GL_PATCH_VERTICES, 1);
28883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "set patch param");
28893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_xfbBuf);
28913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "bind xfb buf");
28923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.beginTransformFeedback(GL_TRIANGLES);
28943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "beginTransformFeedback");
28953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.drawArrays(GL_PATCHES, 0, 1);
28973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
28983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.endTransformFeedback();
29003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "beginTransformFeedback");
29013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying the value of tf_feedback using transform feedback, expecting (3.0, 3.0, 3.0, 3.0)." << tcu::TestLog::EndMessage;
29033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Read back result (one triangle)
29053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec4	feedbackValues[3];
29073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const void* mapPtr				= gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, (int)sizeof(feedbackValues), GL_MAP_READ_BIT);
29083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange");
29093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (mapPtr == DE_NULL)
29113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("mapBufferRange returned null");
29123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemcpy(feedbackValues, mapPtr, sizeof(feedbackValues));
29143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER) != GL_TRUE)
29163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::TestError("unmapBuffer did not return TRUE");
29173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < 3; ++ndx)
29193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
29203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThan(tcu::abs(feedbackValues[ndx] - tcu::Vec4(3.0f)), tcu::Vec4(0.001f))))
29213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
29223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << tcu::TestLog::Message << "Feedback vertex " << ndx << ": expected (3.0, 3.0, 3.0, 3.0), got " << feedbackValues[ndx] << tcu::TestLog::EndMessage;
29233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected feedback results");
29243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
29253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
29263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
29273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
29293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* FeedbackRecordVariableSelectionCase::getVertexSource (void)
29323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return	"#version 310 es\n"
29343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in highp vec4 a_position;\n"
29353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 tf_feedback;\n"
29363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main()\n"
29373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
29383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_Position = a_position;\n"
29393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	tf_feedback = vec4(1.0, 1.0, 1.0, 1.0);\n"
29403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
29413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* FeedbackRecordVariableSelectionCase::getFragmentSource (void)
29443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return s_whiteOutputFragmentShader;
29463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* FeedbackRecordVariableSelectionCase::getTessellationControlSource (void)
29493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return	"#version 310 es\n"
29513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_tessellation_shader : require\n"
29523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(vertices=3) out;\n"
29533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main()\n"
29543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
29553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
29563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_TessLevelOuter[0] = 1.0;\n"
29573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_TessLevelOuter[1] = 1.0;\n"
29583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_TessLevelOuter[2] = 1.0;\n"
29593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_TessLevelInner[0] = 1.0;\n"
29603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
29613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* FeedbackRecordVariableSelectionCase::getTessellationEvaluationSource (void)
29643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return	"#version 310 es\n"
29663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_tessellation_shader : require\n"
29673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(triangles) in;\n"
29683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 tf_feedback;\n"
29693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main()\n"
29703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
29713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	gl_Position = gl_in[0].gl_Position * gl_TessCoord.x + gl_in[1].gl_Position * gl_TessCoord.y + gl_in[2].gl_Position * gl_TessCoord.z;\n"
29723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	tf_feedback = vec4(2.0, 2.0, 2.0, 2.0);\n"
29733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
29743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* FeedbackRecordVariableSelectionCase::getGeometrySource (void)
29773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return	"#version 310 es\n"
29793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#extension GL_EXT_geometry_shader : require\n"
29803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout (triangles) in;\n"
29813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout (triangle_strip, max_vertices=3) out;\n"
29823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"out highp vec4 tf_feedback;\n"
29833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main()\n"
29843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
29853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	for (int ndx = 0; ndx < 3; ++ndx)\n"
29863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	{\n"
29873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		gl_Position = gl_in[ndx].gl_Position + vec4(float(ndx), float(ndx)*float(ndx), 0.0, 0.0);\n"
29883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		tf_feedback = vec4(3.0, 3.0, 3.0, 3.0);\n"
29893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		EmitVertex();\n"
29903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	}\n"
29913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	EndPrimitive();\n"
29923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
29933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
29963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29973c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTessellationGeometryInteractionTests::TessellationGeometryInteractionTests (Context& context)
29983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "tessellation_geometry_interaction", "Tessellation and geometry shader interaction tests")
29993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
30013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30023c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTessellationGeometryInteractionTests::~TessellationGeometryInteractionTests (void)
30033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
30053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TessellationGeometryInteractionTests::init (void)
30073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* const renderGroup		= new tcu::TestCaseGroup(m_testCtx, "render",		"Various render tests");
30093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* const feedbackGroup		= new tcu::TestCaseGroup(m_testCtx, "feedback",		"Test transform feedback");
30103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestCaseGroup* const pointSizeGroup	= new tcu::TestCaseGroup(m_testCtx, "point_size",	"Test point size");
30113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(renderGroup);
30133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(feedbackGroup);
30143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(pointSizeGroup);
30153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .render
30173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const passthroughGroup	= new tcu::TestCaseGroup(m_testCtx, "passthrough",	"Render various types with either passthrough geometry or tessellation shader");
30193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const limitGroup		= new tcu::TestCaseGroup(m_testCtx, "limits",		"Render with properties near their limits");
30203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const scatterGroup		= new tcu::TestCaseGroup(m_testCtx, "scatter",		"Scatter output primitives");
30213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		renderGroup->addChild(passthroughGroup);
30233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		renderGroup->addChild(limitGroup);
30243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		renderGroup->addChild(scatterGroup);
30253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .passthrough
30273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
30283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// tessellate_tris_passthrough_geometry_no_change
30293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// tessellate_quads_passthrough_geometry_no_change
30303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// tessellate_isolines_passthrough_geometry_no_change
30313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			passthroughGroup->addChild(new IdentityGeometryShaderCase(m_context, "tessellate_tris_passthrough_geometry_no_change",		"Passthrough geometry shader has no effect", IdentityGeometryShaderCase::CASE_TRIANGLES));
30323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			passthroughGroup->addChild(new IdentityGeometryShaderCase(m_context, "tessellate_quads_passthrough_geometry_no_change",		"Passthrough geometry shader has no effect", IdentityGeometryShaderCase::CASE_QUADS));
30333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			passthroughGroup->addChild(new IdentityGeometryShaderCase(m_context, "tessellate_isolines_passthrough_geometry_no_change",	"Passthrough geometry shader has no effect", IdentityGeometryShaderCase::CASE_ISOLINES));
30343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// passthrough_tessellation_geometry_shade_triangles_no_change
30363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// passthrough_tessellation_geometry_shade_lines_no_change
30373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			passthroughGroup->addChild(new IdentityTessellationShaderCase(m_context, "passthrough_tessellation_geometry_shade_triangles_no_change",	"Passthrough tessellation shader has no effect", IdentityTessellationShaderCase::CASE_TRIANGLES));
30383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			passthroughGroup->addChild(new IdentityTessellationShaderCase(m_context, "passthrough_tessellation_geometry_shade_lines_no_change",		"Passthrough tessellation shader has no effect", IdentityTessellationShaderCase::CASE_ISOLINES));
30393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
30403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .limits
30423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
30433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			static const struct LimitCaseDef
30443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
30453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char*	name;
30463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const char*	desc;
30473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int			flags;
30483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			} cases[] =
30493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
30503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Test single limit
30513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
30523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"output_required_max_tessellation",
30533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"Minimum maximum tessellation level",
30543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					GridRenderCase::FLAG_TESSELLATION_MAX_SPEC
30553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				},
30563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
30573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"output_implementation_max_tessellation",
30583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"Maximum tessellation level supported by the implementation",
30593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					GridRenderCase::FLAG_TESSELLATION_MAX_IMPLEMENTATION
30603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				},
30613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
30623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"output_required_max_geometry",
30633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"Output minimum maximum number of vertices the geometry shader",
30643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					GridRenderCase::FLAG_GEOMETRY_MAX_SPEC
30653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				},
30663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
30673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"output_implementation_max_geometry",
30683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"Output maximum number of vertices in the geometry shader supported by the implementation",
30693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					GridRenderCase::FLAG_GEOMETRY_MAX_IMPLEMENTATION
30703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				},
30713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
30723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"output_required_max_invocations",
30733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"Minimum maximum number of geometry shader invocations",
30743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					GridRenderCase::FLAG_GEOMETRY_INVOCATIONS_MAX_SPEC
30753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				},
30763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
30773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"output_implementation_max_invocations",
30783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					"Maximum number of geometry shader invocations supported by the implementation",
30793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					GridRenderCase::FLAG_GEOMETRY_INVOCATIONS_MAX_IMPLEMENTATION
30803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				},
30813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
30823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ++ndx)
30843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				limitGroup->addChild(new GridRenderCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].flags));
30853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
30863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .scatter
30883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
30893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			scatterGroup->addChild(new GridRenderCase(m_context,
30903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  "geometry_scatter_instances",
30913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  "Each geometry shader instance outputs its primitives far from other instances of the same execution",
30923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  GridRenderCase::FLAG_GEOMETRY_SCATTER_INSTANCES));
30933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			scatterGroup->addChild(new GridRenderCase(m_context,
30943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  "geometry_scatter_primitives",
30953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  "Each geometry shader instance outputs its primitives far from other primitives of the same instance",
30963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  GridRenderCase::FLAG_GEOMETRY_SCATTER_PRIMITIVES | GridRenderCase::FLAG_GEOMETRY_SEPARATE_PRIMITIVES));
30973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			scatterGroup->addChild(new GridRenderCase(m_context,
30983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  "geometry_scatter_layers",
30993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  "Each geometry shader instance outputs its primitives to multiple layers and far from other primitives of the same instance",
31003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													  GridRenderCase::FLAG_GEOMETRY_SCATTER_LAYERS | GridRenderCase::FLAG_GEOMETRY_SEPARATE_PRIMITIVES));
31013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
31023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
31033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .feedback
31053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
31063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const struct PrimitiveCaseConfig
31073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
31083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*											name;
31093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*											description;
31103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			FeedbackPrimitiveTypeCase::TessellationOutputType	tessellationOutput;
31113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			FeedbackPrimitiveTypeCase::TessellationPointMode	tessellationPointMode;
31123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			FeedbackPrimitiveTypeCase::GeometryOutputType		geometryOutputType;
31133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} caseConfigs[] =
31143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
31153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// tess output triangles -> geo input triangles, output points
31163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
31173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"tessellation_output_triangles_geometry_output_points",
31183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"Tessellation outputs triangles, geometry outputs points",
31193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_OUT_TRIANGLES,
31203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_POINTMODE_OFF,
31213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::GEOMETRY_OUTPUT_POINTS
31223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			},
31233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// tess output quads <-> geo input triangles, output points
31253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
31263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"tessellation_output_quads_geometry_output_points",
31273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"Tessellation outputs quads, geometry outputs points",
31283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_OUT_QUADS,
31293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_POINTMODE_OFF,
31303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::GEOMETRY_OUTPUT_POINTS
31313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			},
31323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// tess output isolines <-> geo input lines, output points
31343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
31353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"tessellation_output_isolines_geometry_output_points",
31363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"Tessellation outputs isolines, geometry outputs points",
31373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_OUT_ISOLINES,
31383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_POINTMODE_OFF,
31393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::GEOMETRY_OUTPUT_POINTS
31403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			},
31413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// tess output triangles, point_mode <-> geo input points, output lines
31433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
31443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"tessellation_output_triangles_point_mode_geometry_output_lines",
31453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"Tessellation outputs triangles in point mode, geometry outputs lines",
31463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_OUT_TRIANGLES,
31473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_POINTMODE_ON,
31483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::GEOMETRY_OUTPUT_LINES
31493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			},
31503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// tess output quads, point_mode <-> geo input points, output lines
31523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
31533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"tessellation_output_quads_point_mode_geometry_output_lines",
31543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"Tessellation outputs quads in point mode, geometry outputs lines",
31553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_OUT_QUADS,
31563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_POINTMODE_ON,
31573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::GEOMETRY_OUTPUT_LINES
31583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			},
31593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// tess output isolines, point_mode <-> geo input points, output triangles
31613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
31623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"tessellation_output_isolines_point_mode_geometry_output_triangles",
31633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"Tessellation outputs isolines in point mode, geometry outputs triangles",
31643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_OUT_ISOLINES,
31653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::TESSELLATION_POINTMODE_ON,
31663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				FeedbackPrimitiveTypeCase::GEOMETRY_OUTPUT_TRIANGLES
31673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			},
31683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
31693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(caseConfigs); ++ndx)
31713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
31723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			feedbackGroup->addChild(new FeedbackPrimitiveTypeCase(m_context,
31733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  caseConfigs[ndx].name,
31743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  caseConfigs[ndx].description,
31753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  caseConfigs[ndx].tessellationOutput,
31763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  caseConfigs[ndx].tessellationPointMode,
31773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																  caseConfigs[ndx].geometryOutputType));
31783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
31793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		feedbackGroup->addChild(new FeedbackRecordVariableSelectionCase(m_context, "record_variable_selection", "Record a variable that has been declared as an output variable in multiple shader stages"));
31813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
31823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .point_size
31843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
31853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const int caseFlags[] =
31863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
31873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			PointSizeCase::FLAG_VERTEX_SET,
31883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												PointSizeCase::FLAG_TESSELLATION_EVALUATION_SET,
31893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																										PointSizeCase::FLAG_GEOMETRY_SET,
31903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			PointSizeCase::FLAG_VERTEX_SET	|	PointSizeCase::FLAG_TESSELLATION_CONTROL_SET,
31913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			PointSizeCase::FLAG_VERTEX_SET	|	PointSizeCase::FLAG_TESSELLATION_EVALUATION_SET,
31923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			PointSizeCase::FLAG_VERTEX_SET	|	PointSizeCase::FLAG_TESSELLATION_DONT_SET,
31933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			PointSizeCase::FLAG_VERTEX_SET 	|															PointSizeCase::FLAG_GEOMETRY_SET,
31943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			PointSizeCase::FLAG_VERTEX_SET	|	PointSizeCase::FLAG_TESSELLATION_EVALUATION_SET		|	PointSizeCase::FLAG_GEOMETRY_SET,
31953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			PointSizeCase::FLAG_VERTEX_SET	|	PointSizeCase::FLAG_TESSELLATION_ADD				|	PointSizeCase::FLAG_GEOMETRY_ADD,
31963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			PointSizeCase::FLAG_VERTEX_SET	|	PointSizeCase::FLAG_TESSELLATION_EVALUATION_SET		|	PointSizeCase::FLAG_GEOMETRY_DONT_SET,
31973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
31983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(caseFlags); ++ndx)
32003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
32013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const std::string name = PointSizeCase::genTestCaseName(caseFlags[ndx]);
32023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const std::string desc = PointSizeCase::genTestCaseDescription(caseFlags[ndx]);
32033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			pointSizeGroup->addChild(new PointSizeCase(m_context, name.c_str(), desc.c_str(), caseFlags[ndx]));
32053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
32063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
32083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
32103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
32113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
3212