1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Texture format performance tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es3pTextureCases.hpp"
25#include "glsShaderPerformanceCase.hpp"
26#include "tcuTextureUtil.hpp"
27#include "tcuRenderTarget.hpp"
28#include "gluTexture.hpp"
29#include "gluTextureUtil.hpp"
30#include "gluStrUtil.hpp"
31
32#include "deStringUtil.hpp"
33
34#include "glwEnums.hpp"
35#include "glwFunctions.hpp"
36
37namespace deqp
38{
39namespace gles3
40{
41namespace Performance
42{
43
44using namespace gls;
45using namespace glw; // GL types
46using tcu::Vec2;
47using tcu::Vec3;
48using tcu::Vec4;
49using tcu::IVec4;
50using std::string;
51using std::vector;
52using tcu::TestLog;
53
54Texture2DRenderCase::Texture2DRenderCase (Context&			context,
55										  const char*		name,
56										  const char*		description,
57										  deUint32			internalFormat,
58										  deUint32			wrapS,
59										  deUint32			wrapT,
60										  deUint32			minFilter,
61										  deUint32			magFilter,
62										  const tcu::Mat3&	coordTransform,
63										  int				numTextures,
64										  bool				powerOfTwo)
65	: ShaderPerformanceCase	(context.getTestContext(), context.getRenderContext(), name, description, CASETYPE_FRAGMENT)
66	, m_internalFormat		(internalFormat)
67	, m_wrapS				(wrapS)
68	, m_wrapT				(wrapT)
69	, m_minFilter			(minFilter)
70	, m_magFilter			(magFilter)
71	, m_coordTransform		(coordTransform)
72	, m_numTextures			(numTextures)
73	, m_powerOfTwo			(powerOfTwo)
74{
75}
76
77Texture2DRenderCase::~Texture2DRenderCase (void)
78{
79	for (vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
80		delete *i;
81	m_textures.clear();
82}
83
84static inline int roundDownToPowerOfTwo (int val)
85{
86	DE_ASSERT(val >= 0);
87	int l0 = deClz32(val);
88	return val & ~((1<<(31-l0))-1);
89}
90
91void Texture2DRenderCase::init (void)
92{
93	TestLog& log = m_testCtx.getLog();
94
95	const tcu::TextureFormat		texFormat	= glu::mapGLInternalFormat(m_internalFormat);
96	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFormat);
97	const glu::Precision			samplerPrec	= (texFormat.type == tcu::TextureFormat::FLOAT			||
98												   texFormat.type == tcu::TextureFormat::UNSIGNED_INT32	||
99												   texFormat.type == tcu::TextureFormat::SIGNED_INT32)
100												? glu::PRECISION_HIGHP : glu::PRECISION_MEDIUMP;
101	const glu::DataType				samplerType	= glu::getSampler2DType(texFormat);
102	const bool						isIntUint	= samplerType == glu::TYPE_INT_SAMPLER_2D || samplerType == glu::TYPE_UINT_SAMPLER_2D;
103
104	int								width		= m_renderCtx.getRenderTarget().getWidth();
105	int								height		= m_renderCtx.getRenderTarget().getHeight();
106
107	if (m_powerOfTwo)
108	{
109		width	= roundDownToPowerOfTwo(width);
110		height	= roundDownToPowerOfTwo(height);
111	}
112
113	bool mipmaps = m_minFilter == GL_NEAREST_MIPMAP_NEAREST ||
114				   m_minFilter == GL_NEAREST_MIPMAP_LINEAR	||
115				   m_minFilter == GL_LINEAR_MIPMAP_NEAREST	||
116				   m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
117
118	DE_ASSERT(m_powerOfTwo || (!mipmaps && m_wrapS == GL_CLAMP_TO_EDGE && m_wrapT == GL_CLAMP_TO_EDGE));
119
120	Vec2 p00 = (m_coordTransform * Vec3(0.0f, 0.0f, 1.0f)).swizzle(0,1);
121	Vec2 p10 = (m_coordTransform * Vec3(1.0f, 0.0f, 1.0f)).swizzle(0,1);
122	Vec2 p01 = (m_coordTransform * Vec3(0.0f, 1.0f, 1.0f)).swizzle(0,1);
123	Vec2 p11 = (m_coordTransform * Vec3(1.0f, 1.0f, 1.0f)).swizzle(0,1);
124
125	m_attributes.push_back(AttribSpec("a_coords", Vec4(p00.x(), p00.y(), 0.0f, 0.0f),
126												  Vec4(p10.x(), p10.y(), 0.0f, 0.0f),
127												  Vec4(p01.x(), p01.y(), 0.0f, 0.0f),
128												  Vec4(p11.x(), p11.y(), 0.0f, 0.0f)));
129
130	log << TestLog::Message << "Size: " << width << "x" << height << TestLog::EndMessage;
131	log << TestLog::Message << "Format: " <<glu::getTextureFormatName(m_internalFormat) << TestLog::EndMessage;
132	log << TestLog::Message << "Coords: " << p00 << ", " << p10 << ", " << p01 << ", " << p11 << TestLog::EndMessage;
133	log << TestLog::Message << "Wrap: " << glu::getTextureWrapModeStr(m_wrapS) << " / " << glu::getTextureWrapModeStr(m_wrapT) << TestLog::EndMessage;
134	log << TestLog::Message << "Filter: " << glu::getTextureFilterStr(m_minFilter) << " / " << glu::getTextureFilterStr(m_magFilter) << TestLog::EndMessage;
135	log << TestLog::Message << "Mipmaps: " << (mipmaps ? "true" : "false") << TestLog::EndMessage;
136	log << TestLog::Message << "Using additive blending." << TestLog::EndMessage;
137
138	// Use same viewport size as texture size.
139	setViewportSize(width, height);
140
141	m_vertShaderSource =
142		"#version 300 es\n"
143		"in highp vec4 a_position;\n"
144		"in mediump vec2 a_coords;\n"
145		"out mediump vec2 v_coords;\n"
146		"void main (void)\n"
147		"{\n"
148		"	gl_Position = a_position;\n"
149		"	v_coords = a_coords;\n"
150		"}\n";
151
152	std::ostringstream fragSrc;
153	fragSrc << "#version 300 es\n";
154	fragSrc << "layout(location = 0) out mediump vec4 o_color;\n";
155	fragSrc << "in mediump vec2 v_coords;\n";
156
157	for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
158		fragSrc << "uniform " << glu::getPrecisionName(samplerPrec) << " " << glu::getDataTypeName(samplerType) << " u_sampler" << texNdx << ";\n";
159
160	fragSrc << "void main (void)\n"
161			<< "{\n";
162
163	for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
164	{
165		if (texNdx == 0)
166			fragSrc << "\t" << glu::getPrecisionName(samplerPrec) << " vec4 r = ";
167		else
168			fragSrc << "\tr += ";
169
170		if (isIntUint)
171			fragSrc << "vec4(";
172
173		fragSrc << "texture(u_sampler" << texNdx << ", v_coords)";
174
175		if (isIntUint)
176			fragSrc << ")";
177
178		fragSrc << ";\n";
179	}
180
181	fragSrc << "	o_color = r;\n"
182			<< "}\n";
183
184	m_fragShaderSource = fragSrc.str();
185
186	m_textures.reserve(m_numTextures);
187	for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
188	{
189		static const IVec4 swizzles[] = { IVec4(0,1,2,3), IVec4(1,2,3,0), IVec4(2,3,0,1), IVec4(3,0,1,2),
190										  IVec4(3,2,1,0), IVec4(2,1,0,3), IVec4(1,0,3,2), IVec4(0,3,2,1) };
191		const IVec4& sw = swizzles[texNdx % DE_LENGTH_OF_ARRAY(swizzles)];
192
193		glu::Texture2D* texture = new glu::Texture2D(m_renderCtx, m_internalFormat, width, height);
194		m_textures.push_back(texture);
195
196		// Fill levels.
197		int numLevels = mipmaps ? texture->getRefTexture().getNumLevels() : 1;
198		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
199		{
200			// \todo [2013-06-02 pyry] Values are not scaled back to 0..1 range in shaders.
201			texture->getRefTexture().allocLevel(levelNdx);
202			tcu::fillWithComponentGradients(texture->getRefTexture().getLevel(levelNdx),
203											fmtInfo.valueMin.swizzle(sw[0], sw[1], sw[2], sw[3]),
204											fmtInfo.valueMax.swizzle(sw[0], sw[1], sw[2], sw[3]));
205		}
206
207		texture->upload();
208	}
209
210	ShaderPerformanceCase::init();
211}
212
213void Texture2DRenderCase::deinit (void)
214{
215	for (vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
216		delete *i;
217	m_textures.clear();
218
219	ShaderPerformanceCase::deinit();
220}
221
222void Texture2DRenderCase::setupProgram (deUint32 program)
223{
224	const glw::Functions& gl = m_renderCtx.getFunctions();
225	for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
226	{
227		int samplerLoc = gl.getUniformLocation(program, (string("u_sampler") + de::toString(texNdx)).c_str());
228		gl.uniform1i(samplerLoc, texNdx);
229	}
230}
231
232void Texture2DRenderCase::setupRenderState (void)
233{
234	const glw::Functions& gl = m_renderCtx.getFunctions();
235
236	// Setup additive blending.
237	gl.enable(GL_BLEND);
238	gl.blendFunc(GL_ONE, GL_ONE);
239	gl.blendEquation(GL_FUNC_ADD);
240
241	// Setup textures.
242	for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
243	{
244		gl.activeTexture(GL_TEXTURE0 + texNdx);
245		gl.bindTexture(GL_TEXTURE_2D, m_textures[texNdx]->getGLTexture());
246		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	m_minFilter);
247		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	m_magFilter);
248		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		m_wrapS);
249		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		m_wrapT);
250	}
251}
252
253
254} // Performance
255} // gles3
256} // deqp
257