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 Shader execution utilities. 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "glsShaderExecUtil.hpp" 25e5c31af7Sopenharmony_ci#include "gluRenderContext.hpp" 26e5c31af7Sopenharmony_ci#include "gluDrawUtil.hpp" 27e5c31af7Sopenharmony_ci#include "gluObjectWrapper.hpp" 28e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp" 29e5c31af7Sopenharmony_ci#include "gluTextureUtil.hpp" 30e5c31af7Sopenharmony_ci#include "gluProgramInterfaceQuery.hpp" 31e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp" 32e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp" 33e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 34e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 35e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 36e5c31af7Sopenharmony_ci#include "deSTLUtil.hpp" 37e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 38e5c31af7Sopenharmony_ci#include "deUniquePtr.hpp" 39e5c31af7Sopenharmony_ci#include "deMemory.h" 40e5c31af7Sopenharmony_ci 41e5c31af7Sopenharmony_ci#include <map> 42e5c31af7Sopenharmony_ci 43e5c31af7Sopenharmony_cinamespace deqp 44e5c31af7Sopenharmony_ci{ 45e5c31af7Sopenharmony_cinamespace gls 46e5c31af7Sopenharmony_ci{ 47e5c31af7Sopenharmony_ci 48e5c31af7Sopenharmony_cinamespace ShaderExecUtil 49e5c31af7Sopenharmony_ci{ 50e5c31af7Sopenharmony_ci 51e5c31af7Sopenharmony_ciusing std::vector; 52e5c31af7Sopenharmony_ci 53e5c31af7Sopenharmony_cistatic bool isExtensionSupported (const glu::RenderContext& renderCtx, const std::string& extension) 54e5c31af7Sopenharmony_ci{ 55e5c31af7Sopenharmony_ci const glw::Functions& gl = renderCtx.getFunctions(); 56e5c31af7Sopenharmony_ci int numExts = 0; 57e5c31af7Sopenharmony_ci 58e5c31af7Sopenharmony_ci gl.getIntegerv(GL_NUM_EXTENSIONS, &numExts); 59e5c31af7Sopenharmony_ci 60e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numExts; ndx++) 61e5c31af7Sopenharmony_ci { 62e5c31af7Sopenharmony_ci const char* curExt = (const char*)gl.getStringi(GL_EXTENSIONS, ndx); 63e5c31af7Sopenharmony_ci 64e5c31af7Sopenharmony_ci if (extension == curExt) 65e5c31af7Sopenharmony_ci return true; 66e5c31af7Sopenharmony_ci } 67e5c31af7Sopenharmony_ci 68e5c31af7Sopenharmony_ci return false; 69e5c31af7Sopenharmony_ci} 70e5c31af7Sopenharmony_ci 71e5c31af7Sopenharmony_cistatic void checkExtension (const glu::RenderContext& renderCtx, const std::string& extension) 72e5c31af7Sopenharmony_ci{ 73e5c31af7Sopenharmony_ci if (!isExtensionSupported(renderCtx, extension)) 74e5c31af7Sopenharmony_ci throw tcu::NotSupportedError(extension + " is not supported"); 75e5c31af7Sopenharmony_ci} 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_cistatic void checkLimit (const glu::RenderContext& renderCtx, deUint32 pname, int required) 78e5c31af7Sopenharmony_ci{ 79e5c31af7Sopenharmony_ci const glw::Functions& gl = renderCtx.getFunctions(); 80e5c31af7Sopenharmony_ci int implementationLimit = -1; 81e5c31af7Sopenharmony_ci deUint32 error; 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_ci gl.getIntegerv(pname, &implementationLimit); 84e5c31af7Sopenharmony_ci error = gl.getError(); 85e5c31af7Sopenharmony_ci 86e5c31af7Sopenharmony_ci if (error != GL_NO_ERROR) 87e5c31af7Sopenharmony_ci throw tcu::TestError("Failed to query " + de::toString(glu::getGettableStateStr(pname)) + " - got " + de::toString(glu::getErrorStr(error))); 88e5c31af7Sopenharmony_ci if (implementationLimit < required) 89e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Test requires " + de::toString(glu::getGettableStateStr(pname)) + " >= " + de::toString(required) + ", got " + de::toString(implementationLimit)); 90e5c31af7Sopenharmony_ci} 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_ci// Shader utilities 93e5c31af7Sopenharmony_ci 94e5c31af7Sopenharmony_cistatic std::string generateVertexShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix) 95e5c31af7Sopenharmony_ci{ 96e5c31af7Sopenharmony_ci const bool usesInout = glu::glslVersionUsesInOutQualifiers(shaderSpec.version); 97e5c31af7Sopenharmony_ci const char* in = usesInout ? "in" : "attribute"; 98e5c31af7Sopenharmony_ci const char* out = usesInout ? "out" : "varying"; 99e5c31af7Sopenharmony_ci std::ostringstream src; 100e5c31af7Sopenharmony_ci 101e5c31af7Sopenharmony_ci DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty()); 102e5c31af7Sopenharmony_ci 103e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"; 104e5c31af7Sopenharmony_ci 105e5c31af7Sopenharmony_ci if (!shaderSpec.globalDeclarations.empty()) 106e5c31af7Sopenharmony_ci src << shaderSpec.globalDeclarations << "\n"; 107e5c31af7Sopenharmony_ci 108e5c31af7Sopenharmony_ci src << in << " highp vec4 a_position;\n"; 109e5c31af7Sopenharmony_ci 110e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 111e5c31af7Sopenharmony_ci src << in << " " << glu::declare(input->varType, inputPrefix + input->name) << ";\n"; 112e5c31af7Sopenharmony_ci 113e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 114e5c31af7Sopenharmony_ci { 115e5c31af7Sopenharmony_ci DE_ASSERT(output->varType.isBasicType()); 116e5c31af7Sopenharmony_ci 117e5c31af7Sopenharmony_ci if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 118e5c31af7Sopenharmony_ci { 119e5c31af7Sopenharmony_ci const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 120e5c31af7Sopenharmony_ci const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 121e5c31af7Sopenharmony_ci const glu::VarType intType (intBaseType, glu::PRECISION_HIGHP); 122e5c31af7Sopenharmony_ci 123e5c31af7Sopenharmony_ci src << "flat " << out << " " << glu::declare(intType, outputPrefix + output->name) << ";\n"; 124e5c31af7Sopenharmony_ci } 125e5c31af7Sopenharmony_ci else 126e5c31af7Sopenharmony_ci src << "flat " << out << " " << glu::declare(output->varType, outputPrefix + output->name) << ";\n"; 127e5c31af7Sopenharmony_ci } 128e5c31af7Sopenharmony_ci 129e5c31af7Sopenharmony_ci src << "\n" 130e5c31af7Sopenharmony_ci << "void main (void)\n" 131e5c31af7Sopenharmony_ci << "{\n" 132e5c31af7Sopenharmony_ci << " gl_Position = a_position;\n" 133e5c31af7Sopenharmony_ci << " gl_PointSize = 1.0;\n\n"; 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_ci // Declare & fetch local input variables 136e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 137e5c31af7Sopenharmony_ci src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n"; 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_ci // Declare local output variables 140e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 141e5c31af7Sopenharmony_ci src << "\t" << glu::declare(output->varType, output->name) << ";\n"; 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci // Operation - indented to correct level. 144e5c31af7Sopenharmony_ci { 145e5c31af7Sopenharmony_ci std::istringstream opSrc (shaderSpec.source); 146e5c31af7Sopenharmony_ci std::string line; 147e5c31af7Sopenharmony_ci 148e5c31af7Sopenharmony_ci while (std::getline(opSrc, line)) 149e5c31af7Sopenharmony_ci src << "\t" << line << "\n"; 150e5c31af7Sopenharmony_ci } 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ci // Assignments to outputs. 153e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 154e5c31af7Sopenharmony_ci { 155e5c31af7Sopenharmony_ci if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 156e5c31af7Sopenharmony_ci { 157e5c31af7Sopenharmony_ci const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 158e5c31af7Sopenharmony_ci const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_ci src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n"; 161e5c31af7Sopenharmony_ci } 162e5c31af7Sopenharmony_ci else 163e5c31af7Sopenharmony_ci src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n"; 164e5c31af7Sopenharmony_ci } 165e5c31af7Sopenharmony_ci 166e5c31af7Sopenharmony_ci src << "}\n"; 167e5c31af7Sopenharmony_ci 168e5c31af7Sopenharmony_ci return src.str(); 169e5c31af7Sopenharmony_ci} 170e5c31af7Sopenharmony_ci 171e5c31af7Sopenharmony_cistatic std::string generateGeometryShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix) 172e5c31af7Sopenharmony_ci{ 173e5c31af7Sopenharmony_ci DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version)); 174e5c31af7Sopenharmony_ci DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty()); 175e5c31af7Sopenharmony_ci 176e5c31af7Sopenharmony_ci std::ostringstream src; 177e5c31af7Sopenharmony_ci 178e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"; 179e5c31af7Sopenharmony_ci 180e5c31af7Sopenharmony_ci if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES) 181e5c31af7Sopenharmony_ci src << "#extension GL_EXT_geometry_shader : require\n"; 182e5c31af7Sopenharmony_ci 183e5c31af7Sopenharmony_ci if (!shaderSpec.globalDeclarations.empty()) 184e5c31af7Sopenharmony_ci src << shaderSpec.globalDeclarations << "\n"; 185e5c31af7Sopenharmony_ci 186e5c31af7Sopenharmony_ci src << "layout(points) in;\n" 187e5c31af7Sopenharmony_ci << "layout(points, max_vertices = 1) out;\n"; 188e5c31af7Sopenharmony_ci 189e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 190e5c31af7Sopenharmony_ci src << "flat in " << glu::declare(input->varType, inputPrefix + input->name) << "[];\n"; 191e5c31af7Sopenharmony_ci 192e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 193e5c31af7Sopenharmony_ci { 194e5c31af7Sopenharmony_ci DE_ASSERT(output->varType.isBasicType()); 195e5c31af7Sopenharmony_ci 196e5c31af7Sopenharmony_ci if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 197e5c31af7Sopenharmony_ci { 198e5c31af7Sopenharmony_ci const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 199e5c31af7Sopenharmony_ci const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 200e5c31af7Sopenharmony_ci const glu::VarType intType (intBaseType, glu::PRECISION_HIGHP); 201e5c31af7Sopenharmony_ci 202e5c31af7Sopenharmony_ci src << "flat out " << glu::declare(intType, outputPrefix + output->name) << ";\n"; 203e5c31af7Sopenharmony_ci } 204e5c31af7Sopenharmony_ci else 205e5c31af7Sopenharmony_ci src << "flat out " << glu::declare(output->varType, outputPrefix + output->name) << ";\n"; 206e5c31af7Sopenharmony_ci } 207e5c31af7Sopenharmony_ci 208e5c31af7Sopenharmony_ci src << "\n" 209e5c31af7Sopenharmony_ci << "void main (void)\n" 210e5c31af7Sopenharmony_ci << "{\n" 211e5c31af7Sopenharmony_ci << " gl_Position = gl_in[0].gl_Position;\n\n"; 212e5c31af7Sopenharmony_ci 213e5c31af7Sopenharmony_ci // Fetch input variables 214e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 215e5c31af7Sopenharmony_ci src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << "[0];\n"; 216e5c31af7Sopenharmony_ci 217e5c31af7Sopenharmony_ci // Declare local output variables. 218e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 219e5c31af7Sopenharmony_ci src << "\t" << glu::declare(output->varType, output->name) << ";\n"; 220e5c31af7Sopenharmony_ci 221e5c31af7Sopenharmony_ci src << "\n"; 222e5c31af7Sopenharmony_ci 223e5c31af7Sopenharmony_ci // Operation - indented to correct level. 224e5c31af7Sopenharmony_ci { 225e5c31af7Sopenharmony_ci std::istringstream opSrc (shaderSpec.source); 226e5c31af7Sopenharmony_ci std::string line; 227e5c31af7Sopenharmony_ci 228e5c31af7Sopenharmony_ci while (std::getline(opSrc, line)) 229e5c31af7Sopenharmony_ci src << "\t" << line << "\n"; 230e5c31af7Sopenharmony_ci } 231e5c31af7Sopenharmony_ci 232e5c31af7Sopenharmony_ci // Assignments to outputs. 233e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 234e5c31af7Sopenharmony_ci { 235e5c31af7Sopenharmony_ci if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 236e5c31af7Sopenharmony_ci { 237e5c31af7Sopenharmony_ci const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 238e5c31af7Sopenharmony_ci const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 239e5c31af7Sopenharmony_ci 240e5c31af7Sopenharmony_ci src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n"; 241e5c31af7Sopenharmony_ci } 242e5c31af7Sopenharmony_ci else 243e5c31af7Sopenharmony_ci src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n"; 244e5c31af7Sopenharmony_ci } 245e5c31af7Sopenharmony_ci 246e5c31af7Sopenharmony_ci src << " EmitVertex();\n" 247e5c31af7Sopenharmony_ci << " EndPrimitive();\n" 248e5c31af7Sopenharmony_ci << "}\n"; 249e5c31af7Sopenharmony_ci 250e5c31af7Sopenharmony_ci return src.str(); 251e5c31af7Sopenharmony_ci} 252e5c31af7Sopenharmony_ci 253e5c31af7Sopenharmony_cistatic std::string generateEmptyFragmentSource (glu::GLSLVersion version) 254e5c31af7Sopenharmony_ci{ 255e5c31af7Sopenharmony_ci const bool customOut = glu::glslVersionUsesInOutQualifiers(version); 256e5c31af7Sopenharmony_ci std::ostringstream src; 257e5c31af7Sopenharmony_ci 258e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(version) << "\n"; 259e5c31af7Sopenharmony_ci 260e5c31af7Sopenharmony_ci // \todo [2013-08-05 pyry] Do we need one unused output? 261e5c31af7Sopenharmony_ci 262e5c31af7Sopenharmony_ci src << "void main (void)\n{\n"; 263e5c31af7Sopenharmony_ci if (!customOut) 264e5c31af7Sopenharmony_ci src << " gl_FragColor = vec4(0.0);\n"; 265e5c31af7Sopenharmony_ci src << "}\n"; 266e5c31af7Sopenharmony_ci 267e5c31af7Sopenharmony_ci return src.str(); 268e5c31af7Sopenharmony_ci} 269e5c31af7Sopenharmony_ci 270e5c31af7Sopenharmony_cistatic std::string generatePassthroughVertexShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix) 271e5c31af7Sopenharmony_ci{ 272e5c31af7Sopenharmony_ci // flat qualifier is not present in earlier versions? 273e5c31af7Sopenharmony_ci DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version)); 274e5c31af7Sopenharmony_ci 275e5c31af7Sopenharmony_ci std::ostringstream src; 276e5c31af7Sopenharmony_ci 277e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n" 278e5c31af7Sopenharmony_ci << "in highp vec4 a_position;\n"; 279e5c31af7Sopenharmony_ci 280e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 281e5c31af7Sopenharmony_ci { 282e5c31af7Sopenharmony_ci src << "in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n" 283e5c31af7Sopenharmony_ci << "flat out " << glu::declare(input->varType, outputPrefix + input->name) << ";\n"; 284e5c31af7Sopenharmony_ci } 285e5c31af7Sopenharmony_ci 286e5c31af7Sopenharmony_ci src << "\nvoid main (void)\n{\n" 287e5c31af7Sopenharmony_ci << " gl_Position = a_position;\n" 288e5c31af7Sopenharmony_ci << " gl_PointSize = 1.0;\n"; 289e5c31af7Sopenharmony_ci 290e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 291e5c31af7Sopenharmony_ci src << "\t" << outputPrefix << input->name << " = " << inputPrefix << input->name << ";\n"; 292e5c31af7Sopenharmony_ci 293e5c31af7Sopenharmony_ci src << "}\n"; 294e5c31af7Sopenharmony_ci 295e5c31af7Sopenharmony_ci return src.str(); 296e5c31af7Sopenharmony_ci} 297e5c31af7Sopenharmony_ci 298e5c31af7Sopenharmony_cistatic void generateFragShaderOutputDecl (std::ostream& src, const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& outputPrefix) 299e5c31af7Sopenharmony_ci{ 300e5c31af7Sopenharmony_ci DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version)); 301e5c31af7Sopenharmony_ci 302e5c31af7Sopenharmony_ci for (int outNdx = 0; outNdx < (int)shaderSpec.outputs.size(); ++outNdx) 303e5c31af7Sopenharmony_ci { 304e5c31af7Sopenharmony_ci const Symbol& output = shaderSpec.outputs[outNdx]; 305e5c31af7Sopenharmony_ci const int location = de::lookup(outLocationMap, output.name); 306e5c31af7Sopenharmony_ci const std::string outVarName = outputPrefix + output.name; 307e5c31af7Sopenharmony_ci glu::VariableDeclaration decl (output.varType, outVarName, glu::STORAGE_OUT, glu::INTERPOLATION_LAST, glu::Layout(location)); 308e5c31af7Sopenharmony_ci 309e5c31af7Sopenharmony_ci TCU_CHECK_INTERNAL(output.varType.isBasicType()); 310e5c31af7Sopenharmony_ci 311e5c31af7Sopenharmony_ci if (useIntOutputs && glu::isDataTypeFloatOrVec(output.varType.getBasicType())) 312e5c31af7Sopenharmony_ci { 313e5c31af7Sopenharmony_ci const int vecSize = glu::getDataTypeScalarSize(output.varType.getBasicType()); 314e5c31af7Sopenharmony_ci const glu::DataType uintBasicType = vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT; 315e5c31af7Sopenharmony_ci const glu::VarType uintType (uintBasicType, glu::PRECISION_HIGHP); 316e5c31af7Sopenharmony_ci 317e5c31af7Sopenharmony_ci decl.varType = uintType; 318e5c31af7Sopenharmony_ci src << decl << ";\n"; 319e5c31af7Sopenharmony_ci } 320e5c31af7Sopenharmony_ci else if (glu::isDataTypeBoolOrBVec(output.varType.getBasicType())) 321e5c31af7Sopenharmony_ci { 322e5c31af7Sopenharmony_ci const int vecSize = glu::getDataTypeScalarSize(output.varType.getBasicType()); 323e5c31af7Sopenharmony_ci const glu::DataType intBasicType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 324e5c31af7Sopenharmony_ci const glu::VarType intType (intBasicType, glu::PRECISION_HIGHP); 325e5c31af7Sopenharmony_ci 326e5c31af7Sopenharmony_ci decl.varType = intType; 327e5c31af7Sopenharmony_ci src << decl << ";\n"; 328e5c31af7Sopenharmony_ci } 329e5c31af7Sopenharmony_ci else if (glu::isDataTypeMatrix(output.varType.getBasicType())) 330e5c31af7Sopenharmony_ci { 331e5c31af7Sopenharmony_ci const int vecSize = glu::getDataTypeMatrixNumRows(output.varType.getBasicType()); 332e5c31af7Sopenharmony_ci const int numVecs = glu::getDataTypeMatrixNumColumns(output.varType.getBasicType()); 333e5c31af7Sopenharmony_ci const glu::DataType uintBasicType = glu::getDataTypeUintVec(vecSize); 334e5c31af7Sopenharmony_ci const glu::VarType uintType (uintBasicType, glu::PRECISION_HIGHP); 335e5c31af7Sopenharmony_ci 336e5c31af7Sopenharmony_ci decl.varType = uintType; 337e5c31af7Sopenharmony_ci for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx) 338e5c31af7Sopenharmony_ci { 339e5c31af7Sopenharmony_ci decl.name = outVarName + "_" + de::toString(vecNdx); 340e5c31af7Sopenharmony_ci decl.layout.location = location + vecNdx; 341e5c31af7Sopenharmony_ci src << decl << ";\n"; 342e5c31af7Sopenharmony_ci } 343e5c31af7Sopenharmony_ci } 344e5c31af7Sopenharmony_ci else 345e5c31af7Sopenharmony_ci src << decl << ";\n"; 346e5c31af7Sopenharmony_ci } 347e5c31af7Sopenharmony_ci} 348e5c31af7Sopenharmony_ci 349e5c31af7Sopenharmony_cistatic void generateFragShaderOutAssign (std::ostream& src, const ShaderSpec& shaderSpec, bool useIntOutputs, const std::string& valuePrefix, const std::string& outputPrefix) 350e5c31af7Sopenharmony_ci{ 351e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 352e5c31af7Sopenharmony_ci { 353e5c31af7Sopenharmony_ci if (useIntOutputs && glu::isDataTypeFloatOrVec(output->varType.getBasicType())) 354e5c31af7Sopenharmony_ci src << " o_" << output->name << " = floatBitsToUint(" << valuePrefix << output->name << ");\n"; 355e5c31af7Sopenharmony_ci else if (glu::isDataTypeMatrix(output->varType.getBasicType())) 356e5c31af7Sopenharmony_ci { 357e5c31af7Sopenharmony_ci const int numVecs = glu::getDataTypeMatrixNumColumns(output->varType.getBasicType()); 358e5c31af7Sopenharmony_ci 359e5c31af7Sopenharmony_ci for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx) 360e5c31af7Sopenharmony_ci if (useIntOutputs) 361e5c31af7Sopenharmony_ci src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = floatBitsToUint(" << valuePrefix << output->name << "[" << vecNdx << "]);\n"; 362e5c31af7Sopenharmony_ci else 363e5c31af7Sopenharmony_ci src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = " << valuePrefix << output->name << "[" << vecNdx << "];\n"; 364e5c31af7Sopenharmony_ci } 365e5c31af7Sopenharmony_ci else if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 366e5c31af7Sopenharmony_ci { 367e5c31af7Sopenharmony_ci const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 368e5c31af7Sopenharmony_ci const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 369e5c31af7Sopenharmony_ci 370e5c31af7Sopenharmony_ci src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << valuePrefix << output->name << ");\n"; 371e5c31af7Sopenharmony_ci } 372e5c31af7Sopenharmony_ci else 373e5c31af7Sopenharmony_ci src << "\t" << outputPrefix << output->name << " = " << valuePrefix << output->name << ";\n"; 374e5c31af7Sopenharmony_ci } 375e5c31af7Sopenharmony_ci} 376e5c31af7Sopenharmony_ci 377e5c31af7Sopenharmony_cistatic std::string generateFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& inputPrefix, const std::string& outputPrefix) 378e5c31af7Sopenharmony_ci{ 379e5c31af7Sopenharmony_ci DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version)); 380e5c31af7Sopenharmony_ci 381e5c31af7Sopenharmony_ci std::ostringstream src; 382e5c31af7Sopenharmony_ci 383e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"; 384e5c31af7Sopenharmony_ci 385e5c31af7Sopenharmony_ci if (!shaderSpec.globalDeclarations.empty()) 386e5c31af7Sopenharmony_ci src << shaderSpec.globalDeclarations << "\n"; 387e5c31af7Sopenharmony_ci 388e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 389e5c31af7Sopenharmony_ci src << "flat in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n"; 390e5c31af7Sopenharmony_ci 391e5c31af7Sopenharmony_ci generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix); 392e5c31af7Sopenharmony_ci 393e5c31af7Sopenharmony_ci src << "\nvoid main (void)\n{\n"; 394e5c31af7Sopenharmony_ci 395e5c31af7Sopenharmony_ci // Declare & fetch local input variables 396e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 397e5c31af7Sopenharmony_ci src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n"; 398e5c31af7Sopenharmony_ci 399e5c31af7Sopenharmony_ci // Declare output variables 400e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 401e5c31af7Sopenharmony_ci src << "\t" << glu::declare(output->varType, output->name) << ";\n"; 402e5c31af7Sopenharmony_ci 403e5c31af7Sopenharmony_ci // Operation - indented to correct level. 404e5c31af7Sopenharmony_ci { 405e5c31af7Sopenharmony_ci std::istringstream opSrc (shaderSpec.source); 406e5c31af7Sopenharmony_ci std::string line; 407e5c31af7Sopenharmony_ci 408e5c31af7Sopenharmony_ci while (std::getline(opSrc, line)) 409e5c31af7Sopenharmony_ci src << "\t" << line << "\n"; 410e5c31af7Sopenharmony_ci } 411e5c31af7Sopenharmony_ci 412e5c31af7Sopenharmony_ci generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, "", outputPrefix); 413e5c31af7Sopenharmony_ci 414e5c31af7Sopenharmony_ci src << "}\n"; 415e5c31af7Sopenharmony_ci 416e5c31af7Sopenharmony_ci return src.str(); 417e5c31af7Sopenharmony_ci} 418e5c31af7Sopenharmony_ci 419e5c31af7Sopenharmony_cistatic std::string generatePassthroughFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& inputPrefix, const std::string& outputPrefix) 420e5c31af7Sopenharmony_ci{ 421e5c31af7Sopenharmony_ci DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version)); 422e5c31af7Sopenharmony_ci 423e5c31af7Sopenharmony_ci std::ostringstream src; 424e5c31af7Sopenharmony_ci 425e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"; 426e5c31af7Sopenharmony_ci 427e5c31af7Sopenharmony_ci if (!shaderSpec.globalDeclarations.empty()) 428e5c31af7Sopenharmony_ci src << shaderSpec.globalDeclarations << "\n"; 429e5c31af7Sopenharmony_ci 430e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 431e5c31af7Sopenharmony_ci { 432e5c31af7Sopenharmony_ci if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 433e5c31af7Sopenharmony_ci { 434e5c31af7Sopenharmony_ci const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 435e5c31af7Sopenharmony_ci const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 436e5c31af7Sopenharmony_ci const glu::VarType intType (intBaseType, glu::PRECISION_HIGHP); 437e5c31af7Sopenharmony_ci 438e5c31af7Sopenharmony_ci src << "flat in " << glu::declare(intType, inputPrefix + output->name) << ";\n"; 439e5c31af7Sopenharmony_ci } 440e5c31af7Sopenharmony_ci else 441e5c31af7Sopenharmony_ci src << "flat in " << glu::declare(output->varType, inputPrefix + output->name) << ";\n"; 442e5c31af7Sopenharmony_ci } 443e5c31af7Sopenharmony_ci 444e5c31af7Sopenharmony_ci generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix); 445e5c31af7Sopenharmony_ci 446e5c31af7Sopenharmony_ci src << "\nvoid main (void)\n{\n"; 447e5c31af7Sopenharmony_ci 448e5c31af7Sopenharmony_ci generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, inputPrefix, outputPrefix); 449e5c31af7Sopenharmony_ci 450e5c31af7Sopenharmony_ci src << "}\n"; 451e5c31af7Sopenharmony_ci 452e5c31af7Sopenharmony_ci return src.str(); 453e5c31af7Sopenharmony_ci} 454e5c31af7Sopenharmony_ci 455e5c31af7Sopenharmony_ci// ShaderExecutor 456e5c31af7Sopenharmony_ci 457e5c31af7Sopenharmony_ciShaderExecutor::ShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 458e5c31af7Sopenharmony_ci : m_renderCtx (renderCtx) 459e5c31af7Sopenharmony_ci , m_inputs (shaderSpec.inputs) 460e5c31af7Sopenharmony_ci , m_outputs (shaderSpec.outputs) 461e5c31af7Sopenharmony_ci{ 462e5c31af7Sopenharmony_ci} 463e5c31af7Sopenharmony_ci 464e5c31af7Sopenharmony_ciShaderExecutor::~ShaderExecutor (void) 465e5c31af7Sopenharmony_ci{ 466e5c31af7Sopenharmony_ci} 467e5c31af7Sopenharmony_ci 468e5c31af7Sopenharmony_civoid ShaderExecutor::useProgram (void) 469e5c31af7Sopenharmony_ci{ 470e5c31af7Sopenharmony_ci DE_ASSERT(isOk()); 471e5c31af7Sopenharmony_ci m_renderCtx.getFunctions().useProgram(getProgram()); 472e5c31af7Sopenharmony_ci} 473e5c31af7Sopenharmony_ci 474e5c31af7Sopenharmony_ci// FragmentOutExecutor 475e5c31af7Sopenharmony_ci 476e5c31af7Sopenharmony_cistruct FragmentOutputLayout 477e5c31af7Sopenharmony_ci{ 478e5c31af7Sopenharmony_ci std::vector<const Symbol*> locationSymbols; //! Symbols by location 479e5c31af7Sopenharmony_ci std::map<std::string, int> locationMap; //! Map from symbol name to start location 480e5c31af7Sopenharmony_ci}; 481e5c31af7Sopenharmony_ci 482e5c31af7Sopenharmony_ciclass FragmentOutExecutor : public ShaderExecutor 483e5c31af7Sopenharmony_ci{ 484e5c31af7Sopenharmony_cipublic: 485e5c31af7Sopenharmony_ci FragmentOutExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 486e5c31af7Sopenharmony_ci ~FragmentOutExecutor (void); 487e5c31af7Sopenharmony_ci 488e5c31af7Sopenharmony_ci void execute (int numValues, const void* const* inputs, void* const* outputs); 489e5c31af7Sopenharmony_ci 490e5c31af7Sopenharmony_ciprotected: 491e5c31af7Sopenharmony_ci const FragmentOutputLayout m_outputLayout; 492e5c31af7Sopenharmony_ci}; 493e5c31af7Sopenharmony_ci 494e5c31af7Sopenharmony_cistatic FragmentOutputLayout computeFragmentOutputLayout (const std::vector<Symbol>& symbols) 495e5c31af7Sopenharmony_ci{ 496e5c31af7Sopenharmony_ci FragmentOutputLayout ret; 497e5c31af7Sopenharmony_ci int location = 0; 498e5c31af7Sopenharmony_ci 499e5c31af7Sopenharmony_ci for (std::vector<Symbol>::const_iterator it = symbols.begin(); it != symbols.end(); ++it) 500e5c31af7Sopenharmony_ci { 501e5c31af7Sopenharmony_ci const int numLocations = glu::getDataTypeNumLocations(it->varType.getBasicType()); 502e5c31af7Sopenharmony_ci 503e5c31af7Sopenharmony_ci TCU_CHECK_INTERNAL(!de::contains(ret.locationMap, it->name)); 504e5c31af7Sopenharmony_ci de::insert(ret.locationMap, it->name, location); 505e5c31af7Sopenharmony_ci location += numLocations; 506e5c31af7Sopenharmony_ci 507e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numLocations; ++ndx) 508e5c31af7Sopenharmony_ci ret.locationSymbols.push_back(&*it); 509e5c31af7Sopenharmony_ci } 510e5c31af7Sopenharmony_ci 511e5c31af7Sopenharmony_ci return ret; 512e5c31af7Sopenharmony_ci} 513e5c31af7Sopenharmony_ci 514e5c31af7Sopenharmony_ciinline bool hasFloatRenderTargets (const glu::RenderContext& renderCtx) 515e5c31af7Sopenharmony_ci{ 516e5c31af7Sopenharmony_ci glu::ContextType type = renderCtx.getType(); 517e5c31af7Sopenharmony_ci return glu::isContextTypeGLCore(type); 518e5c31af7Sopenharmony_ci} 519e5c31af7Sopenharmony_ci 520e5c31af7Sopenharmony_ciFragmentOutExecutor::FragmentOutExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 521e5c31af7Sopenharmony_ci : ShaderExecutor (renderCtx, shaderSpec) 522e5c31af7Sopenharmony_ci , m_outputLayout (computeFragmentOutputLayout(m_outputs)) 523e5c31af7Sopenharmony_ci{ 524e5c31af7Sopenharmony_ci} 525e5c31af7Sopenharmony_ci 526e5c31af7Sopenharmony_ciFragmentOutExecutor::~FragmentOutExecutor (void) 527e5c31af7Sopenharmony_ci{ 528e5c31af7Sopenharmony_ci} 529e5c31af7Sopenharmony_ci 530e5c31af7Sopenharmony_ciinline int queryInt (const glw::Functions& gl, deUint32 pname) 531e5c31af7Sopenharmony_ci{ 532e5c31af7Sopenharmony_ci int value = 0; 533e5c31af7Sopenharmony_ci gl.getIntegerv(pname, &value); 534e5c31af7Sopenharmony_ci return value; 535e5c31af7Sopenharmony_ci} 536e5c31af7Sopenharmony_ci 537e5c31af7Sopenharmony_cistatic tcu::TextureFormat getRenderbufferFormatForOutput (const glu::VarType& outputType, bool useIntOutputs) 538e5c31af7Sopenharmony_ci{ 539e5c31af7Sopenharmony_ci const tcu::TextureFormat::ChannelOrder channelOrderMap[] = 540e5c31af7Sopenharmony_ci { 541e5c31af7Sopenharmony_ci tcu::TextureFormat::R, 542e5c31af7Sopenharmony_ci tcu::TextureFormat::RG, 543e5c31af7Sopenharmony_ci tcu::TextureFormat::RGBA, // No RGB variants available. 544e5c31af7Sopenharmony_ci tcu::TextureFormat::RGBA 545e5c31af7Sopenharmony_ci }; 546e5c31af7Sopenharmony_ci 547e5c31af7Sopenharmony_ci const glu::DataType basicType = outputType.getBasicType(); 548e5c31af7Sopenharmony_ci const int numComps = glu::getDataTypeNumComponents(basicType); 549e5c31af7Sopenharmony_ci tcu::TextureFormat::ChannelType channelType; 550e5c31af7Sopenharmony_ci 551e5c31af7Sopenharmony_ci switch (glu::getDataTypeScalarType(basicType)) 552e5c31af7Sopenharmony_ci { 553e5c31af7Sopenharmony_ci case glu::TYPE_UINT: channelType = tcu::TextureFormat::UNSIGNED_INT32; break; 554e5c31af7Sopenharmony_ci case glu::TYPE_INT: channelType = tcu::TextureFormat::SIGNED_INT32; break; 555e5c31af7Sopenharmony_ci case glu::TYPE_BOOL: channelType = tcu::TextureFormat::SIGNED_INT32; break; 556e5c31af7Sopenharmony_ci case glu::TYPE_FLOAT: channelType = useIntOutputs ? tcu::TextureFormat::UNSIGNED_INT32 : tcu::TextureFormat::FLOAT; break; 557e5c31af7Sopenharmony_ci default: 558e5c31af7Sopenharmony_ci throw tcu::InternalError("Invalid output type"); 559e5c31af7Sopenharmony_ci } 560e5c31af7Sopenharmony_ci 561e5c31af7Sopenharmony_ci DE_ASSERT(de::inRange<int>(numComps, 1, DE_LENGTH_OF_ARRAY(channelOrderMap))); 562e5c31af7Sopenharmony_ci 563e5c31af7Sopenharmony_ci return tcu::TextureFormat(channelOrderMap[numComps-1], channelType); 564e5c31af7Sopenharmony_ci} 565e5c31af7Sopenharmony_ci 566e5c31af7Sopenharmony_civoid FragmentOutExecutor::execute (int numValues, const void* const* inputs, void* const* outputs) 567e5c31af7Sopenharmony_ci{ 568e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderCtx.getFunctions(); 569e5c31af7Sopenharmony_ci const bool useIntOutputs = !hasFloatRenderTargets(m_renderCtx); 570e5c31af7Sopenharmony_ci const int maxRenderbufferSize = queryInt(gl, GL_MAX_RENDERBUFFER_SIZE); 571e5c31af7Sopenharmony_ci const int framebufferW = de::min(maxRenderbufferSize, numValues); 572e5c31af7Sopenharmony_ci const int framebufferH = (numValues / framebufferW) + ((numValues % framebufferW != 0) ? 1 : 0); 573e5c31af7Sopenharmony_ci 574e5c31af7Sopenharmony_ci glu::Framebuffer framebuffer (m_renderCtx); 575e5c31af7Sopenharmony_ci glu::RenderbufferVector renderbuffers (m_renderCtx, m_outputLayout.locationSymbols.size()); 576e5c31af7Sopenharmony_ci 577e5c31af7Sopenharmony_ci vector<glu::VertexArrayBinding> vertexArrays; 578e5c31af7Sopenharmony_ci vector<tcu::Vec2> positions (numValues); 579e5c31af7Sopenharmony_ci 580e5c31af7Sopenharmony_ci if (framebufferH > maxRenderbufferSize) 581e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Value count is too high for maximum supported renderbuffer size"); 582e5c31af7Sopenharmony_ci 583e5c31af7Sopenharmony_ci // Compute positions - 1px points are used to drive fragment shading. 584e5c31af7Sopenharmony_ci for (int valNdx = 0; valNdx < numValues; valNdx++) 585e5c31af7Sopenharmony_ci { 586e5c31af7Sopenharmony_ci const int ix = valNdx % framebufferW; 587e5c31af7Sopenharmony_ci const int iy = valNdx / framebufferW; 588e5c31af7Sopenharmony_ci const float fx = -1.0f + 2.0f*((float(ix) + 0.5f) / float(framebufferW)); 589e5c31af7Sopenharmony_ci const float fy = -1.0f + 2.0f*((float(iy) + 0.5f) / float(framebufferH)); 590e5c31af7Sopenharmony_ci 591e5c31af7Sopenharmony_ci positions[valNdx] = tcu::Vec2(fx, fy); 592e5c31af7Sopenharmony_ci } 593e5c31af7Sopenharmony_ci 594e5c31af7Sopenharmony_ci // Vertex inputs. 595e5c31af7Sopenharmony_ci vertexArrays.push_back(glu::va::Float("a_position", 2, numValues, 0, (const float*)&positions[0])); 596e5c31af7Sopenharmony_ci 597e5c31af7Sopenharmony_ci for (int inputNdx = 0; inputNdx < (int)m_inputs.size(); inputNdx++) 598e5c31af7Sopenharmony_ci { 599e5c31af7Sopenharmony_ci const Symbol& symbol = m_inputs[inputNdx]; 600e5c31af7Sopenharmony_ci const std::string attribName = "a_" + symbol.name; 601e5c31af7Sopenharmony_ci const void* ptr = inputs[inputNdx]; 602e5c31af7Sopenharmony_ci const glu::DataType basicType = symbol.varType.getBasicType(); 603e5c31af7Sopenharmony_ci const int vecSize = glu::getDataTypeScalarSize(basicType); 604e5c31af7Sopenharmony_ci 605e5c31af7Sopenharmony_ci if (glu::isDataTypeFloatOrVec(basicType)) 606e5c31af7Sopenharmony_ci vertexArrays.push_back(glu::va::Float(attribName, vecSize, numValues, 0, (const float*)ptr)); 607e5c31af7Sopenharmony_ci else if (glu::isDataTypeIntOrIVec(basicType)) 608e5c31af7Sopenharmony_ci vertexArrays.push_back(glu::va::Int32(attribName, vecSize, numValues, 0, (const deInt32*)ptr)); 609e5c31af7Sopenharmony_ci else if (glu::isDataTypeUintOrUVec(basicType)) 610e5c31af7Sopenharmony_ci vertexArrays.push_back(glu::va::Uint32(attribName, vecSize, numValues, 0, (const deUint32*)ptr)); 611e5c31af7Sopenharmony_ci else if (glu::isDataTypeMatrix(basicType)) 612e5c31af7Sopenharmony_ci { 613e5c31af7Sopenharmony_ci int numRows = glu::getDataTypeMatrixNumRows(basicType); 614e5c31af7Sopenharmony_ci int numCols = glu::getDataTypeMatrixNumColumns(basicType); 615e5c31af7Sopenharmony_ci int stride = numRows * numCols * (int)sizeof(float); 616e5c31af7Sopenharmony_ci 617e5c31af7Sopenharmony_ci for (int colNdx = 0; colNdx < numCols; ++colNdx) 618e5c31af7Sopenharmony_ci vertexArrays.push_back(glu::va::Float(attribName, colNdx, numRows, numValues, stride, ((const float*)ptr) + colNdx * numRows)); 619e5c31af7Sopenharmony_ci } 620e5c31af7Sopenharmony_ci else 621e5c31af7Sopenharmony_ci DE_ASSERT(false); 622e5c31af7Sopenharmony_ci } 623e5c31af7Sopenharmony_ci 624e5c31af7Sopenharmony_ci // Construct framebuffer. 625e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer); 626e5c31af7Sopenharmony_ci 627e5c31af7Sopenharmony_ci for (int outNdx = 0; outNdx < (int)m_outputLayout.locationSymbols.size(); ++outNdx) 628e5c31af7Sopenharmony_ci { 629e5c31af7Sopenharmony_ci const Symbol& output = *m_outputLayout.locationSymbols[outNdx]; 630e5c31af7Sopenharmony_ci const deUint32 renderbuffer = renderbuffers[outNdx]; 631e5c31af7Sopenharmony_ci const deUint32 format = glu::getInternalFormat(getRenderbufferFormatForOutput(output.varType, useIntOutputs)); 632e5c31af7Sopenharmony_ci 633e5c31af7Sopenharmony_ci gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 634e5c31af7Sopenharmony_ci gl.renderbufferStorage(GL_RENDERBUFFER, format, framebufferW, framebufferH); 635e5c31af7Sopenharmony_ci gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+outNdx, GL_RENDERBUFFER, renderbuffer); 636e5c31af7Sopenharmony_ci } 637e5c31af7Sopenharmony_ci gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 638e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set up framebuffer object"); 639e5c31af7Sopenharmony_ci TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 640e5c31af7Sopenharmony_ci 641e5c31af7Sopenharmony_ci { 642e5c31af7Sopenharmony_ci vector<deUint32> drawBuffers(m_outputLayout.locationSymbols.size()); 643e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)m_outputLayout.locationSymbols.size(); ndx++) 644e5c31af7Sopenharmony_ci drawBuffers[ndx] = GL_COLOR_ATTACHMENT0+ndx; 645e5c31af7Sopenharmony_ci gl.drawBuffers((int)drawBuffers.size(), &drawBuffers[0]); 646e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffers()"); 647e5c31af7Sopenharmony_ci } 648e5c31af7Sopenharmony_ci 649e5c31af7Sopenharmony_ci // Render 650e5c31af7Sopenharmony_ci gl.viewport(0, 0, framebufferW, framebufferH); 651e5c31af7Sopenharmony_ci glu::draw(m_renderCtx, this->getProgram(), (int)vertexArrays.size(), &vertexArrays[0], 652e5c31af7Sopenharmony_ci glu::pr::Points(numValues)); 653e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error in draw"); 654e5c31af7Sopenharmony_ci 655e5c31af7Sopenharmony_ci // Read back pixels. 656e5c31af7Sopenharmony_ci { 657e5c31af7Sopenharmony_ci tcu::TextureLevel tmpBuf; 658e5c31af7Sopenharmony_ci 659e5c31af7Sopenharmony_ci // \todo [2013-08-07 pyry] Some fast-paths could be added here. 660e5c31af7Sopenharmony_ci 661e5c31af7Sopenharmony_ci for (int outNdx = 0; outNdx < (int)m_outputs.size(); ++outNdx) 662e5c31af7Sopenharmony_ci { 663e5c31af7Sopenharmony_ci const Symbol& output = m_outputs[outNdx]; 664e5c31af7Sopenharmony_ci const int outSize = output.varType.getScalarSize(); 665e5c31af7Sopenharmony_ci const int outVecSize = glu::getDataTypeNumComponents(output.varType.getBasicType()); 666e5c31af7Sopenharmony_ci const int outNumLocs = glu::getDataTypeNumLocations(output.varType.getBasicType()); 667e5c31af7Sopenharmony_ci deUint32* dstPtrBase = static_cast<deUint32*>(outputs[outNdx]); 668e5c31af7Sopenharmony_ci const tcu::TextureFormat format = getRenderbufferFormatForOutput(output.varType, useIntOutputs); 669e5c31af7Sopenharmony_ci const tcu::TextureFormat readFormat (tcu::TextureFormat::RGBA, format.type); 670e5c31af7Sopenharmony_ci const int outLocation = de::lookup(m_outputLayout.locationMap, output.name); 671e5c31af7Sopenharmony_ci 672e5c31af7Sopenharmony_ci tmpBuf.setStorage(readFormat, framebufferW, framebufferH); 673e5c31af7Sopenharmony_ci 674e5c31af7Sopenharmony_ci for (int locNdx = 0; locNdx < outNumLocs; ++locNdx) 675e5c31af7Sopenharmony_ci { 676e5c31af7Sopenharmony_ci gl.readBuffer(GL_COLOR_ATTACHMENT0 + outLocation + locNdx); 677e5c31af7Sopenharmony_ci glu::readPixels(m_renderCtx, 0, 0, tmpBuf.getAccess()); 678e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels"); 679e5c31af7Sopenharmony_ci 680e5c31af7Sopenharmony_ci if (outSize == 4 && outNumLocs == 1) 681e5c31af7Sopenharmony_ci deMemcpy(dstPtrBase, tmpBuf.getAccess().getDataPtr(), numValues*outVecSize*sizeof(deUint32)); 682e5c31af7Sopenharmony_ci else 683e5c31af7Sopenharmony_ci { 684e5c31af7Sopenharmony_ci for (int valNdx = 0; valNdx < numValues; valNdx++) 685e5c31af7Sopenharmony_ci { 686e5c31af7Sopenharmony_ci const deUint32* srcPtr = (const deUint32*)tmpBuf.getAccess().getDataPtr() + valNdx*4; 687e5c31af7Sopenharmony_ci deUint32* dstPtr = &dstPtrBase[outSize*valNdx + outVecSize*locNdx]; 688e5c31af7Sopenharmony_ci deMemcpy(dstPtr, srcPtr, outVecSize*sizeof(deUint32)); 689e5c31af7Sopenharmony_ci } 690e5c31af7Sopenharmony_ci } 691e5c31af7Sopenharmony_ci } 692e5c31af7Sopenharmony_ci } 693e5c31af7Sopenharmony_ci } 694e5c31af7Sopenharmony_ci 695e5c31af7Sopenharmony_ci // \todo [2013-08-07 pyry] Clear draw buffers & viewport? 696e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 697e5c31af7Sopenharmony_ci} 698e5c31af7Sopenharmony_ci 699e5c31af7Sopenharmony_ci// VertexShaderExecutor 700e5c31af7Sopenharmony_ci 701e5c31af7Sopenharmony_ciclass VertexShaderExecutor : public FragmentOutExecutor 702e5c31af7Sopenharmony_ci{ 703e5c31af7Sopenharmony_cipublic: 704e5c31af7Sopenharmony_ci VertexShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 705e5c31af7Sopenharmony_ci ~VertexShaderExecutor (void); 706e5c31af7Sopenharmony_ci 707e5c31af7Sopenharmony_ci bool isOk (void) const { return m_program.isOk(); } 708e5c31af7Sopenharmony_ci void log (tcu::TestLog& dst) const { dst << m_program; } 709e5c31af7Sopenharmony_ci deUint32 getProgram (void) const { return m_program.getProgram(); } 710e5c31af7Sopenharmony_ci 711e5c31af7Sopenharmony_ciprotected: 712e5c31af7Sopenharmony_ci const glu::ShaderProgram m_program; 713e5c31af7Sopenharmony_ci}; 714e5c31af7Sopenharmony_ci 715e5c31af7Sopenharmony_ciVertexShaderExecutor::VertexShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 716e5c31af7Sopenharmony_ci : FragmentOutExecutor (renderCtx, shaderSpec) 717e5c31af7Sopenharmony_ci , m_program (renderCtx, 718e5c31af7Sopenharmony_ci glu::ProgramSources() << glu::VertexSource(generateVertexShader(shaderSpec, "a_", "vtx_out_")) 719e5c31af7Sopenharmony_ci << glu::FragmentSource(generatePassthroughFragmentShader(shaderSpec, !hasFloatRenderTargets(renderCtx), m_outputLayout.locationMap, "vtx_out_", "o_"))) 720e5c31af7Sopenharmony_ci{ 721e5c31af7Sopenharmony_ci} 722e5c31af7Sopenharmony_ci 723e5c31af7Sopenharmony_ciVertexShaderExecutor::~VertexShaderExecutor (void) 724e5c31af7Sopenharmony_ci{ 725e5c31af7Sopenharmony_ci} 726e5c31af7Sopenharmony_ci 727e5c31af7Sopenharmony_ci// GeometryShaderExecutor 728e5c31af7Sopenharmony_ci 729e5c31af7Sopenharmony_ciclass GeometryShaderExecutor : public FragmentOutExecutor 730e5c31af7Sopenharmony_ci{ 731e5c31af7Sopenharmony_cipublic: 732e5c31af7Sopenharmony_ci static GeometryShaderExecutor* create (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 733e5c31af7Sopenharmony_ci 734e5c31af7Sopenharmony_ci ~GeometryShaderExecutor (void); 735e5c31af7Sopenharmony_ci 736e5c31af7Sopenharmony_ci bool isOk (void) const { return m_program.isOk(); } 737e5c31af7Sopenharmony_ci void log (tcu::TestLog& dst) const { dst << m_program; } 738e5c31af7Sopenharmony_ci deUint32 getProgram (void) const { return m_program.getProgram(); } 739e5c31af7Sopenharmony_ci 740e5c31af7Sopenharmony_ciprotected: 741e5c31af7Sopenharmony_ci const glu::ShaderProgram m_program; 742e5c31af7Sopenharmony_ci 743e5c31af7Sopenharmony_ciprivate: 744e5c31af7Sopenharmony_ci GeometryShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 745e5c31af7Sopenharmony_ci}; 746e5c31af7Sopenharmony_ci 747e5c31af7Sopenharmony_ciGeometryShaderExecutor* GeometryShaderExecutor::create (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 748e5c31af7Sopenharmony_ci{ 749e5c31af7Sopenharmony_ci if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES 750e5c31af7Sopenharmony_ci && !contextSupports(renderCtx.getType(), glu::ApiType::core(4, 5))) 751e5c31af7Sopenharmony_ci checkExtension(renderCtx, "GL_EXT_geometry_shader"); 752e5c31af7Sopenharmony_ci 753e5c31af7Sopenharmony_ci return new GeometryShaderExecutor(renderCtx, shaderSpec); 754e5c31af7Sopenharmony_ci} 755e5c31af7Sopenharmony_ci 756e5c31af7Sopenharmony_ciGeometryShaderExecutor::GeometryShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 757e5c31af7Sopenharmony_ci : FragmentOutExecutor (renderCtx, shaderSpec) 758e5c31af7Sopenharmony_ci , m_program (renderCtx, 759e5c31af7Sopenharmony_ci glu::ProgramSources() << glu::VertexSource(generatePassthroughVertexShader(shaderSpec, "a_", "vtx_out_")) 760e5c31af7Sopenharmony_ci << glu::GeometrySource(generateGeometryShader(shaderSpec, "vtx_out_", "geom_out_")) 761e5c31af7Sopenharmony_ci << glu::FragmentSource(generatePassthroughFragmentShader(shaderSpec, !hasFloatRenderTargets(renderCtx), m_outputLayout.locationMap, "geom_out_", "o_"))) 762e5c31af7Sopenharmony_ci{ 763e5c31af7Sopenharmony_ci} 764e5c31af7Sopenharmony_ci 765e5c31af7Sopenharmony_ciGeometryShaderExecutor::~GeometryShaderExecutor (void) 766e5c31af7Sopenharmony_ci{ 767e5c31af7Sopenharmony_ci} 768e5c31af7Sopenharmony_ci 769e5c31af7Sopenharmony_ci// FragmentShaderExecutor 770e5c31af7Sopenharmony_ci 771e5c31af7Sopenharmony_ciclass FragmentShaderExecutor : public FragmentOutExecutor 772e5c31af7Sopenharmony_ci{ 773e5c31af7Sopenharmony_cipublic: 774e5c31af7Sopenharmony_ci FragmentShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 775e5c31af7Sopenharmony_ci ~FragmentShaderExecutor (void); 776e5c31af7Sopenharmony_ci 777e5c31af7Sopenharmony_ci bool isOk (void) const { return m_program.isOk(); } 778e5c31af7Sopenharmony_ci void log (tcu::TestLog& dst) const { dst << m_program; } 779e5c31af7Sopenharmony_ci deUint32 getProgram (void) const { return m_program.getProgram(); } 780e5c31af7Sopenharmony_ci 781e5c31af7Sopenharmony_ciprotected: 782e5c31af7Sopenharmony_ci const glu::ShaderProgram m_program; 783e5c31af7Sopenharmony_ci}; 784e5c31af7Sopenharmony_ci 785e5c31af7Sopenharmony_ciFragmentShaderExecutor::FragmentShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 786e5c31af7Sopenharmony_ci : FragmentOutExecutor (renderCtx, shaderSpec) 787e5c31af7Sopenharmony_ci , m_program (renderCtx, 788e5c31af7Sopenharmony_ci glu::ProgramSources() << glu::VertexSource(generatePassthroughVertexShader(shaderSpec, "a_", "vtx_out_")) 789e5c31af7Sopenharmony_ci << glu::FragmentSource(generateFragmentShader(shaderSpec, !hasFloatRenderTargets(renderCtx), m_outputLayout.locationMap, "vtx_out_", "o_"))) 790e5c31af7Sopenharmony_ci{ 791e5c31af7Sopenharmony_ci} 792e5c31af7Sopenharmony_ci 793e5c31af7Sopenharmony_ciFragmentShaderExecutor::~FragmentShaderExecutor (void) 794e5c31af7Sopenharmony_ci{ 795e5c31af7Sopenharmony_ci} 796e5c31af7Sopenharmony_ci 797e5c31af7Sopenharmony_ci// Shared utilities for compute and tess executors 798e5c31af7Sopenharmony_ci 799e5c31af7Sopenharmony_cistatic deUint32 getVecStd430ByteAlignment (glu::DataType type) 800e5c31af7Sopenharmony_ci{ 801e5c31af7Sopenharmony_ci switch (glu::getDataTypeScalarSize(type)) 802e5c31af7Sopenharmony_ci { 803e5c31af7Sopenharmony_ci case 1: return 4u; 804e5c31af7Sopenharmony_ci case 2: return 8u; 805e5c31af7Sopenharmony_ci case 3: return 16u; 806e5c31af7Sopenharmony_ci case 4: return 16u; 807e5c31af7Sopenharmony_ci default: 808e5c31af7Sopenharmony_ci DE_ASSERT(false); 809e5c31af7Sopenharmony_ci return 0u; 810e5c31af7Sopenharmony_ci } 811e5c31af7Sopenharmony_ci} 812e5c31af7Sopenharmony_ci 813e5c31af7Sopenharmony_ciclass BufferIoExecutor : public ShaderExecutor 814e5c31af7Sopenharmony_ci{ 815e5c31af7Sopenharmony_cipublic: 816e5c31af7Sopenharmony_ci BufferIoExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources); 817e5c31af7Sopenharmony_ci ~BufferIoExecutor (void); 818e5c31af7Sopenharmony_ci 819e5c31af7Sopenharmony_ci bool isOk (void) const { return m_program.isOk(); } 820e5c31af7Sopenharmony_ci void log (tcu::TestLog& dst) const { dst << m_program; } 821e5c31af7Sopenharmony_ci deUint32 getProgram (void) const { return m_program.getProgram(); } 822e5c31af7Sopenharmony_ci 823e5c31af7Sopenharmony_ciprotected: 824e5c31af7Sopenharmony_ci enum 825e5c31af7Sopenharmony_ci { 826e5c31af7Sopenharmony_ci INPUT_BUFFER_BINDING = 0, 827e5c31af7Sopenharmony_ci OUTPUT_BUFFER_BINDING = 1, 828e5c31af7Sopenharmony_ci }; 829e5c31af7Sopenharmony_ci 830e5c31af7Sopenharmony_ci void initBuffers (int numValues); 831e5c31af7Sopenharmony_ci deUint32 getInputBuffer (void) const { return *m_inputBuffer; } 832e5c31af7Sopenharmony_ci deUint32 getOutputBuffer (void) const { return *m_outputBuffer; } 833e5c31af7Sopenharmony_ci deUint32 getInputStride (void) const { return getLayoutStride(m_inputLayout); } 834e5c31af7Sopenharmony_ci deUint32 getOutputStride (void) const { return getLayoutStride(m_outputLayout); } 835e5c31af7Sopenharmony_ci 836e5c31af7Sopenharmony_ci void uploadInputBuffer (const void* const* inputPtrs, int numValues); 837e5c31af7Sopenharmony_ci void readOutputBuffer (void* const* outputPtrs, int numValues); 838e5c31af7Sopenharmony_ci 839e5c31af7Sopenharmony_ci static void declareBufferBlocks (std::ostream& src, const ShaderSpec& spec); 840e5c31af7Sopenharmony_ci static void generateExecBufferIo(std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName); 841e5c31af7Sopenharmony_ci 842e5c31af7Sopenharmony_ci glu::ShaderProgram m_program; 843e5c31af7Sopenharmony_ci 844e5c31af7Sopenharmony_ciprivate: 845e5c31af7Sopenharmony_ci struct VarLayout 846e5c31af7Sopenharmony_ci { 847e5c31af7Sopenharmony_ci deUint32 offset; 848e5c31af7Sopenharmony_ci deUint32 stride; 849e5c31af7Sopenharmony_ci deUint32 matrixStride; 850e5c31af7Sopenharmony_ci 851e5c31af7Sopenharmony_ci VarLayout (void) : offset(0), stride(0), matrixStride(0) {} 852e5c31af7Sopenharmony_ci }; 853e5c31af7Sopenharmony_ci 854e5c31af7Sopenharmony_ci void resizeInputBuffer (int newSize); 855e5c31af7Sopenharmony_ci void resizeOutputBuffer (int newSize); 856e5c31af7Sopenharmony_ci 857e5c31af7Sopenharmony_ci static void computeVarLayout (const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout); 858e5c31af7Sopenharmony_ci static deUint32 getLayoutStride (const vector<VarLayout>& layout); 859e5c31af7Sopenharmony_ci 860e5c31af7Sopenharmony_ci static void copyToBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr); 861e5c31af7Sopenharmony_ci static void copyFromBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr); 862e5c31af7Sopenharmony_ci 863e5c31af7Sopenharmony_ci glu::Buffer m_inputBuffer; 864e5c31af7Sopenharmony_ci glu::Buffer m_outputBuffer; 865e5c31af7Sopenharmony_ci 866e5c31af7Sopenharmony_ci vector<VarLayout> m_inputLayout; 867e5c31af7Sopenharmony_ci vector<VarLayout> m_outputLayout; 868e5c31af7Sopenharmony_ci}; 869e5c31af7Sopenharmony_ci 870e5c31af7Sopenharmony_ciBufferIoExecutor::BufferIoExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources) 871e5c31af7Sopenharmony_ci : ShaderExecutor (renderCtx, shaderSpec) 872e5c31af7Sopenharmony_ci , m_program (renderCtx, sources) 873e5c31af7Sopenharmony_ci , m_inputBuffer (renderCtx) 874e5c31af7Sopenharmony_ci , m_outputBuffer (renderCtx) 875e5c31af7Sopenharmony_ci{ 876e5c31af7Sopenharmony_ci computeVarLayout(m_inputs, &m_inputLayout); 877e5c31af7Sopenharmony_ci computeVarLayout(m_outputs, &m_outputLayout); 878e5c31af7Sopenharmony_ci} 879e5c31af7Sopenharmony_ci 880e5c31af7Sopenharmony_ciBufferIoExecutor::~BufferIoExecutor (void) 881e5c31af7Sopenharmony_ci{ 882e5c31af7Sopenharmony_ci} 883e5c31af7Sopenharmony_ci 884e5c31af7Sopenharmony_civoid BufferIoExecutor::resizeInputBuffer (int newSize) 885e5c31af7Sopenharmony_ci{ 886e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderCtx.getFunctions(); 887e5c31af7Sopenharmony_ci gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *m_inputBuffer); 888e5c31af7Sopenharmony_ci gl.bufferData(GL_SHADER_STORAGE_BUFFER, newSize, DE_NULL, GL_STATIC_DRAW); 889e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate input buffer"); 890e5c31af7Sopenharmony_ci} 891e5c31af7Sopenharmony_ci 892e5c31af7Sopenharmony_civoid BufferIoExecutor::resizeOutputBuffer (int newSize) 893e5c31af7Sopenharmony_ci{ 894e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderCtx.getFunctions(); 895e5c31af7Sopenharmony_ci gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *m_outputBuffer); 896e5c31af7Sopenharmony_ci gl.bufferData(GL_SHADER_STORAGE_BUFFER, newSize, DE_NULL, GL_STATIC_DRAW); 897e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate output buffer"); 898e5c31af7Sopenharmony_ci} 899e5c31af7Sopenharmony_ci 900e5c31af7Sopenharmony_civoid BufferIoExecutor::initBuffers (int numValues) 901e5c31af7Sopenharmony_ci{ 902e5c31af7Sopenharmony_ci const deUint32 inputStride = getLayoutStride(m_inputLayout); 903e5c31af7Sopenharmony_ci const deUint32 outputStride = getLayoutStride(m_outputLayout); 904e5c31af7Sopenharmony_ci const int inputBufferSize = numValues * inputStride; 905e5c31af7Sopenharmony_ci const int outputBufferSize = numValues * outputStride; 906e5c31af7Sopenharmony_ci 907e5c31af7Sopenharmony_ci resizeInputBuffer(inputBufferSize); 908e5c31af7Sopenharmony_ci resizeOutputBuffer(outputBufferSize); 909e5c31af7Sopenharmony_ci} 910e5c31af7Sopenharmony_ci 911e5c31af7Sopenharmony_civoid BufferIoExecutor::computeVarLayout (const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout) 912e5c31af7Sopenharmony_ci{ 913e5c31af7Sopenharmony_ci deUint32 maxAlignment = 0; 914e5c31af7Sopenharmony_ci deUint32 curOffset = 0; 915e5c31af7Sopenharmony_ci 916e5c31af7Sopenharmony_ci DE_ASSERT(layout->empty()); 917e5c31af7Sopenharmony_ci layout->resize(symbols.size()); 918e5c31af7Sopenharmony_ci 919e5c31af7Sopenharmony_ci for (size_t varNdx = 0; varNdx < symbols.size(); varNdx++) 920e5c31af7Sopenharmony_ci { 921e5c31af7Sopenharmony_ci const Symbol& symbol = symbols[varNdx]; 922e5c31af7Sopenharmony_ci const glu::DataType basicType = symbol.varType.getBasicType(); 923e5c31af7Sopenharmony_ci VarLayout& layoutEntry = (*layout)[varNdx]; 924e5c31af7Sopenharmony_ci 925e5c31af7Sopenharmony_ci if (glu::isDataTypeScalarOrVector(basicType)) 926e5c31af7Sopenharmony_ci { 927e5c31af7Sopenharmony_ci const deUint32 alignment = getVecStd430ByteAlignment(basicType); 928e5c31af7Sopenharmony_ci const deUint32 size = (deUint32)glu::getDataTypeScalarSize(basicType)*(int)sizeof(deUint32); 929e5c31af7Sopenharmony_ci 930e5c31af7Sopenharmony_ci curOffset = (deUint32)deAlign32((int)curOffset, (int)alignment); 931e5c31af7Sopenharmony_ci maxAlignment = de::max(maxAlignment, alignment); 932e5c31af7Sopenharmony_ci 933e5c31af7Sopenharmony_ci layoutEntry.offset = curOffset; 934e5c31af7Sopenharmony_ci layoutEntry.matrixStride = 0; 935e5c31af7Sopenharmony_ci 936e5c31af7Sopenharmony_ci curOffset += size; 937e5c31af7Sopenharmony_ci } 938e5c31af7Sopenharmony_ci else if (glu::isDataTypeMatrix(basicType)) 939e5c31af7Sopenharmony_ci { 940e5c31af7Sopenharmony_ci const int numVecs = glu::getDataTypeMatrixNumColumns(basicType); 941e5c31af7Sopenharmony_ci const glu::DataType vecType = glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType)); 942e5c31af7Sopenharmony_ci const deUint32 vecAlignment = getVecStd430ByteAlignment(vecType); 943e5c31af7Sopenharmony_ci 944e5c31af7Sopenharmony_ci curOffset = (deUint32)deAlign32((int)curOffset, (int)vecAlignment); 945e5c31af7Sopenharmony_ci maxAlignment = de::max(maxAlignment, vecAlignment); 946e5c31af7Sopenharmony_ci 947e5c31af7Sopenharmony_ci layoutEntry.offset = curOffset; 948e5c31af7Sopenharmony_ci layoutEntry.matrixStride = vecAlignment; 949e5c31af7Sopenharmony_ci 950e5c31af7Sopenharmony_ci curOffset += vecAlignment*numVecs; 951e5c31af7Sopenharmony_ci } 952e5c31af7Sopenharmony_ci else 953e5c31af7Sopenharmony_ci DE_ASSERT(false); 954e5c31af7Sopenharmony_ci } 955e5c31af7Sopenharmony_ci 956e5c31af7Sopenharmony_ci { 957e5c31af7Sopenharmony_ci const deUint32 totalSize = (deUint32)deAlign32(curOffset, maxAlignment); 958e5c31af7Sopenharmony_ci 959e5c31af7Sopenharmony_ci for (vector<VarLayout>::iterator varIter = layout->begin(); varIter != layout->end(); ++varIter) 960e5c31af7Sopenharmony_ci varIter->stride = totalSize; 961e5c31af7Sopenharmony_ci } 962e5c31af7Sopenharmony_ci} 963e5c31af7Sopenharmony_ci 964e5c31af7Sopenharmony_ciinline deUint32 BufferIoExecutor::getLayoutStride (const vector<VarLayout>& layout) 965e5c31af7Sopenharmony_ci{ 966e5c31af7Sopenharmony_ci return layout.empty() ? 0 : layout[0].stride; 967e5c31af7Sopenharmony_ci} 968e5c31af7Sopenharmony_ci 969e5c31af7Sopenharmony_civoid BufferIoExecutor::copyToBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr) 970e5c31af7Sopenharmony_ci{ 971e5c31af7Sopenharmony_ci if (varType.isBasicType()) 972e5c31af7Sopenharmony_ci { 973e5c31af7Sopenharmony_ci const glu::DataType basicType = varType.getBasicType(); 974e5c31af7Sopenharmony_ci const bool isMatrix = glu::isDataTypeMatrix(basicType); 975e5c31af7Sopenharmony_ci const int scalarSize = glu::getDataTypeScalarSize(basicType); 976e5c31af7Sopenharmony_ci const int numVecs = isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1; 977e5c31af7Sopenharmony_ci const int numComps = scalarSize / numVecs; 978e5c31af7Sopenharmony_ci 979e5c31af7Sopenharmony_ci for (int elemNdx = 0; elemNdx < numValues; elemNdx++) 980e5c31af7Sopenharmony_ci { 981e5c31af7Sopenharmony_ci for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 982e5c31af7Sopenharmony_ci { 983e5c31af7Sopenharmony_ci const int srcOffset = (int)sizeof(deUint32)*(elemNdx*scalarSize + vecNdx*numComps); 984e5c31af7Sopenharmony_ci const int dstOffset = layout.offset + layout.stride*elemNdx + (isMatrix ? layout.matrixStride*vecNdx : 0); 985e5c31af7Sopenharmony_ci const deUint8* srcPtr = (const deUint8*)srcBasePtr + srcOffset; 986e5c31af7Sopenharmony_ci deUint8* dstPtr = (deUint8*)dstBasePtr + dstOffset; 987e5c31af7Sopenharmony_ci 988e5c31af7Sopenharmony_ci deMemcpy(dstPtr, srcPtr, sizeof(deUint32)*numComps); 989e5c31af7Sopenharmony_ci } 990e5c31af7Sopenharmony_ci } 991e5c31af7Sopenharmony_ci } 992e5c31af7Sopenharmony_ci else 993e5c31af7Sopenharmony_ci throw tcu::InternalError("Unsupported type"); 994e5c31af7Sopenharmony_ci} 995e5c31af7Sopenharmony_ci 996e5c31af7Sopenharmony_civoid BufferIoExecutor::copyFromBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr) 997e5c31af7Sopenharmony_ci{ 998e5c31af7Sopenharmony_ci if (varType.isBasicType()) 999e5c31af7Sopenharmony_ci { 1000e5c31af7Sopenharmony_ci const glu::DataType basicType = varType.getBasicType(); 1001e5c31af7Sopenharmony_ci const bool isMatrix = glu::isDataTypeMatrix(basicType); 1002e5c31af7Sopenharmony_ci const int scalarSize = glu::getDataTypeScalarSize(basicType); 1003e5c31af7Sopenharmony_ci const int numVecs = isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1; 1004e5c31af7Sopenharmony_ci const int numComps = scalarSize / numVecs; 1005e5c31af7Sopenharmony_ci 1006e5c31af7Sopenharmony_ci for (int elemNdx = 0; elemNdx < numValues; elemNdx++) 1007e5c31af7Sopenharmony_ci { 1008e5c31af7Sopenharmony_ci for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 1009e5c31af7Sopenharmony_ci { 1010e5c31af7Sopenharmony_ci const int srcOffset = layout.offset + layout.stride*elemNdx + (isMatrix ? layout.matrixStride*vecNdx : 0); 1011e5c31af7Sopenharmony_ci const int dstOffset = (int)sizeof(deUint32)*(elemNdx*scalarSize + vecNdx*numComps); 1012e5c31af7Sopenharmony_ci const deUint8* srcPtr = (const deUint8*)srcBasePtr + srcOffset; 1013e5c31af7Sopenharmony_ci deUint8* dstPtr = (deUint8*)dstBasePtr + dstOffset; 1014e5c31af7Sopenharmony_ci 1015e5c31af7Sopenharmony_ci deMemcpy(dstPtr, srcPtr, sizeof(deUint32)*numComps); 1016e5c31af7Sopenharmony_ci } 1017e5c31af7Sopenharmony_ci } 1018e5c31af7Sopenharmony_ci } 1019e5c31af7Sopenharmony_ci else 1020e5c31af7Sopenharmony_ci throw tcu::InternalError("Unsupported type"); 1021e5c31af7Sopenharmony_ci} 1022e5c31af7Sopenharmony_ci 1023e5c31af7Sopenharmony_civoid BufferIoExecutor::uploadInputBuffer (const void* const* inputPtrs, int numValues) 1024e5c31af7Sopenharmony_ci{ 1025e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderCtx.getFunctions(); 1026e5c31af7Sopenharmony_ci const deUint32 buffer = *m_inputBuffer; 1027e5c31af7Sopenharmony_ci const deUint32 inputStride = getLayoutStride(m_inputLayout); 1028e5c31af7Sopenharmony_ci const int inputBufferSize = inputStride*numValues; 1029e5c31af7Sopenharmony_ci 1030e5c31af7Sopenharmony_ci if (inputBufferSize == 0) 1031e5c31af7Sopenharmony_ci return; // No inputs 1032e5c31af7Sopenharmony_ci 1033e5c31af7Sopenharmony_ci gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); 1034e5c31af7Sopenharmony_ci void* mapPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, inputBufferSize, GL_MAP_WRITE_BIT); 1035e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()"); 1036e5c31af7Sopenharmony_ci TCU_CHECK(mapPtr); 1037e5c31af7Sopenharmony_ci 1038e5c31af7Sopenharmony_ci try 1039e5c31af7Sopenharmony_ci { 1040e5c31af7Sopenharmony_ci DE_ASSERT(m_inputs.size() == m_inputLayout.size()); 1041e5c31af7Sopenharmony_ci for (size_t inputNdx = 0; inputNdx < m_inputs.size(); ++inputNdx) 1042e5c31af7Sopenharmony_ci { 1043e5c31af7Sopenharmony_ci const glu::VarType& varType = m_inputs[inputNdx].varType; 1044e5c31af7Sopenharmony_ci const VarLayout& layout = m_inputLayout[inputNdx]; 1045e5c31af7Sopenharmony_ci 1046e5c31af7Sopenharmony_ci copyToBuffer(varType, layout, numValues, inputPtrs[inputNdx], mapPtr); 1047e5c31af7Sopenharmony_ci } 1048e5c31af7Sopenharmony_ci } 1049e5c31af7Sopenharmony_ci catch (...) 1050e5c31af7Sopenharmony_ci { 1051e5c31af7Sopenharmony_ci gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 1052e5c31af7Sopenharmony_ci throw; 1053e5c31af7Sopenharmony_ci } 1054e5c31af7Sopenharmony_ci 1055e5c31af7Sopenharmony_ci gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 1056e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()"); 1057e5c31af7Sopenharmony_ci} 1058e5c31af7Sopenharmony_ci 1059e5c31af7Sopenharmony_civoid BufferIoExecutor::readOutputBuffer (void* const* outputPtrs, int numValues) 1060e5c31af7Sopenharmony_ci{ 1061e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderCtx.getFunctions(); 1062e5c31af7Sopenharmony_ci const deUint32 buffer = *m_outputBuffer; 1063e5c31af7Sopenharmony_ci const deUint32 outputStride = getLayoutStride(m_outputLayout); 1064e5c31af7Sopenharmony_ci const int outputBufferSize = numValues*outputStride; 1065e5c31af7Sopenharmony_ci 1066e5c31af7Sopenharmony_ci DE_ASSERT(outputBufferSize > 0); // At least some outputs are required. 1067e5c31af7Sopenharmony_ci 1068e5c31af7Sopenharmony_ci gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 1069e5c31af7Sopenharmony_ci gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); 1070e5c31af7Sopenharmony_ci void* mapPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, outputBufferSize, GL_MAP_READ_BIT); 1071e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()"); 1072e5c31af7Sopenharmony_ci TCU_CHECK(mapPtr); 1073e5c31af7Sopenharmony_ci 1074e5c31af7Sopenharmony_ci try 1075e5c31af7Sopenharmony_ci { 1076e5c31af7Sopenharmony_ci DE_ASSERT(m_outputs.size() == m_outputLayout.size()); 1077e5c31af7Sopenharmony_ci for (size_t outputNdx = 0; outputNdx < m_outputs.size(); ++outputNdx) 1078e5c31af7Sopenharmony_ci { 1079e5c31af7Sopenharmony_ci const glu::VarType& varType = m_outputs[outputNdx].varType; 1080e5c31af7Sopenharmony_ci const VarLayout& layout = m_outputLayout[outputNdx]; 1081e5c31af7Sopenharmony_ci 1082e5c31af7Sopenharmony_ci copyFromBuffer(varType, layout, numValues, mapPtr, outputPtrs[outputNdx]); 1083e5c31af7Sopenharmony_ci } 1084e5c31af7Sopenharmony_ci } 1085e5c31af7Sopenharmony_ci catch (...) 1086e5c31af7Sopenharmony_ci { 1087e5c31af7Sopenharmony_ci gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 1088e5c31af7Sopenharmony_ci throw; 1089e5c31af7Sopenharmony_ci } 1090e5c31af7Sopenharmony_ci 1091e5c31af7Sopenharmony_ci gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 1092e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()"); 1093e5c31af7Sopenharmony_ci} 1094e5c31af7Sopenharmony_ci 1095e5c31af7Sopenharmony_civoid BufferIoExecutor::declareBufferBlocks (std::ostream& src, const ShaderSpec& spec) 1096e5c31af7Sopenharmony_ci{ 1097e5c31af7Sopenharmony_ci // Input struct 1098e5c31af7Sopenharmony_ci if (!spec.inputs.empty()) 1099e5c31af7Sopenharmony_ci { 1100e5c31af7Sopenharmony_ci glu::StructType inputStruct("Inputs"); 1101e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter) 1102e5c31af7Sopenharmony_ci inputStruct.addMember(symIter->name.c_str(), symIter->varType); 1103e5c31af7Sopenharmony_ci src << glu::declare(&inputStruct) << ";\n"; 1104e5c31af7Sopenharmony_ci } 1105e5c31af7Sopenharmony_ci 1106e5c31af7Sopenharmony_ci // Output struct 1107e5c31af7Sopenharmony_ci { 1108e5c31af7Sopenharmony_ci glu::StructType outputStruct("Outputs"); 1109e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter) 1110e5c31af7Sopenharmony_ci outputStruct.addMember(symIter->name.c_str(), symIter->varType); 1111e5c31af7Sopenharmony_ci src << glu::declare(&outputStruct) << ";\n"; 1112e5c31af7Sopenharmony_ci } 1113e5c31af7Sopenharmony_ci 1114e5c31af7Sopenharmony_ci src << "\n"; 1115e5c31af7Sopenharmony_ci 1116e5c31af7Sopenharmony_ci if (!spec.inputs.empty()) 1117e5c31af7Sopenharmony_ci { 1118e5c31af7Sopenharmony_ci src << "layout(binding = " << int(INPUT_BUFFER_BINDING) << ", std430) buffer InBuffer\n" 1119e5c31af7Sopenharmony_ci << "{\n" 1120e5c31af7Sopenharmony_ci << " Inputs inputs[];\n" 1121e5c31af7Sopenharmony_ci << "};\n"; 1122e5c31af7Sopenharmony_ci } 1123e5c31af7Sopenharmony_ci 1124e5c31af7Sopenharmony_ci src << "layout(binding = " << int(OUTPUT_BUFFER_BINDING) << ", std430) buffer OutBuffer\n" 1125e5c31af7Sopenharmony_ci << "{\n" 1126e5c31af7Sopenharmony_ci << " Outputs outputs[];\n" 1127e5c31af7Sopenharmony_ci << "};\n" 1128e5c31af7Sopenharmony_ci << "\n"; 1129e5c31af7Sopenharmony_ci} 1130e5c31af7Sopenharmony_ci 1131e5c31af7Sopenharmony_civoid BufferIoExecutor::generateExecBufferIo (std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName) 1132e5c31af7Sopenharmony_ci{ 1133e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter) 1134e5c31af7Sopenharmony_ci src << "\t" << glu::declare(symIter->varType, symIter->name) << " = inputs[" << invocationNdxName << "]." << symIter->name << ";\n"; 1135e5c31af7Sopenharmony_ci 1136e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter) 1137e5c31af7Sopenharmony_ci src << "\t" << glu::declare(symIter->varType, symIter->name) << ";\n"; 1138e5c31af7Sopenharmony_ci 1139e5c31af7Sopenharmony_ci src << "\n"; 1140e5c31af7Sopenharmony_ci 1141e5c31af7Sopenharmony_ci { 1142e5c31af7Sopenharmony_ci std::istringstream opSrc (spec.source); 1143e5c31af7Sopenharmony_ci std::string line; 1144e5c31af7Sopenharmony_ci 1145e5c31af7Sopenharmony_ci while (std::getline(opSrc, line)) 1146e5c31af7Sopenharmony_ci src << "\t" << line << "\n"; 1147e5c31af7Sopenharmony_ci } 1148e5c31af7Sopenharmony_ci 1149e5c31af7Sopenharmony_ci src << "\n"; 1150e5c31af7Sopenharmony_ci for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter) 1151e5c31af7Sopenharmony_ci src << "\toutputs[" << invocationNdxName << "]." << symIter->name << " = " << symIter->name << ";\n"; 1152e5c31af7Sopenharmony_ci} 1153e5c31af7Sopenharmony_ci 1154e5c31af7Sopenharmony_ci// ComputeShaderExecutor 1155e5c31af7Sopenharmony_ci 1156e5c31af7Sopenharmony_ciclass ComputeShaderExecutor : public BufferIoExecutor 1157e5c31af7Sopenharmony_ci{ 1158e5c31af7Sopenharmony_cipublic: 1159e5c31af7Sopenharmony_ci ComputeShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 1160e5c31af7Sopenharmony_ci ~ComputeShaderExecutor (void); 1161e5c31af7Sopenharmony_ci 1162e5c31af7Sopenharmony_ci void execute (int numValues, const void* const* inputs, void* const* outputs); 1163e5c31af7Sopenharmony_ci 1164e5c31af7Sopenharmony_ciprotected: 1165e5c31af7Sopenharmony_ci static std::string generateComputeShader (const ShaderSpec& spec); 1166e5c31af7Sopenharmony_ci 1167e5c31af7Sopenharmony_ci tcu::IVec3 m_maxWorkSize; 1168e5c31af7Sopenharmony_ci}; 1169e5c31af7Sopenharmony_ci 1170e5c31af7Sopenharmony_cistd::string ComputeShaderExecutor::generateComputeShader (const ShaderSpec& spec) 1171e5c31af7Sopenharmony_ci{ 1172e5c31af7Sopenharmony_ci std::ostringstream src; 1173e5c31af7Sopenharmony_ci 1174e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(spec.version) << "\n"; 1175e5c31af7Sopenharmony_ci 1176e5c31af7Sopenharmony_ci if (!spec.globalDeclarations.empty()) 1177e5c31af7Sopenharmony_ci src << spec.globalDeclarations << "\n"; 1178e5c31af7Sopenharmony_ci 1179e5c31af7Sopenharmony_ci src << "layout(local_size_x = 1) in;\n" 1180e5c31af7Sopenharmony_ci << "\n"; 1181e5c31af7Sopenharmony_ci 1182e5c31af7Sopenharmony_ci declareBufferBlocks(src, spec); 1183e5c31af7Sopenharmony_ci 1184e5c31af7Sopenharmony_ci src << "void main (void)\n" 1185e5c31af7Sopenharmony_ci << "{\n" 1186e5c31af7Sopenharmony_ci << " uint invocationNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z\n" 1187e5c31af7Sopenharmony_ci << " + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n"; 1188e5c31af7Sopenharmony_ci 1189e5c31af7Sopenharmony_ci generateExecBufferIo(src, spec, "invocationNdx"); 1190e5c31af7Sopenharmony_ci 1191e5c31af7Sopenharmony_ci src << "}\n"; 1192e5c31af7Sopenharmony_ci 1193e5c31af7Sopenharmony_ci return src.str(); 1194e5c31af7Sopenharmony_ci} 1195e5c31af7Sopenharmony_ci 1196e5c31af7Sopenharmony_ciComputeShaderExecutor::ComputeShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 1197e5c31af7Sopenharmony_ci : BufferIoExecutor (renderCtx, shaderSpec, 1198e5c31af7Sopenharmony_ci glu::ProgramSources() << glu::ComputeSource(generateComputeShader(shaderSpec))) 1199e5c31af7Sopenharmony_ci{ 1200e5c31af7Sopenharmony_ci m_maxWorkSize = tcu::IVec3(128,128,64); // Minimum in 3plus 1201e5c31af7Sopenharmony_ci} 1202e5c31af7Sopenharmony_ci 1203e5c31af7Sopenharmony_ciComputeShaderExecutor::~ComputeShaderExecutor (void) 1204e5c31af7Sopenharmony_ci{ 1205e5c31af7Sopenharmony_ci} 1206e5c31af7Sopenharmony_ci 1207e5c31af7Sopenharmony_civoid ComputeShaderExecutor::execute (int numValues, const void* const* inputs, void* const* outputs) 1208e5c31af7Sopenharmony_ci{ 1209e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderCtx.getFunctions(); 1210e5c31af7Sopenharmony_ci const int maxValuesPerInvocation = m_maxWorkSize[0]; 1211e5c31af7Sopenharmony_ci const deUint32 inputStride = getInputStride(); 1212e5c31af7Sopenharmony_ci const deUint32 outputStride = getOutputStride(); 1213e5c31af7Sopenharmony_ci 1214e5c31af7Sopenharmony_ci initBuffers(numValues); 1215e5c31af7Sopenharmony_ci 1216e5c31af7Sopenharmony_ci // Setup input buffer & copy data 1217e5c31af7Sopenharmony_ci uploadInputBuffer(inputs, numValues); 1218e5c31af7Sopenharmony_ci 1219e5c31af7Sopenharmony_ci // Perform compute invocations 1220e5c31af7Sopenharmony_ci { 1221e5c31af7Sopenharmony_ci int curOffset = 0; 1222e5c31af7Sopenharmony_ci while (curOffset < numValues) 1223e5c31af7Sopenharmony_ci { 1224e5c31af7Sopenharmony_ci const int numToExec = de::min(maxValuesPerInvocation, numValues-curOffset); 1225e5c31af7Sopenharmony_ci 1226e5c31af7Sopenharmony_ci if (inputStride > 0) 1227e5c31af7Sopenharmony_ci gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer(), curOffset*inputStride, numToExec*inputStride); 1228e5c31af7Sopenharmony_ci 1229e5c31af7Sopenharmony_ci gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer(), curOffset*outputStride, numToExec*outputStride); 1230e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange(GL_SHADER_STORAGE_BUFFER)"); 1231e5c31af7Sopenharmony_ci 1232e5c31af7Sopenharmony_ci gl.dispatchCompute(numToExec, 1, 1); 1233e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute()"); 1234e5c31af7Sopenharmony_ci 1235e5c31af7Sopenharmony_ci curOffset += numToExec; 1236e5c31af7Sopenharmony_ci } 1237e5c31af7Sopenharmony_ci } 1238e5c31af7Sopenharmony_ci 1239e5c31af7Sopenharmony_ci // Read back data 1240e5c31af7Sopenharmony_ci readOutputBuffer(outputs, numValues); 1241e5c31af7Sopenharmony_ci} 1242e5c31af7Sopenharmony_ci 1243e5c31af7Sopenharmony_ci// Tessellation utils 1244e5c31af7Sopenharmony_ci 1245e5c31af7Sopenharmony_cistatic std::string generateVertexShaderForTess (glu::GLSLVersion version) 1246e5c31af7Sopenharmony_ci{ 1247e5c31af7Sopenharmony_ci std::ostringstream src; 1248e5c31af7Sopenharmony_ci 1249e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(version) << "\n"; 1250e5c31af7Sopenharmony_ci 1251e5c31af7Sopenharmony_ci src << "void main (void)\n{\n" 1252e5c31af7Sopenharmony_ci << " gl_Position = vec4(gl_VertexID/2, gl_VertexID%2, 0.0, 1.0);\n" 1253e5c31af7Sopenharmony_ci << "}\n"; 1254e5c31af7Sopenharmony_ci 1255e5c31af7Sopenharmony_ci return src.str(); 1256e5c31af7Sopenharmony_ci} 1257e5c31af7Sopenharmony_ci 1258e5c31af7Sopenharmony_civoid checkTessSupport (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, glu::ShaderType stage) 1259e5c31af7Sopenharmony_ci{ 1260e5c31af7Sopenharmony_ci const int numBlockRequired = 2; // highest binding is always 1 (output) i.e. count == 2 1261e5c31af7Sopenharmony_ci 1262e5c31af7Sopenharmony_ci if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES 1263e5c31af7Sopenharmony_ci && !contextSupports(renderCtx.getType(), glu::ApiType::core(4, 5))) 1264e5c31af7Sopenharmony_ci checkExtension(renderCtx, "GL_EXT_tessellation_shader"); 1265e5c31af7Sopenharmony_ci 1266e5c31af7Sopenharmony_ci if (stage == glu::SHADERTYPE_TESSELLATION_CONTROL) 1267e5c31af7Sopenharmony_ci checkLimit(renderCtx, GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, numBlockRequired); 1268e5c31af7Sopenharmony_ci else if (stage == glu::SHADERTYPE_TESSELLATION_EVALUATION) 1269e5c31af7Sopenharmony_ci checkLimit(renderCtx, GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, numBlockRequired); 1270e5c31af7Sopenharmony_ci else 1271e5c31af7Sopenharmony_ci DE_ASSERT(false); 1272e5c31af7Sopenharmony_ci} 1273e5c31af7Sopenharmony_ci 1274e5c31af7Sopenharmony_ci// TessControlExecutor 1275e5c31af7Sopenharmony_ci 1276e5c31af7Sopenharmony_ciclass TessControlExecutor : public BufferIoExecutor 1277e5c31af7Sopenharmony_ci{ 1278e5c31af7Sopenharmony_cipublic: 1279e5c31af7Sopenharmony_ci static TessControlExecutor* create (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 1280e5c31af7Sopenharmony_ci 1281e5c31af7Sopenharmony_ci ~TessControlExecutor (void); 1282e5c31af7Sopenharmony_ci 1283e5c31af7Sopenharmony_ci void execute (int numValues, const void* const* inputs, void* const* outputs); 1284e5c31af7Sopenharmony_ci 1285e5c31af7Sopenharmony_ci 1286e5c31af7Sopenharmony_ciprotected: 1287e5c31af7Sopenharmony_ci static std::string generateTessControlShader (const ShaderSpec& shaderSpec); 1288e5c31af7Sopenharmony_ci 1289e5c31af7Sopenharmony_ciprivate: 1290e5c31af7Sopenharmony_ci TessControlExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 1291e5c31af7Sopenharmony_ci}; 1292e5c31af7Sopenharmony_ci 1293e5c31af7Sopenharmony_ciTessControlExecutor* TessControlExecutor::create (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 1294e5c31af7Sopenharmony_ci{ 1295e5c31af7Sopenharmony_ci checkTessSupport(renderCtx, shaderSpec, glu::SHADERTYPE_TESSELLATION_CONTROL); 1296e5c31af7Sopenharmony_ci 1297e5c31af7Sopenharmony_ci return new TessControlExecutor(renderCtx, shaderSpec); 1298e5c31af7Sopenharmony_ci} 1299e5c31af7Sopenharmony_ci 1300e5c31af7Sopenharmony_cistd::string TessControlExecutor::generateTessControlShader (const ShaderSpec& shaderSpec) 1301e5c31af7Sopenharmony_ci{ 1302e5c31af7Sopenharmony_ci std::ostringstream src; 1303e5c31af7Sopenharmony_ci 1304e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"; 1305e5c31af7Sopenharmony_ci 1306e5c31af7Sopenharmony_ci if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES) 1307e5c31af7Sopenharmony_ci src << "#extension GL_EXT_tessellation_shader : require\n"; 1308e5c31af7Sopenharmony_ci 1309e5c31af7Sopenharmony_ci if (!shaderSpec.globalDeclarations.empty()) 1310e5c31af7Sopenharmony_ci src << shaderSpec.globalDeclarations << "\n"; 1311e5c31af7Sopenharmony_ci 1312e5c31af7Sopenharmony_ci src << "\nlayout(vertices = 1) out;\n\n"; 1313e5c31af7Sopenharmony_ci 1314e5c31af7Sopenharmony_ci declareBufferBlocks(src, shaderSpec); 1315e5c31af7Sopenharmony_ci 1316e5c31af7Sopenharmony_ci src << "void main (void)\n{\n"; 1317e5c31af7Sopenharmony_ci 1318e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < 2; ndx++) 1319e5c31af7Sopenharmony_ci src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n"; 1320e5c31af7Sopenharmony_ci 1321e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < 4; ndx++) 1322e5c31af7Sopenharmony_ci src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n"; 1323e5c31af7Sopenharmony_ci 1324e5c31af7Sopenharmony_ci src << "\n" 1325e5c31af7Sopenharmony_ci << "\thighp uint invocationId = uint(gl_PrimitiveID);\n"; 1326e5c31af7Sopenharmony_ci 1327e5c31af7Sopenharmony_ci generateExecBufferIo(src, shaderSpec, "invocationId"); 1328e5c31af7Sopenharmony_ci 1329e5c31af7Sopenharmony_ci src << "}\n"; 1330e5c31af7Sopenharmony_ci 1331e5c31af7Sopenharmony_ci return src.str(); 1332e5c31af7Sopenharmony_ci} 1333e5c31af7Sopenharmony_ci 1334e5c31af7Sopenharmony_cistatic std::string generateEmptyTessEvalShader (glu::GLSLVersion version) 1335e5c31af7Sopenharmony_ci{ 1336e5c31af7Sopenharmony_ci std::ostringstream src; 1337e5c31af7Sopenharmony_ci 1338e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(version) << "\n"; 1339e5c31af7Sopenharmony_ci 1340e5c31af7Sopenharmony_ci if (glu::glslVersionIsES(version) && version <= glu::GLSL_VERSION_310_ES) 1341e5c31af7Sopenharmony_ci src << "#extension GL_EXT_tessellation_shader : require\n\n"; 1342e5c31af7Sopenharmony_ci 1343e5c31af7Sopenharmony_ci src << "layout(triangles, ccw) in;\n"; 1344e5c31af7Sopenharmony_ci 1345e5c31af7Sopenharmony_ci src << "\nvoid main (void)\n{\n" 1346e5c31af7Sopenharmony_ci << "\tgl_Position = vec4(gl_TessCoord.xy, 0.0, 1.0);\n" 1347e5c31af7Sopenharmony_ci << "}\n"; 1348e5c31af7Sopenharmony_ci 1349e5c31af7Sopenharmony_ci return src.str(); 1350e5c31af7Sopenharmony_ci} 1351e5c31af7Sopenharmony_ci 1352e5c31af7Sopenharmony_ciTessControlExecutor::TessControlExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 1353e5c31af7Sopenharmony_ci : BufferIoExecutor (renderCtx, shaderSpec, glu::ProgramSources() 1354e5c31af7Sopenharmony_ci << glu::VertexSource(generateVertexShaderForTess(shaderSpec.version)) 1355e5c31af7Sopenharmony_ci << glu::TessellationControlSource(generateTessControlShader(shaderSpec)) 1356e5c31af7Sopenharmony_ci << glu::TessellationEvaluationSource(generateEmptyTessEvalShader(shaderSpec.version)) 1357e5c31af7Sopenharmony_ci << glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version))) 1358e5c31af7Sopenharmony_ci{ 1359e5c31af7Sopenharmony_ci} 1360e5c31af7Sopenharmony_ci 1361e5c31af7Sopenharmony_ciTessControlExecutor::~TessControlExecutor (void) 1362e5c31af7Sopenharmony_ci{ 1363e5c31af7Sopenharmony_ci} 1364e5c31af7Sopenharmony_ci 1365e5c31af7Sopenharmony_civoid TessControlExecutor::execute (int numValues, const void* const* inputs, void* const* outputs) 1366e5c31af7Sopenharmony_ci{ 1367e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderCtx.getFunctions(); 1368e5c31af7Sopenharmony_ci 1369e5c31af7Sopenharmony_ci initBuffers(numValues); 1370e5c31af7Sopenharmony_ci 1371e5c31af7Sopenharmony_ci // Setup input buffer & copy data 1372e5c31af7Sopenharmony_ci uploadInputBuffer(inputs, numValues); 1373e5c31af7Sopenharmony_ci 1374e5c31af7Sopenharmony_ci if (!m_inputs.empty()) 1375e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer()); 1376e5c31af7Sopenharmony_ci 1377e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer()); 1378e5c31af7Sopenharmony_ci 1379e5c31af7Sopenharmony_ci deUint32 vertexArray; 1380e5c31af7Sopenharmony_ci gl.genVertexArrays(1, &vertexArray); 1381e5c31af7Sopenharmony_ci gl.bindVertexArray(vertexArray); 1382e5c31af7Sopenharmony_ci 1383e5c31af7Sopenharmony_ci // Render patches 1384e5c31af7Sopenharmony_ci gl.patchParameteri(GL_PATCH_VERTICES, 3); 1385e5c31af7Sopenharmony_ci gl.drawArrays(GL_PATCHES, 0, 3*numValues); 1386e5c31af7Sopenharmony_ci 1387e5c31af7Sopenharmony_ci gl.bindVertexArray(0); 1388e5c31af7Sopenharmony_ci gl.deleteVertexArrays(1, &vertexArray); 1389e5c31af7Sopenharmony_ci 1390e5c31af7Sopenharmony_ci // Read back data 1391e5c31af7Sopenharmony_ci readOutputBuffer(outputs, numValues); 1392e5c31af7Sopenharmony_ci} 1393e5c31af7Sopenharmony_ci 1394e5c31af7Sopenharmony_ci// TessEvaluationExecutor 1395e5c31af7Sopenharmony_ci 1396e5c31af7Sopenharmony_ciclass TessEvaluationExecutor : public BufferIoExecutor 1397e5c31af7Sopenharmony_ci{ 1398e5c31af7Sopenharmony_cipublic: 1399e5c31af7Sopenharmony_ci static TessEvaluationExecutor* create (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 1400e5c31af7Sopenharmony_ci 1401e5c31af7Sopenharmony_ci ~TessEvaluationExecutor (void); 1402e5c31af7Sopenharmony_ci 1403e5c31af7Sopenharmony_ci void execute (int numValues, const void* const* inputs, void* const* outputs); 1404e5c31af7Sopenharmony_ci 1405e5c31af7Sopenharmony_ci 1406e5c31af7Sopenharmony_ciprotected: 1407e5c31af7Sopenharmony_ci static std::string generateTessEvalShader (const ShaderSpec& shaderSpec); 1408e5c31af7Sopenharmony_ci 1409e5c31af7Sopenharmony_ciprivate: 1410e5c31af7Sopenharmony_ci TessEvaluationExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 1411e5c31af7Sopenharmony_ci}; 1412e5c31af7Sopenharmony_ci 1413e5c31af7Sopenharmony_ciTessEvaluationExecutor* TessEvaluationExecutor::create (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 1414e5c31af7Sopenharmony_ci{ 1415e5c31af7Sopenharmony_ci checkTessSupport(renderCtx, shaderSpec, glu::SHADERTYPE_TESSELLATION_EVALUATION); 1416e5c31af7Sopenharmony_ci 1417e5c31af7Sopenharmony_ci return new TessEvaluationExecutor(renderCtx, shaderSpec); 1418e5c31af7Sopenharmony_ci} 1419e5c31af7Sopenharmony_ci 1420e5c31af7Sopenharmony_cistatic std::string generatePassthroughTessControlShader (glu::GLSLVersion version) 1421e5c31af7Sopenharmony_ci{ 1422e5c31af7Sopenharmony_ci std::ostringstream src; 1423e5c31af7Sopenharmony_ci 1424e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(version) << "\n"; 1425e5c31af7Sopenharmony_ci 1426e5c31af7Sopenharmony_ci if (glu::glslVersionIsES(version) && version <= glu::GLSL_VERSION_310_ES) 1427e5c31af7Sopenharmony_ci src << "#extension GL_EXT_tessellation_shader : require\n\n"; 1428e5c31af7Sopenharmony_ci 1429e5c31af7Sopenharmony_ci src << "layout(vertices = 1) out;\n\n"; 1430e5c31af7Sopenharmony_ci 1431e5c31af7Sopenharmony_ci src << "void main (void)\n{\n"; 1432e5c31af7Sopenharmony_ci 1433e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < 2; ndx++) 1434e5c31af7Sopenharmony_ci src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n"; 1435e5c31af7Sopenharmony_ci 1436e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < 4; ndx++) 1437e5c31af7Sopenharmony_ci src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n"; 1438e5c31af7Sopenharmony_ci 1439e5c31af7Sopenharmony_ci src << "}\n"; 1440e5c31af7Sopenharmony_ci 1441e5c31af7Sopenharmony_ci return src.str(); 1442e5c31af7Sopenharmony_ci} 1443e5c31af7Sopenharmony_ci 1444e5c31af7Sopenharmony_cistd::string TessEvaluationExecutor::generateTessEvalShader (const ShaderSpec& shaderSpec) 1445e5c31af7Sopenharmony_ci{ 1446e5c31af7Sopenharmony_ci std::ostringstream src; 1447e5c31af7Sopenharmony_ci 1448e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"; 1449e5c31af7Sopenharmony_ci 1450e5c31af7Sopenharmony_ci if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES) 1451e5c31af7Sopenharmony_ci src << "#extension GL_EXT_tessellation_shader : require\n"; 1452e5c31af7Sopenharmony_ci 1453e5c31af7Sopenharmony_ci if (!shaderSpec.globalDeclarations.empty()) 1454e5c31af7Sopenharmony_ci src << shaderSpec.globalDeclarations << "\n"; 1455e5c31af7Sopenharmony_ci 1456e5c31af7Sopenharmony_ci src << "\n"; 1457e5c31af7Sopenharmony_ci 1458e5c31af7Sopenharmony_ci src << "layout(isolines, equal_spacing) in;\n\n"; 1459e5c31af7Sopenharmony_ci 1460e5c31af7Sopenharmony_ci declareBufferBlocks(src, shaderSpec); 1461e5c31af7Sopenharmony_ci 1462e5c31af7Sopenharmony_ci src << "void main (void)\n{\n" 1463e5c31af7Sopenharmony_ci << "\tgl_Position = vec4(gl_TessCoord.x, 0.0, 0.0, 1.0);\n" 1464e5c31af7Sopenharmony_ci << "\thighp uint invocationId = uint(gl_PrimitiveID)*2u + (gl_TessCoord.x > 0.5 ? 1u : 0u);\n"; 1465e5c31af7Sopenharmony_ci 1466e5c31af7Sopenharmony_ci generateExecBufferIo(src, shaderSpec, "invocationId"); 1467e5c31af7Sopenharmony_ci 1468e5c31af7Sopenharmony_ci src << "}\n"; 1469e5c31af7Sopenharmony_ci 1470e5c31af7Sopenharmony_ci return src.str(); 1471e5c31af7Sopenharmony_ci} 1472e5c31af7Sopenharmony_ci 1473e5c31af7Sopenharmony_ciTessEvaluationExecutor::TessEvaluationExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 1474e5c31af7Sopenharmony_ci : BufferIoExecutor (renderCtx, shaderSpec, glu::ProgramSources() 1475e5c31af7Sopenharmony_ci << glu::VertexSource(generateVertexShaderForTess(shaderSpec.version)) 1476e5c31af7Sopenharmony_ci << glu::TessellationControlSource(generatePassthroughTessControlShader(shaderSpec.version)) 1477e5c31af7Sopenharmony_ci << glu::TessellationEvaluationSource(generateTessEvalShader(shaderSpec)) 1478e5c31af7Sopenharmony_ci << glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version))) 1479e5c31af7Sopenharmony_ci{ 1480e5c31af7Sopenharmony_ci} 1481e5c31af7Sopenharmony_ci 1482e5c31af7Sopenharmony_ciTessEvaluationExecutor::~TessEvaluationExecutor (void) 1483e5c31af7Sopenharmony_ci{ 1484e5c31af7Sopenharmony_ci} 1485e5c31af7Sopenharmony_ci 1486e5c31af7Sopenharmony_civoid TessEvaluationExecutor::execute (int numValues, const void* const* inputs, void* const* outputs) 1487e5c31af7Sopenharmony_ci{ 1488e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderCtx.getFunctions(); 1489e5c31af7Sopenharmony_ci const int alignedValues = deAlign32(numValues, 2); 1490e5c31af7Sopenharmony_ci 1491e5c31af7Sopenharmony_ci // Initialize buffers with aligned value count to make room for padding 1492e5c31af7Sopenharmony_ci initBuffers(alignedValues); 1493e5c31af7Sopenharmony_ci 1494e5c31af7Sopenharmony_ci // Setup input buffer & copy data 1495e5c31af7Sopenharmony_ci uploadInputBuffer(inputs, numValues); 1496e5c31af7Sopenharmony_ci 1497e5c31af7Sopenharmony_ci // \todo [2014-06-26 pyry] Duplicate last value in the buffer to prevent infinite loops for example? 1498e5c31af7Sopenharmony_ci 1499e5c31af7Sopenharmony_ci if (!m_inputs.empty()) 1500e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer()); 1501e5c31af7Sopenharmony_ci 1502e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer()); 1503e5c31af7Sopenharmony_ci 1504e5c31af7Sopenharmony_ci deUint32 vertexArray; 1505e5c31af7Sopenharmony_ci gl.genVertexArrays(1, &vertexArray); 1506e5c31af7Sopenharmony_ci gl.bindVertexArray(vertexArray); 1507e5c31af7Sopenharmony_ci 1508e5c31af7Sopenharmony_ci // Render patches 1509e5c31af7Sopenharmony_ci gl.patchParameteri(GL_PATCH_VERTICES, 2); 1510e5c31af7Sopenharmony_ci gl.drawArrays(GL_PATCHES, 0, alignedValues); 1511e5c31af7Sopenharmony_ci 1512e5c31af7Sopenharmony_ci gl.bindVertexArray(0); 1513e5c31af7Sopenharmony_ci gl.deleteVertexArrays(1, &vertexArray); 1514e5c31af7Sopenharmony_ci 1515e5c31af7Sopenharmony_ci // Read back data 1516e5c31af7Sopenharmony_ci readOutputBuffer(outputs, numValues); 1517e5c31af7Sopenharmony_ci} 1518e5c31af7Sopenharmony_ci 1519e5c31af7Sopenharmony_ci// Utilities 1520e5c31af7Sopenharmony_ci 1521e5c31af7Sopenharmony_ciShaderExecutor* createExecutor (const glu::RenderContext& renderCtx, glu::ShaderType shaderType, const ShaderSpec& shaderSpec) 1522e5c31af7Sopenharmony_ci{ 1523e5c31af7Sopenharmony_ci switch (shaderType) 1524e5c31af7Sopenharmony_ci { 1525e5c31af7Sopenharmony_ci case glu::SHADERTYPE_VERTEX: return new VertexShaderExecutor (renderCtx, shaderSpec); 1526e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_CONTROL: return TessControlExecutor::create (renderCtx, shaderSpec); 1527e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_EVALUATION: return TessEvaluationExecutor::create (renderCtx, shaderSpec); 1528e5c31af7Sopenharmony_ci case glu::SHADERTYPE_GEOMETRY: return GeometryShaderExecutor::create (renderCtx, shaderSpec); 1529e5c31af7Sopenharmony_ci case glu::SHADERTYPE_FRAGMENT: return new FragmentShaderExecutor (renderCtx, shaderSpec); 1530e5c31af7Sopenharmony_ci case glu::SHADERTYPE_COMPUTE: return new ComputeShaderExecutor (renderCtx, shaderSpec); 1531e5c31af7Sopenharmony_ci default: 1532e5c31af7Sopenharmony_ci throw tcu::InternalError("Unsupported shader type"); 1533e5c31af7Sopenharmony_ci } 1534e5c31af7Sopenharmony_ci} 1535e5c31af7Sopenharmony_ci 1536e5c31af7Sopenharmony_cibool executorSupported(glu::ShaderType shaderType) 1537e5c31af7Sopenharmony_ci{ 1538e5c31af7Sopenharmony_ci switch (shaderType) 1539e5c31af7Sopenharmony_ci { 1540e5c31af7Sopenharmony_ci case glu::SHADERTYPE_VERTEX: 1541e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_CONTROL: 1542e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_EVALUATION: 1543e5c31af7Sopenharmony_ci case glu::SHADERTYPE_GEOMETRY: 1544e5c31af7Sopenharmony_ci case glu::SHADERTYPE_FRAGMENT: 1545e5c31af7Sopenharmony_ci case glu::SHADERTYPE_COMPUTE: 1546e5c31af7Sopenharmony_ci return true; 1547e5c31af7Sopenharmony_ci default: 1548e5c31af7Sopenharmony_ci return false; 1549e5c31af7Sopenharmony_ci } 1550e5c31af7Sopenharmony_ci} 1551e5c31af7Sopenharmony_ci 1552e5c31af7Sopenharmony_ci} // ShaderExecUtil 1553e5c31af7Sopenharmony_ci} // gls 1554e5c31af7Sopenharmony_ci} // deqp 1555