13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL (ES) Module 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ----------------------------------------------- 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Shader execution utilities. 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderExecUtil.hpp" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp" 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDrawUtil.hpp" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluObjectWrapper.hpp" 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp" 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluTextureUtil.hpp" 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluProgramInterfaceQuery.hpp" 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp" 32582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry#include "gluStrUtil.hpp" 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp" 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp" 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp" 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSTLUtil.hpp" 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp" 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deUniquePtr.hpp" 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h" 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <map> 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gls 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace ShaderExecUtil 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector; 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool isExtensionSupported (const glu::RenderContext& renderCtx, const std::string& extension) 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = renderCtx.getFunctions(); 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numExts = 0; 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.getIntegerv(GL_NUM_EXTENSIONS, &numExts); 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numExts; ndx++) 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* curExt = (const char*)gl.getStringi(GL_EXTENSIONS, ndx); 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (extension == curExt) 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void checkExtension (const glu::RenderContext& renderCtx, const std::string& extension) 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!isExtensionSupported(renderCtx, extension)) 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::NotSupportedError(extension + " is not supported"); 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 77582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyrystatic void checkLimit (const glu::RenderContext& renderCtx, deUint32 pname, int required) 78582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry{ 79582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry const glw::Functions& gl = renderCtx.getFunctions(); 80582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry int implementationLimit = -1; 81582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry deUint32 error; 82582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry 83582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry gl.getIntegerv(pname, &implementationLimit); 84582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry error = gl.getError(); 85582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry 86582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry if (error != GL_NO_ERROR) 87582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry throw tcu::TestError("Failed to query " + de::toString(glu::getGettableStateStr(pname)) + " - got " + de::toString(glu::getErrorStr(error))); 88582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry if (implementationLimit < required) 89582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry throw tcu::NotSupportedError("Test requires " + de::toString(glu::getGettableStateStr(pname)) + " >= " + de::toString(required) + ", got " + de::toString(implementationLimit)); 90582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry} 91582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Shader utilities 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string generateVertexShader (const ShaderSpec& shaderSpec) 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool usesInout = glu::glslVersionUsesInOutQualifiers(shaderSpec.version); 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* in = usesInout ? "in" : "attribute"; 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* out = usesInout ? "out" : "varying"; 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"; 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!shaderSpec.globalDeclarations.empty()) 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << shaderSpec.globalDeclarations << "\n"; 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << in << " " << glu::declare(input->varType, input->name) << ";\n"; 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(output->varType.isBasicType()); 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::VarType intType (intBaseType, glu::PRECISION_HIGHP); 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "flat " << out << " " << glu::declare(intType, "o_" + output->name) << ";\n"; 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "flat " << out << " " << glu::declare(output->varType, output->name) << ";\n"; 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\n" 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "void main (void)\n" 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "{\n" 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " gl_Position = vec4(0.0);\n" 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " gl_PointSize = 1.0;\n\n"; 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Declare necessary output variables (bools). 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\t" << glu::declare(output->varType, output->name) << ";\n"; 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Operation - indented to correct level. 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::istringstream opSrc (shaderSpec.source); 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::string line; 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (std::getline(opSrc, line)) 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\t" << line << "\n"; 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Assignments to outputs. 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\to_" << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n"; 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "}\n"; 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return src.str(); 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string generateGeometryShader (const ShaderSpec& shaderSpec) 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version)); 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"; 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES) 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "#extension GL_EXT_geometry_shader : require\n"; 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!shaderSpec.globalDeclarations.empty()) 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << shaderSpec.globalDeclarations << "\n"; 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "layout(points) in;\n" 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "layout(points, max_vertices = 1) out;\n"; 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "flat in " << glu::declare(input->varType, "geom_" + input->name) << "[];\n"; 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(output->varType.isBasicType()); 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::VarType intType (intBaseType, glu::PRECISION_HIGHP); 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "flat out " << glu::declare(intType, "o_" + output->name) << ";\n"; 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "flat out " << glu::declare(output->varType, output->name) << ";\n"; 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\n" 2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "void main (void)\n" 2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "{\n" 2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " gl_Position = gl_in[0].gl_Position;\n\n"; 2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Fetch input variables 2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\t" << glu::declare(input->varType, input->name) << " = geom_" << input->name << "[0];\n"; 2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Declare necessary output variables (bools). 2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\t" << glu::declare(output->varType, output->name) << ";\n"; 2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\n"; 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Operation - indented to correct level. 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::istringstream opSrc (shaderSpec.source); 2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::string line; 2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (std::getline(opSrc, line)) 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\t" << line << "\n"; 2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Assignments to outputs. 2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\to_" << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n"; 2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << " EmitVertex();\n" 2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " EndPrimitive();\n" 2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "}\n"; 2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return src.str(); 2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string generateEmptyFragmentSource (glu::GLSLVersion version) 2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool customOut = glu::glslVersionUsesInOutQualifiers(version); 2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::getGLSLVersionDeclaration(version) << "\n"; 2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \todo [2013-08-05 pyry] Do we need one dummy output? 2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "void main (void)\n{\n"; 2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!customOut) 2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << " gl_FragColor = vec4(0.0);\n"; 2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "}\n"; 2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return src.str(); 2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string generatePassthroughVertexShader (const ShaderSpec& shaderSpec, const char* inputPrefix, const char* outputPrefix) 2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // flat qualifier is not present in earlier versions? 2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version)); 2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n" 2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "in highp vec4 a_position;\n"; 2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n" 2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "flat out " << glu::declare(input->varType, outputPrefix + input->name) << ";\n"; 2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\nvoid main (void)\n{\n" 2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " gl_Position = a_position;\n" 2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " gl_PointSize = 1.0;\n"; 2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\t" << outputPrefix << input->name << " = " << inputPrefix << input->name << ";\n"; 2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "}\n"; 2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return src.str(); 2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string generateFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap) 2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version)); 2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"; 2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!shaderSpec.globalDeclarations.empty()) 2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << shaderSpec.globalDeclarations << "\n"; 3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "flat in " << glu::declare(input->varType, input->name) << ";\n"; 3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int outNdx = 0; outNdx < (int)shaderSpec.outputs.size(); ++outNdx) 3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Symbol& output = shaderSpec.outputs[outNdx]; 3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int location = de::lookup(outLocationMap, output.name); 3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const std::string outVarName = "o_" + output.name; 3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::VariableDeclaration decl (output.varType, outVarName, glu::STORAGE_OUT, glu::INTERPOLATION_LAST, glu::Layout(location)); 3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK_INTERNAL(output.varType.isBasicType()); 3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (useIntOutputs && glu::isDataTypeFloatOrVec(output.varType.getBasicType())) 3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(output.varType.getBasicType()); 3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType uintBasicType = vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT; 3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::VarType uintType (uintBasicType, glu::PRECISION_HIGHP); 3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry decl.varType = uintType; 3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << decl << ";\n"; 3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (glu::isDataTypeBoolOrBVec(output.varType.getBasicType())) 3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(output.varType.getBasicType()); 3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intBasicType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::VarType intType (intBasicType, glu::PRECISION_HIGHP); 3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry decl.varType = intType; 3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << decl << ";\n"; 3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (glu::isDataTypeMatrix(output.varType.getBasicType())) 3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeMatrixNumRows(output.varType.getBasicType()); 3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numVecs = glu::getDataTypeMatrixNumColumns(output.varType.getBasicType()); 3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType uintBasicType = glu::getDataTypeUintVec(vecSize); 3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::VarType uintType (uintBasicType, glu::PRECISION_HIGHP); 3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry decl.varType = uintType; 3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx) 3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry decl.name = outVarName + "_" + de::toString(vecNdx); 3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry decl.layout.location = location + vecNdx; 3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << decl << ";\n"; 3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::VariableDeclaration(output.varType, output.name, glu::STORAGE_OUT, glu::INTERPOLATION_LAST, location) << ";\n"; 3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\nvoid main (void)\n{\n"; 3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((useIntOutputs && glu::isDataTypeFloatOrVec(output->varType.getBasicType())) || 3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::isDataTypeBoolOrBVec(output->varType.getBasicType()) || 3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::isDataTypeMatrix(output->varType.getBasicType())) 3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\t" << glu::declare(output->varType, output->name) << ";\n"; 3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Operation - indented to correct level. 3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::istringstream opSrc (shaderSpec.source); 3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::string line; 3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (std::getline(opSrc, line)) 3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\t" << line << "\n"; 3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (useIntOutputs && glu::isDataTypeFloatOrVec(output->varType.getBasicType())) 3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << " o_" << output->name << " = floatBitsToUint(" << output->name << ");\n"; 3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (glu::isDataTypeMatrix(output->varType.getBasicType())) 3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numVecs = glu::getDataTypeMatrixNumColumns(output->varType.getBasicType()); 3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx) 3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (useIntOutputs) 3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\to_" << output->name << "_" << vecNdx << " = floatBitsToUint(" << output->name << "[" << vecNdx << "]);\n"; 3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\to_" << output->name << "_" << vecNdx << " = " << output->name << "[" << vecNdx << "];\n"; 3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\to_" << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n"; 3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "}\n"; 3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return src.str(); 3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ShaderExecutor 3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3993c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderExecutor::ShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_renderCtx (renderCtx) 4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_inputs (shaderSpec.inputs) 4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_outputs (shaderSpec.outputs) 4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4063c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderExecutor::~ShaderExecutor (void) 4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderExecutor::useProgram (void) 4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(isOk()); 4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_renderCtx.getFunctions().useProgram(getProgram()); 4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// VertexProcessorExecutor (base class for vertex and geometry executors) 4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass VertexProcessorExecutor : public ShaderExecutor 4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VertexProcessorExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources); 4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~VertexProcessorExecutor(void); 4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool isOk (void) const { return m_program.isOk(); } 4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void log (tcu::TestLog& dst) const { dst << m_program; } 4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 getProgram (void) const { return m_program.getProgram(); } 4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void execute (int numValues, const void* const* inputs, void* const* outputs); 4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ShaderProgram m_program; 4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename Iterator> 4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct SymbolNameIterator 4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Iterator symbolIter; 4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SymbolNameIterator (Iterator symbolIter_) : symbolIter(symbolIter_) {} 4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline SymbolNameIterator& operator++ (void) { ++symbolIter; return *this; } 4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline bool operator== (const SymbolNameIterator& other) { return symbolIter == other.symbolIter; } 4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline bool operator!= (const SymbolNameIterator& other) { return symbolIter != other.symbolIter; } 4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline std::string operator* (void) const 4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeBoolOrBVec(symbolIter->varType.getBasicType())) 4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return "o_" + symbolIter->name; 4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return symbolIter->name; 4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename Iterator> 4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline glu::TransformFeedbackVaryings<SymbolNameIterator<Iterator> > getTFVaryings (Iterator begin, Iterator end) 4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return glu::TransformFeedbackVaryings<SymbolNameIterator<Iterator> >(SymbolNameIterator<Iterator>(begin), SymbolNameIterator<Iterator>(end)); 4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4613c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertexProcessorExecutor::VertexProcessorExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources) 4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ShaderExecutor (renderCtx, shaderSpec) 4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_program (renderCtx, 4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources(sources) << getTFVaryings(shaderSpec.outputs.begin(), shaderSpec.outputs.end()) 4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS)) 4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4693c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertexProcessorExecutor::~VertexProcessorExecutor (void) 4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename Iterator> 4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int computeTotalScalarSize (Iterator begin, Iterator end) 4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int size = 0; 4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (Iterator cur = begin; cur != end; ++cur) 4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry size += cur->varType.getScalarSize(); 4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return size; 4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VertexProcessorExecutor::execute (int numValues, const void* const* inputs, void* const* outputs) 4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = m_renderCtx.getFunctions(); 4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool useTFObject = isContextTypeES(m_renderCtx.getType()) || (isContextTypeGLCore(m_renderCtx.getType()) && m_renderCtx.getType().getMajorVersion() >= 4); 4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<glu::VertexArrayBinding> vertexArrays; 4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::UniquePtr<glu::TransformFeedback> transformFeedback (useTFObject ? new glu::TransformFeedback(m_renderCtx) : DE_NULL); 4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::Buffer outputBuffer (m_renderCtx); 4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outputBufferStride = computeTotalScalarSize(m_outputs.begin(), m_outputs.end())*sizeof(deUint32); 4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup inputs. 4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int inputNdx = 0; inputNdx < (int)m_inputs.size(); inputNdx++) 4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Symbol& symbol = m_inputs[inputNdx]; 4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const void* ptr = inputs[inputNdx]; 4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType basicType = symbol.varType.getBasicType(); 4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(basicType); 4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeFloatOrVec(basicType)) 5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vertexArrays.push_back(glu::va::Float(symbol.name, vecSize, numValues, 0, (const float*)ptr)); 5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (glu::isDataTypeIntOrIVec(basicType)) 5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vertexArrays.push_back(glu::va::Int32(symbol.name, vecSize, numValues, 0, (const deInt32*)ptr)); 5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (glu::isDataTypeUintOrUVec(basicType)) 5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vertexArrays.push_back(glu::va::Uint32(symbol.name, vecSize, numValues, 0, (const deUint32*)ptr)); 5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (glu::isDataTypeMatrix(basicType)) 5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numRows = glu::getDataTypeMatrixNumRows(basicType); 5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numCols = glu::getDataTypeMatrixNumColumns(basicType); 5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int stride = numRows * numCols * sizeof(float); 5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int colNdx = 0; colNdx < numCols; ++colNdx) 5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vertexArrays.push_back(glu::va::Float(symbol.name, colNdx, numRows, numValues, stride, ((const float*)ptr) + colNdx * numRows)); 5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup TF outputs. 5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (useTFObject) 5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, **transformFeedback); 5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, *outputBuffer); 5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, outputBufferStride*numValues, DE_NULL, GL_STREAM_READ); 5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, *outputBuffer); 5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "Error in TF setup"); 5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Draw with rasterization disabled. 5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.beginTransformFeedback(GL_POINTS); 5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.enable(GL_RASTERIZER_DISCARD); 5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::draw(m_renderCtx, m_program.getProgram(), (int)vertexArrays.size(), vertexArrays.empty() ? DE_NULL : &vertexArrays[0], 5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::pr::Points(numValues)); 5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.disable(GL_RASTERIZER_DISCARD); 5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.endTransformFeedback(); 5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "Error in draw"); 5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read back data. 5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const void* srcPtr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, outputBufferStride*numValues, GL_MAP_READ_BIT); 5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int curOffset = 0; // Offset in buffer in bytes. 5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER)"); 5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(srcPtr != DE_NULL); 5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int outputNdx = 0; outputNdx < (int)m_outputs.size(); outputNdx++) 5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Symbol& symbol = m_outputs[outputNdx]; 5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void* dstPtr = outputs[outputNdx]; 5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = symbol.varType.getScalarSize(); 5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues; ndx++) 5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deMemcpy((deUint32*)dstPtr + scalarSize*ndx, (const deUint8*)srcPtr + curOffset + ndx*outputBufferStride, scalarSize*sizeof(deUint32)); 5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curOffset += scalarSize*sizeof(deUint32); 5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()"); 5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (useTFObject) 5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); 5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); 5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "Restore state"); 5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// VertexShaderExecutor 5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass VertexShaderExecutor : public VertexProcessorExecutor 5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VertexShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5733c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertexShaderExecutor::VertexShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : VertexProcessorExecutor (renderCtx, shaderSpec, 5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::VertexSource(generateVertexShader(shaderSpec)) 5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version))) 5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// GeometryShaderExecutor 5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5828852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryclass CheckGeomSupport 5838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{ 5848852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrypublic: 5858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry inline CheckGeomSupport (const glu::RenderContext& renderCtx) 5868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry { 5878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry if (renderCtx.getType().getAPI().getProfile() == glu::PROFILE_ES) 5888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry checkExtension(renderCtx, "GL_EXT_geometry_shader"); 5898852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry } 5908852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}; 5918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry 5928852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryclass GeometryShaderExecutor : private CheckGeomSupport, public VertexProcessorExecutor 5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GeometryShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5983c827367444ee418f129b2c238299f49d3264554Jarkko PoyryGeometryShaderExecutor::GeometryShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 5998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry : CheckGeomSupport (renderCtx) 6008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry , VertexProcessorExecutor (renderCtx, shaderSpec, 6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::VertexSource(generatePassthroughVertexShader(shaderSpec, "", "geom_")) 6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::GeometrySource(generateGeometryShader(shaderSpec)) 6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version))) 6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// FragmentShaderExecutor 6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FragmentShaderExecutor : public ShaderExecutor 6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FragmentShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~FragmentShaderExecutor (void); 6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool isOk (void) const { return m_program.isOk(); } 6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void log (tcu::TestLog& dst) const { dst << m_program; } 6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 getProgram (void) const { return m_program.getProgram(); } 6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void execute (int numValues, const void* const* inputs, void* const* outputs); 6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::vector<const Symbol*> m_outLocationSymbols; 6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::map<std::string, int> m_outLocationMap; 6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ShaderProgram m_program; 6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::map<std::string, int> generateLocationMap (const std::vector<Symbol>& symbols, std::vector<const Symbol*>& locationSymbols) 6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::map<std::string, int> ret; 6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int location = 0; 6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry locationSymbols.clear(); 6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (std::vector<Symbol>::const_iterator it = symbols.begin(); it != symbols.end(); ++it) 6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numLocations = glu::getDataTypeNumLocations(it->varType.getBasicType()); 6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK_INTERNAL(!de::contains(ret, it->name)); 6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::insert(ret, it->name, location); 6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry location += numLocations; 6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numLocations; ++ndx) 6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry locationSymbols.push_back(&*it); 6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return ret; 6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline bool hasFloatRenderTargets (const glu::RenderContext& renderCtx) 6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ContextType type = renderCtx.getType(); 6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return glu::isContextTypeGLCore(type); 6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6553c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFragmentShaderExecutor::FragmentShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ShaderExecutor (renderCtx, shaderSpec) 6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_outLocationSymbols () 6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_outLocationMap (generateLocationMap(m_outputs, m_outLocationSymbols)) 6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_program (renderCtx, 6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::VertexSource(generatePassthroughVertexShader(shaderSpec, "a_", "")) 6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::FragmentSource(generateFragmentShader(shaderSpec, !hasFloatRenderTargets(renderCtx), m_outLocationMap))) 6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6653c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFragmentShaderExecutor::~FragmentShaderExecutor (void) 6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline int queryInt (const glw::Functions& gl, deUint32 pname) 6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int value = 0; 6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.getIntegerv(pname, &value); 6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return value; 6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::TextureFormat getRenderbufferFormatForOutput (const glu::VarType& outputType, bool useIntOutputs) 6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::TextureFormat::ChannelOrder channelOrderMap[] = 6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureFormat::R, 6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureFormat::RG, 6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureFormat::RGBA, // No RGB variants available. 6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureFormat::RGBA 6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType basicType = outputType.getBasicType(); 6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numComps = glu::getDataTypeNumComponents(basicType); 6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureFormat::ChannelType channelType; 6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (glu::getDataTypeScalarType(basicType)) 6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_UINT: channelType = tcu::TextureFormat::UNSIGNED_INT32; break; 6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_INT: channelType = tcu::TextureFormat::SIGNED_INT32; break; 6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_BOOL: channelType = tcu::TextureFormat::SIGNED_INT32; break; 6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_FLOAT: channelType = useIntOutputs ? tcu::TextureFormat::UNSIGNED_INT32 : tcu::TextureFormat::FLOAT; break; 6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::InternalError("Invalid output type"); 6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(de::inRange<int>(numComps, 1, DE_LENGTH_OF_ARRAY(channelOrderMap))); 7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return tcu::TextureFormat(channelOrderMap[numComps-1], channelType); 7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FragmentShaderExecutor::execute (int numValues, const void* const* inputs, void* const* outputs) 7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = m_renderCtx.getFunctions(); 7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool useIntOutputs = !hasFloatRenderTargets(m_renderCtx); 7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxRenderbufferSize = queryInt(gl, GL_MAX_RENDERBUFFER_SIZE); 7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int framebufferW = de::min(maxRenderbufferSize, numValues); 7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int framebufferH = (numValues / framebufferW) + ((numValues % framebufferW != 0) ? 1 : 0); 7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::Framebuffer framebuffer (m_renderCtx); 7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::RenderbufferVector renderbuffers (m_renderCtx, m_outLocationSymbols.size()); 7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<glu::VertexArrayBinding> vertexArrays; 7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<tcu::Vec2> positions (numValues); 7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (framebufferH > maxRenderbufferSize) 7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::NotSupportedError("Value count is too high for maximum supported renderbuffer size"); 7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compute positions - 1px points are used to drive fragment shading. 7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int valNdx = 0; valNdx < numValues; valNdx++) 7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int ix = valNdx % framebufferW; 7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int iy = valNdx / framebufferW; 7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float fx = -1.0f + 2.0f*((float(ix) + 0.5f) / float(framebufferW)); 7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float fy = -1.0f + 2.0f*((float(iy) + 0.5f) / float(framebufferH)); 7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry positions[valNdx] = tcu::Vec2(fx, fy); 7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Vertex inputs. 7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vertexArrays.push_back(glu::va::Float("a_position", 2, numValues, 0, (const float*)&positions[0])); 7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int inputNdx = 0; inputNdx < (int)m_inputs.size(); inputNdx++) 7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Symbol& symbol = m_inputs[inputNdx]; 7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const std::string attribName = "a_" + symbol.name; 7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const void* ptr = inputs[inputNdx]; 7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType basicType = symbol.varType.getBasicType(); 7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(basicType); 7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeFloatOrVec(basicType)) 7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vertexArrays.push_back(glu::va::Float(attribName, vecSize, numValues, 0, (const float*)ptr)); 7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (glu::isDataTypeIntOrIVec(basicType)) 7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vertexArrays.push_back(glu::va::Int32(attribName, vecSize, numValues, 0, (const deInt32*)ptr)); 7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (glu::isDataTypeUintOrUVec(basicType)) 7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vertexArrays.push_back(glu::va::Uint32(attribName, vecSize, numValues, 0, (const deUint32*)ptr)); 7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (glu::isDataTypeMatrix(basicType)) 7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numRows = glu::getDataTypeMatrixNumRows(basicType); 7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numCols = glu::getDataTypeMatrixNumColumns(basicType); 7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int stride = numRows * numCols * sizeof(float); 7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int colNdx = 0; colNdx < numCols; ++colNdx) 7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vertexArrays.push_back(glu::va::Float(attribName, colNdx, numRows, numValues, stride, ((const float*)ptr) + colNdx * numRows)); 7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Construct framebuffer. 7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer); 7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int outNdx = 0; outNdx < (int)m_outLocationSymbols.size(); ++outNdx) 7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Symbol& output = *m_outLocationSymbols[outNdx]; 7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 renderbuffer = renderbuffers[outNdx]; 7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 format = glu::getInternalFormat(getRenderbufferFormatForOutput(output.varType, useIntOutputs)); 7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.renderbufferStorage(GL_RENDERBUFFER, format, framebufferW, framebufferH); 7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+outNdx, GL_RENDERBUFFER, renderbuffer); 7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set up framebuffer object"); 7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<deUint32> drawBuffers(m_outLocationSymbols.size()); 7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < (int)m_outLocationSymbols.size(); ndx++) 7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry drawBuffers[ndx] = GL_COLOR_ATTACHMENT0+ndx; 7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.drawBuffers((int)drawBuffers.size(), &drawBuffers[0]); 7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffers()"); 7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Render 7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.viewport(0, 0, framebufferW, framebufferH); 7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::draw(m_renderCtx, m_program.getProgram(), (int)vertexArrays.size(), &vertexArrays[0], 7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::pr::Points(numValues)); 7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "Error in draw"); 7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read back pixels. 7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureLevel tmpBuf; 7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \todo [2013-08-07 pyry] Some fast-paths could be added here. 7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int outNdx = 0; outNdx < (int)m_outputs.size(); ++outNdx) 8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Symbol& output = m_outputs[outNdx]; 8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outSize = output.varType.getScalarSize(); 8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outVecSize = glu::getDataTypeNumComponents(output.varType.getBasicType()); 8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outNumLocs = glu::getDataTypeNumLocations(output.varType.getBasicType()); 8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32* dstPtrBase = static_cast<deUint32*>(outputs[outNdx]); 8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::TextureFormat format = getRenderbufferFormatForOutput(output.varType, useIntOutputs); 8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::TextureFormat readFormat (tcu::TextureFormat::RGBA, format.type); 8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outLocation = de::lookup(m_outLocationMap, output.name); 8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tmpBuf.setStorage(readFormat, framebufferW, framebufferH); 8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int locNdx = 0; locNdx < outNumLocs; ++locNdx) 8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.readBuffer(GL_COLOR_ATTACHMENT0 + outLocation + locNdx); 8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::readPixels(m_renderCtx, 0, 0, tmpBuf.getAccess()); 8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels"); 8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (outSize == 4 && outNumLocs == 1) 8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deMemcpy(dstPtrBase, tmpBuf.getAccess().getDataPtr(), numValues*outVecSize*sizeof(deUint32)); 8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int valNdx = 0; valNdx < numValues; valNdx++) 8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32* srcPtr = (const deUint32*)tmpBuf.getAccess().getDataPtr() + valNdx*4; 8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32* dstPtr = &dstPtrBase[outSize*valNdx + outVecSize*locNdx]; 8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deMemcpy(dstPtr, srcPtr, outVecSize*sizeof(deUint32)); 8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \todo [2013-08-07 pyry] Clear draw buffers & viewport? 8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Shared utilities for compute and tess executors 8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deUint32 getVecStd430ByteAlignment (glu::DataType type) 8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (glu::getDataTypeScalarSize(type)) 8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 1: return 4u; 8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 2: return 8u; 8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 3: return 16u; 8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 4: return 16u; 8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return 0u; 8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BufferIoExecutor : public ShaderExecutor 8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BufferIoExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources); 8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~BufferIoExecutor (void); 8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool isOk (void) const { return m_program.isOk(); } 8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void log (tcu::TestLog& dst) const { dst << m_program; } 8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 getProgram (void) const { return m_program.getProgram(); } 8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry enum 8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry INPUT_BUFFER_BINDING = 0, 8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry OUTPUT_BUFFER_BINDING = 1, 8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void initBuffers (int numValues); 8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 getInputBuffer (void) const { return *m_inputBuffer; } 8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 getOutputBuffer (void) const { return *m_outputBuffer; } 8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 getInputStride (void) const { return getLayoutStride(m_inputLayout); } 8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 getOutputStride (void) const { return getLayoutStride(m_outputLayout); } 8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void uploadInputBuffer (const void* const* inputPtrs, int numValues); 8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void readOutputBuffer (void* const* outputPtrs, int numValues); 8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static void declareBufferBlocks (std::ostream& src, const ShaderSpec& spec); 8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static void generateExecBufferIo(std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName); 8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ShaderProgram m_program; 8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry struct VarLayout 8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 offset; 8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 stride; 8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 matrixStride; 8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VarLayout (void) : offset(0), stride(0), matrixStride(0) {} 8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void resizeInputBuffer (int newSize); 8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void resizeOutputBuffer (int newSize); 8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static void computeVarLayout (const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout); 8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static deUint32 getLayoutStride (const vector<VarLayout>& layout); 9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static void copyToBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr); 9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static void copyFromBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr); 9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::Buffer m_inputBuffer; 9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::Buffer m_outputBuffer; 9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<VarLayout> m_inputLayout; 9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<VarLayout> m_outputLayout; 9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9113c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBufferIoExecutor::BufferIoExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources) 9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ShaderExecutor (renderCtx, shaderSpec) 9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_program (renderCtx, sources) 9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_inputBuffer (renderCtx) 9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_outputBuffer (renderCtx) 9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry computeVarLayout(m_inputs, &m_inputLayout); 9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry computeVarLayout(m_outputs, &m_outputLayout); 9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9213c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBufferIoExecutor::~BufferIoExecutor (void) 9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferIoExecutor::resizeInputBuffer (int newSize) 9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = m_renderCtx.getFunctions(); 9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *m_inputBuffer); 9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bufferData(GL_SHADER_STORAGE_BUFFER, newSize, DE_NULL, GL_STATIC_DRAW); 9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate input buffer"); 9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferIoExecutor::resizeOutputBuffer (int newSize) 9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = m_renderCtx.getFunctions(); 9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *m_outputBuffer); 9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bufferData(GL_SHADER_STORAGE_BUFFER, newSize, DE_NULL, GL_STATIC_DRAW); 9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate output buffer"); 9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferIoExecutor::initBuffers (int numValues) 9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 inputStride = getLayoutStride(m_inputLayout); 9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 outputStride = getLayoutStride(m_outputLayout); 9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int inputBufferSize = numValues * inputStride; 9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outputBufferSize = numValues * outputStride; 9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry resizeInputBuffer(inputBufferSize); 9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry resizeOutputBuffer(outputBufferSize); 9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferIoExecutor::computeVarLayout (const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout) 9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 maxAlignment = 0; 9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 curOffset = 0; 9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(layout->empty()); 9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry layout->resize(symbols.size()); 9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (size_t varNdx = 0; varNdx < symbols.size(); varNdx++) 9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Symbol& symbol = symbols[varNdx]; 9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType basicType = symbol.varType.getBasicType(); 9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VarLayout& layoutEntry = (*layout)[varNdx]; 9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeScalarOrVector(basicType)) 9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 alignment = getVecStd430ByteAlignment(basicType); 9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 size = (deUint32)glu::getDataTypeScalarSize(basicType)*sizeof(deUint32); 9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curOffset = (deUint32)deAlign32((int)curOffset, (int)alignment); 9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry maxAlignment = de::max(maxAlignment, alignment); 9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry layoutEntry.offset = curOffset; 9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry layoutEntry.matrixStride = 0; 9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curOffset += size; 9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (glu::isDataTypeMatrix(basicType)) 9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numVecs = glu::getDataTypeMatrixNumColumns(basicType); 9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType vecType = glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType)); 9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 vecAlignment = getVecStd430ByteAlignment(vecType); 9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curOffset = (deUint32)deAlign32((int)curOffset, (int)vecAlignment); 9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry maxAlignment = de::max(maxAlignment, vecAlignment); 9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry layoutEntry.offset = curOffset; 9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry layoutEntry.matrixStride = vecAlignment; 9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curOffset += vecAlignment*numVecs; 9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 totalSize = (deUint32)deAlign32(curOffset, maxAlignment); 9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<VarLayout>::iterator varIter = layout->begin(); varIter != layout->end(); ++varIter) 10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry varIter->stride = totalSize; 10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 BufferIoExecutor::getLayoutStride (const vector<VarLayout>& layout) 10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return layout.empty() ? 0 : layout[0].stride; 10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferIoExecutor::copyToBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr) 10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (varType.isBasicType()) 10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType basicType = varType.getBasicType(); 10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isMatrix = glu::isDataTypeMatrix(basicType); 10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(basicType); 10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numVecs = isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1; 10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numComps = scalarSize / numVecs; 10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int elemNdx = 0; elemNdx < numValues; elemNdx++) 10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int srcOffset = sizeof(deUint32)*(elemNdx*scalarSize + vecNdx*numComps); 10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int dstOffset = layout.offset + layout.stride*elemNdx + (isMatrix ? layout.matrixStride*vecNdx : 0); 10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint8* srcPtr = (const deUint8*)srcBasePtr + srcOffset; 10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8* dstPtr = (deUint8*)dstBasePtr + dstOffset; 10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deMemcpy(dstPtr, srcPtr, sizeof(deUint32)*numComps); 10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::InternalError("Unsupported type"); 10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferIoExecutor::copyFromBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr) 10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (varType.isBasicType()) 10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType basicType = varType.getBasicType(); 10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isMatrix = glu::isDataTypeMatrix(basicType); 10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(basicType); 10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numVecs = isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1; 10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numComps = scalarSize / numVecs; 10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int elemNdx = 0; elemNdx < numValues; elemNdx++) 10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int srcOffset = layout.offset + layout.stride*elemNdx + (isMatrix ? layout.matrixStride*vecNdx : 0); 10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int dstOffset = sizeof(deUint32)*(elemNdx*scalarSize + vecNdx*numComps); 10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint8* srcPtr = (const deUint8*)srcBasePtr + srcOffset; 10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8* dstPtr = (deUint8*)dstBasePtr + dstOffset; 10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deMemcpy(dstPtr, srcPtr, sizeof(deUint32)*numComps); 10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::InternalError("Unsupported type"); 10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferIoExecutor::uploadInputBuffer (const void* const* inputPtrs, int numValues) 10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = m_renderCtx.getFunctions(); 10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 buffer = *m_inputBuffer; 10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 inputStride = getLayoutStride(m_inputLayout); 10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int inputBufferSize = inputStride*numValues; 10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (inputBufferSize == 0) 10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return; // No inputs 10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); 10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void* mapPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, inputBufferSize, GL_MAP_WRITE_BIT); 10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()"); 10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(mapPtr); 10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_inputs.size() == m_inputLayout.size()); 10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (size_t inputNdx = 0; inputNdx < m_inputs.size(); ++inputNdx) 10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::VarType& varType = m_inputs[inputNdx].varType; 10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const VarLayout& layout = m_inputLayout[inputNdx]; 10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry copyToBuffer(varType, layout, numValues, inputPtrs[inputNdx], mapPtr); 10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (...) 10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw; 10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()"); 10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferIoExecutor::readOutputBuffer (void* const* outputPtrs, int numValues) 11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = m_renderCtx.getFunctions(); 11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 buffer = *m_outputBuffer; 11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 outputStride = getLayoutStride(m_outputLayout); 11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outputBufferSize = numValues*outputStride; 11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(outputBufferSize > 0); // At least some outputs are required. 11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); 11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void* mapPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, outputBufferSize, GL_MAP_READ_BIT); 11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()"); 11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(mapPtr); 11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(m_outputs.size() == m_outputLayout.size()); 11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (size_t outputNdx = 0; outputNdx < m_outputs.size(); ++outputNdx) 11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::VarType& varType = m_outputs[outputNdx].varType; 11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const VarLayout& layout = m_outputLayout[outputNdx]; 11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry copyFromBuffer(varType, layout, numValues, mapPtr, outputPtrs[outputNdx]); 11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (...) 11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw; 11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()"); 11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferIoExecutor::declareBufferBlocks (std::ostream& src, const ShaderSpec& spec) 11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Input struct 11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!spec.inputs.empty()) 11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::StructType inputStruct("Inputs"); 11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter) 11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inputStruct.addMember(symIter->name.c_str(), symIter->varType); 11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::declare(&inputStruct) << ";\n"; 11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Output struct 11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::StructType outputStruct("Outputs"); 11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter) 11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry outputStruct.addMember(symIter->name.c_str(), symIter->varType); 11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::declare(&outputStruct) << ";\n"; 11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\n"; 11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!spec.inputs.empty()) 11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "layout(binding = " << int(INPUT_BUFFER_BINDING) << ", std430) buffer InBuffer\n" 11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "{\n" 11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " Inputs inputs[];\n" 11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "};\n"; 11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "layout(binding = " << int(OUTPUT_BUFFER_BINDING) << ", std430) buffer OutBuffer\n" 11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "{\n" 11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " Outputs outputs[];\n" 11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "};\n" 11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\n"; 11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BufferIoExecutor::generateExecBufferIo (std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName) 11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter) 11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\t" << glu::declare(symIter->varType, symIter->name) << " = inputs[" << invocationNdxName << "]." << symIter->name << ";\n"; 11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter) 11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\t" << glu::declare(symIter->varType, symIter->name) << ";\n"; 11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\n"; 11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::istringstream opSrc (spec.source); 11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::string line; 11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (std::getline(opSrc, line)) 11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\t" << line << "\n"; 11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\n"; 11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter) 11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\toutputs[" << invocationNdxName << "]." << symIter->name << " = " << symIter->name << ";\n"; 11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ComputeShaderExecutor 11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ComputeShaderExecutor : public BufferIoExecutor 11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ComputeShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~ComputeShaderExecutor (void); 12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void execute (int numValues, const void* const* inputs, void* const* outputs); 12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static std::string generateComputeShader (const ShaderSpec& spec); 12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::IVec3 m_maxWorkSize; 12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string ComputeShaderExecutor::generateComputeShader (const ShaderSpec& spec) 12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::getGLSLVersionDeclaration(spec.version) << "\n"; 12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!spec.globalDeclarations.empty()) 12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << spec.globalDeclarations << "\n"; 12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "layout(local_size_x = 1) in;\n" 12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\n"; 12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry declareBufferBlocks(src, spec); 12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "void main (void)\n" 12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "{\n" 12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " uint invocationNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z\n" 12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n"; 12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry generateExecBufferIo(src, spec, "invocationNdx"); 12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "}\n"; 12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return src.str(); 12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12363c827367444ee418f129b2c238299f49d3264554Jarkko PoyryComputeShaderExecutor::ComputeShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : BufferIoExecutor (renderCtx, shaderSpec, 12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ProgramSources() << glu::ComputeSource(generateComputeShader(shaderSpec))) 12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_maxWorkSize = tcu::IVec3(128,128,64); // Minimum in 3plus 12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12433c827367444ee418f129b2c238299f49d3264554Jarkko PoyryComputeShaderExecutor::~ComputeShaderExecutor (void) 12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ComputeShaderExecutor::execute (int numValues, const void* const* inputs, void* const* outputs) 12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = m_renderCtx.getFunctions(); 12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxValuesPerInvocation = m_maxWorkSize[0]; 12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 inputStride = getInputStride(); 12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 outputStride = getOutputStride(); 12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry initBuffers(numValues); 12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup input buffer & copy data 12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uploadInputBuffer(inputs, numValues); 12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Perform compute invocations 12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int curOffset = 0; 12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (curOffset < numValues) 12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numToExec = de::min(maxValuesPerInvocation, numValues-curOffset); 12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (inputStride > 0) 12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer(), curOffset*inputStride, numToExec*inputStride); 12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer(), curOffset*outputStride, numToExec*outputStride); 12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange(GL_SHADER_STORAGE_BUFFER)"); 12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.dispatchCompute(numToExec, 1, 1); 12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute()"); 12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curOffset += numToExec; 12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read back data 12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry readOutputBuffer(outputs, numValues); 12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Tessellation utils 12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string generateVertexShaderForTess (glu::GLSLVersion version) 12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::getGLSLVersionDeclaration(version) << "\n"; 12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "void main (void)\n{\n" 12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " gl_Position = vec4(gl_VertexID/2, gl_VertexID%2, 0.0, 1.0);\n" 12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "}\n"; 12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return src.str(); 12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryclass CheckTessSupport 12998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{ 13008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrypublic: 1301582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry enum Stage 1302582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry { 1303582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry STAGE_CONTROL = 0, 1304582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry STAGE_EVAL, 1305582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry }; 1306582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry 1307582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry inline CheckTessSupport (const glu::RenderContext& renderCtx, Stage stage) 13088852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry { 1309582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry const int numBlockRequired = 2; // highest binding is always 1 (output) i.e. count == 2 1310582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry 13118852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry if (renderCtx.getType().getAPI().getProfile() == glu::PROFILE_ES) 13128852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry checkExtension(renderCtx, "GL_EXT_tessellation_shader"); 1313582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry 1314582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry if (stage == STAGE_CONTROL) 1315582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry checkLimit(renderCtx, GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, numBlockRequired); 1316582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry else if (stage == STAGE_EVAL) 1317582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry checkLimit(renderCtx, GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, numBlockRequired); 1318582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry else 1319582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry DE_ASSERT(false); 13208852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry } 13218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}; 13228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry 13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// TessControlExecutor 13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryclass TessControlExecutor : private CheckTessSupport, public BufferIoExecutor 13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TessControlExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~TessControlExecutor (void); 13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void execute (int numValues, const void* const* inputs, void* const* outputs); 13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static std::string generateTessControlShader (const ShaderSpec& shaderSpec); 13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string TessControlExecutor::generateTessControlShader (const ShaderSpec& shaderSpec) 13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"; 13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (shaderSpec.version == glu::GLSL_VERSION_310_ES) 13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "#extension GL_EXT_tessellation_shader : require\n"; 13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!shaderSpec.globalDeclarations.empty()) 13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << shaderSpec.globalDeclarations << "\n"; 13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\nlayout(vertices = 1) out;\n\n"; 13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry declareBufferBlocks(src, shaderSpec); 13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "void main (void)\n{\n"; 13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < 2; ndx++) 13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n"; 13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < 4; ndx++) 13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n"; 13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\n" 13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\thighp uint invocationId = uint(gl_PrimitiveID);\n"; 13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry generateExecBufferIo(src, shaderSpec, "invocationId"); 13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "}\n"; 13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return src.str(); 13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string generateEmptyTessEvalShader (glu::GLSLVersion version) 13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::getGLSLVersionDeclaration(version) << "\n"; 13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (version == glu::GLSL_VERSION_310_ES) 13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "#extension GL_EXT_tessellation_shader : require\n\n"; 13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "layout(triangles, ccw) in;\n"; 13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\nvoid main (void)\n{\n" 13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tgl_Position = vec4(gl_TessCoord.xy, 0.0, 1.0);\n" 13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "}\n"; 13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return src.str(); 13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13893c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTessControlExecutor::TessControlExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 1390582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry : CheckTessSupport (renderCtx, STAGE_CONTROL) 13918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry , BufferIoExecutor (renderCtx, shaderSpec, glu::ProgramSources() 13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::VertexSource(generateVertexShaderForTess(shaderSpec.version)) 13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::TessellationControlSource(generateTessControlShader(shaderSpec)) 13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::TessellationEvaluationSource(generateEmptyTessEvalShader(shaderSpec.version)) 13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version))) 13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13993c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTessControlExecutor::~TessControlExecutor (void) 14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TessControlExecutor::execute (int numValues, const void* const* inputs, void* const* outputs) 14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = m_renderCtx.getFunctions(); 14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry initBuffers(numValues); 14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup input buffer & copy data 14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uploadInputBuffer(inputs, numValues); 14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_inputs.empty()) 14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer()); 14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer()); 14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Render patches 14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.patchParameteri(GL_PATCH_VERTICES, 3); 14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.drawArrays(GL_PATCHES, 0, 3*numValues); 14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read back data 14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry readOutputBuffer(outputs, numValues); 14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// TessEvaluationExecutor 14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryclass TessEvaluationExecutor : private CheckTessSupport, public BufferIoExecutor 14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TessEvaluationExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec); 14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~TessEvaluationExecutor (void); 14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void execute (int numValues, const void* const* inputs, void* const* outputs); 14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static std::string generateTessEvalShader (const ShaderSpec& shaderSpec); 14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string generatePassthroughTessControlShader (glu::GLSLVersion version) 14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::getGLSLVersionDeclaration(version) << "\n"; 14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (version == glu::GLSL_VERSION_310_ES) 14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "#extension GL_EXT_tessellation_shader : require\n\n"; 14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "layout(vertices = 1) out;\n\n"; 14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "void main (void)\n{\n"; 14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < 2; ndx++) 14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n"; 14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < 4; ndx++) 14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n"; 14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "}\n"; 14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return src.str(); 14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string TessEvaluationExecutor::generateTessEvalShader (const ShaderSpec& shaderSpec) 14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"; 14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (shaderSpec.version == glu::GLSL_VERSION_310_ES) 14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "#extension GL_EXT_tessellation_shader : require\n"; 14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!shaderSpec.globalDeclarations.empty()) 14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << shaderSpec.globalDeclarations << "\n"; 14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\n"; 14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "layout(isolines, equal_spacing) in;\n\n"; 14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry declareBufferBlocks(src, shaderSpec); 14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "void main (void)\n{\n" 14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tgl_Position = vec4(gl_TessCoord.x, 0.0, 0.0, 1.0);\n" 1483a2d25ce999fbbe13789e80ce803cc7b96d2a4c9dPyry Haulos << "\thighp uint invocationId = uint(gl_PrimitiveID)*2u + (gl_TessCoord.x > 0.5 ? 1u : 0u);\n"; 14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry generateExecBufferIo(src, shaderSpec, "invocationId"); 14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "}\n"; 14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return src.str(); 14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14923c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTessEvaluationExecutor::TessEvaluationExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec) 1493582ae6e4b619cd8255b95447a3475070fff1b6b4Jarkko Pöyry : CheckTessSupport (renderCtx, STAGE_EVAL) 14948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry , BufferIoExecutor (renderCtx, shaderSpec, glu::ProgramSources() 14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::VertexSource(generateVertexShaderForTess(shaderSpec.version)) 14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::TessellationControlSource(generatePassthroughTessControlShader(shaderSpec.version)) 14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::TessellationEvaluationSource(generateTessEvalShader(shaderSpec)) 14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version))) 14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15023c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTessEvaluationExecutor::~TessEvaluationExecutor (void) 15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TessEvaluationExecutor::execute (int numValues, const void* const* inputs, void* const* outputs) 15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = m_renderCtx.getFunctions(); 15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int alignedValues = deAlign32(numValues, 2); 15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Initialize buffers with aligned value count to make room for padding 15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry initBuffers(alignedValues); 15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup input buffer & copy data 15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uploadInputBuffer(inputs, numValues); 15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \todo [2014-06-26 pyry] Duplicate last value in the buffer to prevent infinite loops for example? 15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_inputs.empty()) 15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer()); 15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer()); 15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Render patches 15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.patchParameteri(GL_PATCH_VERTICES, 2); 1526a2d25ce999fbbe13789e80ce803cc7b96d2a4c9dPyry Haulos gl.drawArrays(GL_PATCHES, 0, alignedValues); 15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read back data 15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry readOutputBuffer(outputs, numValues); 15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Utilities 15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15343c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderExecutor* createExecutor (const glu::RenderContext& renderCtx, glu::ShaderType shaderType, const ShaderSpec& shaderSpec) 15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (shaderType) 15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::SHADERTYPE_VERTEX: return new VertexShaderExecutor (renderCtx, shaderSpec); 15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::SHADERTYPE_TESSELLATION_CONTROL: return new TessControlExecutor (renderCtx, shaderSpec); 15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::SHADERTYPE_TESSELLATION_EVALUATION: return new TessEvaluationExecutor (renderCtx, shaderSpec); 15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::SHADERTYPE_GEOMETRY: return new GeometryShaderExecutor (renderCtx, shaderSpec); 15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::SHADERTYPE_FRAGMENT: return new FragmentShaderExecutor (renderCtx, shaderSpec); 15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::SHADERTYPE_COMPUTE: return new ComputeShaderExecutor (renderCtx, shaderSpec); 15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::InternalError("Unsupported shader type"); 15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // ShaderExecUtil 15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gls 15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp 1552