1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL (ES) Module
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 sglr-rsg adaptation.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "glsRandomShaderProgram.hpp"
25e5c31af7Sopenharmony_ci#include "rsgShader.hpp"
26e5c31af7Sopenharmony_ci
27e5c31af7Sopenharmony_cinamespace deqp
28e5c31af7Sopenharmony_ci{
29e5c31af7Sopenharmony_cinamespace gls
30e5c31af7Sopenharmony_ci{
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ciusing std::vector;
33e5c31af7Sopenharmony_ci
34e5c31af7Sopenharmony_cistatic rr::GenericVecType mapToGenericVecType (const rsg::VariableType& varType)
35e5c31af7Sopenharmony_ci{
36e5c31af7Sopenharmony_ci	if (varType.isFloatOrVec())
37e5c31af7Sopenharmony_ci		return rr::GENERICVECTYPE_FLOAT;
38e5c31af7Sopenharmony_ci	else if (varType.isIntOrVec())
39e5c31af7Sopenharmony_ci		return rr::GENERICVECTYPE_INT32;
40e5c31af7Sopenharmony_ci	else
41e5c31af7Sopenharmony_ci	{
42e5c31af7Sopenharmony_ci		DE_ASSERT(false);
43e5c31af7Sopenharmony_ci		return rr::GENERICVECTYPE_LAST;
44e5c31af7Sopenharmony_ci	}
45e5c31af7Sopenharmony_ci}
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_cistatic glu::DataType mapToBasicType (const rsg::VariableType& varType)
48e5c31af7Sopenharmony_ci{
49e5c31af7Sopenharmony_ci	if (varType.isFloatOrVec() || varType.isIntOrVec() || varType.isBoolOrVec())
50e5c31af7Sopenharmony_ci	{
51e5c31af7Sopenharmony_ci		const glu::DataType		scalarType		= varType.isFloatOrVec()	? glu::TYPE_FLOAT	:
52e5c31af7Sopenharmony_ci												  varType.isIntOrVec()		? glu::TYPE_INT		:
53e5c31af7Sopenharmony_ci												  varType.isBoolOrVec()		? glu::TYPE_BOOL	: glu::TYPE_LAST;
54e5c31af7Sopenharmony_ci		const int				numComps		= varType.getNumElements();
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_ci		DE_ASSERT(de::inRange(numComps, 1, 4));
57e5c31af7Sopenharmony_ci		return glu::DataType(scalarType + numComps - 1);
58e5c31af7Sopenharmony_ci	}
59e5c31af7Sopenharmony_ci	else if (varType.getBaseType() == rsg::VariableType::TYPE_SAMPLER_2D)
60e5c31af7Sopenharmony_ci		return glu::TYPE_SAMPLER_2D;
61e5c31af7Sopenharmony_ci	else if (varType.getBaseType() == rsg::VariableType::TYPE_SAMPLER_CUBE)
62e5c31af7Sopenharmony_ci		return glu::TYPE_SAMPLER_CUBE;
63e5c31af7Sopenharmony_ci	else
64e5c31af7Sopenharmony_ci	{
65e5c31af7Sopenharmony_ci		DE_ASSERT(false);
66e5c31af7Sopenharmony_ci		return glu::TYPE_LAST;
67e5c31af7Sopenharmony_ci	}
68e5c31af7Sopenharmony_ci}
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_cistatic void generateProgramDeclaration (sglr::pdec::ShaderProgramDeclaration& decl, const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
71e5c31af7Sopenharmony_ci{
72e5c31af7Sopenharmony_ci	decl << sglr::pdec::VertexSource(vertexShader.getSource())
73e5c31af7Sopenharmony_ci		 << sglr::pdec::FragmentSource(fragmentShader.getSource());
74e5c31af7Sopenharmony_ci
75e5c31af7Sopenharmony_ci	for (vector<rsg::ShaderInput*>::const_iterator vtxInIter = vertexShader.getInputs().begin(); vtxInIter != vertexShader.getInputs().end(); ++vtxInIter)
76e5c31af7Sopenharmony_ci	{
77e5c31af7Sopenharmony_ci		const rsg::ShaderInput*	vertexInput	= *vtxInIter;
78e5c31af7Sopenharmony_ci		decl << sglr::pdec::VertexAttribute(vertexInput->getVariable()->getName(), mapToGenericVecType(vertexInput->getVariable()->getType()));
79e5c31af7Sopenharmony_ci	}
80e5c31af7Sopenharmony_ci
81e5c31af7Sopenharmony_ci	for (vector<rsg::ShaderInput*>::const_iterator fragInIter = fragmentShader.getInputs().begin(); fragInIter != fragmentShader.getInputs().end(); ++fragInIter)
82e5c31af7Sopenharmony_ci	{
83e5c31af7Sopenharmony_ci		const rsg::ShaderInput*	fragInput	= *fragInIter;
84e5c31af7Sopenharmony_ci		decl << sglr::pdec::VertexToFragmentVarying(mapToGenericVecType(fragInput->getVariable()->getType()));
85e5c31af7Sopenharmony_ci	}
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_ci	for (int uniformNdx = 0; uniformNdx < numUnifiedUniforms; uniformNdx++)
88e5c31af7Sopenharmony_ci	{
89e5c31af7Sopenharmony_ci		const rsg::ShaderInput*	uniform	= unifiedUniforms[uniformNdx];
90e5c31af7Sopenharmony_ci		decl << sglr::pdec::Uniform(uniform->getVariable()->getName(), mapToBasicType(uniform->getVariable()->getType()));
91e5c31af7Sopenharmony_ci	}
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_ci	decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);
94e5c31af7Sopenharmony_ci}
95e5c31af7Sopenharmony_ci
96e5c31af7Sopenharmony_cistatic sglr::pdec::ShaderProgramDeclaration generateProgramDeclaration (const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
97e5c31af7Sopenharmony_ci{
98e5c31af7Sopenharmony_ci	sglr::pdec::ShaderProgramDeclaration decl;
99e5c31af7Sopenharmony_ci	generateProgramDeclaration(decl, vertexShader, fragmentShader, numUnifiedUniforms, unifiedUniforms);
100e5c31af7Sopenharmony_ci	return decl;
101e5c31af7Sopenharmony_ci}
102e5c31af7Sopenharmony_ci
103e5c31af7Sopenharmony_cistatic const rsg::Variable* findShaderOutputByName (const rsg::Shader& shader, const char* name)
104e5c31af7Sopenharmony_ci{
105e5c31af7Sopenharmony_ci	vector<const rsg::Variable*> outputs;
106e5c31af7Sopenharmony_ci	shader.getOutputs(outputs);
107e5c31af7Sopenharmony_ci
108e5c31af7Sopenharmony_ci	for (vector<const rsg::Variable*>::const_iterator iter = outputs.begin(); iter != outputs.end(); ++iter)
109e5c31af7Sopenharmony_ci	{
110e5c31af7Sopenharmony_ci		if (deStringEqual((*iter)->getName(), name))
111e5c31af7Sopenharmony_ci			return *iter;
112e5c31af7Sopenharmony_ci	}
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_ci	return DE_NULL;
115e5c31af7Sopenharmony_ci}
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_cistatic const rsg::Variable* findShaderOutputByLocation (const rsg::Shader& shader, int location)
118e5c31af7Sopenharmony_ci{
119e5c31af7Sopenharmony_ci	vector<const rsg::Variable*> outputs;
120e5c31af7Sopenharmony_ci	shader.getOutputs(outputs);
121e5c31af7Sopenharmony_ci
122e5c31af7Sopenharmony_ci	for (vector<const rsg::Variable*>::const_iterator iter = outputs.begin(); iter != outputs.end(); iter++)
123e5c31af7Sopenharmony_ci	{
124e5c31af7Sopenharmony_ci		if ((*iter)->getLayoutLocation() == location)
125e5c31af7Sopenharmony_ci			return *iter;
126e5c31af7Sopenharmony_ci	}
127e5c31af7Sopenharmony_ci
128e5c31af7Sopenharmony_ci	return DE_NULL;
129e5c31af7Sopenharmony_ci}
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ciRandomShaderProgram::RandomShaderProgram (const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
132e5c31af7Sopenharmony_ci	: sglr::ShaderProgram	(generateProgramDeclaration(vertexShader, fragmentShader, numUnifiedUniforms, unifiedUniforms))
133e5c31af7Sopenharmony_ci	, m_vertexShader		(vertexShader)
134e5c31af7Sopenharmony_ci	, m_fragmentShader		(fragmentShader)
135e5c31af7Sopenharmony_ci	, m_numUnifiedUniforms	(numUnifiedUniforms)
136e5c31af7Sopenharmony_ci	, m_unifiedUniforms		(unifiedUniforms)
137e5c31af7Sopenharmony_ci	, m_positionVar			(findShaderOutputByName(vertexShader, "gl_Position"))
138e5c31af7Sopenharmony_ci	, m_fragColorVar		(findShaderOutputByLocation(fragmentShader, 0))
139e5c31af7Sopenharmony_ci	, m_execCtx				(m_sampler2DMap, m_samplerCubeMap)
140e5c31af7Sopenharmony_ci{
141e5c31af7Sopenharmony_ci	TCU_CHECK_INTERNAL(m_positionVar && m_positionVar->getType().getBaseType() == rsg::VariableType::TYPE_FLOAT && m_positionVar->getType().getNumElements() == 4);
142e5c31af7Sopenharmony_ci	TCU_CHECK_INTERNAL(m_fragColorVar && m_fragColorVar->getType().getBaseType() == rsg::VariableType::TYPE_FLOAT && m_fragColorVar->getType().getNumElements() == 4);
143e5c31af7Sopenharmony_ci
144e5c31af7Sopenharmony_ci	// Build list of vertex outputs.
145e5c31af7Sopenharmony_ci	for (vector<rsg::ShaderInput*>::const_iterator fragInIter = fragmentShader.getInputs().begin(); fragInIter != fragmentShader.getInputs().end(); ++fragInIter)
146e5c31af7Sopenharmony_ci	{
147e5c31af7Sopenharmony_ci		const rsg::ShaderInput*	fragInput		= *fragInIter;
148e5c31af7Sopenharmony_ci		const rsg::Variable*	vertexOutput	= findShaderOutputByName(vertexShader, fragInput->getVariable()->getName());
149e5c31af7Sopenharmony_ci
150e5c31af7Sopenharmony_ci		TCU_CHECK_INTERNAL(vertexOutput);
151e5c31af7Sopenharmony_ci		m_vertexOutputs.push_back(vertexOutput);
152e5c31af7Sopenharmony_ci	}
153e5c31af7Sopenharmony_ci}
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_civoid RandomShaderProgram::refreshUniforms (void) const
156e5c31af7Sopenharmony_ci{
157e5c31af7Sopenharmony_ci	DE_ASSERT(m_numUnifiedUniforms == (int)m_uniforms.size());
158e5c31af7Sopenharmony_ci
159e5c31af7Sopenharmony_ci	for (int uniformNdx = 0; uniformNdx < m_numUnifiedUniforms; uniformNdx++)
160e5c31af7Sopenharmony_ci	{
161e5c31af7Sopenharmony_ci		const rsg::Variable*		uniformVar	= m_unifiedUniforms[uniformNdx]->getVariable();
162e5c31af7Sopenharmony_ci		const rsg::VariableType&	uniformType	= uniformVar->getType();
163e5c31af7Sopenharmony_ci		const sglr::UniformSlot&	uniformSlot	= m_uniforms[uniformNdx];
164e5c31af7Sopenharmony_ci
165e5c31af7Sopenharmony_ci		m_execCtx.getValue(uniformVar) = rsg::ConstValueAccess(uniformType, (const rsg::Scalar*)&uniformSlot.value).value();
166e5c31af7Sopenharmony_ci	}
167e5c31af7Sopenharmony_ci}
168e5c31af7Sopenharmony_ci
169e5c31af7Sopenharmony_civoid RandomShaderProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
170e5c31af7Sopenharmony_ci{
171e5c31af7Sopenharmony_ci	// \todo [2013-12-13 pyry] Do only when necessary.
172e5c31af7Sopenharmony_ci	refreshUniforms();
173e5c31af7Sopenharmony_ci
174e5c31af7Sopenharmony_ci	int packetOffset = 0;
175e5c31af7Sopenharmony_ci
176e5c31af7Sopenharmony_ci	while (packetOffset < numPackets)
177e5c31af7Sopenharmony_ci	{
178e5c31af7Sopenharmony_ci		const int	numToExecute	= de::min(numPackets-packetOffset, (int)rsg::EXEC_VEC_WIDTH);
179e5c31af7Sopenharmony_ci
180e5c31af7Sopenharmony_ci		// Fetch attributes.
181e5c31af7Sopenharmony_ci		for (int attribNdx = 0; attribNdx < (int)m_vertexShader.getInputs().size(); ++attribNdx)
182e5c31af7Sopenharmony_ci		{
183e5c31af7Sopenharmony_ci			const rsg::Variable*		attribVar		= m_vertexShader.getInputs()[attribNdx]->getVariable();
184e5c31af7Sopenharmony_ci			const rsg::VariableType&	attribType		= attribVar->getType();
185e5c31af7Sopenharmony_ci			const int					numComponents	= attribType.getNumElements();
186e5c31af7Sopenharmony_ci			rsg::ExecValueAccess		access			= m_execCtx.getValue(attribVar);
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ci			DE_ASSERT(attribType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
189e5c31af7Sopenharmony_ci
190e5c31af7Sopenharmony_ci			for (int ndx = 0; ndx < numToExecute; ndx++)
191e5c31af7Sopenharmony_ci			{
192e5c31af7Sopenharmony_ci				const int				packetNdx	= ndx+packetOffset;
193e5c31af7Sopenharmony_ci				const rr::VertexPacket*	packet		= packets[packetNdx];
194e5c31af7Sopenharmony_ci				const tcu::Vec4			attribValue	= rr::readVertexAttribFloat(inputs[attribNdx], packet->instanceNdx, packet->vertexNdx);
195e5c31af7Sopenharmony_ci
196e5c31af7Sopenharmony_ci										access.component(0).asFloat(ndx) = attribValue[0];
197e5c31af7Sopenharmony_ci				if (numComponents >= 2)	access.component(1).asFloat(ndx) = attribValue[1];
198e5c31af7Sopenharmony_ci				if (numComponents >= 3)	access.component(2).asFloat(ndx) = attribValue[2];
199e5c31af7Sopenharmony_ci				if (numComponents >= 4)	access.component(3).asFloat(ndx) = attribValue[3];
200e5c31af7Sopenharmony_ci			}
201e5c31af7Sopenharmony_ci		}
202e5c31af7Sopenharmony_ci
203e5c31af7Sopenharmony_ci		m_vertexShader.execute(m_execCtx);
204e5c31af7Sopenharmony_ci
205e5c31af7Sopenharmony_ci		// Store position
206e5c31af7Sopenharmony_ci		{
207e5c31af7Sopenharmony_ci			const rsg::ExecConstValueAccess	access	= m_execCtx.getValue(m_positionVar);
208e5c31af7Sopenharmony_ci
209e5c31af7Sopenharmony_ci			for (int ndx = 0; ndx < numToExecute; ndx++)
210e5c31af7Sopenharmony_ci			{
211e5c31af7Sopenharmony_ci				const int			packetNdx	= ndx+packetOffset;
212e5c31af7Sopenharmony_ci				rr::VertexPacket*	packet		= packets[packetNdx];
213e5c31af7Sopenharmony_ci
214e5c31af7Sopenharmony_ci				packet->position[0] = access.component(0).asFloat(ndx);
215e5c31af7Sopenharmony_ci				packet->position[1] = access.component(1).asFloat(ndx);
216e5c31af7Sopenharmony_ci				packet->position[2] = access.component(2).asFloat(ndx);
217e5c31af7Sopenharmony_ci				packet->position[3] = access.component(3).asFloat(ndx);
218e5c31af7Sopenharmony_ci			}
219e5c31af7Sopenharmony_ci		}
220e5c31af7Sopenharmony_ci
221e5c31af7Sopenharmony_ci		// Other varyings
222e5c31af7Sopenharmony_ci		for (int varNdx = 0; varNdx < (int)m_vertexOutputs.size(); varNdx++)
223e5c31af7Sopenharmony_ci		{
224e5c31af7Sopenharmony_ci			const rsg::Variable*			var				= m_vertexOutputs[varNdx];
225e5c31af7Sopenharmony_ci			const rsg::VariableType&		varType			= var->getType();
226e5c31af7Sopenharmony_ci			const int						numComponents	= varType.getNumElements();
227e5c31af7Sopenharmony_ci			const rsg::ExecConstValueAccess	access			= m_execCtx.getValue(var);
228e5c31af7Sopenharmony_ci
229e5c31af7Sopenharmony_ci			DE_ASSERT(varType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
230e5c31af7Sopenharmony_ci
231e5c31af7Sopenharmony_ci			for (int ndx = 0; ndx < numToExecute; ndx++)
232e5c31af7Sopenharmony_ci			{
233e5c31af7Sopenharmony_ci				const int				packetNdx	= ndx+packetOffset;
234e5c31af7Sopenharmony_ci				rr::VertexPacket* const	packet		= packets[packetNdx];
235e5c31af7Sopenharmony_ci				float* const			dst			= packet->outputs[varNdx].getAccess<float>();
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ci										dst[0] = access.component(0).asFloat(ndx);
238e5c31af7Sopenharmony_ci				if (numComponents >= 2) dst[1] = access.component(1).asFloat(ndx);
239e5c31af7Sopenharmony_ci				if (numComponents >= 3) dst[2] = access.component(2).asFloat(ndx);
240e5c31af7Sopenharmony_ci				if (numComponents >= 4) dst[3] = access.component(3).asFloat(ndx);
241e5c31af7Sopenharmony_ci			}
242e5c31af7Sopenharmony_ci		}
243e5c31af7Sopenharmony_ci
244e5c31af7Sopenharmony_ci		packetOffset += numToExecute;
245e5c31af7Sopenharmony_ci	}
246e5c31af7Sopenharmony_ci}
247e5c31af7Sopenharmony_ci
248e5c31af7Sopenharmony_civoid RandomShaderProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
249e5c31af7Sopenharmony_ci{
250e5c31af7Sopenharmony_ci	const rsg::ExecConstValueAccess	fragColorAccess	= m_execCtx.getValue(m_fragColorVar);
251e5c31af7Sopenharmony_ci	int								packetOffset	= 0;
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(rsg::EXEC_VEC_WIDTH % rr::NUM_FRAGMENTS_PER_PACKET == 0);
254e5c31af7Sopenharmony_ci
255e5c31af7Sopenharmony_ci	while (packetOffset < numPackets)
256e5c31af7Sopenharmony_ci	{
257e5c31af7Sopenharmony_ci		const int	numPacketsToExecute	= de::min(numPackets-packetOffset, (int)rsg::EXEC_VEC_WIDTH / (int)rr::NUM_FRAGMENTS_PER_PACKET);
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_ci		// Interpolate varyings.
260e5c31af7Sopenharmony_ci		for (int varNdx = 0; varNdx < (int)m_fragmentShader.getInputs().size(); ++varNdx)
261e5c31af7Sopenharmony_ci		{
262e5c31af7Sopenharmony_ci			const rsg::Variable*		var				= m_fragmentShader.getInputs()[varNdx]->getVariable();
263e5c31af7Sopenharmony_ci			const rsg::VariableType&	varType			= var->getType();
264e5c31af7Sopenharmony_ci			const int					numComponents	= varType.getNumElements();
265e5c31af7Sopenharmony_ci			rsg::ExecValueAccess		access			= m_execCtx.getValue(var);
266e5c31af7Sopenharmony_ci
267e5c31af7Sopenharmony_ci			DE_ASSERT(varType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
268e5c31af7Sopenharmony_ci
269e5c31af7Sopenharmony_ci			for (int packetNdx = 0; packetNdx < numPacketsToExecute; packetNdx++)
270e5c31af7Sopenharmony_ci			{
271e5c31af7Sopenharmony_ci				const rr::FragmentPacket&	packet		= packets[packetOffset+packetNdx];
272e5c31af7Sopenharmony_ci
273e5c31af7Sopenharmony_ci				for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; fragNdx++)
274e5c31af7Sopenharmony_ci				{
275e5c31af7Sopenharmony_ci					const tcu::Vec4		varValue	= rr::readVarying<float>(packet, context, varNdx, fragNdx);
276e5c31af7Sopenharmony_ci					const int			dstNdx		= packetNdx*rr::NUM_FRAGMENTS_PER_PACKET + fragNdx;
277e5c31af7Sopenharmony_ci
278e5c31af7Sopenharmony_ci											access.component(0).asFloat(dstNdx) = varValue[0];
279e5c31af7Sopenharmony_ci					if (numComponents >= 2)	access.component(1).asFloat(dstNdx) = varValue[1];
280e5c31af7Sopenharmony_ci					if (numComponents >= 3)	access.component(2).asFloat(dstNdx) = varValue[2];
281e5c31af7Sopenharmony_ci					if (numComponents >= 4)	access.component(3).asFloat(dstNdx) = varValue[3];
282e5c31af7Sopenharmony_ci				}
283e5c31af7Sopenharmony_ci			}
284e5c31af7Sopenharmony_ci		}
285e5c31af7Sopenharmony_ci
286e5c31af7Sopenharmony_ci		m_fragmentShader.execute(m_execCtx);
287e5c31af7Sopenharmony_ci
288e5c31af7Sopenharmony_ci		// Store color
289e5c31af7Sopenharmony_ci		for (int packetNdx = 0; packetNdx < numPacketsToExecute; packetNdx++)
290e5c31af7Sopenharmony_ci		{
291e5c31af7Sopenharmony_ci			for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; fragNdx++)
292e5c31af7Sopenharmony_ci			{
293e5c31af7Sopenharmony_ci				const int		srcNdx	= packetNdx*rr::NUM_FRAGMENTS_PER_PACKET + fragNdx;
294e5c31af7Sopenharmony_ci				const tcu::Vec4 color	(fragColorAccess.component(0).asFloat(srcNdx),
295e5c31af7Sopenharmony_ci										 fragColorAccess.component(1).asFloat(srcNdx),
296e5c31af7Sopenharmony_ci										 fragColorAccess.component(2).asFloat(srcNdx),
297e5c31af7Sopenharmony_ci										 fragColorAccess.component(3).asFloat(srcNdx));
298e5c31af7Sopenharmony_ci
299e5c31af7Sopenharmony_ci				rr::writeFragmentOutput(context, packetOffset+packetNdx, fragNdx, 0, color);
300e5c31af7Sopenharmony_ci			}
301e5c31af7Sopenharmony_ci		}
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ci		packetOffset += numPacketsToExecute;
304e5c31af7Sopenharmony_ci	}
305e5c31af7Sopenharmony_ci}
306e5c31af7Sopenharmony_ci
307e5c31af7Sopenharmony_ci} // gls
308e5c31af7Sopenharmony_ci} // deqp
309