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 Compiler test case. 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "glsShaderLibraryCase.hpp" 25e5c31af7Sopenharmony_ci 26e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 27e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp" 28e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp" 29e5c31af7Sopenharmony_ci#include "tcuSurface.hpp" 30e5c31af7Sopenharmony_ci 31e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp" 32e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp" 33e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp" 34e5c31af7Sopenharmony_ci#include "gluDrawUtil.hpp" 35e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp" 36e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp" 37e5c31af7Sopenharmony_ci 38e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 39e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 40e5c31af7Sopenharmony_ci 41e5c31af7Sopenharmony_ci#include "deRandom.hpp" 42e5c31af7Sopenharmony_ci#include "deInt32.h" 43e5c31af7Sopenharmony_ci#include "deMath.h" 44e5c31af7Sopenharmony_ci#include "deString.h" 45e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 46e5c31af7Sopenharmony_ci#include "deSharedPtr.hpp" 47e5c31af7Sopenharmony_ci 48e5c31af7Sopenharmony_ci#include <map> 49e5c31af7Sopenharmony_ci#include <vector> 50e5c31af7Sopenharmony_ci#include <string> 51e5c31af7Sopenharmony_ci#include <sstream> 52e5c31af7Sopenharmony_ci 53e5c31af7Sopenharmony_cinamespace deqp 54e5c31af7Sopenharmony_ci{ 55e5c31af7Sopenharmony_cinamespace gls 56e5c31af7Sopenharmony_ci{ 57e5c31af7Sopenharmony_ci 58e5c31af7Sopenharmony_ciusing namespace tcu; 59e5c31af7Sopenharmony_ciusing namespace glu; 60e5c31af7Sopenharmony_ciusing namespace glu::sl; 61e5c31af7Sopenharmony_ci 62e5c31af7Sopenharmony_ciusing std::vector; 63e5c31af7Sopenharmony_ciusing std::string; 64e5c31af7Sopenharmony_ciusing std::ostringstream; 65e5c31af7Sopenharmony_ciusing std::map; 66e5c31af7Sopenharmony_ciusing std::pair; 67e5c31af7Sopenharmony_ci 68e5c31af7Sopenharmony_ciusing de::SharedPtr; 69e5c31af7Sopenharmony_ci 70e5c31af7Sopenharmony_ci// OpenGL-specific specialization utils 71e5c31af7Sopenharmony_ci 72e5c31af7Sopenharmony_cistatic vector<RequiredExtension> checkAndSpecializeExtensions (const vector<RequiredExtension>& src, 73e5c31af7Sopenharmony_ci const ContextInfo& ctxInfo) 74e5c31af7Sopenharmony_ci{ 75e5c31af7Sopenharmony_ci vector<RequiredExtension> specialized; 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_ci for (size_t extNdx = 0; extNdx < src.size(); ++extNdx) 78e5c31af7Sopenharmony_ci { 79e5c31af7Sopenharmony_ci const RequiredExtension& extension = src[extNdx]; 80e5c31af7Sopenharmony_ci int supportedAltNdx = -1; 81e5c31af7Sopenharmony_ci 82e5c31af7Sopenharmony_ci for (size_t alternativeNdx = 0; alternativeNdx < extension.alternatives.size(); ++alternativeNdx) 83e5c31af7Sopenharmony_ci { 84e5c31af7Sopenharmony_ci if (ctxInfo.isExtensionSupported(extension.alternatives[alternativeNdx].c_str())) 85e5c31af7Sopenharmony_ci { 86e5c31af7Sopenharmony_ci supportedAltNdx = (int)alternativeNdx; 87e5c31af7Sopenharmony_ci break; 88e5c31af7Sopenharmony_ci } 89e5c31af7Sopenharmony_ci } 90e5c31af7Sopenharmony_ci 91e5c31af7Sopenharmony_ci if (supportedAltNdx >= 0) 92e5c31af7Sopenharmony_ci { 93e5c31af7Sopenharmony_ci specialized.push_back(RequiredExtension(extension.alternatives[supportedAltNdx], extension.effectiveStages)); 94e5c31af7Sopenharmony_ci } 95e5c31af7Sopenharmony_ci else 96e5c31af7Sopenharmony_ci { 97e5c31af7Sopenharmony_ci // no extension(s). Make a nice output 98e5c31af7Sopenharmony_ci std::ostringstream extensionList; 99e5c31af7Sopenharmony_ci 100e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < extension.alternatives.size(); ++ndx) 101e5c31af7Sopenharmony_ci { 102e5c31af7Sopenharmony_ci if (!extensionList.str().empty()) 103e5c31af7Sopenharmony_ci extensionList << ", "; 104e5c31af7Sopenharmony_ci extensionList << extension.alternatives[ndx]; 105e5c31af7Sopenharmony_ci } 106e5c31af7Sopenharmony_ci 107e5c31af7Sopenharmony_ci if (extension.alternatives.size() == 1) 108e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Test requires extension " + extensionList.str()); 109e5c31af7Sopenharmony_ci else 110e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Test requires any extension of " + extensionList.str()); 111e5c31af7Sopenharmony_ci } 112e5c31af7Sopenharmony_ci } 113e5c31af7Sopenharmony_ci 114e5c31af7Sopenharmony_ci return specialized; 115e5c31af7Sopenharmony_ci} 116e5c31af7Sopenharmony_ci 117e5c31af7Sopenharmony_cistatic void checkImplementationLimits (const vector<RequiredCapability>& requiredCaps, 118e5c31af7Sopenharmony_ci const ContextInfo& ctxInfo) 119e5c31af7Sopenharmony_ci{ 120e5c31af7Sopenharmony_ci for (size_t capNdx = 0; capNdx < requiredCaps.size(); ++capNdx) 121e5c31af7Sopenharmony_ci { 122e5c31af7Sopenharmony_ci const RequiredCapability& capability = requiredCaps[capNdx]; 123e5c31af7Sopenharmony_ci if (capability.type != CAPABILITY_LIMIT) 124e5c31af7Sopenharmony_ci continue; 125e5c31af7Sopenharmony_ci 126e5c31af7Sopenharmony_ci const deUint32 pname = capability.enumName; 127e5c31af7Sopenharmony_ci const int requiredValue = capability.referenceValue; 128e5c31af7Sopenharmony_ci const int supportedValue = ctxInfo.getInt((int)pname); 129e5c31af7Sopenharmony_ci 130e5c31af7Sopenharmony_ci if (supportedValue <= requiredValue) 131e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Test requires " + de::toString(glu::getGettableStateStr(pname)) + " (" + de::toString(supportedValue) + ") >= " + de::toString(requiredValue)); 132e5c31af7Sopenharmony_ci } 133e5c31af7Sopenharmony_ci} 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_ci// Shader source specialization 136e5c31af7Sopenharmony_ci 137e5c31af7Sopenharmony_ci// This functions builds a matching vertex shader for a 'both' case, when 138e5c31af7Sopenharmony_ci// the fragment shader is being tested. 139e5c31af7Sopenharmony_ci// We need to build attributes and varyings for each 'input'. 140e5c31af7Sopenharmony_cistatic string genVertexShader (const ShaderCaseSpecification& spec) 141e5c31af7Sopenharmony_ci{ 142e5c31af7Sopenharmony_ci ostringstream res; 143e5c31af7Sopenharmony_ci const bool usesInout = glslVersionUsesInOutQualifiers(spec.targetVersion); 144e5c31af7Sopenharmony_ci const char* const vtxIn = usesInout ? "in" : "attribute"; 145e5c31af7Sopenharmony_ci const char* const vtxOut = usesInout ? "out" : "varying"; 146e5c31af7Sopenharmony_ci 147e5c31af7Sopenharmony_ci res << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n"; 148e5c31af7Sopenharmony_ci 149e5c31af7Sopenharmony_ci // Declarations (position + attribute/varying for each input). 150e5c31af7Sopenharmony_ci res << "precision highp float;\n"; 151e5c31af7Sopenharmony_ci res << "precision highp int;\n"; 152e5c31af7Sopenharmony_ci res << "\n"; 153e5c31af7Sopenharmony_ci res << vtxIn << " highp vec4 dEQP_Position;\n"; 154e5c31af7Sopenharmony_ci 155e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++) 156e5c31af7Sopenharmony_ci { 157e5c31af7Sopenharmony_ci const Value& val = spec.values.inputs[ndx]; 158e5c31af7Sopenharmony_ci const DataType basicType = val.type.getBasicType(); 159e5c31af7Sopenharmony_ci const DataType floatType = getDataTypeFloatScalars(basicType); 160e5c31af7Sopenharmony_ci const char* const typeStr = getDataTypeName(floatType); 161e5c31af7Sopenharmony_ci 162e5c31af7Sopenharmony_ci res << vtxIn << " " << typeStr << " a_" << val.name << ";\n"; 163e5c31af7Sopenharmony_ci 164e5c31af7Sopenharmony_ci if (getDataTypeScalarType(basicType) == TYPE_FLOAT) 165e5c31af7Sopenharmony_ci res << vtxOut << " " << typeStr << " " << val.name << ";\n"; 166e5c31af7Sopenharmony_ci else 167e5c31af7Sopenharmony_ci res << vtxOut << " " << typeStr << " v_" << val.name << ";\n"; 168e5c31af7Sopenharmony_ci } 169e5c31af7Sopenharmony_ci res << "\n"; 170e5c31af7Sopenharmony_ci 171e5c31af7Sopenharmony_ci // Main function. 172e5c31af7Sopenharmony_ci // - gl_Position = dEQP_Position; 173e5c31af7Sopenharmony_ci // - for each input: write attribute directly to varying 174e5c31af7Sopenharmony_ci res << "void main()\n"; 175e5c31af7Sopenharmony_ci res << "{\n"; 176e5c31af7Sopenharmony_ci res << " gl_Position = dEQP_Position;\n"; 177e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++) 178e5c31af7Sopenharmony_ci { 179e5c31af7Sopenharmony_ci const Value& val = spec.values.inputs[ndx]; 180e5c31af7Sopenharmony_ci const string& name = val.name; 181e5c31af7Sopenharmony_ci 182e5c31af7Sopenharmony_ci if (getDataTypeScalarType(val.type.getBasicType()) == TYPE_FLOAT) 183e5c31af7Sopenharmony_ci res << " " << name << " = a_" << name << ";\n"; 184e5c31af7Sopenharmony_ci else 185e5c31af7Sopenharmony_ci res << " v_" << name << " = a_" << name << ";\n"; 186e5c31af7Sopenharmony_ci } 187e5c31af7Sopenharmony_ci 188e5c31af7Sopenharmony_ci res << "}\n"; 189e5c31af7Sopenharmony_ci return res.str(); 190e5c31af7Sopenharmony_ci} 191e5c31af7Sopenharmony_ci 192e5c31af7Sopenharmony_cistatic void genCompareOp (ostringstream& output, const char* dstVec4Var, const ValueBlock& valueBlock, const char* nonFloatNamePrefix, const char* checkVarName) 193e5c31af7Sopenharmony_ci{ 194e5c31af7Sopenharmony_ci bool isFirstOutput = true; 195e5c31af7Sopenharmony_ci 196e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < valueBlock.outputs.size(); ndx++) 197e5c31af7Sopenharmony_ci { 198e5c31af7Sopenharmony_ci const Value& val = valueBlock.outputs[ndx]; 199e5c31af7Sopenharmony_ci 200e5c31af7Sopenharmony_ci // Check if we're only interested in one variable (then skip if not the right one). 201e5c31af7Sopenharmony_ci if (checkVarName && val.name != checkVarName) 202e5c31af7Sopenharmony_ci continue; 203e5c31af7Sopenharmony_ci 204e5c31af7Sopenharmony_ci // Prefix. 205e5c31af7Sopenharmony_ci if (isFirstOutput) 206e5c31af7Sopenharmony_ci { 207e5c31af7Sopenharmony_ci output << "bool RES = "; 208e5c31af7Sopenharmony_ci isFirstOutput = false; 209e5c31af7Sopenharmony_ci } 210e5c31af7Sopenharmony_ci else 211e5c31af7Sopenharmony_ci output << "RES = RES && "; 212e5c31af7Sopenharmony_ci 213e5c31af7Sopenharmony_ci // Generate actual comparison. 214e5c31af7Sopenharmony_ci if (getDataTypeScalarType(val.type.getBasicType()) == TYPE_FLOAT) 215e5c31af7Sopenharmony_ci output << "isOk(" << val.name << ", ref_" << val.name << ", 0.05);\n"; 216e5c31af7Sopenharmony_ci else 217e5c31af7Sopenharmony_ci output << "isOk(" << nonFloatNamePrefix << val.name << ", ref_" << val.name << ");\n"; 218e5c31af7Sopenharmony_ci } 219e5c31af7Sopenharmony_ci 220e5c31af7Sopenharmony_ci if (isFirstOutput) 221e5c31af7Sopenharmony_ci output << dstVec4Var << " = vec4(1.0);\n"; // \todo [petri] Should we give warning if not expect-failure case? 222e5c31af7Sopenharmony_ci else 223e5c31af7Sopenharmony_ci output << dstVec4Var << " = vec4(RES, RES, RES, 1.0);\n"; 224e5c31af7Sopenharmony_ci} 225e5c31af7Sopenharmony_ci 226e5c31af7Sopenharmony_cistatic inline bool supportsFragmentHighp (glu::GLSLVersion version) 227e5c31af7Sopenharmony_ci{ 228e5c31af7Sopenharmony_ci return version != glu::GLSL_VERSION_100_ES; 229e5c31af7Sopenharmony_ci} 230e5c31af7Sopenharmony_ci 231e5c31af7Sopenharmony_cistatic string genFragmentShader (const ShaderCaseSpecification& spec) 232e5c31af7Sopenharmony_ci{ 233e5c31af7Sopenharmony_ci ostringstream shader; 234e5c31af7Sopenharmony_ci const bool usesInout = glslVersionUsesInOutQualifiers(spec.targetVersion); 235e5c31af7Sopenharmony_ci const bool customColorOut = usesInout; 236e5c31af7Sopenharmony_ci const char* const fragIn = usesInout ? "in" : "varying"; 237e5c31af7Sopenharmony_ci const char* const prec = supportsFragmentHighp(spec.targetVersion) ? "highp" : "mediump"; 238e5c31af7Sopenharmony_ci 239e5c31af7Sopenharmony_ci shader << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n"; 240e5c31af7Sopenharmony_ci 241e5c31af7Sopenharmony_ci shader << "precision " << prec << " float;\n"; 242e5c31af7Sopenharmony_ci shader << "precision " << prec << " int;\n"; 243e5c31af7Sopenharmony_ci shader << "\n"; 244e5c31af7Sopenharmony_ci 245e5c31af7Sopenharmony_ci if (customColorOut) 246e5c31af7Sopenharmony_ci { 247e5c31af7Sopenharmony_ci shader << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 248e5c31af7Sopenharmony_ci shader << "\n"; 249e5c31af7Sopenharmony_ci } 250e5c31af7Sopenharmony_ci 251e5c31af7Sopenharmony_ci genCompareFunctions(shader, spec.values, true); 252e5c31af7Sopenharmony_ci shader << "\n"; 253e5c31af7Sopenharmony_ci 254e5c31af7Sopenharmony_ci // Declarations (varying, reference for each output). 255e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++) 256e5c31af7Sopenharmony_ci { 257e5c31af7Sopenharmony_ci const Value& val = spec.values.outputs[ndx]; 258e5c31af7Sopenharmony_ci const DataType basicType = val.type.getBasicType(); 259e5c31af7Sopenharmony_ci const DataType floatType = getDataTypeFloatScalars(basicType); 260e5c31af7Sopenharmony_ci const char* const floatTypeStr = getDataTypeName(floatType); 261e5c31af7Sopenharmony_ci const char* const refTypeStr = getDataTypeName(basicType); 262e5c31af7Sopenharmony_ci 263e5c31af7Sopenharmony_ci if (getDataTypeScalarType(basicType) == TYPE_FLOAT) 264e5c31af7Sopenharmony_ci shader << fragIn << " " << floatTypeStr << " " << val.name << ";\n"; 265e5c31af7Sopenharmony_ci else 266e5c31af7Sopenharmony_ci shader << fragIn << " " << floatTypeStr << " v_" << val.name << ";\n"; 267e5c31af7Sopenharmony_ci 268e5c31af7Sopenharmony_ci shader << "uniform " << refTypeStr << " ref_" << val.name << ";\n"; 269e5c31af7Sopenharmony_ci } 270e5c31af7Sopenharmony_ci 271e5c31af7Sopenharmony_ci shader << "\n"; 272e5c31af7Sopenharmony_ci shader << "void main()\n"; 273e5c31af7Sopenharmony_ci shader << "{\n"; 274e5c31af7Sopenharmony_ci 275e5c31af7Sopenharmony_ci shader << " "; 276e5c31af7Sopenharmony_ci genCompareOp(shader, customColorOut ? "dEQP_FragColor" : "gl_FragColor", spec.values, "v_", DE_NULL); 277e5c31af7Sopenharmony_ci 278e5c31af7Sopenharmony_ci shader << "}\n"; 279e5c31af7Sopenharmony_ci return shader.str(); 280e5c31af7Sopenharmony_ci} 281e5c31af7Sopenharmony_ci 282e5c31af7Sopenharmony_ci// Specialize a shader for the vertex shader test case. 283e5c31af7Sopenharmony_cistatic string specializeVertexShader (const ShaderCaseSpecification& spec, const std::string& src, const vector<RequiredExtension>& extensions) 284e5c31af7Sopenharmony_ci{ 285e5c31af7Sopenharmony_ci ostringstream decl; 286e5c31af7Sopenharmony_ci ostringstream setup; 287e5c31af7Sopenharmony_ci ostringstream output; 288e5c31af7Sopenharmony_ci const bool usesInout = glslVersionUsesInOutQualifiers(spec.targetVersion); 289e5c31af7Sopenharmony_ci const char* const vtxIn = usesInout ? "in" : "attribute"; 290e5c31af7Sopenharmony_ci const char* const vtxOut = usesInout ? "out" : "varying"; 291e5c31af7Sopenharmony_ci 292e5c31af7Sopenharmony_ci // generated from "both" case 293e5c31af7Sopenharmony_ci DE_ASSERT(spec.caseType == CASETYPE_VERTEX_ONLY); 294e5c31af7Sopenharmony_ci 295e5c31af7Sopenharmony_ci // Output (write out position). 296e5c31af7Sopenharmony_ci output << "gl_Position = dEQP_Position;\n"; 297e5c31af7Sopenharmony_ci 298e5c31af7Sopenharmony_ci // Declarations (position + attribute for each input, varying for each output). 299e5c31af7Sopenharmony_ci decl << vtxIn << " highp vec4 dEQP_Position;\n"; 300e5c31af7Sopenharmony_ci 301e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++) 302e5c31af7Sopenharmony_ci { 303e5c31af7Sopenharmony_ci const Value& val = spec.values.inputs[ndx]; 304e5c31af7Sopenharmony_ci const DataType basicType = val.type.getBasicType(); 305e5c31af7Sopenharmony_ci const DataType floatType = getDataTypeFloatScalars(basicType); 306e5c31af7Sopenharmony_ci const char* const floatTypeStr = getDataTypeName(floatType); 307e5c31af7Sopenharmony_ci const char* const refTypeStr = getDataTypeName(basicType); 308e5c31af7Sopenharmony_ci 309e5c31af7Sopenharmony_ci if (getDataTypeScalarType(basicType) == TYPE_FLOAT) 310e5c31af7Sopenharmony_ci { 311e5c31af7Sopenharmony_ci decl << vtxIn << " " << floatTypeStr << " " << val.name << ";\n"; 312e5c31af7Sopenharmony_ci } 313e5c31af7Sopenharmony_ci else 314e5c31af7Sopenharmony_ci { 315e5c31af7Sopenharmony_ci decl << vtxIn << " " << floatTypeStr << " a_" << val.name << ";\n"; 316e5c31af7Sopenharmony_ci setup << refTypeStr << " " << val.name << " = " << refTypeStr << "(a_" << val.name << ");\n"; 317e5c31af7Sopenharmony_ci } 318e5c31af7Sopenharmony_ci } 319e5c31af7Sopenharmony_ci 320e5c31af7Sopenharmony_ci // \todo [2015-07-24 pyry] Why are uniforms missing? 321e5c31af7Sopenharmony_ci 322e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++) 323e5c31af7Sopenharmony_ci { 324e5c31af7Sopenharmony_ci const Value& val = spec.values.outputs[ndx]; 325e5c31af7Sopenharmony_ci const DataType basicType = val.type.getBasicType(); 326e5c31af7Sopenharmony_ci const DataType floatType = getDataTypeFloatScalars(basicType); 327e5c31af7Sopenharmony_ci const char* const floatTypeStr = getDataTypeName(floatType); 328e5c31af7Sopenharmony_ci const char* const refTypeStr = getDataTypeName(basicType); 329e5c31af7Sopenharmony_ci 330e5c31af7Sopenharmony_ci if (getDataTypeScalarType(basicType) == TYPE_FLOAT) 331e5c31af7Sopenharmony_ci decl << vtxOut << " " << floatTypeStr << " " << val.name << ";\n"; 332e5c31af7Sopenharmony_ci else 333e5c31af7Sopenharmony_ci { 334e5c31af7Sopenharmony_ci decl << vtxOut << " " << floatTypeStr << " v_" << val.name << ";\n"; 335e5c31af7Sopenharmony_ci decl << refTypeStr << " " << val.name << ";\n"; 336e5c31af7Sopenharmony_ci 337e5c31af7Sopenharmony_ci output << "v_" << val.name << " = " << floatTypeStr << "(" << val.name << ");\n"; 338e5c31af7Sopenharmony_ci } 339e5c31af7Sopenharmony_ci } 340e5c31af7Sopenharmony_ci 341e5c31af7Sopenharmony_ci // Shader specialization. 342e5c31af7Sopenharmony_ci map<string, string> params; 343e5c31af7Sopenharmony_ci params.insert(pair<string, string>("DECLARATIONS", decl.str())); 344e5c31af7Sopenharmony_ci params.insert(pair<string, string>("SETUP", setup.str())); 345e5c31af7Sopenharmony_ci params.insert(pair<string, string>("OUTPUT", output.str())); 346e5c31af7Sopenharmony_ci params.insert(pair<string, string>("POSITION_FRAG_COLOR", "gl_Position")); 347e5c31af7Sopenharmony_ci 348e5c31af7Sopenharmony_ci StringTemplate tmpl (src); 349e5c31af7Sopenharmony_ci const string baseSrc = tmpl.specialize(params); 350e5c31af7Sopenharmony_ci const string withExt = injectExtensionRequirements(baseSrc, extensions, SHADERTYPE_VERTEX); 351e5c31af7Sopenharmony_ci 352e5c31af7Sopenharmony_ci return withExt; 353e5c31af7Sopenharmony_ci} 354e5c31af7Sopenharmony_ci 355e5c31af7Sopenharmony_ci// Specialize a shader for the fragment shader test case. 356e5c31af7Sopenharmony_cistatic string specializeFragmentShader (const ShaderCaseSpecification& spec, const std::string& src, const vector<RequiredExtension>& extensions) 357e5c31af7Sopenharmony_ci{ 358e5c31af7Sopenharmony_ci ostringstream decl; 359e5c31af7Sopenharmony_ci ostringstream setup; 360e5c31af7Sopenharmony_ci ostringstream output; 361e5c31af7Sopenharmony_ci 362e5c31af7Sopenharmony_ci const bool usesInout = glslVersionUsesInOutQualifiers(spec.targetVersion); 363e5c31af7Sopenharmony_ci const bool customColorOut = usesInout; 364e5c31af7Sopenharmony_ci const char* const fragIn = usesInout ? "in" : "varying"; 365e5c31af7Sopenharmony_ci const char* const fragColor = customColorOut ? "dEQP_FragColor" : "gl_FragColor"; 366e5c31af7Sopenharmony_ci 367e5c31af7Sopenharmony_ci // generated from "both" case 368e5c31af7Sopenharmony_ci DE_ASSERT(spec.caseType == CASETYPE_FRAGMENT_ONLY); 369e5c31af7Sopenharmony_ci 370e5c31af7Sopenharmony_ci genCompareFunctions(decl, spec.values, false); 371e5c31af7Sopenharmony_ci genCompareOp(output, fragColor, spec.values, "", DE_NULL); 372e5c31af7Sopenharmony_ci 373e5c31af7Sopenharmony_ci if (customColorOut) 374e5c31af7Sopenharmony_ci decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 375e5c31af7Sopenharmony_ci 376e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++) 377e5c31af7Sopenharmony_ci { 378e5c31af7Sopenharmony_ci const Value& val = spec.values.inputs[ndx]; 379e5c31af7Sopenharmony_ci const DataType basicType = val.type.getBasicType(); 380e5c31af7Sopenharmony_ci const DataType floatType = getDataTypeFloatScalars(basicType); 381e5c31af7Sopenharmony_ci const char* const floatTypeStr = getDataTypeName(floatType); 382e5c31af7Sopenharmony_ci const char* const refTypeStr = getDataTypeName(basicType); 383e5c31af7Sopenharmony_ci 384e5c31af7Sopenharmony_ci if (getDataTypeScalarType(basicType) == TYPE_FLOAT) 385e5c31af7Sopenharmony_ci decl << fragIn << " " << floatTypeStr << " " << val.name << ";\n"; 386e5c31af7Sopenharmony_ci else 387e5c31af7Sopenharmony_ci { 388e5c31af7Sopenharmony_ci decl << fragIn << " " << floatTypeStr << " v_" << val.name << ";\n"; 389e5c31af7Sopenharmony_ci std::string offset = isDataTypeIntOrIVec(basicType) ? " * 1.0025" : ""; // \todo [petri] bit of a hack to avoid errors in chop() due to varying interpolation 390e5c31af7Sopenharmony_ci setup << refTypeStr << " " << val.name << " = " << refTypeStr << "(v_" << val.name << offset << ");\n"; 391e5c31af7Sopenharmony_ci } 392e5c31af7Sopenharmony_ci } 393e5c31af7Sopenharmony_ci 394e5c31af7Sopenharmony_ci // \todo [2015-07-24 pyry] Why are uniforms missing? 395e5c31af7Sopenharmony_ci 396e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++) 397e5c31af7Sopenharmony_ci { 398e5c31af7Sopenharmony_ci const Value& val = spec.values.outputs[ndx]; 399e5c31af7Sopenharmony_ci const DataType basicType = val.type.getBasicType(); 400e5c31af7Sopenharmony_ci const char* const refTypeStr = getDataTypeName(basicType); 401e5c31af7Sopenharmony_ci 402e5c31af7Sopenharmony_ci decl << "uniform " << refTypeStr << " ref_" << val.name << ";\n"; 403e5c31af7Sopenharmony_ci decl << refTypeStr << " " << val.name << ";\n"; 404e5c31af7Sopenharmony_ci } 405e5c31af7Sopenharmony_ci 406e5c31af7Sopenharmony_ci /* \todo [2010-04-01 petri] Check all outputs. */ 407e5c31af7Sopenharmony_ci 408e5c31af7Sopenharmony_ci // Shader specialization. 409e5c31af7Sopenharmony_ci map<string, string> params; 410e5c31af7Sopenharmony_ci params.insert(pair<string, string>("DECLARATIONS", decl.str())); 411e5c31af7Sopenharmony_ci params.insert(pair<string, string>("SETUP", setup.str())); 412e5c31af7Sopenharmony_ci params.insert(pair<string, string>("OUTPUT", output.str())); 413e5c31af7Sopenharmony_ci params.insert(pair<string, string>("POSITION_FRAG_COLOR", fragColor)); 414e5c31af7Sopenharmony_ci 415e5c31af7Sopenharmony_ci StringTemplate tmpl (src); 416e5c31af7Sopenharmony_ci const string baseSrc = tmpl.specialize(params); 417e5c31af7Sopenharmony_ci const string withExt = injectExtensionRequirements(baseSrc, extensions, SHADERTYPE_FRAGMENT); 418e5c31af7Sopenharmony_ci 419e5c31af7Sopenharmony_ci return withExt; 420e5c31af7Sopenharmony_ci} 421e5c31af7Sopenharmony_ci 422e5c31af7Sopenharmony_cistatic void generateUniformDeclarations (std::ostream& dst, const ValueBlock& valueBlock) 423e5c31af7Sopenharmony_ci{ 424e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < valueBlock.uniforms.size(); ndx++) 425e5c31af7Sopenharmony_ci { 426e5c31af7Sopenharmony_ci const Value& val = valueBlock.uniforms[ndx]; 427e5c31af7Sopenharmony_ci const char* const typeStr = getDataTypeName(val.type.getBasicType()); 428e5c31af7Sopenharmony_ci 429e5c31af7Sopenharmony_ci if (val.name.find('.') == string::npos) 430e5c31af7Sopenharmony_ci dst << "uniform " << typeStr << " " << val.name << ";\n"; 431e5c31af7Sopenharmony_ci } 432e5c31af7Sopenharmony_ci} 433e5c31af7Sopenharmony_ci 434e5c31af7Sopenharmony_cistatic map<string, string> generateVertexSpecialization (const ProgramSpecializationParams& specParams) 435e5c31af7Sopenharmony_ci{ 436e5c31af7Sopenharmony_ci const bool usesInout = glslVersionUsesInOutQualifiers(specParams.caseSpec.targetVersion); 437e5c31af7Sopenharmony_ci const char* vtxIn = usesInout ? "in" : "attribute"; 438e5c31af7Sopenharmony_ci ostringstream decl; 439e5c31af7Sopenharmony_ci ostringstream setup; 440e5c31af7Sopenharmony_ci map<string, string> params; 441e5c31af7Sopenharmony_ci 442e5c31af7Sopenharmony_ci decl << vtxIn << " highp vec4 dEQP_Position;\n"; 443e5c31af7Sopenharmony_ci 444e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < specParams.caseSpec.values.inputs.size(); ndx++) 445e5c31af7Sopenharmony_ci { 446e5c31af7Sopenharmony_ci const Value& val = specParams.caseSpec.values.inputs[ndx]; 447e5c31af7Sopenharmony_ci const DataType basicType = val.type.getBasicType(); 448e5c31af7Sopenharmony_ci const char* const typeStr = getDataTypeName(val.type.getBasicType()); 449e5c31af7Sopenharmony_ci 450e5c31af7Sopenharmony_ci if (getDataTypeScalarType(basicType) == TYPE_FLOAT) 451e5c31af7Sopenharmony_ci { 452e5c31af7Sopenharmony_ci decl << vtxIn << " " << typeStr << " " << val.name << ";\n"; 453e5c31af7Sopenharmony_ci } 454e5c31af7Sopenharmony_ci else 455e5c31af7Sopenharmony_ci { 456e5c31af7Sopenharmony_ci const DataType floatType = getDataTypeFloatScalars(basicType); 457e5c31af7Sopenharmony_ci const char* const floatTypeStr = getDataTypeName(floatType); 458e5c31af7Sopenharmony_ci 459e5c31af7Sopenharmony_ci decl << vtxIn << " " << floatTypeStr << " a_" << val.name << ";\n"; 460e5c31af7Sopenharmony_ci setup << typeStr << " " << val.name << " = " << typeStr << "(a_" << val.name << ");\n"; 461e5c31af7Sopenharmony_ci } 462e5c31af7Sopenharmony_ci } 463e5c31af7Sopenharmony_ci 464e5c31af7Sopenharmony_ci generateUniformDeclarations(decl, specParams.caseSpec.values); 465e5c31af7Sopenharmony_ci 466e5c31af7Sopenharmony_ci params.insert(pair<string, string>("VERTEX_DECLARATIONS", decl.str())); 467e5c31af7Sopenharmony_ci params.insert(pair<string, string>("VERTEX_SETUP", setup.str())); 468e5c31af7Sopenharmony_ci params.insert(pair<string, string>("VERTEX_OUTPUT", string("gl_Position = dEQP_Position;\n"))); 469e5c31af7Sopenharmony_ci 470e5c31af7Sopenharmony_ci return params; 471e5c31af7Sopenharmony_ci} 472e5c31af7Sopenharmony_ci 473e5c31af7Sopenharmony_cistatic map<string, string> generateFragmentSpecialization (const ProgramSpecializationParams& specParams) 474e5c31af7Sopenharmony_ci{ 475e5c31af7Sopenharmony_ci const bool usesInout = glslVersionUsesInOutQualifiers(specParams.caseSpec.targetVersion); 476e5c31af7Sopenharmony_ci const bool customColorOut = usesInout; 477e5c31af7Sopenharmony_ci const char* const fragColor = customColorOut ? "dEQP_FragColor" : "gl_FragColor"; 478e5c31af7Sopenharmony_ci ostringstream decl; 479e5c31af7Sopenharmony_ci ostringstream output; 480e5c31af7Sopenharmony_ci map<string, string> params; 481e5c31af7Sopenharmony_ci 482e5c31af7Sopenharmony_ci genCompareFunctions(decl, specParams.caseSpec.values, false); 483e5c31af7Sopenharmony_ci genCompareOp(output, fragColor, specParams.caseSpec.values, "", DE_NULL); 484e5c31af7Sopenharmony_ci 485e5c31af7Sopenharmony_ci if (customColorOut) 486e5c31af7Sopenharmony_ci decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 487e5c31af7Sopenharmony_ci 488e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < specParams.caseSpec.values.outputs.size(); ndx++) 489e5c31af7Sopenharmony_ci { 490e5c31af7Sopenharmony_ci const Value& val = specParams.caseSpec.values.outputs[ndx]; 491e5c31af7Sopenharmony_ci const char* const refTypeStr = getDataTypeName(val.type.getBasicType()); 492e5c31af7Sopenharmony_ci 493e5c31af7Sopenharmony_ci decl << "uniform " << refTypeStr << " ref_" << val.name << ";\n"; 494e5c31af7Sopenharmony_ci decl << refTypeStr << " " << val.name << ";\n"; 495e5c31af7Sopenharmony_ci } 496e5c31af7Sopenharmony_ci 497e5c31af7Sopenharmony_ci generateUniformDeclarations(decl, specParams.caseSpec.values); 498e5c31af7Sopenharmony_ci 499e5c31af7Sopenharmony_ci params.insert(pair<string, string>("FRAGMENT_DECLARATIONS", decl.str())); 500e5c31af7Sopenharmony_ci params.insert(pair<string, string>("FRAGMENT_OUTPUT", output.str())); 501e5c31af7Sopenharmony_ci params.insert(pair<string, string>("FRAG_COLOR", fragColor)); 502e5c31af7Sopenharmony_ci 503e5c31af7Sopenharmony_ci return params; 504e5c31af7Sopenharmony_ci} 505e5c31af7Sopenharmony_ci 506e5c31af7Sopenharmony_cistatic map<string, string> generateGeometrySpecialization (const ProgramSpecializationParams& specParams) 507e5c31af7Sopenharmony_ci{ 508e5c31af7Sopenharmony_ci ostringstream decl; 509e5c31af7Sopenharmony_ci map<string, string> params; 510e5c31af7Sopenharmony_ci 511e5c31af7Sopenharmony_ci decl << "layout (triangles) in;\n"; 512e5c31af7Sopenharmony_ci decl << "layout (triangle_strip, max_vertices=3) out;\n"; 513e5c31af7Sopenharmony_ci decl << "\n"; 514e5c31af7Sopenharmony_ci 515e5c31af7Sopenharmony_ci generateUniformDeclarations(decl, specParams.caseSpec.values); 516e5c31af7Sopenharmony_ci 517e5c31af7Sopenharmony_ci params.insert(pair<string, string>("GEOMETRY_DECLARATIONS", decl.str())); 518e5c31af7Sopenharmony_ci 519e5c31af7Sopenharmony_ci return params; 520e5c31af7Sopenharmony_ci} 521e5c31af7Sopenharmony_ci 522e5c31af7Sopenharmony_cistatic map<string, string> generateTessControlSpecialization (const ProgramSpecializationParams& specParams) 523e5c31af7Sopenharmony_ci{ 524e5c31af7Sopenharmony_ci ostringstream decl; 525e5c31af7Sopenharmony_ci ostringstream output; 526e5c31af7Sopenharmony_ci map<string, string> params; 527e5c31af7Sopenharmony_ci 528e5c31af7Sopenharmony_ci decl << "layout (vertices=3) out;\n"; 529e5c31af7Sopenharmony_ci decl << "\n"; 530e5c31af7Sopenharmony_ci 531e5c31af7Sopenharmony_ci generateUniformDeclarations(decl, specParams.caseSpec.values); 532e5c31af7Sopenharmony_ci 533e5c31af7Sopenharmony_ci output << "gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 534e5c31af7Sopenharmony_ci "gl_TessLevelInner[0] = 2.0;\n" 535e5c31af7Sopenharmony_ci "gl_TessLevelInner[1] = 2.0;\n" 536e5c31af7Sopenharmony_ci "gl_TessLevelOuter[0] = 2.0;\n" 537e5c31af7Sopenharmony_ci "gl_TessLevelOuter[1] = 2.0;\n" 538e5c31af7Sopenharmony_ci "gl_TessLevelOuter[2] = 2.0;\n" 539e5c31af7Sopenharmony_ci "gl_TessLevelOuter[3] = 2.0;"; 540e5c31af7Sopenharmony_ci 541e5c31af7Sopenharmony_ci params.insert(pair<string, string>("TESSELLATION_CONTROL_DECLARATIONS", decl.str())); 542e5c31af7Sopenharmony_ci params.insert(pair<string, string>("TESSELLATION_CONTROL_OUTPUT", output.str())); 543e5c31af7Sopenharmony_ci params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices))); 544e5c31af7Sopenharmony_ci 545e5c31af7Sopenharmony_ci return params; 546e5c31af7Sopenharmony_ci} 547e5c31af7Sopenharmony_ci 548e5c31af7Sopenharmony_cistatic map<string, string> generateTessEvalSpecialization (const ProgramSpecializationParams& specParams) 549e5c31af7Sopenharmony_ci{ 550e5c31af7Sopenharmony_ci ostringstream decl; 551e5c31af7Sopenharmony_ci ostringstream output; 552e5c31af7Sopenharmony_ci map<string, string> params; 553e5c31af7Sopenharmony_ci 554e5c31af7Sopenharmony_ci decl << "layout (triangles) in;\n"; 555e5c31af7Sopenharmony_ci decl << "\n"; 556e5c31af7Sopenharmony_ci 557e5c31af7Sopenharmony_ci generateUniformDeclarations(decl, specParams.caseSpec.values); 558e5c31af7Sopenharmony_ci 559e5c31af7Sopenharmony_ci output << "gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n"; 560e5c31af7Sopenharmony_ci 561e5c31af7Sopenharmony_ci params.insert(pair<string, string>("TESSELLATION_EVALUATION_DECLARATIONS", decl.str())); 562e5c31af7Sopenharmony_ci params.insert(pair<string, string>("TESSELLATION_EVALUATION_OUTPUT", output.str())); 563e5c31af7Sopenharmony_ci params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices))); 564e5c31af7Sopenharmony_ci 565e5c31af7Sopenharmony_ci return params; 566e5c31af7Sopenharmony_ci} 567e5c31af7Sopenharmony_ci 568e5c31af7Sopenharmony_cistatic void specializeShaderSources (ProgramSources& dst, 569e5c31af7Sopenharmony_ci const ProgramSources& src, 570e5c31af7Sopenharmony_ci const ProgramSpecializationParams& specParams, 571e5c31af7Sopenharmony_ci glu::ShaderType shaderType, 572e5c31af7Sopenharmony_ci map<string, string> (*specializationGenerator) (const ProgramSpecializationParams& specParams)) 573e5c31af7Sopenharmony_ci{ 574e5c31af7Sopenharmony_ci if (!src.sources[shaderType].empty()) 575e5c31af7Sopenharmony_ci { 576e5c31af7Sopenharmony_ci const map<string, string> tmplParams = specializationGenerator(specParams); 577e5c31af7Sopenharmony_ci 578e5c31af7Sopenharmony_ci for (size_t ndx = 0; ndx < src.sources[shaderType].size(); ++ndx) 579e5c31af7Sopenharmony_ci { 580e5c31af7Sopenharmony_ci const StringTemplate tmpl (src.sources[shaderType][ndx]); 581e5c31af7Sopenharmony_ci const std::string baseGLSLCode = tmpl.specialize(tmplParams); 582e5c31af7Sopenharmony_ci const std::string sourceWithExts = injectExtensionRequirements(baseGLSLCode, specParams.requiredExtensions, shaderType); 583e5c31af7Sopenharmony_ci 584e5c31af7Sopenharmony_ci dst << glu::ShaderSource(shaderType, sourceWithExts); 585e5c31af7Sopenharmony_ci } 586e5c31af7Sopenharmony_ci } 587e5c31af7Sopenharmony_ci} 588e5c31af7Sopenharmony_ci 589e5c31af7Sopenharmony_cistatic void specializeProgramSources (glu::ProgramSources& dst, 590e5c31af7Sopenharmony_ci const glu::ProgramSources& src, 591e5c31af7Sopenharmony_ci const ProgramSpecializationParams& specParams) 592e5c31af7Sopenharmony_ci{ 593e5c31af7Sopenharmony_ci specializeShaderSources(dst, src, specParams, SHADERTYPE_VERTEX, generateVertexSpecialization); 594e5c31af7Sopenharmony_ci specializeShaderSources(dst, src, specParams, SHADERTYPE_FRAGMENT, generateFragmentSpecialization); 595e5c31af7Sopenharmony_ci specializeShaderSources(dst, src, specParams, SHADERTYPE_GEOMETRY, generateGeometrySpecialization); 596e5c31af7Sopenharmony_ci specializeShaderSources(dst, src, specParams, SHADERTYPE_TESSELLATION_CONTROL, generateTessControlSpecialization); 597e5c31af7Sopenharmony_ci specializeShaderSources(dst, src, specParams, SHADERTYPE_TESSELLATION_EVALUATION, generateTessEvalSpecialization); 598e5c31af7Sopenharmony_ci 599e5c31af7Sopenharmony_ci dst << ProgramSeparable(src.separable); 600e5c31af7Sopenharmony_ci} 601e5c31af7Sopenharmony_ci 602e5c31af7Sopenharmony_cienum 603e5c31af7Sopenharmony_ci{ 604e5c31af7Sopenharmony_ci VIEWPORT_WIDTH = 128, 605e5c31af7Sopenharmony_ci VIEWPORT_HEIGHT = 128 606e5c31af7Sopenharmony_ci}; 607e5c31af7Sopenharmony_ci 608e5c31af7Sopenharmony_ciclass BeforeDrawValidator : public glu::DrawUtilCallback 609e5c31af7Sopenharmony_ci{ 610e5c31af7Sopenharmony_cipublic: 611e5c31af7Sopenharmony_ci enum TargetType 612e5c31af7Sopenharmony_ci { 613e5c31af7Sopenharmony_ci TARGETTYPE_PROGRAM = 0, 614e5c31af7Sopenharmony_ci TARGETTYPE_PIPELINE, 615e5c31af7Sopenharmony_ci 616e5c31af7Sopenharmony_ci TARGETTYPE_LAST 617e5c31af7Sopenharmony_ci }; 618e5c31af7Sopenharmony_ci 619e5c31af7Sopenharmony_ci BeforeDrawValidator (const glw::Functions& gl, glw::GLuint target, TargetType targetType); 620e5c31af7Sopenharmony_ci 621e5c31af7Sopenharmony_ci void beforeDrawCall (void); 622e5c31af7Sopenharmony_ci 623e5c31af7Sopenharmony_ci const std::string& getInfoLog (void) const; 624e5c31af7Sopenharmony_ci glw::GLint getValidateStatus (void) const; 625e5c31af7Sopenharmony_ci 626e5c31af7Sopenharmony_ciprivate: 627e5c31af7Sopenharmony_ci const glw::Functions& m_gl; 628e5c31af7Sopenharmony_ci const glw::GLuint m_target; 629e5c31af7Sopenharmony_ci const TargetType m_targetType; 630e5c31af7Sopenharmony_ci 631e5c31af7Sopenharmony_ci glw::GLint m_validateStatus; 632e5c31af7Sopenharmony_ci std::string m_logMessage; 633e5c31af7Sopenharmony_ci}; 634e5c31af7Sopenharmony_ci 635e5c31af7Sopenharmony_ciBeforeDrawValidator::BeforeDrawValidator (const glw::Functions& gl, glw::GLuint target, TargetType targetType) 636e5c31af7Sopenharmony_ci : m_gl (gl) 637e5c31af7Sopenharmony_ci , m_target (target) 638e5c31af7Sopenharmony_ci , m_targetType (targetType) 639e5c31af7Sopenharmony_ci , m_validateStatus (-1) 640e5c31af7Sopenharmony_ci{ 641e5c31af7Sopenharmony_ci DE_ASSERT(targetType < TARGETTYPE_LAST); 642e5c31af7Sopenharmony_ci} 643e5c31af7Sopenharmony_ci 644e5c31af7Sopenharmony_civoid BeforeDrawValidator::beforeDrawCall (void) 645e5c31af7Sopenharmony_ci{ 646e5c31af7Sopenharmony_ci glw::GLint bytesWritten = 0; 647e5c31af7Sopenharmony_ci glw::GLint infoLogLength; 648e5c31af7Sopenharmony_ci std::vector<glw::GLchar> logBuffer; 649e5c31af7Sopenharmony_ci int stringLength; 650e5c31af7Sopenharmony_ci 651e5c31af7Sopenharmony_ci // validate 652e5c31af7Sopenharmony_ci if (m_targetType == TARGETTYPE_PROGRAM) 653e5c31af7Sopenharmony_ci m_gl.validateProgram(m_target); 654e5c31af7Sopenharmony_ci else if (m_targetType == TARGETTYPE_PIPELINE) 655e5c31af7Sopenharmony_ci m_gl.validateProgramPipeline(m_target); 656e5c31af7Sopenharmony_ci else 657e5c31af7Sopenharmony_ci DE_ASSERT(false); 658e5c31af7Sopenharmony_ci 659e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "validate"); 660e5c31af7Sopenharmony_ci 661e5c31af7Sopenharmony_ci // check status 662e5c31af7Sopenharmony_ci m_validateStatus = -1; 663e5c31af7Sopenharmony_ci 664e5c31af7Sopenharmony_ci if (m_targetType == TARGETTYPE_PROGRAM) 665e5c31af7Sopenharmony_ci m_gl.getProgramiv(m_target, GL_VALIDATE_STATUS, &m_validateStatus); 666e5c31af7Sopenharmony_ci else if (m_targetType == TARGETTYPE_PIPELINE) 667e5c31af7Sopenharmony_ci m_gl.getProgramPipelineiv(m_target, GL_VALIDATE_STATUS, &m_validateStatus); 668e5c31af7Sopenharmony_ci else 669e5c31af7Sopenharmony_ci DE_ASSERT(false); 670e5c31af7Sopenharmony_ci 671e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "get validate status"); 672e5c31af7Sopenharmony_ci TCU_CHECK(m_validateStatus == GL_TRUE || m_validateStatus == GL_FALSE); 673e5c31af7Sopenharmony_ci 674e5c31af7Sopenharmony_ci // read log 675e5c31af7Sopenharmony_ci 676e5c31af7Sopenharmony_ci infoLogLength = 0; 677e5c31af7Sopenharmony_ci 678e5c31af7Sopenharmony_ci if (m_targetType == TARGETTYPE_PROGRAM) 679e5c31af7Sopenharmony_ci m_gl.getProgramiv(m_target, GL_INFO_LOG_LENGTH, &infoLogLength); 680e5c31af7Sopenharmony_ci else if (m_targetType == TARGETTYPE_PIPELINE) 681e5c31af7Sopenharmony_ci m_gl.getProgramPipelineiv(m_target, GL_INFO_LOG_LENGTH, &infoLogLength); 682e5c31af7Sopenharmony_ci else 683e5c31af7Sopenharmony_ci DE_ASSERT(false); 684e5c31af7Sopenharmony_ci 685e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(m_gl.getError(), "get info log length"); 686e5c31af7Sopenharmony_ci 687e5c31af7Sopenharmony_ci if (infoLogLength <= 0) 688e5c31af7Sopenharmony_ci { 689e5c31af7Sopenharmony_ci m_logMessage.clear(); 690e5c31af7Sopenharmony_ci return; 691e5c31af7Sopenharmony_ci } 692e5c31af7Sopenharmony_ci 693e5c31af7Sopenharmony_ci logBuffer.resize(infoLogLength + 2, '0'); // +1 for zero terminator (infoLogLength should include it, but better play it safe), +1 to make sure buffer is always larger 694e5c31af7Sopenharmony_ci 695e5c31af7Sopenharmony_ci if (m_targetType == TARGETTYPE_PROGRAM) 696e5c31af7Sopenharmony_ci m_gl.getProgramInfoLog(m_target, infoLogLength + 1, &bytesWritten, &logBuffer[0]); 697e5c31af7Sopenharmony_ci else if (m_targetType == TARGETTYPE_PIPELINE) 698e5c31af7Sopenharmony_ci m_gl.getProgramPipelineInfoLog(m_target, infoLogLength + 1, &bytesWritten, &logBuffer[0]); 699e5c31af7Sopenharmony_ci else 700e5c31af7Sopenharmony_ci DE_ASSERT(false); 701e5c31af7Sopenharmony_ci 702e5c31af7Sopenharmony_ci // just ignore bytesWritten to be safe, find the null terminator 703e5c31af7Sopenharmony_ci stringLength = (int)(std::find(logBuffer.begin(), logBuffer.end(), '0') - logBuffer.begin()); 704e5c31af7Sopenharmony_ci m_logMessage.assign(&logBuffer[0], stringLength); 705e5c31af7Sopenharmony_ci} 706e5c31af7Sopenharmony_ci 707e5c31af7Sopenharmony_ciconst std::string& BeforeDrawValidator::getInfoLog (void) const 708e5c31af7Sopenharmony_ci{ 709e5c31af7Sopenharmony_ci return m_logMessage; 710e5c31af7Sopenharmony_ci} 711e5c31af7Sopenharmony_ci 712e5c31af7Sopenharmony_ciglw::GLint BeforeDrawValidator::getValidateStatus (void) const 713e5c31af7Sopenharmony_ci{ 714e5c31af7Sopenharmony_ci return m_validateStatus; 715e5c31af7Sopenharmony_ci} 716e5c31af7Sopenharmony_ci 717e5c31af7Sopenharmony_ci// ShaderCase. 718e5c31af7Sopenharmony_ci 719e5c31af7Sopenharmony_ciShaderLibraryCase::ShaderLibraryCase (tcu::TestContext& testCtx, RenderContext& renderCtx, const glu::ContextInfo& contextInfo, const char* name, const char* description, const ShaderCaseSpecification& specification) 720e5c31af7Sopenharmony_ci : tcu::TestCase (testCtx, name, description) 721e5c31af7Sopenharmony_ci , m_renderCtx (renderCtx) 722e5c31af7Sopenharmony_ci , m_contextInfo (contextInfo) 723e5c31af7Sopenharmony_ci , m_spec (specification) 724e5c31af7Sopenharmony_ci{ 725e5c31af7Sopenharmony_ci} 726e5c31af7Sopenharmony_ci 727e5c31af7Sopenharmony_ciShaderLibraryCase::~ShaderLibraryCase (void) 728e5c31af7Sopenharmony_ci{ 729e5c31af7Sopenharmony_ci} 730e5c31af7Sopenharmony_ci 731e5c31af7Sopenharmony_cistatic inline void requireExtension(const glu::ContextInfo& info, const ShaderCaseSpecification& spec, const char *extension) 732e5c31af7Sopenharmony_ci{ 733e5c31af7Sopenharmony_ci if (!info.isExtensionSupported(extension)) 734e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, (string(getGLSLVersionName(spec.targetVersion)) + " is not supported").c_str()); 735e5c31af7Sopenharmony_ci} 736e5c31af7Sopenharmony_ci 737e5c31af7Sopenharmony_civoid ShaderLibraryCase::init (void) 738e5c31af7Sopenharmony_ci{ 739e5c31af7Sopenharmony_ci DE_ASSERT(isValid(m_spec)); 740e5c31af7Sopenharmony_ci 741e5c31af7Sopenharmony_ci // Check for ES compatibility extensions, e.g. if we are on desktop context but require GLSL ES 742e5c31af7Sopenharmony_ci if (!isContextTypeES(m_renderCtx.getType()) && glslVersionIsES(m_spec.targetVersion)) { 743e5c31af7Sopenharmony_ci switch (m_spec.targetVersion) { 744e5c31af7Sopenharmony_ci case GLSL_VERSION_300_ES: 745e5c31af7Sopenharmony_ci requireExtension(m_contextInfo, m_spec, "GL_ARB_ES3_compatibility"); 746e5c31af7Sopenharmony_ci break; 747e5c31af7Sopenharmony_ci case GLSL_VERSION_310_ES: 748e5c31af7Sopenharmony_ci requireExtension(m_contextInfo, m_spec, "GL_ARB_ES3_1_compatibility"); 749e5c31af7Sopenharmony_ci break; 750e5c31af7Sopenharmony_ci case GLSL_VERSION_320_ES: 751e5c31af7Sopenharmony_ci requireExtension(m_contextInfo, m_spec, "GL_ARB_ES3_2_compatibility"); 752e5c31af7Sopenharmony_ci break; 753e5c31af7Sopenharmony_ci default: 754e5c31af7Sopenharmony_ci DE_ASSERT(false); 755e5c31af7Sopenharmony_ci } 756e5c31af7Sopenharmony_ci } else { 757e5c31af7Sopenharmony_ci if (!isGLSLVersionSupported(m_renderCtx.getType(), m_spec.targetVersion)) 758e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, (string(getGLSLVersionName(m_spec.targetVersion)) + " is not supported").c_str()); 759e5c31af7Sopenharmony_ci } 760e5c31af7Sopenharmony_ci 761e5c31af7Sopenharmony_ci checkImplementationLimits(m_spec.requiredCaps, m_contextInfo); 762e5c31af7Sopenharmony_ci 763e5c31af7Sopenharmony_ci // log the expected result 764e5c31af7Sopenharmony_ci switch (m_spec.expectResult) 765e5c31af7Sopenharmony_ci { 766e5c31af7Sopenharmony_ci case EXPECT_PASS: 767e5c31af7Sopenharmony_ci // Don't write anything 768e5c31af7Sopenharmony_ci break; 769e5c31af7Sopenharmony_ci 770e5c31af7Sopenharmony_ci case EXPECT_COMPILE_FAIL: 771e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Expecting shader compilation to fail." << tcu::TestLog::EndMessage; 772e5c31af7Sopenharmony_ci break; 773e5c31af7Sopenharmony_ci 774e5c31af7Sopenharmony_ci case EXPECT_LINK_FAIL: 775e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Expecting program linking to fail." << tcu::TestLog::EndMessage; 776e5c31af7Sopenharmony_ci break; 777e5c31af7Sopenharmony_ci 778e5c31af7Sopenharmony_ci case EXPECT_COMPILE_LINK_FAIL: 779e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Expecting either shader compilation or program linking to fail." << tcu::TestLog::EndMessage; 780e5c31af7Sopenharmony_ci break; 781e5c31af7Sopenharmony_ci 782e5c31af7Sopenharmony_ci case EXPECT_VALIDATION_FAIL: 783e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Expecting program validation to fail." << tcu::TestLog::EndMessage; 784e5c31af7Sopenharmony_ci break; 785e5c31af7Sopenharmony_ci 786e5c31af7Sopenharmony_ci case EXPECT_BUILD_SUCCESSFUL: 787e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Expecting shader compilation and program linking to succeed. Resulting program will not be executed." << tcu::TestLog::EndMessage; 788e5c31af7Sopenharmony_ci break; 789e5c31af7Sopenharmony_ci 790e5c31af7Sopenharmony_ci default: 791e5c31af7Sopenharmony_ci DE_ASSERT(false); 792e5c31af7Sopenharmony_ci break; 793e5c31af7Sopenharmony_ci } 794e5c31af7Sopenharmony_ci} 795e5c31af7Sopenharmony_ci 796e5c31af7Sopenharmony_cistatic void setUniformValue (const glw::Functions& gl, const std::vector<deUint32>& pipelinePrograms, const std::string& name, const Value& val, int arrayNdx, tcu::TestLog& log) 797e5c31af7Sopenharmony_ci{ 798e5c31af7Sopenharmony_ci bool foundAnyMatch = false; 799e5c31af7Sopenharmony_ci 800e5c31af7Sopenharmony_ci for (int programNdx = 0; programNdx < (int)pipelinePrograms.size(); ++programNdx) 801e5c31af7Sopenharmony_ci { 802e5c31af7Sopenharmony_ci const DataType dataType = val.type.getBasicType(); 803e5c31af7Sopenharmony_ci const int scalarSize = getDataTypeScalarSize(dataType); 804e5c31af7Sopenharmony_ci const int loc = gl.getUniformLocation(pipelinePrograms[programNdx], name.c_str()); 805e5c31af7Sopenharmony_ci const int elemNdx = arrayNdx * scalarSize; 806e5c31af7Sopenharmony_ci 807e5c31af7Sopenharmony_ci DE_ASSERT(elemNdx+scalarSize <= (int)val.elements.size()); 808e5c31af7Sopenharmony_ci 809e5c31af7Sopenharmony_ci if (loc == -1) 810e5c31af7Sopenharmony_ci continue; 811e5c31af7Sopenharmony_ci 812e5c31af7Sopenharmony_ci foundAnyMatch = true; 813e5c31af7Sopenharmony_ci 814e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(sizeof(Value::Element) == sizeof(glw::GLfloat)); 815e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(sizeof(Value::Element) == sizeof(glw::GLint)); 816e5c31af7Sopenharmony_ci 817e5c31af7Sopenharmony_ci gl.useProgram(pipelinePrograms[programNdx]); 818e5c31af7Sopenharmony_ci 819e5c31af7Sopenharmony_ci switch (dataType) 820e5c31af7Sopenharmony_ci { 821e5c31af7Sopenharmony_ci case TYPE_FLOAT: gl.uniform1fv(loc, 1, &val.elements[elemNdx].float32); break; 822e5c31af7Sopenharmony_ci case TYPE_FLOAT_VEC2: gl.uniform2fv(loc, 1, &val.elements[elemNdx].float32); break; 823e5c31af7Sopenharmony_ci case TYPE_FLOAT_VEC3: gl.uniform3fv(loc, 1, &val.elements[elemNdx].float32); break; 824e5c31af7Sopenharmony_ci case TYPE_FLOAT_VEC4: gl.uniform4fv(loc, 1, &val.elements[elemNdx].float32); break; 825e5c31af7Sopenharmony_ci case TYPE_FLOAT_MAT2: gl.uniformMatrix2fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32); break; 826e5c31af7Sopenharmony_ci case TYPE_FLOAT_MAT3: gl.uniformMatrix3fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32); break; 827e5c31af7Sopenharmony_ci case TYPE_FLOAT_MAT4: gl.uniformMatrix4fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32); break; 828e5c31af7Sopenharmony_ci case TYPE_INT: gl.uniform1iv(loc, 1, &val.elements[elemNdx].int32); break; 829e5c31af7Sopenharmony_ci case TYPE_INT_VEC2: gl.uniform2iv(loc, 1, &val.elements[elemNdx].int32); break; 830e5c31af7Sopenharmony_ci case TYPE_INT_VEC3: gl.uniform3iv(loc, 1, &val.elements[elemNdx].int32); break; 831e5c31af7Sopenharmony_ci case TYPE_INT_VEC4: gl.uniform4iv(loc, 1, &val.elements[elemNdx].int32); break; 832e5c31af7Sopenharmony_ci case TYPE_BOOL: gl.uniform1iv(loc, 1, &val.elements[elemNdx].int32); break; 833e5c31af7Sopenharmony_ci case TYPE_BOOL_VEC2: gl.uniform2iv(loc, 1, &val.elements[elemNdx].int32); break; 834e5c31af7Sopenharmony_ci case TYPE_BOOL_VEC3: gl.uniform3iv(loc, 1, &val.elements[elemNdx].int32); break; 835e5c31af7Sopenharmony_ci case TYPE_BOOL_VEC4: gl.uniform4iv(loc, 1, &val.elements[elemNdx].int32); break; 836e5c31af7Sopenharmony_ci case TYPE_UINT: gl.uniform1uiv(loc, 1, (const deUint32*)&val.elements[elemNdx].int32); break; 837e5c31af7Sopenharmony_ci case TYPE_UINT_VEC2: gl.uniform2uiv(loc, 1, (const deUint32*)&val.elements[elemNdx].int32); break; 838e5c31af7Sopenharmony_ci case TYPE_UINT_VEC3: gl.uniform3uiv(loc, 1, (const deUint32*)&val.elements[elemNdx].int32); break; 839e5c31af7Sopenharmony_ci case TYPE_UINT_VEC4: gl.uniform4uiv(loc, 1, (const deUint32*)&val.elements[elemNdx].int32); break; 840e5c31af7Sopenharmony_ci case TYPE_FLOAT_MAT2X3: gl.uniformMatrix2x3fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32); break; 841e5c31af7Sopenharmony_ci case TYPE_FLOAT_MAT2X4: gl.uniformMatrix2x4fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32); break; 842e5c31af7Sopenharmony_ci case TYPE_FLOAT_MAT3X2: gl.uniformMatrix3x2fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32); break; 843e5c31af7Sopenharmony_ci case TYPE_FLOAT_MAT3X4: gl.uniformMatrix3x4fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32); break; 844e5c31af7Sopenharmony_ci case TYPE_FLOAT_MAT4X2: gl.uniformMatrix4x2fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32); break; 845e5c31af7Sopenharmony_ci case TYPE_FLOAT_MAT4X3: gl.uniformMatrix4x3fv(loc, 1, GL_FALSE, &val.elements[elemNdx].float32); break; 846e5c31af7Sopenharmony_ci 847e5c31af7Sopenharmony_ci case TYPE_SAMPLER_2D: 848e5c31af7Sopenharmony_ci case TYPE_SAMPLER_CUBE: 849e5c31af7Sopenharmony_ci DE_FATAL("implement!"); 850e5c31af7Sopenharmony_ci break; 851e5c31af7Sopenharmony_ci 852e5c31af7Sopenharmony_ci default: 853e5c31af7Sopenharmony_ci DE_ASSERT(false); 854e5c31af7Sopenharmony_ci } 855e5c31af7Sopenharmony_ci } 856e5c31af7Sopenharmony_ci 857e5c31af7Sopenharmony_ci if (!foundAnyMatch) 858e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "WARNING // Uniform \"" << name << "\" location is not valid, location = -1. Cannot set value to the uniform." << tcu::TestLog::EndMessage; 859e5c31af7Sopenharmony_ci} 860e5c31af7Sopenharmony_ci 861e5c31af7Sopenharmony_cistatic bool isTessellationPresent (const ShaderCaseSpecification& spec) 862e5c31af7Sopenharmony_ci{ 863e5c31af7Sopenharmony_ci if (spec.programs[0].sources.separable) 864e5c31af7Sopenharmony_ci { 865e5c31af7Sopenharmony_ci const deUint32 tessellationBits = (1 << glu::SHADERTYPE_TESSELLATION_CONTROL) | 866e5c31af7Sopenharmony_ci (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION); 867e5c31af7Sopenharmony_ci 868e5c31af7Sopenharmony_ci for (int programNdx = 0; programNdx < (int)spec.programs.size(); ++programNdx) 869e5c31af7Sopenharmony_ci if (spec.programs[programNdx].activeStages & tessellationBits) 870e5c31af7Sopenharmony_ci return true; 871e5c31af7Sopenharmony_ci return false; 872e5c31af7Sopenharmony_ci } 873e5c31af7Sopenharmony_ci else 874e5c31af7Sopenharmony_ci return !spec.programs[0].sources.sources[glu::SHADERTYPE_TESSELLATION_CONTROL].empty() || 875e5c31af7Sopenharmony_ci !spec.programs[0].sources.sources[glu::SHADERTYPE_TESSELLATION_EVALUATION].empty(); 876e5c31af7Sopenharmony_ci} 877e5c31af7Sopenharmony_ci 878e5c31af7Sopenharmony_cistatic bool isTessellationSupported (const glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo) 879e5c31af7Sopenharmony_ci{ 880e5c31af7Sopenharmony_ci if (renderCtx.getType().getProfile() == PROFILE_ES) 881e5c31af7Sopenharmony_ci { 882e5c31af7Sopenharmony_ci const int majorVer = renderCtx.getType().getMajorVersion(); 883e5c31af7Sopenharmony_ci const int minorVer = renderCtx.getType().getMinorVersion(); 884e5c31af7Sopenharmony_ci 885e5c31af7Sopenharmony_ci return (majorVer > 3) || (majorVer == 3 && minorVer >= 2) || 886e5c31af7Sopenharmony_ci ctxInfo.isExtensionSupported("GL_EXT_tessellation_shader"); 887e5c31af7Sopenharmony_ci } 888e5c31af7Sopenharmony_ci else 889e5c31af7Sopenharmony_ci return false; 890e5c31af7Sopenharmony_ci} 891e5c31af7Sopenharmony_ci 892e5c31af7Sopenharmony_cistatic bool checkPixels (tcu::TestLog& log, const tcu::ConstPixelBufferAccess& surface) 893e5c31af7Sopenharmony_ci{ 894e5c31af7Sopenharmony_ci bool allWhite = true; 895e5c31af7Sopenharmony_ci bool allBlack = true; 896e5c31af7Sopenharmony_ci bool anyUnexpected = false; 897e5c31af7Sopenharmony_ci 898e5c31af7Sopenharmony_ci for (int y = 0; y < surface.getHeight(); y++) 899e5c31af7Sopenharmony_ci { 900e5c31af7Sopenharmony_ci for (int x = 0; x < surface.getWidth(); x++) 901e5c31af7Sopenharmony_ci { 902e5c31af7Sopenharmony_ci const tcu::IVec4 pixel = surface.getPixelInt(x, y); 903e5c31af7Sopenharmony_ci // Note: we really do not want to involve alpha in the check comparison 904e5c31af7Sopenharmony_ci // \todo [2010-09-22 kalle] Do we know that alpha would be one? If yes, could use color constants white and black. 905e5c31af7Sopenharmony_ci const bool isWhite = (pixel[0] == 255) && (pixel[1] == 255) && (pixel[2] == 255); 906e5c31af7Sopenharmony_ci const bool isBlack = (pixel[0] == 0) && (pixel[1] == 0) && (pixel[2] == 0); 907e5c31af7Sopenharmony_ci 908e5c31af7Sopenharmony_ci allWhite = allWhite && isWhite; 909e5c31af7Sopenharmony_ci allBlack = allBlack && isBlack; 910e5c31af7Sopenharmony_ci anyUnexpected = anyUnexpected || (!isWhite && !isBlack); 911e5c31af7Sopenharmony_ci } 912e5c31af7Sopenharmony_ci } 913e5c31af7Sopenharmony_ci 914e5c31af7Sopenharmony_ci if (!allWhite) 915e5c31af7Sopenharmony_ci { 916e5c31af7Sopenharmony_ci if (anyUnexpected) 917e5c31af7Sopenharmony_ci log << TestLog::Message << "WARNING: expecting all rendered pixels to be white or black, but got other colors as well!" << TestLog::EndMessage; 918e5c31af7Sopenharmony_ci else if (!allBlack) 919e5c31af7Sopenharmony_ci log << TestLog::Message << "WARNING: got inconsistent results over the image, when all pixels should be the same color!" << TestLog::EndMessage; 920e5c31af7Sopenharmony_ci 921e5c31af7Sopenharmony_ci return false; 922e5c31af7Sopenharmony_ci } 923e5c31af7Sopenharmony_ci 924e5c31af7Sopenharmony_ci return true; 925e5c31af7Sopenharmony_ci} 926e5c31af7Sopenharmony_ci 927e5c31af7Sopenharmony_cibool ShaderLibraryCase::execute (void) 928e5c31af7Sopenharmony_ci{ 929e5c31af7Sopenharmony_ci const float quadSize = 1.0f; 930e5c31af7Sopenharmony_ci static const float s_positions[4*4] = 931e5c31af7Sopenharmony_ci { 932e5c31af7Sopenharmony_ci -quadSize, -quadSize, 0.0f, 1.0f, 933e5c31af7Sopenharmony_ci -quadSize, +quadSize, 0.0f, 1.0f, 934e5c31af7Sopenharmony_ci +quadSize, -quadSize, 0.0f, 1.0f, 935e5c31af7Sopenharmony_ci +quadSize, +quadSize, 0.0f, 1.0f 936e5c31af7Sopenharmony_ci }; 937e5c31af7Sopenharmony_ci 938e5c31af7Sopenharmony_ci static const deUint16 s_indices[2*3] = 939e5c31af7Sopenharmony_ci { 940e5c31af7Sopenharmony_ci 0, 1, 2, 941e5c31af7Sopenharmony_ci 1, 3, 2 942e5c31af7Sopenharmony_ci }; 943e5c31af7Sopenharmony_ci 944e5c31af7Sopenharmony_ci TestLog& log = m_testCtx.getLog(); 945e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderCtx.getFunctions(); 946e5c31af7Sopenharmony_ci 947e5c31af7Sopenharmony_ci // Compute viewport. 948e5c31af7Sopenharmony_ci const tcu::RenderTarget& renderTarget = m_renderCtx.getRenderTarget(); 949e5c31af7Sopenharmony_ci de::Random rnd (deStringHash(getName())); 950e5c31af7Sopenharmony_ci const int width = deMin32(renderTarget.getWidth(), VIEWPORT_WIDTH); 951e5c31af7Sopenharmony_ci const int height = deMin32(renderTarget.getHeight(), VIEWPORT_HEIGHT); 952e5c31af7Sopenharmony_ci const int viewportX = rnd.getInt(0, renderTarget.getWidth() - width); 953e5c31af7Sopenharmony_ci const int viewportY = rnd.getInt(0, renderTarget.getHeight() - height); 954e5c31af7Sopenharmony_ci const int numVerticesPerDraw = 4; 955e5c31af7Sopenharmony_ci const bool tessellationPresent = isTessellationPresent(m_spec); 956e5c31af7Sopenharmony_ci const bool separablePrograms = m_spec.programs[0].sources.separable; 957e5c31af7Sopenharmony_ci 958e5c31af7Sopenharmony_ci bool allCompilesOk = true; 959e5c31af7Sopenharmony_ci bool allLinksOk = true; 960e5c31af7Sopenharmony_ci const char* failReason = DE_NULL; 961e5c31af7Sopenharmony_ci 962e5c31af7Sopenharmony_ci vector<ProgramSources> specializedSources (m_spec.programs.size()); 963e5c31af7Sopenharmony_ci 964e5c31af7Sopenharmony_ci deUint32 vertexProgramID = -1; 965e5c31af7Sopenharmony_ci vector<deUint32> pipelineProgramIDs; 966e5c31af7Sopenharmony_ci vector<SharedPtr<ShaderProgram> > programs; 967e5c31af7Sopenharmony_ci SharedPtr<ProgramPipeline> programPipeline; 968e5c31af7Sopenharmony_ci 969e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderCase::execute(): start"); 970e5c31af7Sopenharmony_ci 971e5c31af7Sopenharmony_ci if(isCapabilityRequired(CAPABILITY_ONLY_GLSL_ES_100_SUPPORT, m_spec) && glu::IsES3Compatible(gl)) 972e5c31af7Sopenharmony_ci return true; 973e5c31af7Sopenharmony_ci 974e5c31af7Sopenharmony_ci if(isCapabilityRequired(CAPABILITY_EXACTLY_ONE_DRAW_BUFFER, m_spec)) 975e5c31af7Sopenharmony_ci { 976e5c31af7Sopenharmony_ci // on unextended ES2 there is only one draw buffer 977e5c31af7Sopenharmony_ci // and there is no GL_MAX_DRAW_BUFFERS query 978e5c31af7Sopenharmony_ci glw::GLint maxDrawBuffers = 0; 979e5c31af7Sopenharmony_ci gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); 980e5c31af7Sopenharmony_ci if ((gl.getError() == GL_NO_ERROR) && (maxDrawBuffers > 1)) 981e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Test requires exactly one draw buffer"); 982e5c31af7Sopenharmony_ci } 983e5c31af7Sopenharmony_ci 984e5c31af7Sopenharmony_ci // Specialize shaders 985e5c31af7Sopenharmony_ci if (m_spec.caseType == CASETYPE_VERTEX_ONLY) 986e5c31af7Sopenharmony_ci { 987e5c31af7Sopenharmony_ci const vector<RequiredExtension> reqExt = checkAndSpecializeExtensions(m_spec.programs[0].requiredExtensions, m_contextInfo); 988e5c31af7Sopenharmony_ci 989e5c31af7Sopenharmony_ci DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[SHADERTYPE_VERTEX].size() == 1); 990e5c31af7Sopenharmony_ci specializedSources[0] << glu::VertexSource(specializeVertexShader(m_spec, m_spec.programs[0].sources.sources[SHADERTYPE_VERTEX][0], reqExt)) 991e5c31af7Sopenharmony_ci << glu::FragmentSource(genFragmentShader(m_spec)); 992e5c31af7Sopenharmony_ci } 993e5c31af7Sopenharmony_ci else if (m_spec.caseType == CASETYPE_FRAGMENT_ONLY) 994e5c31af7Sopenharmony_ci { 995e5c31af7Sopenharmony_ci const vector<RequiredExtension> reqExt = checkAndSpecializeExtensions(m_spec.programs[0].requiredExtensions, m_contextInfo); 996e5c31af7Sopenharmony_ci 997e5c31af7Sopenharmony_ci DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[SHADERTYPE_FRAGMENT].size() == 1); 998e5c31af7Sopenharmony_ci specializedSources[0] << glu::VertexSource(genVertexShader(m_spec)) 999e5c31af7Sopenharmony_ci << glu::FragmentSource(specializeFragmentShader(m_spec, m_spec.programs[0].sources.sources[SHADERTYPE_FRAGMENT][0], reqExt)); 1000e5c31af7Sopenharmony_ci } 1001e5c31af7Sopenharmony_ci else 1002e5c31af7Sopenharmony_ci { 1003e5c31af7Sopenharmony_ci DE_ASSERT(m_spec.caseType == CASETYPE_COMPLETE); 1004e5c31af7Sopenharmony_ci 1005e5c31af7Sopenharmony_ci const int maxPatchVertices = isTessellationPresent(m_spec) && isTessellationSupported(m_renderCtx, m_contextInfo) 1006e5c31af7Sopenharmony_ci ? m_contextInfo.getInt(GL_MAX_PATCH_VERTICES) : 0; 1007e5c31af7Sopenharmony_ci 1008e5c31af7Sopenharmony_ci for (size_t progNdx = 0; progNdx < m_spec.programs.size(); progNdx++) 1009e5c31af7Sopenharmony_ci { 1010e5c31af7Sopenharmony_ci const ProgramSpecializationParams progSpecParams (m_spec, checkAndSpecializeExtensions(m_spec.programs[progNdx].requiredExtensions, m_contextInfo), maxPatchVertices); 1011e5c31af7Sopenharmony_ci 1012e5c31af7Sopenharmony_ci specializeProgramSources(specializedSources[progNdx], m_spec.programs[progNdx].sources, progSpecParams); 1013e5c31af7Sopenharmony_ci } 1014e5c31af7Sopenharmony_ci } 1015e5c31af7Sopenharmony_ci 1016e5c31af7Sopenharmony_ci if (!separablePrograms) 1017e5c31af7Sopenharmony_ci { 1018e5c31af7Sopenharmony_ci de::SharedPtr<glu::ShaderProgram> program (new glu::ShaderProgram(m_renderCtx, specializedSources[0])); 1019e5c31af7Sopenharmony_ci 1020e5c31af7Sopenharmony_ci vertexProgramID = program->getProgram(); 1021e5c31af7Sopenharmony_ci pipelineProgramIDs.push_back(program->getProgram()); 1022e5c31af7Sopenharmony_ci programs.push_back(program); 1023e5c31af7Sopenharmony_ci 1024e5c31af7Sopenharmony_ci // Check that compile/link results are what we expect. 1025e5c31af7Sopenharmony_ci 1026e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(glu::SHADERTYPE_VERTEX == 0); 1027e5c31af7Sopenharmony_ci for (int stage = glu::SHADERTYPE_VERTEX; stage < glu::SHADERTYPE_LAST; ++stage) 1028e5c31af7Sopenharmony_ci if (program->hasShader((glu::ShaderType)stage) && !program->getShaderInfo((glu::ShaderType)stage).compileOk) 1029e5c31af7Sopenharmony_ci allCompilesOk = false; 1030e5c31af7Sopenharmony_ci 1031e5c31af7Sopenharmony_ci if (!program->getProgramInfo().linkOk) 1032e5c31af7Sopenharmony_ci allLinksOk = false; 1033e5c31af7Sopenharmony_ci 1034e5c31af7Sopenharmony_ci log << *program; 1035e5c31af7Sopenharmony_ci } 1036e5c31af7Sopenharmony_ci else 1037e5c31af7Sopenharmony_ci { 1038e5c31af7Sopenharmony_ci // Separate programs 1039e5c31af7Sopenharmony_ci for (size_t programNdx = 0; programNdx < m_spec.programs.size(); ++programNdx) 1040e5c31af7Sopenharmony_ci { 1041e5c31af7Sopenharmony_ci de::SharedPtr<glu::ShaderProgram> program(new glu::ShaderProgram(m_renderCtx, specializedSources[programNdx])); 1042e5c31af7Sopenharmony_ci 1043e5c31af7Sopenharmony_ci if (m_spec.programs[programNdx].activeStages & (1u << glu::SHADERTYPE_VERTEX)) 1044e5c31af7Sopenharmony_ci vertexProgramID = program->getProgram(); 1045e5c31af7Sopenharmony_ci 1046e5c31af7Sopenharmony_ci pipelineProgramIDs.push_back(program->getProgram()); 1047e5c31af7Sopenharmony_ci programs.push_back(program); 1048e5c31af7Sopenharmony_ci 1049e5c31af7Sopenharmony_ci // Check that compile/link results are what we expect. 1050e5c31af7Sopenharmony_ci 1051e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(glu::SHADERTYPE_VERTEX == 0); 1052e5c31af7Sopenharmony_ci for (int stage = glu::SHADERTYPE_VERTEX; stage < glu::SHADERTYPE_LAST; ++stage) 1053e5c31af7Sopenharmony_ci if (program->hasShader((glu::ShaderType)stage) && !program->getShaderInfo((glu::ShaderType)stage).compileOk) 1054e5c31af7Sopenharmony_ci allCompilesOk = false; 1055e5c31af7Sopenharmony_ci 1056e5c31af7Sopenharmony_ci if (!program->getProgramInfo().linkOk) 1057e5c31af7Sopenharmony_ci allLinksOk = false; 1058e5c31af7Sopenharmony_ci 1059e5c31af7Sopenharmony_ci // Log program and active stages 1060e5c31af7Sopenharmony_ci { 1061e5c31af7Sopenharmony_ci const tcu::ScopedLogSection section (log, "Program", "Program " + de::toString(programNdx+1)); 1062e5c31af7Sopenharmony_ci tcu::MessageBuilder builder (&log); 1063e5c31af7Sopenharmony_ci bool firstStage = true; 1064e5c31af7Sopenharmony_ci 1065e5c31af7Sopenharmony_ci builder << "Pipeline uses stages: "; 1066e5c31af7Sopenharmony_ci for (int stage = glu::SHADERTYPE_VERTEX; stage < glu::SHADERTYPE_LAST; ++stage) 1067e5c31af7Sopenharmony_ci { 1068e5c31af7Sopenharmony_ci if (m_spec.programs[programNdx].activeStages & (1u << stage)) 1069e5c31af7Sopenharmony_ci { 1070e5c31af7Sopenharmony_ci if (!firstStage) 1071e5c31af7Sopenharmony_ci builder << ", "; 1072e5c31af7Sopenharmony_ci builder << glu::getShaderTypeName((glu::ShaderType)stage); 1073e5c31af7Sopenharmony_ci firstStage = true; 1074e5c31af7Sopenharmony_ci } 1075e5c31af7Sopenharmony_ci } 1076e5c31af7Sopenharmony_ci builder << tcu::TestLog::EndMessage; 1077e5c31af7Sopenharmony_ci 1078e5c31af7Sopenharmony_ci log << *program; 1079e5c31af7Sopenharmony_ci } 1080e5c31af7Sopenharmony_ci } 1081e5c31af7Sopenharmony_ci } 1082e5c31af7Sopenharmony_ci 1083e5c31af7Sopenharmony_ci switch (m_spec.expectResult) 1084e5c31af7Sopenharmony_ci { 1085e5c31af7Sopenharmony_ci case EXPECT_PASS: 1086e5c31af7Sopenharmony_ci case EXPECT_VALIDATION_FAIL: 1087e5c31af7Sopenharmony_ci case EXPECT_BUILD_SUCCESSFUL: 1088e5c31af7Sopenharmony_ci if (!allCompilesOk) 1089e5c31af7Sopenharmony_ci failReason = "expected shaders to compile and link properly, but failed to compile."; 1090e5c31af7Sopenharmony_ci else if (!allLinksOk) 1091e5c31af7Sopenharmony_ci failReason = "expected shaders to compile and link properly, but failed to link."; 1092e5c31af7Sopenharmony_ci break; 1093e5c31af7Sopenharmony_ci 1094e5c31af7Sopenharmony_ci case EXPECT_COMPILE_FAIL: 1095e5c31af7Sopenharmony_ci if (allCompilesOk && !allLinksOk) 1096e5c31af7Sopenharmony_ci failReason = "expected compilation to fail, but shaders compiled and link failed."; 1097e5c31af7Sopenharmony_ci else if (allCompilesOk) 1098e5c31af7Sopenharmony_ci failReason = "expected compilation to fail, but shaders compiled correctly."; 1099e5c31af7Sopenharmony_ci break; 1100e5c31af7Sopenharmony_ci 1101e5c31af7Sopenharmony_ci case EXPECT_LINK_FAIL: 1102e5c31af7Sopenharmony_ci if (!allCompilesOk) 1103e5c31af7Sopenharmony_ci failReason = "expected linking to fail, but unable to compile."; 1104e5c31af7Sopenharmony_ci else if (allLinksOk) 1105e5c31af7Sopenharmony_ci failReason = "expected linking to fail, but passed."; 1106e5c31af7Sopenharmony_ci break; 1107e5c31af7Sopenharmony_ci 1108e5c31af7Sopenharmony_ci case EXPECT_COMPILE_LINK_FAIL: 1109e5c31af7Sopenharmony_ci if (allCompilesOk && allLinksOk) 1110e5c31af7Sopenharmony_ci failReason = "expected compile or link to fail, but passed."; 1111e5c31af7Sopenharmony_ci break; 1112e5c31af7Sopenharmony_ci 1113e5c31af7Sopenharmony_ci default: 1114e5c31af7Sopenharmony_ci DE_ASSERT(false); 1115e5c31af7Sopenharmony_ci return false; 1116e5c31af7Sopenharmony_ci } 1117e5c31af7Sopenharmony_ci 1118e5c31af7Sopenharmony_ci if (failReason != DE_NULL) 1119e5c31af7Sopenharmony_ci { 1120e5c31af7Sopenharmony_ci // \todo [2010-06-07 petri] These should be handled in the test case? 1121e5c31af7Sopenharmony_ci log << TestLog::Message << "ERROR: " << failReason << TestLog::EndMessage; 1122e5c31af7Sopenharmony_ci 1123e5c31af7Sopenharmony_ci if (isCapabilityRequired(CAPABILITY_FULL_GLSL_ES_100_SUPPORT, m_spec)) 1124e5c31af7Sopenharmony_ci { 1125e5c31af7Sopenharmony_ci log << TestLog::Message 1126e5c31af7Sopenharmony_ci << "Assuming build failure is caused by implementation not supporting full GLSL ES 100 specification, which is not required." 1127e5c31af7Sopenharmony_ci << TestLog::EndMessage; 1128e5c31af7Sopenharmony_ci 1129e5c31af7Sopenharmony_ci if (allCompilesOk && !allLinksOk) 1130e5c31af7Sopenharmony_ci { 1131e5c31af7Sopenharmony_ci // Used features are detectable at compile time. If implementation parses shader 1132e5c31af7Sopenharmony_ci // at link time, report it as quality warning. 1133e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, failReason); 1134e5c31af7Sopenharmony_ci } 1135e5c31af7Sopenharmony_ci else 1136e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Full GLSL ES 100 is not supported"); 1137e5c31af7Sopenharmony_ci } 1138e5c31af7Sopenharmony_ci else if (m_spec.expectResult == EXPECT_COMPILE_FAIL && allCompilesOk && !allLinksOk) 1139e5c31af7Sopenharmony_ci { 1140e5c31af7Sopenharmony_ci // If implementation parses shader at link time, report it as quality warning. 1141e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, failReason); 1142e5c31af7Sopenharmony_ci } 1143e5c31af7Sopenharmony_ci else 1144e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, failReason); 1145e5c31af7Sopenharmony_ci return false; 1146e5c31af7Sopenharmony_ci } 1147e5c31af7Sopenharmony_ci 1148e5c31af7Sopenharmony_ci // Return if shader is not intended to be run 1149e5c31af7Sopenharmony_ci if (m_spec.expectResult == EXPECT_COMPILE_FAIL || 1150e5c31af7Sopenharmony_ci m_spec.expectResult == EXPECT_COMPILE_LINK_FAIL || 1151e5c31af7Sopenharmony_ci m_spec.expectResult == EXPECT_LINK_FAIL || 1152e5c31af7Sopenharmony_ci m_spec.expectResult == EXPECT_BUILD_SUCCESSFUL) 1153e5c31af7Sopenharmony_ci return true; 1154e5c31af7Sopenharmony_ci 1155e5c31af7Sopenharmony_ci // Setup viewport. 1156e5c31af7Sopenharmony_ci gl.viewport(viewportX, viewportY, width, height); 1157e5c31af7Sopenharmony_ci 1158e5c31af7Sopenharmony_ci if (separablePrograms) 1159e5c31af7Sopenharmony_ci { 1160e5c31af7Sopenharmony_ci programPipeline = de::SharedPtr<glu::ProgramPipeline>(new glu::ProgramPipeline(m_renderCtx)); 1161e5c31af7Sopenharmony_ci 1162e5c31af7Sopenharmony_ci // Setup pipeline 1163e5c31af7Sopenharmony_ci gl.bindProgramPipeline(programPipeline->getPipeline()); 1164e5c31af7Sopenharmony_ci for (int programNdx = 0; programNdx < (int)m_spec.programs.size(); ++programNdx) 1165e5c31af7Sopenharmony_ci { 1166e5c31af7Sopenharmony_ci deUint32 shaderFlags = 0; 1167e5c31af7Sopenharmony_ci for (int stage = glu::SHADERTYPE_VERTEX; stage < glu::SHADERTYPE_LAST; ++stage) 1168e5c31af7Sopenharmony_ci if (m_spec.programs[programNdx].activeStages & (1u << stage)) 1169e5c31af7Sopenharmony_ci shaderFlags |= glu::getGLShaderTypeBit((glu::ShaderType)stage); 1170e5c31af7Sopenharmony_ci 1171e5c31af7Sopenharmony_ci programPipeline->useProgramStages(shaderFlags, pipelineProgramIDs[programNdx]); 1172e5c31af7Sopenharmony_ci } 1173e5c31af7Sopenharmony_ci 1174e5c31af7Sopenharmony_ci programPipeline->activeShaderProgram(vertexProgramID); 1175e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "setup pipeline"); 1176e5c31af7Sopenharmony_ci } 1177e5c31af7Sopenharmony_ci else 1178e5c31af7Sopenharmony_ci { 1179e5c31af7Sopenharmony_ci // Start using program 1180e5c31af7Sopenharmony_ci gl.useProgram(vertexProgramID); 1181e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram()"); 1182e5c31af7Sopenharmony_ci } 1183e5c31af7Sopenharmony_ci 1184e5c31af7Sopenharmony_ci // Fetch location for positions positions. 1185e5c31af7Sopenharmony_ci int positionLoc = gl.getAttribLocation(vertexProgramID, "dEQP_Position"); 1186e5c31af7Sopenharmony_ci if (positionLoc == -1) 1187e5c31af7Sopenharmony_ci { 1188e5c31af7Sopenharmony_ci string errStr = string("no location found for attribute 'dEQP_Position'"); 1189e5c31af7Sopenharmony_ci TCU_FAIL(errStr.c_str()); 1190e5c31af7Sopenharmony_ci } 1191e5c31af7Sopenharmony_ci 1192e5c31af7Sopenharmony_ci // Iterate all value blocks. 1193e5c31af7Sopenharmony_ci { 1194e5c31af7Sopenharmony_ci const ValueBlock& valueBlock = m_spec.values; 1195e5c31af7Sopenharmony_ci 1196e5c31af7Sopenharmony_ci // always render at least one pass even if there is no input/output data 1197e5c31af7Sopenharmony_ci const int numRenderPasses = valueBlock.outputs.empty() ? 1 : (int)valueBlock.outputs[0].elements.size() / valueBlock.outputs[0].type.getScalarSize(); 1198e5c31af7Sopenharmony_ci 1199e5c31af7Sopenharmony_ci // Iterate all array sub-cases. 1200e5c31af7Sopenharmony_ci for (int arrayNdx = 0; arrayNdx < numRenderPasses; arrayNdx++) 1201e5c31af7Sopenharmony_ci { 1202e5c31af7Sopenharmony_ci vector<VertexArrayBinding> vertexArrays; 1203e5c31af7Sopenharmony_ci int attribValueNdx = 0; 1204e5c31af7Sopenharmony_ci vector<vector<float> > attribValues (valueBlock.inputs.size()); 1205e5c31af7Sopenharmony_ci glw::GLenum postDrawError; 1206e5c31af7Sopenharmony_ci BeforeDrawValidator beforeDrawValidator (gl, 1207e5c31af7Sopenharmony_ci (separablePrograms) ? (programPipeline->getPipeline()) : (vertexProgramID), 1208e5c31af7Sopenharmony_ci (separablePrograms) ? (BeforeDrawValidator::TARGETTYPE_PIPELINE) : (BeforeDrawValidator::TARGETTYPE_PROGRAM)); 1209e5c31af7Sopenharmony_ci 1210e5c31af7Sopenharmony_ci vertexArrays.push_back(va::Float(positionLoc, 4, numVerticesPerDraw, 0, &s_positions[0])); 1211e5c31af7Sopenharmony_ci 1212e5c31af7Sopenharmony_ci // Collect VA pointer for inputs 1213e5c31af7Sopenharmony_ci for (size_t valNdx = 0; valNdx < valueBlock.inputs.size(); valNdx++) 1214e5c31af7Sopenharmony_ci { 1215e5c31af7Sopenharmony_ci const Value& val = valueBlock.inputs[valNdx]; 1216e5c31af7Sopenharmony_ci const char* const valueName = val.name.c_str(); 1217e5c31af7Sopenharmony_ci const DataType dataType = val.type.getBasicType(); 1218e5c31af7Sopenharmony_ci const int scalarSize = getDataTypeScalarSize(dataType); 1219e5c31af7Sopenharmony_ci 1220e5c31af7Sopenharmony_ci // Replicate values four times. 1221e5c31af7Sopenharmony_ci std::vector<float>& scalars = attribValues[attribValueNdx++]; 1222e5c31af7Sopenharmony_ci scalars.resize(numVerticesPerDraw * scalarSize); 1223e5c31af7Sopenharmony_ci if (isDataTypeFloatOrVec(dataType) || isDataTypeMatrix(dataType)) 1224e5c31af7Sopenharmony_ci { 1225e5c31af7Sopenharmony_ci for (int repNdx = 0; repNdx < numVerticesPerDraw; repNdx++) 1226e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < scalarSize; ndx++) 1227e5c31af7Sopenharmony_ci scalars[repNdx*scalarSize + ndx] = val.elements[arrayNdx*scalarSize + ndx].float32; 1228e5c31af7Sopenharmony_ci } 1229e5c31af7Sopenharmony_ci else 1230e5c31af7Sopenharmony_ci { 1231e5c31af7Sopenharmony_ci // convert to floats. 1232e5c31af7Sopenharmony_ci for (int repNdx = 0; repNdx < numVerticesPerDraw; repNdx++) 1233e5c31af7Sopenharmony_ci { 1234e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < scalarSize; ndx++) 1235e5c31af7Sopenharmony_ci { 1236e5c31af7Sopenharmony_ci float v = (float)val.elements[arrayNdx*scalarSize + ndx].int32; 1237e5c31af7Sopenharmony_ci DE_ASSERT(val.elements[arrayNdx*scalarSize + ndx].int32 == (int)v); 1238e5c31af7Sopenharmony_ci scalars[repNdx*scalarSize + ndx] = v; 1239e5c31af7Sopenharmony_ci } 1240e5c31af7Sopenharmony_ci } 1241e5c31af7Sopenharmony_ci } 1242e5c31af7Sopenharmony_ci 1243e5c31af7Sopenharmony_ci // Attribute name prefix. 1244e5c31af7Sopenharmony_ci string attribPrefix = ""; 1245e5c31af7Sopenharmony_ci // \todo [2010-05-27 petri] Should latter condition only apply for vertex cases (or actually non-fragment cases)? 1246e5c31af7Sopenharmony_ci if ((m_spec.caseType == CASETYPE_FRAGMENT_ONLY) || (getDataTypeScalarType(dataType) != TYPE_FLOAT)) 1247e5c31af7Sopenharmony_ci attribPrefix = "a_"; 1248e5c31af7Sopenharmony_ci 1249e5c31af7Sopenharmony_ci // Input always given as attribute. 1250e5c31af7Sopenharmony_ci string attribName = attribPrefix + valueName; 1251e5c31af7Sopenharmony_ci int attribLoc = gl.getAttribLocation(vertexProgramID, attribName.c_str()); 1252e5c31af7Sopenharmony_ci if (attribLoc == -1) 1253e5c31af7Sopenharmony_ci { 1254e5c31af7Sopenharmony_ci log << TestLog::Message << "Warning: no location found for attribute '" << attribName << "'" << TestLog::EndMessage; 1255e5c31af7Sopenharmony_ci continue; 1256e5c31af7Sopenharmony_ci } 1257e5c31af7Sopenharmony_ci 1258e5c31af7Sopenharmony_ci if (isDataTypeMatrix(dataType)) 1259e5c31af7Sopenharmony_ci { 1260e5c31af7Sopenharmony_ci int numCols = getDataTypeMatrixNumColumns(dataType); 1261e5c31af7Sopenharmony_ci int numRows = getDataTypeMatrixNumRows(dataType); 1262e5c31af7Sopenharmony_ci DE_ASSERT(scalarSize == numCols*numRows); 1263e5c31af7Sopenharmony_ci 1264e5c31af7Sopenharmony_ci for (int i = 0; i < numCols; i++) 1265e5c31af7Sopenharmony_ci vertexArrays.push_back(va::Float(attribLoc + i, numRows, numVerticesPerDraw, scalarSize*(int)sizeof(float), &scalars[i * numRows])); 1266e5c31af7Sopenharmony_ci } 1267e5c31af7Sopenharmony_ci else 1268e5c31af7Sopenharmony_ci { 1269e5c31af7Sopenharmony_ci DE_ASSERT(isDataTypeFloatOrVec(dataType) || isDataTypeIntOrIVec(dataType) || isDataTypeUintOrUVec(dataType) || isDataTypeBoolOrBVec(dataType)); 1270e5c31af7Sopenharmony_ci vertexArrays.push_back(va::Float(attribLoc, scalarSize, numVerticesPerDraw, 0, &scalars[0])); 1271e5c31af7Sopenharmony_ci } 1272e5c31af7Sopenharmony_ci 1273e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "set vertex attrib array"); 1274e5c31af7Sopenharmony_ci } 1275e5c31af7Sopenharmony_ci 1276e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "before set uniforms"); 1277e5c31af7Sopenharmony_ci 1278e5c31af7Sopenharmony_ci // set reference values for outputs. 1279e5c31af7Sopenharmony_ci for (size_t valNdx = 0; valNdx < valueBlock.outputs.size(); valNdx++) 1280e5c31af7Sopenharmony_ci { 1281e5c31af7Sopenharmony_ci const Value& val = valueBlock.outputs[valNdx]; 1282e5c31af7Sopenharmony_ci const char* const valueName = val.name.c_str(); 1283e5c31af7Sopenharmony_ci 1284e5c31af7Sopenharmony_ci // Set reference value. 1285e5c31af7Sopenharmony_ci string refName = string("ref_") + valueName; 1286e5c31af7Sopenharmony_ci setUniformValue(gl, pipelineProgramIDs, refName, val, arrayNdx, m_testCtx.getLog()); 1287e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "set reference uniforms"); 1288e5c31af7Sopenharmony_ci } 1289e5c31af7Sopenharmony_ci 1290e5c31af7Sopenharmony_ci // set uniform values 1291e5c31af7Sopenharmony_ci for (size_t valNdx = 0; valNdx < valueBlock.uniforms.size(); valNdx++) 1292e5c31af7Sopenharmony_ci { 1293e5c31af7Sopenharmony_ci const Value& val = valueBlock.uniforms[valNdx]; 1294e5c31af7Sopenharmony_ci const char* const valueName = val.name.c_str(); 1295e5c31af7Sopenharmony_ci 1296e5c31af7Sopenharmony_ci setUniformValue(gl, pipelineProgramIDs, valueName, val, arrayNdx, m_testCtx.getLog()); 1297e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "set uniforms"); 1298e5c31af7Sopenharmony_ci } 1299e5c31af7Sopenharmony_ci 1300e5c31af7Sopenharmony_ci // Clear. 1301e5c31af7Sopenharmony_ci gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f); 1302e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 1303e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "clear buffer"); 1304e5c31af7Sopenharmony_ci 1305e5c31af7Sopenharmony_ci // Use program or pipeline 1306e5c31af7Sopenharmony_ci if (separablePrograms) 1307e5c31af7Sopenharmony_ci gl.useProgram(0); 1308e5c31af7Sopenharmony_ci else 1309e5c31af7Sopenharmony_ci gl.useProgram(vertexProgramID); 1310e5c31af7Sopenharmony_ci 1311e5c31af7Sopenharmony_ci // Draw. 1312e5c31af7Sopenharmony_ci if (tessellationPresent) 1313e5c31af7Sopenharmony_ci { 1314e5c31af7Sopenharmony_ci gl.patchParameteri(GL_PATCH_VERTICES, 3); 1315e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "set patchParameteri(PATCH_VERTICES, 3)"); 1316e5c31af7Sopenharmony_ci } 1317e5c31af7Sopenharmony_ci 1318e5c31af7Sopenharmony_ci draw(m_renderCtx, 1319e5c31af7Sopenharmony_ci vertexProgramID, 1320e5c31af7Sopenharmony_ci (int)vertexArrays.size(), 1321e5c31af7Sopenharmony_ci &vertexArrays[0], 1322e5c31af7Sopenharmony_ci (tessellationPresent) ? 1323e5c31af7Sopenharmony_ci (pr::Patches(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0])) : 1324e5c31af7Sopenharmony_ci (pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0])), 1325e5c31af7Sopenharmony_ci (m_spec.expectResult == EXPECT_VALIDATION_FAIL) ? 1326e5c31af7Sopenharmony_ci (&beforeDrawValidator) : 1327e5c31af7Sopenharmony_ci (DE_NULL)); 1328e5c31af7Sopenharmony_ci 1329e5c31af7Sopenharmony_ci postDrawError = gl.getError(); 1330e5c31af7Sopenharmony_ci 1331e5c31af7Sopenharmony_ci if (m_spec.expectResult == EXPECT_PASS) 1332e5c31af7Sopenharmony_ci { 1333e5c31af7Sopenharmony_ci // Read back results. 1334e5c31af7Sopenharmony_ci Surface surface (width, height); 1335e5c31af7Sopenharmony_ci const float w = s_positions[3]; 1336e5c31af7Sopenharmony_ci const int minY = deCeilFloatToInt32 (((-quadSize / w) * 0.5f + 0.5f) * (float)height + 1.0f); 1337e5c31af7Sopenharmony_ci const int maxY = deFloorFloatToInt32(((+quadSize / w) * 0.5f + 0.5f) * (float)height - 0.5f); 1338e5c31af7Sopenharmony_ci const int minX = deCeilFloatToInt32 (((-quadSize / w) * 0.5f + 0.5f) * (float)width + 1.0f); 1339e5c31af7Sopenharmony_ci const int maxX = deFloorFloatToInt32(((+quadSize / w) * 0.5f + 0.5f) * (float)width - 0.5f); 1340e5c31af7Sopenharmony_ci 1341e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(postDrawError, "draw"); 1342e5c31af7Sopenharmony_ci 1343e5c31af7Sopenharmony_ci glu::readPixels(m_renderCtx, viewportX, viewportY, surface.getAccess()); 1344e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "read pixels"); 1345e5c31af7Sopenharmony_ci 1346e5c31af7Sopenharmony_ci if (!checkPixels(log, tcu::getSubregion(surface.getAccess(), minX, minY, maxX-minX+1, maxY-minY+1))) 1347e5c31af7Sopenharmony_ci { 1348e5c31af7Sopenharmony_ci log << TestLog::Message << "INCORRECT RESULT for sub-case " << arrayNdx+1 << " of " << numRenderPasses << "):" 1349e5c31af7Sopenharmony_ci << TestLog::EndMessage; 1350e5c31af7Sopenharmony_ci 1351e5c31af7Sopenharmony_ci log << TestLog::Message << "Failing shader input/output values:" << TestLog::EndMessage; 1352e5c31af7Sopenharmony_ci dumpValues(log, valueBlock, arrayNdx); 1353e5c31af7Sopenharmony_ci 1354e5c31af7Sopenharmony_ci // Dump image on failure. 1355e5c31af7Sopenharmony_ci log << TestLog::Image("Result", "Rendered result image", surface); 1356e5c31af7Sopenharmony_ci 1357e5c31af7Sopenharmony_ci gl.useProgram(0); 1358e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 1359e5c31af7Sopenharmony_ci return false; 1360e5c31af7Sopenharmony_ci } 1361e5c31af7Sopenharmony_ci } 1362e5c31af7Sopenharmony_ci else if (m_spec.expectResult == EXPECT_VALIDATION_FAIL) 1363e5c31af7Sopenharmony_ci { 1364e5c31af7Sopenharmony_ci log << TestLog::Message 1365e5c31af7Sopenharmony_ci << "Draw call generated error: " 1366e5c31af7Sopenharmony_ci << glu::getErrorStr(postDrawError) << " " 1367e5c31af7Sopenharmony_ci << ((postDrawError == GL_INVALID_OPERATION) ? ("(expected)") : ("(unexpected)")) << "\n" 1368e5c31af7Sopenharmony_ci << "Validate status: " 1369e5c31af7Sopenharmony_ci << glu::getBooleanStr(beforeDrawValidator.getValidateStatus()) << " " 1370e5c31af7Sopenharmony_ci << ((beforeDrawValidator.getValidateStatus() == GL_FALSE) ? ("(expected)") : ("(unexpected)")) << "\n" 1371e5c31af7Sopenharmony_ci << "Info log: " 1372e5c31af7Sopenharmony_ci << ((beforeDrawValidator.getInfoLog().empty()) ? ("[empty string]") : (beforeDrawValidator.getInfoLog())) << "\n" 1373e5c31af7Sopenharmony_ci << TestLog::EndMessage; 1374e5c31af7Sopenharmony_ci 1375e5c31af7Sopenharmony_ci // test result 1376e5c31af7Sopenharmony_ci 1377e5c31af7Sopenharmony_ci if (postDrawError != GL_NO_ERROR && postDrawError != GL_INVALID_OPERATION) 1378e5c31af7Sopenharmony_ci { 1379e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, ("Draw: got unexpected error: " + de::toString(glu::getErrorStr(postDrawError))).c_str()); 1380e5c31af7Sopenharmony_ci return false; 1381e5c31af7Sopenharmony_ci } 1382e5c31af7Sopenharmony_ci 1383e5c31af7Sopenharmony_ci if (beforeDrawValidator.getValidateStatus() == GL_TRUE) 1384e5c31af7Sopenharmony_ci { 1385e5c31af7Sopenharmony_ci if (postDrawError == GL_NO_ERROR) 1386e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "expected validation and rendering to fail but validation and rendering succeeded"); 1387e5c31af7Sopenharmony_ci else if (postDrawError == GL_INVALID_OPERATION) 1388e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "expected validation and rendering to fail but validation succeeded (rendering failed as expected)"); 1389e5c31af7Sopenharmony_ci else 1390e5c31af7Sopenharmony_ci DE_ASSERT(false); 1391e5c31af7Sopenharmony_ci return false; 1392e5c31af7Sopenharmony_ci } 1393e5c31af7Sopenharmony_ci else if (beforeDrawValidator.getValidateStatus() == GL_FALSE && postDrawError == GL_NO_ERROR) 1394e5c31af7Sopenharmony_ci { 1395e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "expected validation and rendering to fail but rendering succeeded (validation failed as expected)"); 1396e5c31af7Sopenharmony_ci return false; 1397e5c31af7Sopenharmony_ci } 1398e5c31af7Sopenharmony_ci else if (beforeDrawValidator.getValidateStatus() == GL_FALSE && postDrawError == GL_INVALID_OPERATION) 1399e5c31af7Sopenharmony_ci { 1400e5c31af7Sopenharmony_ci // Validation does not depend on input values, no need to test all values 1401e5c31af7Sopenharmony_ci return true; 1402e5c31af7Sopenharmony_ci } 1403e5c31af7Sopenharmony_ci else 1404e5c31af7Sopenharmony_ci DE_ASSERT(false); 1405e5c31af7Sopenharmony_ci } 1406e5c31af7Sopenharmony_ci else 1407e5c31af7Sopenharmony_ci DE_ASSERT(false); 1408e5c31af7Sopenharmony_ci } 1409e5c31af7Sopenharmony_ci } 1410e5c31af7Sopenharmony_ci 1411e5c31af7Sopenharmony_ci gl.useProgram(0); 1412e5c31af7Sopenharmony_ci if (separablePrograms) 1413e5c31af7Sopenharmony_ci gl.bindProgramPipeline(0); 1414e5c31af7Sopenharmony_ci 1415e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderCase::execute(): end"); 1416e5c31af7Sopenharmony_ci return true; 1417e5c31af7Sopenharmony_ci} 1418e5c31af7Sopenharmony_ci 1419e5c31af7Sopenharmony_ciTestCase::IterateResult ShaderLibraryCase::iterate (void) 1420e5c31af7Sopenharmony_ci{ 1421e5c31af7Sopenharmony_ci // Initialize state to pass. 1422e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1423e5c31af7Sopenharmony_ci 1424e5c31af7Sopenharmony_ci bool executeOk = execute(); 1425e5c31af7Sopenharmony_ci 1426e5c31af7Sopenharmony_ci DE_ASSERT(executeOk ? m_testCtx.getTestResult() == QP_TEST_RESULT_PASS : m_testCtx.getTestResult() != QP_TEST_RESULT_PASS); 1427e5c31af7Sopenharmony_ci DE_UNREF(executeOk); 1428e5c31af7Sopenharmony_ci return TestCase::STOP; 1429e5c31af7Sopenharmony_ci} 1430e5c31af7Sopenharmony_ci 1431e5c31af7Sopenharmony_ci} // gls 1432e5c31af7Sopenharmony_ci} // deqp 1433