1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2016 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Negative Shader Storage Tests 22 *//*--------------------------------------------------------------------*/ 23 24#include "es31fNegativeShaderStorageTests.hpp" 25 26#include "gluShaderProgram.hpp" 27#include "glwDefs.hpp" 28#include "glwEnums.hpp" 29 30namespace deqp 31{ 32namespace gles31 33{ 34namespace Functional 35{ 36namespace NegativeTestShared 37{ 38namespace 39{ 40 41void verifyProgram(NegativeTestContext& ctx, glu::ProgramSources sources) 42{ 43 tcu::TestLog& log = ctx.getLog(); 44 const glu::ShaderProgram program (ctx.getRenderContext(), sources); 45 bool testFailed = false; 46 47 log << program; 48 49 testFailed = program.getProgramInfo().linkOk; 50 51 if (testFailed) 52 { 53 const char* const message("Program was not expected to link."); 54 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage; 55 ctx.fail(message); 56 } 57} 58 59const char* getShaderExtensionDeclaration (glw::GLenum glShaderType) 60{ 61 switch (glShaderType) 62 { 63 case GL_TESS_CONTROL_SHADER: 64 case GL_TESS_EVALUATION_SHADER: return "#extension GL_EXT_tessellation_shader : require\n"; 65 case GL_GEOMETRY_SHADER: return "#extension GL_EXT_geometry_shader : require\n"; 66 default: 67 return ""; 68 } 69} 70 71glu::ShaderType getGLUShaderType (glw::GLenum glShaderType) 72{ 73 switch (glShaderType) 74 { 75 case GL_VERTEX_SHADER: return glu::SHADERTYPE_VERTEX; 76 case GL_FRAGMENT_SHADER: return glu::SHADERTYPE_FRAGMENT; 77 case GL_TESS_CONTROL_SHADER: return glu::SHADERTYPE_TESSELLATION_CONTROL; 78 case GL_TESS_EVALUATION_SHADER: return glu::SHADERTYPE_TESSELLATION_EVALUATION; 79 case GL_GEOMETRY_SHADER: return glu::SHADERTYPE_GEOMETRY; 80 case GL_COMPUTE_SHADER: return glu::SHADERTYPE_COMPUTE; 81 default: 82 DE_FATAL("Unknown shader type"); 83 return glu::SHADERTYPE_LAST; 84 } 85} 86 87glw::GLenum getMaxSSBlockSizeEnum (glw::GLenum glShaderType) 88{ 89 switch (glShaderType) 90 { 91 case GL_VERTEX_SHADER: return GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS; 92 case GL_FRAGMENT_SHADER: return GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS; 93 case GL_TESS_CONTROL_SHADER: return GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS; 94 case GL_TESS_EVALUATION_SHADER: return GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS; 95 case GL_GEOMETRY_SHADER: return GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS; 96 case GL_COMPUTE_SHADER: return GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS; 97 default: 98 DE_FATAL("Unknown shader type"); 99 return -1; 100 } 101} 102 103int getMaxSSBlockSize (NegativeTestContext& ctx, glw::GLenum glShaderType) 104{ 105 int maxSSBlocks = 0; 106 ctx.glGetIntegerv(getMaxSSBlockSizeEnum(glShaderType), &maxSSBlocks); 107 108 return maxSSBlocks; 109} 110 111std::string genBlockSource (NegativeTestContext& ctx, deInt64 numSSBlocks, glw::GLenum shaderType) 112{ 113 const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)); 114 const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES; 115 std::ostringstream source; 116 117 source << glu::getGLSLVersionDeclaration(version) << "\n" 118 << ((isES32) ? "" : getShaderExtensionDeclaration(shaderType)); 119 120 switch (shaderType) 121 { 122 case GL_VERTEX_SHADER: 123 case GL_FRAGMENT_SHADER: 124 break; 125 126 case GL_COMPUTE_SHADER: 127 source << "layout (local_size_x = 1) in;\n"; 128 break; 129 130 case GL_GEOMETRY_SHADER: 131 source << "layout(points) in;\n" 132 << "layout(line_strip, max_vertices = 3) out;\n"; 133 break; 134 135 case GL_TESS_CONTROL_SHADER: 136 source << "layout(vertices = 10) out;\n"; 137 break; 138 139 case GL_TESS_EVALUATION_SHADER: 140 source << "layout(triangles) in;\n"; 141 break; 142 143 default: 144 DE_FATAL("Unknown shader type"); 145 break; 146 } 147 148 source << "\n" 149 << "layout(std430, binding = 0) buffer Block {\n" 150 << " int value;\n" 151 << "} sb_in[" << numSSBlocks << "];\n" 152 << "void main(void) { sb_in[0].value = 1; }\n"; 153 154 return source.str(); 155} 156 157std::string genCommonSource (NegativeTestContext& ctx, glw::GLenum shaderType) 158{ 159 const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)); 160 const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES; 161 std::ostringstream source; 162 163 source << glu::getGLSLVersionDeclaration(version) << "\n" 164 << ((isES32) ? "" : getShaderExtensionDeclaration(shaderType)); 165 166 switch (shaderType) 167 { 168 case GL_TESS_CONTROL_SHADER: 169 source << "layout(vertices = 3) out;\n" 170 << "void main() {}\n"; 171 break; 172 173 case GL_TESS_EVALUATION_SHADER: 174 source << "layout(triangles, equal_spacing, cw) in;\n" 175 << "void main() {}\n"; 176 break; 177 178 default: 179 source << "void main() {}\n"; 180 break; 181 } 182 183 return source.str(); 184} 185 186int genMaxSSBlocksSource (NegativeTestContext& ctx, glw::GLenum glShaderType, glu::ProgramSources& sources) 187{ 188 int maxSSBlocks = getMaxSSBlockSize(ctx, glShaderType); 189 const std::string shaderSrc = genBlockSource(ctx, (maxSSBlocks), glShaderType); 190 191 sources.sources[getGLUShaderType(glShaderType)].push_back(shaderSrc); 192 193 return maxSSBlocks; 194} 195 196void block_number_limits (NegativeTestContext& ctx) 197{ 198 const glw::GLenum glShaderTypes[] = 199 { 200 GL_VERTEX_SHADER, 201 GL_FRAGMENT_SHADER, 202 GL_TESS_CONTROL_SHADER, 203 GL_TESS_EVALUATION_SHADER, 204 GL_GEOMETRY_SHADER, 205 GL_COMPUTE_SHADER, 206 }; 207 208 const std::string vertSource = genCommonSource(ctx, GL_VERTEX_SHADER); 209 const std::string fragSource = genCommonSource(ctx, GL_FRAGMENT_SHADER); 210 const std::string tessControlSource = genCommonSource(ctx, GL_TESS_CONTROL_SHADER); 211 const std::string tessEvalSource = genCommonSource(ctx, GL_TESS_EVALUATION_SHADER); 212 213 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(glShaderTypes); ndx++) 214 { 215 ctx.beginSection("maxShaderStorageBlocks: Exceed limits"); 216 217 if (!ctx.isShaderSupported(static_cast<glu::ShaderType>(getGLUShaderType(glShaderTypes[ndx])))) 218 { 219 ctx.endSection(); 220 continue; 221 } 222 223 int maxSSBlocks = getMaxSSBlockSize(ctx, glShaderTypes[ndx]); 224 std::string source = genBlockSource(ctx, maxSSBlocks+1, glShaderTypes[ndx]); 225 226 glu::ProgramSources sources; 227 228 if (maxSSBlocks == 0) 229 { 230 ctx.endSection(); 231 continue; 232 } 233 234 switch (glShaderTypes[ndx]) 235 { 236 case GL_VERTEX_SHADER: 237 sources << glu::VertexSource(source) 238 << glu::FragmentSource(fragSource); 239 break; 240 241 case GL_FRAGMENT_SHADER: 242 sources << glu::VertexSource(vertSource) 243 << glu::FragmentSource(source); 244 break; 245 246 case GL_TESS_CONTROL_SHADER: 247 sources << glu::VertexSource(vertSource) 248 << glu::FragmentSource(fragSource) 249 << glu::TessellationControlSource(source) 250 << glu::TessellationEvaluationSource(tessEvalSource); 251 break; 252 253 case GL_TESS_EVALUATION_SHADER: 254 sources << glu::VertexSource(vertSource) 255 << glu::FragmentSource(fragSource) 256 << glu::TessellationControlSource(tessControlSource) 257 << glu::TessellationEvaluationSource(source); 258 break; 259 260 case GL_GEOMETRY_SHADER: 261 sources << glu::VertexSource(vertSource) 262 << glu::FragmentSource(fragSource) 263 << glu::GeometrySource(source); 264 break; 265 266 case GL_COMPUTE_SHADER: 267 sources << glu::ComputeSource(source); 268 break; 269 270 default: 271 DE_FATAL("Unknown shader type"); 272 break; 273 } 274 275 verifyProgram(ctx, sources); 276 ctx.endSection(); 277 } 278} 279 280void max_combined_block_number_limit (NegativeTestContext& ctx) 281{ 282 ctx.beginSection("maxCombinedShaderStorageBlocks: Exceed limits"); 283 284 glu::ProgramSources sources; 285 286 int combinedSSBlocks = 0; 287 int maxCombinedSSBlocks = 0; 288 289 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_VERTEX_SHADER, sources); 290 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_FRAGMENT_SHADER, sources); 291 292 if ((ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_CONTROL)) && (ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_EVALUATION))) 293 { 294 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_CONTROL_SHADER, sources); 295 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_EVALUATION_SHADER, sources); 296 } 297 298 if (ctx.isShaderSupported(glu::SHADERTYPE_GEOMETRY)) 299 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_GEOMETRY_SHADER, sources); 300 301 ctx.glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedSSBlocks); 302 303 ctx.getLog() << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << maxCombinedSSBlocks << tcu::TestLog::EndMessage; 304 ctx.getLog() << tcu::TestLog::Message << "Combined shader storage blocks: " << combinedSSBlocks << tcu::TestLog::EndMessage; 305 306 if (combinedSSBlocks > maxCombinedSSBlocks) 307 verifyProgram(ctx, sources); 308 else 309 ctx.getLog() << tcu::TestLog::Message << "Test skipped: Combined shader storage blocks < GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << tcu::TestLog::EndMessage; 310 311 ctx.endSection(); 312} 313 314} // anonymous 315 316std::vector<FunctionContainer> getNegativeShaderStorageTestFunctions () 317{ 318 const FunctionContainer funcs[] = 319 { 320 { block_number_limits, "block_number_limits", "Invalid shader linkage" }, 321 { max_combined_block_number_limit, "max_combined_block_number_limit", "Invalid shader linkage" }, 322 }; 323 324 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs)); 325} 326 327} // NegativeTestShared 328} // Functional 329} // gles31 330} // deqp 331