1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL (ES) Module
3 * -----------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief sglr-rsg adaptation.
22 *//*--------------------------------------------------------------------*/
24 #include "glsRandomShaderProgram.hpp"
25 #include "rsgShader.hpp"
34 static rr::GenericVecType mapToGenericVecType (const rsg::VariableType& varType)
36 if (varType.isFloatOrVec())
37 return rr::GENERICVECTYPE_FLOAT;
38 else if (varType.isIntOrVec())
39 return rr::GENERICVECTYPE_INT32;
43 return rr::GENERICVECTYPE_LAST;
47 static glu::DataType mapToBasicType (const rsg::VariableType& varType)
49 if (varType.isFloatOrVec() || varType.isIntOrVec() || varType.isBoolOrVec())
51 const glu::DataType scalarType = varType.isFloatOrVec() ? glu::TYPE_FLOAT :
52 varType.isIntOrVec() ? glu::TYPE_INT :
53 varType.isBoolOrVec() ? glu::TYPE_BOOL : glu::TYPE_LAST;
54 const int numComps = varType.getNumElements();
56 DE_ASSERT(de::inRange(numComps, 1, 4));
57 return glu::DataType(scalarType + numComps - 1);
59 else if (varType.getBaseType() == rsg::VariableType::TYPE_SAMPLER_2D)
60 return glu::TYPE_SAMPLER_2D;
61 else if (varType.getBaseType() == rsg::VariableType::TYPE_SAMPLER_CUBE)
62 return glu::TYPE_SAMPLER_CUBE;
66 return glu::TYPE_LAST;
70 static void generateProgramDeclaration (sglr::pdec::ShaderProgramDeclaration& decl, const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
72 decl << sglr::pdec::VertexSource(vertexShader.getSource())
73 << sglr::pdec::FragmentSource(fragmentShader.getSource());
75 for (vector<rsg::ShaderInput*>::const_iterator vtxInIter = vertexShader.getInputs().begin(); vtxInIter != vertexShader.getInputs().end(); ++vtxInIter)
77 const rsg::ShaderInput* vertexInput = *vtxInIter;
78 decl << sglr::pdec::VertexAttribute(vertexInput->getVariable()->getName(), mapToGenericVecType(vertexInput->getVariable()->getType()));
81 for (vector<rsg::ShaderInput*>::const_iterator fragInIter = fragmentShader.getInputs().begin(); fragInIter != fragmentShader.getInputs().end(); ++fragInIter)
83 const rsg::ShaderInput* fragInput = *fragInIter;
84 decl << sglr::pdec::VertexToFragmentVarying(mapToGenericVecType(fragInput->getVariable()->getType()));
87 for (int uniformNdx = 0; uniformNdx < numUnifiedUniforms; uniformNdx++)
89 const rsg::ShaderInput* uniform = unifiedUniforms[uniformNdx];
90 decl << sglr::pdec::Uniform(uniform->getVariable()->getName(), mapToBasicType(uniform->getVariable()->getType()));
93 decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);
96 static sglr::pdec::ShaderProgramDeclaration generateProgramDeclaration (const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
98 sglr::pdec::ShaderProgramDeclaration decl;
99 generateProgramDeclaration(decl, vertexShader, fragmentShader, numUnifiedUniforms, unifiedUniforms);
103 static const rsg::Variable* findShaderOutputByName (const rsg::Shader& shader, const char* name)
105 vector<const rsg::Variable*> outputs;
106 shader.getOutputs(outputs);
108 for (vector<const rsg::Variable*>::const_iterator iter = outputs.begin(); iter != outputs.end(); ++iter)
110 if (deStringEqual((*iter)->getName(), name))
117 static const rsg::Variable* findShaderOutputByLocation (const rsg::Shader& shader, int location)
119 vector<const rsg::Variable*> outputs;
120 shader.getOutputs(outputs);
122 for (vector<const rsg::Variable*>::const_iterator iter = outputs.begin(); iter != outputs.end(); iter++)
124 if ((*iter)->getLayoutLocation() == location)
131 RandomShaderProgram::RandomShaderProgram (const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
132 : sglr::ShaderProgram (generateProgramDeclaration(vertexShader, fragmentShader, numUnifiedUniforms, unifiedUniforms))
133 , m_vertexShader (vertexShader)
134 , m_fragmentShader (fragmentShader)
135 , m_numUnifiedUniforms (numUnifiedUniforms)
136 , m_unifiedUniforms (unifiedUniforms)
137 , m_positionVar (findShaderOutputByName(vertexShader, "gl_Position"))
138 , m_fragColorVar (findShaderOutputByLocation(fragmentShader, 0))
139 , m_execCtx (m_sampler2DMap, m_samplerCubeMap)
141 TCU_CHECK_INTERNAL(m_positionVar && m_positionVar->getType().getBaseType() == rsg::VariableType::TYPE_FLOAT && m_positionVar->getType().getNumElements() == 4);
142 TCU_CHECK_INTERNAL(m_fragColorVar && m_fragColorVar->getType().getBaseType() == rsg::VariableType::TYPE_FLOAT && m_fragColorVar->getType().getNumElements() == 4);
144 // Build list of vertex outputs.
145 for (vector<rsg::ShaderInput*>::const_iterator fragInIter = fragmentShader.getInputs().begin(); fragInIter != fragmentShader.getInputs().end(); ++fragInIter)
147 const rsg::ShaderInput* fragInput = *fragInIter;
148 const rsg::Variable* vertexOutput = findShaderOutputByName(vertexShader, fragInput->getVariable()->getName());
150 TCU_CHECK_INTERNAL(vertexOutput);
151 m_vertexOutputs.push_back(vertexOutput);
155 void RandomShaderProgram::refreshUniforms (void) const
157 DE_ASSERT(m_numUnifiedUniforms == (int)m_uniforms.size());
159 for (int uniformNdx = 0; uniformNdx < m_numUnifiedUniforms; uniformNdx++)
161 const rsg::Variable* uniformVar = m_unifiedUniforms[uniformNdx]->getVariable();
162 const rsg::VariableType& uniformType = uniformVar->getType();
163 const sglr::UniformSlot& uniformSlot = m_uniforms[uniformNdx];
165 m_execCtx.getValue(uniformVar) = rsg::ConstValueAccess(uniformType, (const rsg::Scalar*)&uniformSlot.value).value();
169 void RandomShaderProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
171 // \todo [2013-12-13 pyry] Do only when necessary.
174 int packetOffset = 0;
176 while (packetOffset < numPackets)
178 const int numToExecute = de::min(numPackets-packetOffset, (int)rsg::EXEC_VEC_WIDTH);
181 for (int attribNdx = 0; attribNdx < (int)m_vertexShader.getInputs().size(); ++attribNdx)
183 const rsg::Variable* attribVar = m_vertexShader.getInputs()[attribNdx]->getVariable();
184 const rsg::VariableType& attribType = attribVar->getType();
185 const int numComponents = attribType.getNumElements();
186 rsg::ExecValueAccess access = m_execCtx.getValue(attribVar);
188 DE_ASSERT(attribType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
190 for (int ndx = 0; ndx < numToExecute; ndx++)
192 const int packetNdx = ndx+packetOffset;
193 const rr::VertexPacket* packet = packets[packetNdx];
194 const tcu::Vec4 attribValue = rr::readVertexAttribFloat(inputs[attribNdx], packet->instanceNdx, packet->vertexNdx);
196 access.component(0).asFloat(ndx) = attribValue[0];
197 if (numComponents >= 2) access.component(1).asFloat(ndx) = attribValue[1];
198 if (numComponents >= 3) access.component(2).asFloat(ndx) = attribValue[2];
199 if (numComponents >= 4) access.component(3).asFloat(ndx) = attribValue[3];
203 m_vertexShader.execute(m_execCtx);
207 const rsg::ExecConstValueAccess access = m_execCtx.getValue(m_positionVar);
209 for (int ndx = 0; ndx < numToExecute; ndx++)
211 const int packetNdx = ndx+packetOffset;
212 rr::VertexPacket* packet = packets[packetNdx];
214 packet->position[0] = access.component(0).asFloat(ndx);
215 packet->position[1] = access.component(1).asFloat(ndx);
216 packet->position[2] = access.component(2).asFloat(ndx);
217 packet->position[3] = access.component(3).asFloat(ndx);
222 for (int varNdx = 0; varNdx < (int)m_vertexOutputs.size(); varNdx++)
224 const rsg::Variable* var = m_vertexOutputs[varNdx];
225 const rsg::VariableType& varType = var->getType();
226 const int numComponents = varType.getNumElements();
227 const rsg::ExecConstValueAccess access = m_execCtx.getValue(var);
229 DE_ASSERT(varType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
231 for (int ndx = 0; ndx < numToExecute; ndx++)
233 const int packetNdx = ndx+packetOffset;
234 rr::VertexPacket* const packet = packets[packetNdx];
235 float* const dst = packet->outputs[varNdx].getAccess<float>();
237 dst[0] = access.component(0).asFloat(ndx);
238 if (numComponents >= 2) dst[1] = access.component(1).asFloat(ndx);
239 if (numComponents >= 3) dst[2] = access.component(2).asFloat(ndx);
240 if (numComponents >= 4) dst[3] = access.component(3).asFloat(ndx);
244 packetOffset += numToExecute;
248 void RandomShaderProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
250 const rsg::ExecConstValueAccess fragColorAccess = m_execCtx.getValue(m_fragColorVar);
251 int packetOffset = 0;
253 DE_STATIC_ASSERT(rsg::EXEC_VEC_WIDTH % rr::NUM_FRAGMENTS_PER_PACKET == 0);
255 while (packetOffset < numPackets)
257 const int numPacketsToExecute = de::min(numPackets-packetOffset, (int)rsg::EXEC_VEC_WIDTH / (int)rr::NUM_FRAGMENTS_PER_PACKET);
259 // Interpolate varyings.
260 for (int varNdx = 0; varNdx < (int)m_fragmentShader.getInputs().size(); ++varNdx)
262 const rsg::Variable* var = m_fragmentShader.getInputs()[varNdx]->getVariable();
263 const rsg::VariableType& varType = var->getType();
264 const int numComponents = varType.getNumElements();
265 rsg::ExecValueAccess access = m_execCtx.getValue(var);
267 DE_ASSERT(varType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
269 for (int packetNdx = 0; packetNdx < numPacketsToExecute; packetNdx++)
271 const rr::FragmentPacket& packet = packets[packetOffset+packetNdx];
273 for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; fragNdx++)
275 const tcu::Vec4 varValue = rr::readVarying<float>(packet, context, varNdx, fragNdx);
276 const int dstNdx = packetNdx*rr::NUM_FRAGMENTS_PER_PACKET + fragNdx;
278 access.component(0).asFloat(dstNdx) = varValue[0];
279 if (numComponents >= 2) access.component(1).asFloat(dstNdx) = varValue[1];
280 if (numComponents >= 3) access.component(2).asFloat(dstNdx) = varValue[2];
281 if (numComponents >= 4) access.component(3).asFloat(dstNdx) = varValue[3];
286 m_fragmentShader.execute(m_execCtx);
289 for (int packetNdx = 0; packetNdx < numPacketsToExecute; packetNdx++)
291 for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; fragNdx++)
293 const int srcNdx = packetNdx*rr::NUM_FRAGMENTS_PER_PACKET + fragNdx;
294 const tcu::Vec4 color (fragColorAccess.component(0).asFloat(srcNdx),
295 fragColorAccess.component(1).asFloat(srcNdx),
296 fragColorAccess.component(2).asFloat(srcNdx),
297 fragColorAccess.component(3).asFloat(srcNdx));
299 rr::writeFragmentOutput(context, packetOffset+packetNdx, fragNdx, 0, color);
303 packetOffset += numPacketsToExecute;