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
37 namespace deqp
38 {
39 namespace gles3
40 {
41 namespace Performance
42 {
43
44 using namespace gls;
45 using namespace glw; // GL types
46 using std::string;
47 using std::vector;
48 using tcu::IVec4;
49 using tcu::TestLog;
50 using tcu::Vec2;
51 using tcu::Vec3;
52 using tcu::Vec4;
53
Texture2DRenderCase(Context & context,const char * name,const char * description,uint32_t internalFormat,uint32_t wrapS,uint32_t wrapT,uint32_t minFilter,uint32_t magFilter,const tcu::Mat3 & coordTransform,int numTextures,bool powerOfTwo)54 Texture2DRenderCase::Texture2DRenderCase(Context &context, const char *name, const char *description,
55 uint32_t internalFormat, uint32_t wrapS, uint32_t wrapT, uint32_t minFilter,
56 uint32_t magFilter, const tcu::Mat3 &coordTransform, int numTextures,
57 bool powerOfTwo)
58 : ShaderPerformanceCase(context.getTestContext(), context.getRenderContext(), name, description, CASETYPE_FRAGMENT)
59 , m_internalFormat(internalFormat)
60 , m_wrapS(wrapS)
61 , m_wrapT(wrapT)
62 , m_minFilter(minFilter)
63 , m_magFilter(magFilter)
64 , m_coordTransform(coordTransform)
65 , m_numTextures(numTextures)
66 , m_powerOfTwo(powerOfTwo)
67 {
68 }
69
~Texture2DRenderCase(void)70 Texture2DRenderCase::~Texture2DRenderCase(void)
71 {
72 for (vector<glu::Texture2D *>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
73 delete *i;
74 m_textures.clear();
75 }
76
roundDownToPowerOfTwo(int val)77 static inline int roundDownToPowerOfTwo(int val)
78 {
79 DE_ASSERT(val >= 0);
80 int l0 = deClz32(val);
81 return val & ~((1 << (31 - l0)) - 1);
82 }
83
init(void)84 void Texture2DRenderCase::init(void)
85 {
86 TestLog &log = m_testCtx.getLog();
87
88 const tcu::TextureFormat texFormat = glu::mapGLInternalFormat(m_internalFormat);
89 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFormat);
90 const glu::Precision samplerPrec =
91 (texFormat.type == tcu::TextureFormat::FLOAT || texFormat.type == tcu::TextureFormat::UNSIGNED_INT32 ||
92 texFormat.type == tcu::TextureFormat::SIGNED_INT32) ?
93 glu::PRECISION_HIGHP :
94 glu::PRECISION_MEDIUMP;
95 const glu::DataType samplerType = glu::getSampler2DType(texFormat);
96 const bool isIntUint = samplerType == glu::TYPE_INT_SAMPLER_2D || samplerType == glu::TYPE_UINT_SAMPLER_2D;
97
98 int width = m_renderCtx.getRenderTarget().getWidth();
99 int height = m_renderCtx.getRenderTarget().getHeight();
100
101 if (m_powerOfTwo)
102 {
103 width = roundDownToPowerOfTwo(width);
104 height = roundDownToPowerOfTwo(height);
105 }
106
107 bool mipmaps = m_minFilter == GL_NEAREST_MIPMAP_NEAREST || m_minFilter == GL_NEAREST_MIPMAP_LINEAR ||
108 m_minFilter == GL_LINEAR_MIPMAP_NEAREST || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
109
110 DE_ASSERT(m_powerOfTwo || (!mipmaps && m_wrapS == GL_CLAMP_TO_EDGE && m_wrapT == GL_CLAMP_TO_EDGE));
111
112 Vec2 p00 = (m_coordTransform * Vec3(0.0f, 0.0f, 1.0f)).swizzle(0, 1);
113 Vec2 p10 = (m_coordTransform * Vec3(1.0f, 0.0f, 1.0f)).swizzle(0, 1);
114 Vec2 p01 = (m_coordTransform * Vec3(0.0f, 1.0f, 1.0f)).swizzle(0, 1);
115 Vec2 p11 = (m_coordTransform * Vec3(1.0f, 1.0f, 1.0f)).swizzle(0, 1);
116
117 m_attributes.push_back(AttribSpec("a_coords", Vec4(p00.x(), p00.y(), 0.0f, 0.0f),
118 Vec4(p10.x(), p10.y(), 0.0f, 0.0f), Vec4(p01.x(), p01.y(), 0.0f, 0.0f),
119 Vec4(p11.x(), p11.y(), 0.0f, 0.0f)));
120
121 log << TestLog::Message << "Size: " << width << "x" << height << TestLog::EndMessage;
122 log << TestLog::Message << "Format: " << glu::getTextureFormatName(m_internalFormat) << TestLog::EndMessage;
123 log << TestLog::Message << "Coords: " << p00 << ", " << p10 << ", " << p01 << ", " << p11 << TestLog::EndMessage;
124 log << TestLog::Message << "Wrap: " << glu::getTextureWrapModeStr(m_wrapS) << " / "
125 << glu::getTextureWrapModeStr(m_wrapT) << TestLog::EndMessage;
126 log << TestLog::Message << "Filter: " << glu::getTextureFilterStr(m_minFilter) << " / "
127 << glu::getTextureFilterStr(m_magFilter) << TestLog::EndMessage;
128 log << TestLog::Message << "Mipmaps: " << (mipmaps ? "true" : "false") << TestLog::EndMessage;
129 log << TestLog::Message << "Using additive blending." << TestLog::EndMessage;
130
131 // Use same viewport size as texture size.
132 setViewportSize(width, height);
133
134 m_vertShaderSource = "#version 300 es\n"
135 "in highp vec4 a_position;\n"
136 "in mediump vec2 a_coords;\n"
137 "out mediump vec2 v_coords;\n"
138 "void main (void)\n"
139 "{\n"
140 " gl_Position = a_position;\n"
141 " v_coords = a_coords;\n"
142 "}\n";
143
144 std::ostringstream fragSrc;
145 fragSrc << "#version 300 es\n";
146 fragSrc << "layout(location = 0) out mediump vec4 o_color;\n";
147 fragSrc << "in mediump vec2 v_coords;\n";
148
149 for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
150 fragSrc << "uniform " << glu::getPrecisionName(samplerPrec) << " " << glu::getDataTypeName(samplerType)
151 << " u_sampler" << texNdx << ";\n";
152
153 fragSrc << "void main (void)\n"
154 << "{\n";
155
156 for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
157 {
158 if (texNdx == 0)
159 fragSrc << "\t" << glu::getPrecisionName(samplerPrec) << " vec4 r = ";
160 else
161 fragSrc << "\tr += ";
162
163 if (isIntUint)
164 fragSrc << "vec4(";
165
166 fragSrc << "texture(u_sampler" << texNdx << ", v_coords)";
167
168 if (isIntUint)
169 fragSrc << ")";
170
171 fragSrc << ";\n";
172 }
173
174 fragSrc << " o_color = r;\n"
175 << "}\n";
176
177 m_fragShaderSource = fragSrc.str();
178
179 m_textures.reserve(m_numTextures);
180 for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
181 {
182 static const IVec4 swizzles[] = {IVec4(0, 1, 2, 3), IVec4(1, 2, 3, 0), IVec4(2, 3, 0, 1), IVec4(3, 0, 1, 2),
183 IVec4(3, 2, 1, 0), IVec4(2, 1, 0, 3), IVec4(1, 0, 3, 2), IVec4(0, 3, 2, 1)};
184 const IVec4 &sw = swizzles[texNdx % DE_LENGTH_OF_ARRAY(swizzles)];
185
186 glu::Texture2D *texture = new glu::Texture2D(m_renderCtx, m_internalFormat, width, height);
187 m_textures.push_back(texture);
188
189 // Fill levels.
190 int numLevels = mipmaps ? texture->getRefTexture().getNumLevels() : 1;
191 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
192 {
193 // \todo [2013-06-02 pyry] Values are not scaled back to 0..1 range in shaders.
194 texture->getRefTexture().allocLevel(levelNdx);
195 tcu::fillWithComponentGradients(texture->getRefTexture().getLevel(levelNdx),
196 fmtInfo.valueMin.swizzle(sw[0], sw[1], sw[2], sw[3]),
197 fmtInfo.valueMax.swizzle(sw[0], sw[1], sw[2], sw[3]));
198 }
199
200 texture->upload();
201 }
202
203 ShaderPerformanceCase::init();
204 }
205
deinit(void)206 void Texture2DRenderCase::deinit(void)
207 {
208 for (vector<glu::Texture2D *>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
209 delete *i;
210 m_textures.clear();
211
212 ShaderPerformanceCase::deinit();
213 }
214
setupProgram(uint32_t program)215 void Texture2DRenderCase::setupProgram(uint32_t program)
216 {
217 const glw::Functions &gl = m_renderCtx.getFunctions();
218 for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
219 {
220 int samplerLoc = gl.getUniformLocation(program, (string("u_sampler") + de::toString(texNdx)).c_str());
221 gl.uniform1i(samplerLoc, texNdx);
222 }
223 }
224
setupRenderState(void)225 void Texture2DRenderCase::setupRenderState(void)
226 {
227 const glw::Functions &gl = m_renderCtx.getFunctions();
228
229 // Setup additive blending.
230 gl.enable(GL_BLEND);
231 gl.blendFunc(GL_ONE, GL_ONE);
232 gl.blendEquation(GL_FUNC_ADD);
233
234 // Setup textures.
235 for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
236 {
237 gl.activeTexture(GL_TEXTURE0 + texNdx);
238 gl.bindTexture(GL_TEXTURE_2D, m_textures[texNdx]->getGLTexture());
239 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
240 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter);
241 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS);
242 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT);
243 }
244 }
245
246 } // namespace Performance
247 } // namespace gles3
248 } // namespace deqp
249