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