1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL (ES) 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 Single-program test case wrapper for ShaderPerformanceMeasurer.
22 *//*--------------------------------------------------------------------*/
23
24 #include "glsShaderPerformanceCase.hpp"
25 #include "tcuRenderTarget.hpp"
26 #include "deStringUtil.hpp"
27 #include "deMath.h"
28
29 #include "glwFunctions.hpp"
30 #include "glwEnums.hpp"
31
32 using tcu::TestLog;
33 using tcu::Vec4;
34 using namespace glw; // GL types
35
36 namespace deqp
37 {
38 namespace gls
39 {
40
ShaderPerformanceCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * description,PerfCaseType caseType)41 ShaderPerformanceCase::ShaderPerformanceCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const char *name,
42 const char *description, PerfCaseType caseType)
43 : tcu::TestCase(testCtx, tcu::NODETYPE_PERFORMANCE, name, description)
44 , m_renderCtx(renderCtx)
45 , m_caseType(caseType)
46 , m_program(DE_NULL)
47 , m_measurer(renderCtx, caseType)
48 {
49 }
50
~ShaderPerformanceCase(void)51 ShaderPerformanceCase::~ShaderPerformanceCase(void)
52 {
53 ShaderPerformanceCase::deinit();
54 }
55
setGridSize(int gridW,int gridH)56 void ShaderPerformanceCase::setGridSize(int gridW, int gridH)
57 {
58 m_measurer.setGridSize(gridW, gridH);
59 }
60
setViewportSize(int width,int height)61 void ShaderPerformanceCase::setViewportSize(int width, int height)
62 {
63 m_measurer.setViewportSize(width, height);
64 }
65
setVertexFragmentRatio(float fragmentsPerVertices)66 void ShaderPerformanceCase::setVertexFragmentRatio(float fragmentsPerVertices)
67 {
68 const float eps = 0.01f;
69 int gridW = 255;
70 int gridH = 255;
71 int viewportW = m_renderCtx.getRenderTarget().getWidth();
72 int viewportH = m_renderCtx.getRenderTarget().getHeight();
73
74 for (int i = 0; i < 10; i++)
75 {
76 int numVert = (gridW + 1) * (gridH + 1);
77 int numFrag = viewportW * viewportH;
78 float ratio = (float)numFrag / (float)numVert;
79
80 if (de::abs(ratio - fragmentsPerVertices) < eps)
81 break;
82 else if (ratio < fragmentsPerVertices)
83 {
84 // Not enough fragments.
85 numVert = deRoundFloatToInt32((float)numFrag / fragmentsPerVertices);
86
87 while ((gridW + 1) * (gridH + 1) > numVert)
88 {
89 if (gridW > gridH)
90 gridW -= 1;
91 else
92 gridH -= 1;
93 }
94 }
95 else
96 {
97 // Not enough vertices.
98 numFrag = deRoundFloatToInt32((float)numVert * fragmentsPerVertices);
99
100 while (viewportW * viewportH > numFrag)
101 {
102 if (viewportW > viewportH)
103 viewportW -= 1;
104 else
105 viewportH -= 1;
106 }
107 }
108 }
109
110 float finalRatio = (float)(viewportW * viewportH) / (float)((gridW + 1) * (gridH + 1));
111 m_testCtx.getLog() << TestLog::Message
112 << "Requested fragment/vertex-ratio: " << de::floatToString(fragmentsPerVertices, 2) << "\n"
113 << "Computed fragment/vertex-ratio: " << de::floatToString(finalRatio, 2) << TestLog::EndMessage;
114
115 setGridSize(gridW, gridH);
116 setViewportSize(viewportW, viewportH);
117 }
118
logRenderTargetInfo(TestLog & log,const tcu::RenderTarget & renderTarget)119 static void logRenderTargetInfo(TestLog &log, const tcu::RenderTarget &renderTarget)
120 {
121 log << TestLog::Section("RenderTarget", "Render target") << TestLog::Message << "size: " << renderTarget.getWidth()
122 << "x" << renderTarget.getHeight() << TestLog::EndMessage << TestLog::Message << "bits:"
123 << " R" << renderTarget.getPixelFormat().redBits << " G" << renderTarget.getPixelFormat().greenBits << " B"
124 << renderTarget.getPixelFormat().blueBits << " A" << renderTarget.getPixelFormat().alphaBits << " D"
125 << renderTarget.getDepthBits() << " S" << renderTarget.getStencilBits() << TestLog::EndMessage;
126
127 if (renderTarget.getNumSamples() != 0)
128 log << TestLog::Message << renderTarget.getNumSamples() << "x MSAA" << TestLog::EndMessage;
129 else
130 log << TestLog::Message << "No MSAA" << TestLog::EndMessage;
131
132 log << TestLog::EndSection;
133 }
134
init(void)135 void ShaderPerformanceCase::init(void)
136 {
137 tcu::TestLog &log = m_testCtx.getLog();
138
139 m_program = new glu::ShaderProgram(m_renderCtx, glu::makeVtxFragSources(m_vertShaderSource, m_fragShaderSource));
140
141 if (m_program->isOk())
142 {
143 const int initialCallCount = m_initialCalibration ? m_initialCalibration->initialNumCalls : 1;
144 logRenderTargetInfo(log, m_renderCtx.getRenderTarget());
145 m_measurer.init(m_program->getProgram(), m_attributes, initialCallCount);
146 m_measurer.logParameters(log);
147 log << *m_program;
148 }
149 else
150 {
151 log << *m_program;
152 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed");
153 return; // Skip rest of init.
154 }
155
156 setupProgram(m_program->getProgram());
157 setupRenderState();
158 }
159
deinit(void)160 void ShaderPerformanceCase::deinit(void)
161 {
162 delete m_program;
163 m_program = DE_NULL;
164
165 m_measurer.deinit();
166 }
167
setupProgram(uint32_t program)168 void ShaderPerformanceCase::setupProgram(uint32_t program)
169 {
170 DE_UNREF(program);
171 }
172
setupRenderState(void)173 void ShaderPerformanceCase::setupRenderState(void)
174 {
175 }
176
iterate(void)177 ShaderPerformanceCase::IterateResult ShaderPerformanceCase::iterate(void)
178 {
179 DE_ASSERT(m_program);
180
181 if (!m_program->isOk()) // This happens when compilation failed in init().
182 return STOP;
183
184 m_measurer.iterate();
185
186 if (m_measurer.isFinished())
187 {
188 m_measurer.logMeasurementInfo(m_testCtx.getLog());
189
190 if (m_initialCalibration)
191 m_initialCalibration->initialNumCalls = de::max(1, m_measurer.getFinalCallCount());
192
193 const ShaderPerformanceMeasurer::Result result = m_measurer.getResult();
194 reportResult(result.megaVertPerSec, result.megaFragPerSec);
195 return STOP;
196 }
197 else
198 return CONTINUE;
199 }
200
reportResult(float mvertPerSecond,float mfragPerSecond)201 void ShaderPerformanceCase::reportResult(float mvertPerSecond, float mfragPerSecond)
202 {
203 float result = 0.0f;
204 switch (m_caseType)
205 {
206 case CASETYPE_VERTEX:
207 result = mvertPerSecond;
208 break;
209 case CASETYPE_FRAGMENT:
210 result = mfragPerSecond;
211 break;
212 case CASETYPE_BALANCED:
213 result = mfragPerSecond;
214 break;
215 default:
216 DE_ASSERT(false);
217 }
218
219 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString(result, 2).c_str());
220 }
221
ShaderPerformanceCaseGroup(tcu::TestContext & testCtx,const char * name,const char * description)222 ShaderPerformanceCaseGroup::ShaderPerformanceCaseGroup(tcu::TestContext &testCtx, const char *name,
223 const char *description)
224 : TestCaseGroup(testCtx, name, description)
225 , m_initialCalibrationStorage(new ShaderPerformanceCase::InitialCalibration)
226 {
227 }
228
addChild(ShaderPerformanceCase * perfCase)229 void ShaderPerformanceCaseGroup::addChild(ShaderPerformanceCase *perfCase)
230 {
231 perfCase->setCalibrationInitialParamStorage(m_initialCalibrationStorage);
232 TestCaseGroup::addChild(perfCase);
233 }
234
235 } // namespace gls
236 } // namespace deqp
237