1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program Random Shader Generator
3e5c31af7Sopenharmony_ci * ----------------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Program Executor.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "rsgProgramExecutor.hpp"
25e5c31af7Sopenharmony_ci#include "rsgExecutionContext.hpp"
26e5c31af7Sopenharmony_ci#include "rsgVariableValue.hpp"
27e5c31af7Sopenharmony_ci#include "rsgUtils.hpp"
28e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
29e5c31af7Sopenharmony_ci#include "deMath.h"
30e5c31af7Sopenharmony_ci#include "deString.h"
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ci#include <set>
33e5c31af7Sopenharmony_ci#include <string>
34e5c31af7Sopenharmony_ci#include <map>
35e5c31af7Sopenharmony_ci
36e5c31af7Sopenharmony_ciusing std::set;
37e5c31af7Sopenharmony_ciusing std::string;
38e5c31af7Sopenharmony_ciusing std::vector;
39e5c31af7Sopenharmony_ciusing std::map;
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_cinamespace rsg
42e5c31af7Sopenharmony_ci{
43e5c31af7Sopenharmony_ci
44e5c31af7Sopenharmony_ciclass VaryingStorage
45e5c31af7Sopenharmony_ci{
46e5c31af7Sopenharmony_cipublic:
47e5c31af7Sopenharmony_ci							VaryingStorage		(const VariableType& type, int numVertices);
48e5c31af7Sopenharmony_ci							~VaryingStorage		(void) {}
49e5c31af7Sopenharmony_ci
50e5c31af7Sopenharmony_ci	ValueAccess				getValue			(const VariableType& type, int vtxNdx);
51e5c31af7Sopenharmony_ci	ConstValueAccess		getValue			(const VariableType& type, int vtxNdx) const;
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_ciprivate:
54e5c31af7Sopenharmony_ci	std::vector<Scalar>		m_value;
55e5c31af7Sopenharmony_ci};
56e5c31af7Sopenharmony_ci
57e5c31af7Sopenharmony_ciVaryingStorage::VaryingStorage (const VariableType& type, int numVertices)
58e5c31af7Sopenharmony_ci	: m_value(type.getScalarSize()*numVertices)
59e5c31af7Sopenharmony_ci{
60e5c31af7Sopenharmony_ci}
61e5c31af7Sopenharmony_ci
62e5c31af7Sopenharmony_ciValueAccess VaryingStorage::getValue (const VariableType& type, int vtxNdx)
63e5c31af7Sopenharmony_ci{
64e5c31af7Sopenharmony_ci	return ValueAccess(type, &m_value[type.getScalarSize()*vtxNdx]);
65e5c31af7Sopenharmony_ci}
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ciConstValueAccess VaryingStorage::getValue (const VariableType& type, int vtxNdx) const
68e5c31af7Sopenharmony_ci{
69e5c31af7Sopenharmony_ci	return ConstValueAccess(type, &m_value[type.getScalarSize()*vtxNdx]);
70e5c31af7Sopenharmony_ci}
71e5c31af7Sopenharmony_ci
72e5c31af7Sopenharmony_ciclass VaryingStore
73e5c31af7Sopenharmony_ci{
74e5c31af7Sopenharmony_cipublic:
75e5c31af7Sopenharmony_ci							VaryingStore		(int numVertices);
76e5c31af7Sopenharmony_ci							~VaryingStore		(void);
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_ci	VaryingStorage*			getStorage			(const VariableType& type, const char* name);
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_ciprivate:
81e5c31af7Sopenharmony_ci	int											m_numVertices;
82e5c31af7Sopenharmony_ci	std::map<std::string, VaryingStorage*>		m_values;
83e5c31af7Sopenharmony_ci};
84e5c31af7Sopenharmony_ci
85e5c31af7Sopenharmony_ciVaryingStore::VaryingStore (int numVertices)
86e5c31af7Sopenharmony_ci	: m_numVertices(numVertices)
87e5c31af7Sopenharmony_ci{
88e5c31af7Sopenharmony_ci}
89e5c31af7Sopenharmony_ci
90e5c31af7Sopenharmony_ciVaryingStore::~VaryingStore (void)
91e5c31af7Sopenharmony_ci{
92e5c31af7Sopenharmony_ci	for (map<string, VaryingStorage*>::iterator i = m_values.begin(); i != m_values.end(); i++)
93e5c31af7Sopenharmony_ci		delete i->second;
94e5c31af7Sopenharmony_ci	m_values.clear();
95e5c31af7Sopenharmony_ci}
96e5c31af7Sopenharmony_ci
97e5c31af7Sopenharmony_ciVaryingStorage* VaryingStore::getStorage (const VariableType& type, const char* name)
98e5c31af7Sopenharmony_ci{
99e5c31af7Sopenharmony_ci	VaryingStorage* storage = m_values[name];
100e5c31af7Sopenharmony_ci
101e5c31af7Sopenharmony_ci	if (!storage)
102e5c31af7Sopenharmony_ci	{
103e5c31af7Sopenharmony_ci		storage = new VaryingStorage(type, m_numVertices);
104e5c31af7Sopenharmony_ci		m_values[name] = storage;
105e5c31af7Sopenharmony_ci	}
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci	return storage;
108e5c31af7Sopenharmony_ci}
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ciinline float interpolateVertexQuad (const tcu::Vec4& quad, float x, float y)
111e5c31af7Sopenharmony_ci{
112e5c31af7Sopenharmony_ci	float w00 = (1.0f-x)*(1.0f-y);
113e5c31af7Sopenharmony_ci	float w01 = (1.0f-x)*y;
114e5c31af7Sopenharmony_ci	float w10 = x*(1.0f-y);
115e5c31af7Sopenharmony_ci	float w11 = x*y;
116e5c31af7Sopenharmony_ci	return quad.x()*w00 + quad.y()*w10 + quad.z()*w01 + quad.w()*w11;
117e5c31af7Sopenharmony_ci}
118e5c31af7Sopenharmony_ci
119e5c31af7Sopenharmony_ciinline float interpolateVertex (float x0y0, float x1y1, float x, float y)
120e5c31af7Sopenharmony_ci{
121e5c31af7Sopenharmony_ci	return interpolateVertexQuad(tcu::Vec4(x0y0, (x0y0+x1y1)*0.5f, (x0y0+x1y1)*0.5f, x1y1), x, y);
122e5c31af7Sopenharmony_ci}
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ciinline float interpolateTri (float v0, float v1, float v2, float x, float y)
125e5c31af7Sopenharmony_ci{
126e5c31af7Sopenharmony_ci	return v0 + (v1-v0)*x + (v2-v0)*y;
127e5c31af7Sopenharmony_ci}
128e5c31af7Sopenharmony_ci
129e5c31af7Sopenharmony_ciinline float interpolateFragment (const tcu::Vec4& quad, float x, float y)
130e5c31af7Sopenharmony_ci{
131e5c31af7Sopenharmony_ci	if (x + y < 1.0f)
132e5c31af7Sopenharmony_ci		return interpolateTri(quad.x(), quad.y(), quad.z(), x, y);
133e5c31af7Sopenharmony_ci	else
134e5c31af7Sopenharmony_ci		return interpolateTri(quad.w(), quad.z(), quad.y(), 1.0f-x, 1.0f-y);
135e5c31af7Sopenharmony_ci}
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_citemplate <int Stride>
138e5c31af7Sopenharmony_civoid interpolateVertexInput (StridedValueAccess<Stride> dst, int dstComp, const ConstValueRangeAccess valueRange, float x, float y)
139e5c31af7Sopenharmony_ci{
140e5c31af7Sopenharmony_ci	TCU_CHECK(valueRange.getType().getBaseType() == VariableType::TYPE_FLOAT);
141e5c31af7Sopenharmony_ci	int numElements = valueRange.getType().getNumElements();
142e5c31af7Sopenharmony_ci	for (int elementNdx = 0; elementNdx < numElements; elementNdx++)
143e5c31af7Sopenharmony_ci	{
144e5c31af7Sopenharmony_ci		float xd, yd;
145e5c31af7Sopenharmony_ci		getVertexInterpolationCoords(xd, yd, x, y, elementNdx);
146e5c31af7Sopenharmony_ci		dst.component(elementNdx).asFloat(dstComp) = interpolateVertex(valueRange.getMin().component(elementNdx).asFloat(), valueRange.getMax().component(elementNdx).asFloat(), xd, yd);
147e5c31af7Sopenharmony_ci	}
148e5c31af7Sopenharmony_ci}
149e5c31af7Sopenharmony_ci
150e5c31af7Sopenharmony_citemplate <int Stride>
151e5c31af7Sopenharmony_civoid interpolateFragmentInput (StridedValueAccess<Stride> dst, int dstComp, ConstValueAccess vtx0, ConstValueAccess vtx1, ConstValueAccess vtx2, ConstValueAccess vtx3, float x, float y)
152e5c31af7Sopenharmony_ci{
153e5c31af7Sopenharmony_ci	TCU_CHECK(dst.getType().getBaseType() == VariableType::TYPE_FLOAT);
154e5c31af7Sopenharmony_ci	int numElements = dst.getType().getNumElements();
155e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < numElements; ndx++)
156e5c31af7Sopenharmony_ci		dst.component(ndx).asFloat(dstComp) = interpolateFragment(tcu::Vec4(vtx0.component(ndx).asFloat(), vtx1.component(ndx).asFloat(), vtx2.component(ndx).asFloat(), vtx3.component(ndx).asFloat()), x, y);
157e5c31af7Sopenharmony_ci}
158e5c31af7Sopenharmony_ci
159e5c31af7Sopenharmony_citemplate <int Stride>
160e5c31af7Sopenharmony_civoid copyVarying (ValueAccess dst, ConstStridedValueAccess<Stride> src, int compNdx)
161e5c31af7Sopenharmony_ci{
162e5c31af7Sopenharmony_ci	TCU_CHECK(dst.getType().getBaseType() == VariableType::TYPE_FLOAT);
163e5c31af7Sopenharmony_ci	for (int elemNdx = 0; elemNdx < dst.getType().getNumElements(); elemNdx++)
164e5c31af7Sopenharmony_ci		dst.component(elemNdx).asFloat() = src.component(elemNdx).asFloat(compNdx);
165e5c31af7Sopenharmony_ci}
166e5c31af7Sopenharmony_ci
167e5c31af7Sopenharmony_ciProgramExecutor::ProgramExecutor (const tcu::PixelBufferAccess& dst, int gridWidth, int gridHeight)
168e5c31af7Sopenharmony_ci	: m_dst			(dst)
169e5c31af7Sopenharmony_ci	, m_gridWidth	(gridWidth)
170e5c31af7Sopenharmony_ci	, m_gridHeight	(gridHeight)
171e5c31af7Sopenharmony_ci{
172e5c31af7Sopenharmony_ci}
173e5c31af7Sopenharmony_ci
174e5c31af7Sopenharmony_ciProgramExecutor::~ProgramExecutor (void)
175e5c31af7Sopenharmony_ci{
176e5c31af7Sopenharmony_ci}
177e5c31af7Sopenharmony_ci
178e5c31af7Sopenharmony_civoid ProgramExecutor::setTexture (int samplerNdx, const tcu::Texture2D* texture, const tcu::Sampler& sampler)
179e5c31af7Sopenharmony_ci{
180e5c31af7Sopenharmony_ci	m_samplers2D[samplerNdx] = Sampler2D(texture, sampler);
181e5c31af7Sopenharmony_ci}
182e5c31af7Sopenharmony_ci
183e5c31af7Sopenharmony_civoid ProgramExecutor::setTexture (int samplerNdx, const tcu::TextureCube* texture, const tcu::Sampler& sampler)
184e5c31af7Sopenharmony_ci{
185e5c31af7Sopenharmony_ci	m_samplersCube[samplerNdx] = SamplerCube(texture, sampler);
186e5c31af7Sopenharmony_ci}
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ciinline tcu::IVec4 computeVertexIndices (float cellWidth, float cellHeight, int gridVtxWidth, int gridVtxHeight, int x, int y)
189e5c31af7Sopenharmony_ci{
190e5c31af7Sopenharmony_ci	DE_UNREF(gridVtxHeight);
191e5c31af7Sopenharmony_ci	int x0 = (int)deFloatFloor((float)x / cellWidth);
192e5c31af7Sopenharmony_ci	int y0 = (int)deFloatFloor((float)y / cellHeight);
193e5c31af7Sopenharmony_ci	return tcu::IVec4(y0*gridVtxWidth + x0, y0*gridVtxWidth + x0 + 1, (y0+1)*gridVtxWidth + x0, (y0+1)*gridVtxWidth + x0 + 1);
194e5c31af7Sopenharmony_ci}
195e5c31af7Sopenharmony_ci
196e5c31af7Sopenharmony_ciinline tcu::Vec2 computeGridCellWeights (float cellWidth, float cellHeight, int x, int y)
197e5c31af7Sopenharmony_ci{
198e5c31af7Sopenharmony_ci	float gx = ((float)x + 0.5f) / cellWidth;
199e5c31af7Sopenharmony_ci	float gy = ((float)y + 0.5f) / cellHeight;
200e5c31af7Sopenharmony_ci	return tcu::Vec2(deFloatFrac(gx), deFloatFrac(gy));
201e5c31af7Sopenharmony_ci}
202e5c31af7Sopenharmony_ci
203e5c31af7Sopenharmony_ciinline tcu::RGBA toColor (tcu::Vec4 rgba)
204e5c31af7Sopenharmony_ci{
205e5c31af7Sopenharmony_ci	return tcu::RGBA(deClamp32(deRoundFloatToInt32(rgba.x()*255), 0, 255),
206e5c31af7Sopenharmony_ci					 deClamp32(deRoundFloatToInt32(rgba.y()*255), 0, 255),
207e5c31af7Sopenharmony_ci					 deClamp32(deRoundFloatToInt32(rgba.z()*255), 0, 255),
208e5c31af7Sopenharmony_ci					 deClamp32(deRoundFloatToInt32(rgba.w()*255), 0, 255));
209e5c31af7Sopenharmony_ci}
210e5c31af7Sopenharmony_ci
211e5c31af7Sopenharmony_civoid ProgramExecutor::execute (const Shader& vertexShader, const Shader& fragmentShader, const vector<VariableValue>& uniformValues)
212e5c31af7Sopenharmony_ci{
213e5c31af7Sopenharmony_ci	int	gridVtxWidth	= m_gridWidth+1;
214e5c31af7Sopenharmony_ci	int gridVtxHeight	= m_gridHeight+1;
215e5c31af7Sopenharmony_ci	int numVertices		= gridVtxWidth*gridVtxHeight;
216e5c31af7Sopenharmony_ci
217e5c31af7Sopenharmony_ci	VaryingStore varyingStore(numVertices);
218e5c31af7Sopenharmony_ci
219e5c31af7Sopenharmony_ci	// Execute vertex shader
220e5c31af7Sopenharmony_ci	{
221e5c31af7Sopenharmony_ci		ExecutionContext	execCtx(m_samplers2D, m_samplersCube);
222e5c31af7Sopenharmony_ci		int					numPackets	= numVertices + ((numVertices%EXEC_VEC_WIDTH) ? 1 : 0);
223e5c31af7Sopenharmony_ci
224e5c31af7Sopenharmony_ci		const vector<ShaderInput*>& inputs	= vertexShader.getInputs();
225e5c31af7Sopenharmony_ci		vector<const Variable*>		outputs;
226e5c31af7Sopenharmony_ci		vertexShader.getOutputs(outputs);
227e5c31af7Sopenharmony_ci
228e5c31af7Sopenharmony_ci		// Set uniform values
229e5c31af7Sopenharmony_ci		for (vector<VariableValue>::const_iterator uniformIter = uniformValues.begin(); uniformIter != uniformValues.end(); uniformIter++)
230e5c31af7Sopenharmony_ci			execCtx.getValue(uniformIter->getVariable()) = uniformIter->getValue().value();
231e5c31af7Sopenharmony_ci
232e5c31af7Sopenharmony_ci		for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
233e5c31af7Sopenharmony_ci		{
234e5c31af7Sopenharmony_ci			int packetStart	= packetNdx*EXEC_VEC_WIDTH;
235e5c31af7Sopenharmony_ci			int packetEnd	= deMin32((packetNdx+1)*EXEC_VEC_WIDTH, numVertices);
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ci			// Compute values for vertex shader inputs
238e5c31af7Sopenharmony_ci			for (vector<ShaderInput*>::const_iterator i = inputs.begin(); i != inputs.end(); i++)
239e5c31af7Sopenharmony_ci			{
240e5c31af7Sopenharmony_ci				const ShaderInput*	input	= *i;
241e5c31af7Sopenharmony_ci				ExecValueAccess		access	= execCtx.getValue(input->getVariable());
242e5c31af7Sopenharmony_ci
243e5c31af7Sopenharmony_ci				for (int vtxNdx = packetStart; vtxNdx < packetEnd; vtxNdx++)
244e5c31af7Sopenharmony_ci				{
245e5c31af7Sopenharmony_ci					int		y	= (vtxNdx/gridVtxWidth);
246e5c31af7Sopenharmony_ci					int		x	= vtxNdx - y*gridVtxWidth;
247e5c31af7Sopenharmony_ci					float	xf	= (float)x / (float)(gridVtxWidth-1);
248e5c31af7Sopenharmony_ci					float	yf	= (float)y / (float)(gridVtxHeight-1);
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_ci					interpolateVertexInput(access, vtxNdx-packetStart, input->getValueRange(), xf, yf);
251e5c31af7Sopenharmony_ci				}
252e5c31af7Sopenharmony_ci			}
253e5c31af7Sopenharmony_ci
254e5c31af7Sopenharmony_ci			// Execute vertex shader for packet
255e5c31af7Sopenharmony_ci			vertexShader.execute(execCtx);
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_ci			// Store output values
258e5c31af7Sopenharmony_ci			for (vector<const Variable*>::const_iterator i = outputs.begin(); i != outputs.end(); i++)
259e5c31af7Sopenharmony_ci			{
260e5c31af7Sopenharmony_ci				const Variable*			output	= *i;
261e5c31af7Sopenharmony_ci
262e5c31af7Sopenharmony_ci				if (deStringEqual(output->getName(), "gl_Position"))
263e5c31af7Sopenharmony_ci					continue; // Do not store position
264e5c31af7Sopenharmony_ci
265e5c31af7Sopenharmony_ci				ExecConstValueAccess	access	= execCtx.getValue(output);
266e5c31af7Sopenharmony_ci				VaryingStorage*			dst		= varyingStore.getStorage(output->getType(), output->getName());
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci				for (int vtxNdx = packetStart; vtxNdx < packetEnd; vtxNdx++)
269e5c31af7Sopenharmony_ci				{
270e5c31af7Sopenharmony_ci					ValueAccess varyingAccess = dst->getValue(output->getType(), vtxNdx);
271e5c31af7Sopenharmony_ci					copyVarying(varyingAccess, access, vtxNdx-packetStart);
272e5c31af7Sopenharmony_ci				}
273e5c31af7Sopenharmony_ci			}
274e5c31af7Sopenharmony_ci		}
275e5c31af7Sopenharmony_ci	}
276e5c31af7Sopenharmony_ci
277e5c31af7Sopenharmony_ci	// Execute fragment shader
278e5c31af7Sopenharmony_ci	{
279e5c31af7Sopenharmony_ci		ExecutionContext execCtx(m_samplers2D, m_samplersCube);
280e5c31af7Sopenharmony_ci
281e5c31af7Sopenharmony_ci		// Assign uniform values
282e5c31af7Sopenharmony_ci		for (vector<VariableValue>::const_iterator i = uniformValues.begin(); i != uniformValues.end(); i++)
283e5c31af7Sopenharmony_ci			execCtx.getValue(i->getVariable()) = i->getValue().value();
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_ci		const vector<ShaderInput*>& inputs			= fragmentShader.getInputs();
286e5c31af7Sopenharmony_ci		const Variable*				fragColorVar	= DE_NULL;
287e5c31af7Sopenharmony_ci		vector<const Variable*>		outputs;
288e5c31af7Sopenharmony_ci
289e5c31af7Sopenharmony_ci		// Find fragment shader output assigned to location 0. This is fragment color.
290e5c31af7Sopenharmony_ci		fragmentShader.getOutputs(outputs);
291e5c31af7Sopenharmony_ci		for (vector<const Variable*>::const_iterator i = outputs.begin(); i != outputs.end(); i++)
292e5c31af7Sopenharmony_ci		{
293e5c31af7Sopenharmony_ci			if ((*i)->getLayoutLocation() == 0)
294e5c31af7Sopenharmony_ci			{
295e5c31af7Sopenharmony_ci				fragColorVar = *i;
296e5c31af7Sopenharmony_ci				break;
297e5c31af7Sopenharmony_ci			}
298e5c31af7Sopenharmony_ci		}
299e5c31af7Sopenharmony_ci		TCU_CHECK(fragColorVar);
300e5c31af7Sopenharmony_ci
301e5c31af7Sopenharmony_ci		int	width		= m_dst.getWidth();
302e5c31af7Sopenharmony_ci		int height		= m_dst.getHeight();
303e5c31af7Sopenharmony_ci		int numPackets	= (width*height)/EXEC_VEC_WIDTH + (((width*height)%EXEC_VEC_WIDTH) ? 1 : 0);
304e5c31af7Sopenharmony_ci
305e5c31af7Sopenharmony_ci		float cellWidth		= (float)width	/ (float)m_gridWidth;
306e5c31af7Sopenharmony_ci		float cellHeight	= (float)height	/ (float)m_gridHeight;
307e5c31af7Sopenharmony_ci
308e5c31af7Sopenharmony_ci		for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
309e5c31af7Sopenharmony_ci		{
310e5c31af7Sopenharmony_ci			int packetStart	= packetNdx*EXEC_VEC_WIDTH;
311e5c31af7Sopenharmony_ci			int packetEnd	= deMin32((packetNdx+1)*EXEC_VEC_WIDTH, width*height);
312e5c31af7Sopenharmony_ci
313e5c31af7Sopenharmony_ci			// Interpolate varyings
314e5c31af7Sopenharmony_ci			for (vector<ShaderInput*>::const_iterator i = inputs.begin(); i != inputs.end(); i++)
315e5c31af7Sopenharmony_ci			{
316e5c31af7Sopenharmony_ci				const ShaderInput*		input	= *i;
317e5c31af7Sopenharmony_ci				ExecValueAccess			access	= execCtx.getValue(input->getVariable());
318e5c31af7Sopenharmony_ci				const VariableType&		type	= input->getVariable()->getType();
319e5c31af7Sopenharmony_ci				const VaryingStorage*	src		= varyingStore.getStorage(type, input->getVariable()->getName());
320e5c31af7Sopenharmony_ci
321e5c31af7Sopenharmony_ci				// \todo [2011-03-08 pyry] Part of this could be pre-computed...
322e5c31af7Sopenharmony_ci				for (int fragNdx = packetStart; fragNdx < packetEnd; fragNdx++)
323e5c31af7Sopenharmony_ci				{
324e5c31af7Sopenharmony_ci					int y = fragNdx/width;
325e5c31af7Sopenharmony_ci					int x = fragNdx - y*width;
326e5c31af7Sopenharmony_ci					tcu::IVec4	vtxIndices	= computeVertexIndices(cellWidth, cellHeight, gridVtxWidth, gridVtxHeight, x, y);
327e5c31af7Sopenharmony_ci					tcu::Vec2	weights		= computeGridCellWeights(cellWidth, cellHeight, x, y);
328e5c31af7Sopenharmony_ci
329e5c31af7Sopenharmony_ci					interpolateFragmentInput(access, fragNdx-packetStart,
330e5c31af7Sopenharmony_ci											 src->getValue(type, vtxIndices.x()),
331e5c31af7Sopenharmony_ci											 src->getValue(type, vtxIndices.y()),
332e5c31af7Sopenharmony_ci											 src->getValue(type, vtxIndices.z()),
333e5c31af7Sopenharmony_ci											 src->getValue(type, vtxIndices.w()),
334e5c31af7Sopenharmony_ci											 weights.x(), weights.y());
335e5c31af7Sopenharmony_ci				}
336e5c31af7Sopenharmony_ci			}
337e5c31af7Sopenharmony_ci
338e5c31af7Sopenharmony_ci			// Execute fragment shader
339e5c31af7Sopenharmony_ci			fragmentShader.execute(execCtx);
340e5c31af7Sopenharmony_ci
341e5c31af7Sopenharmony_ci			// Write resulting color
342e5c31af7Sopenharmony_ci			ExecConstValueAccess colorValue = execCtx.getValue(fragColorVar);
343e5c31af7Sopenharmony_ci			for (int fragNdx = packetStart; fragNdx < packetEnd; fragNdx++)
344e5c31af7Sopenharmony_ci			{
345e5c31af7Sopenharmony_ci				int			y		= fragNdx/width;
346e5c31af7Sopenharmony_ci				int			x		= fragNdx - y*width;
347e5c31af7Sopenharmony_ci				int			cNdx	= fragNdx-packetStart;
348e5c31af7Sopenharmony_ci				tcu::Vec4	c		= tcu::Vec4(colorValue.component(0).asFloat(cNdx),
349e5c31af7Sopenharmony_ci												colorValue.component(1).asFloat(cNdx),
350e5c31af7Sopenharmony_ci												colorValue.component(2).asFloat(cNdx),
351e5c31af7Sopenharmony_ci												colorValue.component(3).asFloat(cNdx));
352e5c31af7Sopenharmony_ci
353e5c31af7Sopenharmony_ci				// \todo [2012-11-13 pyry] Reverse order.
354e5c31af7Sopenharmony_ci				m_dst.setPixel(c, x, m_dst.getHeight()-y-1);
355e5c31af7Sopenharmony_ci			}
356e5c31af7Sopenharmony_ci		}
357e5c31af7Sopenharmony_ci	}
358e5c31af7Sopenharmony_ci}
359e5c31af7Sopenharmony_ci
360e5c31af7Sopenharmony_ci} // rsg
361