1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2015 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 Atomic Counter Tests 22 *//*--------------------------------------------------------------------*/ 23 24#include "es31fNegativeAtomicCounterTests.hpp" 25 26#include "deUniquePtr.hpp" 27 28#include "glwEnums.hpp" 29#include "gluShaderProgram.hpp" 30 31#include "tcuTestLog.hpp" 32 33namespace deqp 34{ 35namespace gles31 36{ 37namespace Functional 38{ 39namespace NegativeTestShared 40{ 41namespace 42{ 43 44enum TestCase 45{ 46 TESTCASE_LAYOUT_LARGE_BINDING = 0, 47 TESTCASE_LAYOUT_MEDIUMP_PRECISION, 48 TESTCASE_LAYOUT_LOWP_PRECISION, 49 TESTCASE_LAYOUT_BINDING_OFFSET_OVERLAP, 50 TESTCASE_LAYOUT_BINDING_OMITTED, 51 TESTCASE_STRUCT, 52 TESTCASE_BODY_WRITE, 53 TESTCASE_BODY_DECLARE, 54 55 TESTCASE_LAST 56}; 57 58static const glu::ShaderType s_shaders[] = 59{ 60 glu::SHADERTYPE_VERTEX, 61 glu::SHADERTYPE_FRAGMENT, 62 glu::SHADERTYPE_GEOMETRY, 63 glu::SHADERTYPE_TESSELLATION_CONTROL, 64 glu::SHADERTYPE_TESSELLATION_EVALUATION, 65 glu::SHADERTYPE_COMPUTE 66}; 67 68std::string genShaderSource (NegativeTestContext& ctx, TestCase test, glu::ShaderType type) 69{ 70 DE_ASSERT(test < TESTCASE_LAST && type < glu::SHADERTYPE_LAST); 71 72 glw::GLint maxBuffers = -1; 73 std::ostringstream shader; 74 75 ctx.glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &maxBuffers); 76 77 shader << getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"; 78 79 switch (type) 80 { 81 case glu::SHADERTYPE_GEOMETRY: 82 shader << "#extension GL_EXT_geometry_shader : enable\n"; 83 shader << "layout(max_vertices = 3) out;\n"; 84 break; 85 86 case glu::SHADERTYPE_TESSELLATION_CONTROL: 87 case glu::SHADERTYPE_TESSELLATION_EVALUATION: 88 shader << "#extension GL_EXT_tessellation_shader : enable\n"; 89 break; 90 91 default: 92 break; 93 } 94 95 switch (test) 96 { 97 case TESTCASE_LAYOUT_LARGE_BINDING: 98 shader << "layout (binding = " << maxBuffers << ", offset = 0) uniform atomic_uint counter0;\n"; 99 break; 100 101 case TESTCASE_LAYOUT_MEDIUMP_PRECISION: 102 shader << "layout (binding = 1, offset = 0) " << glu::getPrecisionName(glu::PRECISION_MEDIUMP) << " uniform atomic_uint counter0;\n"; 103 break; 104 105 case TESTCASE_LAYOUT_LOWP_PRECISION: 106 shader << "layout (binding = 1, offset = 0) " << glu::getPrecisionName(glu::PRECISION_LOWP) << " uniform atomic_uint counter0;\n"; 107 break; 108 109 case TESTCASE_LAYOUT_BINDING_OFFSET_OVERLAP: 110 shader << "layout (binding = 1, offset = 0) uniform atomic_uint counter0;\n" 111 << "layout (binding = 1, offset = 2) uniform atomic_uint counter1;\n"; 112 break; 113 114 case TESTCASE_LAYOUT_BINDING_OMITTED: 115 shader << "layout (offset = 0) uniform atomic_uint counter0;\n"; 116 break; 117 118 case TESTCASE_STRUCT: 119 shader << "struct\n" 120 << "{\n" 121 << " int a;\n" 122 << " atomic_uint counter;\n" 123 << "} S;\n"; 124 break; 125 126 case TESTCASE_BODY_WRITE: 127 shader << "layout (binding = 1) uniform atomic_uint counter;\n"; 128 break; 129 130 default: 131 break; 132 } 133 134 shader << "void main (void)\n" 135 << "{\n"; 136 137 switch (test) 138 { 139 case TESTCASE_BODY_WRITE: 140 shader << "counter = 1;\n"; 141 break; 142 143 case TESTCASE_BODY_DECLARE: 144 shader << "atomic_uint counter;\n"; 145 break; 146 147 default: 148 break; 149 } 150 151 shader << "}\n"; 152 153 return shader.str(); 154} 155 156void iterateShaders (NegativeTestContext& ctx, TestCase testCase) 157{ 158 tcu::TestLog& log = ctx.getLog(); 159 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_shaders); ndx++) 160 { 161 if (ctx.isShaderSupported(s_shaders[ndx])) 162 { 163 ctx.beginSection(std::string("Verify shader: ") + glu::getShaderTypeName(s_shaders[ndx])); 164 const glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources() << glu::ShaderSource(s_shaders[ndx], genShaderSource(ctx, testCase, s_shaders[ndx]))); 165 if (program.getShaderInfo(s_shaders[ndx]).compileOk) 166 { 167 log << program; 168 log << tcu::TestLog::Message << "Expected program to fail, but compilation passed." << tcu::TestLog::EndMessage; 169 ctx.fail("Shader was not expected to compile."); 170 } 171 ctx.endSection(); 172 } 173 } 174} 175 176void atomic_max_counter_bindings (NegativeTestContext& ctx) 177{ 178 ctx.beginSection("It is a compile-time error to bind an atomic counter with a binding value greater than or equal to gl_MaxAtomicCounterBindings."); 179 iterateShaders(ctx, TESTCASE_LAYOUT_LARGE_BINDING); 180 ctx.endSection(); 181} 182 183void atomic_precision (NegativeTestContext& ctx) 184{ 185 ctx.beginSection("It is an error to declare an atomic type with a lowp or mediump precision."); 186 iterateShaders(ctx, TESTCASE_LAYOUT_MEDIUMP_PRECISION); 187 iterateShaders(ctx, TESTCASE_LAYOUT_LOWP_PRECISION); 188 ctx.endSection(); 189} 190 191void atomic_binding_offset_overlap (NegativeTestContext& ctx) 192{ 193 ctx.beginSection("Atomic counters may not have overlapping offsets in the same binding."); 194 iterateShaders(ctx, TESTCASE_LAYOUT_BINDING_OFFSET_OVERLAP); 195 ctx.endSection(); 196} 197 198void atomic_binding_omitted (NegativeTestContext& ctx) 199{ 200 ctx.beginSection("Atomic counters must specify a binding point"); 201 iterateShaders(ctx, TESTCASE_LAYOUT_BINDING_OMITTED); 202 ctx.endSection(); 203} 204 205void atomic_struct (NegativeTestContext& ctx) 206{ 207 ctx.beginSection("Structures may not have an atomic_uint variable."); 208 iterateShaders(ctx, TESTCASE_STRUCT); 209 ctx.endSection(); 210} 211 212void atomic_body_write (NegativeTestContext& ctx) 213{ 214 ctx.beginSection("An atomic_uint variable cannot be directly written to."); 215 iterateShaders(ctx, TESTCASE_BODY_WRITE); 216 ctx.endSection(); 217} 218 219void atomic_body_declare (NegativeTestContext& ctx) 220{ 221 ctx.beginSection("An atomic_uint variable cannot be declared in local scope"); 222 iterateShaders(ctx, TESTCASE_BODY_DECLARE); 223 ctx.endSection(); 224} 225 226} // anonymous 227 228std::vector<FunctionContainer> getNegativeAtomicCounterTestFunctions () 229{ 230 const FunctionContainer funcs[] = 231 { 232 {atomic_max_counter_bindings, "atomic_max_counter_bindings", "Invalid atomic counter buffer binding." }, 233 {atomic_precision, "atomic_precision", "Invalid precision qualifier." }, 234 {atomic_binding_offset_overlap, "atomic_binding_offset_overlap", "Invalid offset." }, 235 {atomic_binding_omitted, "atomic_binding_omitted", "Binding not specified." }, 236 {atomic_struct, "atomic_struct", "Invalid atomic_uint usage in struct." }, 237 {atomic_body_write, "atomic_body_write", "Invalid write access to atomic_uint." }, 238 {atomic_body_declare, "atomic_body_declare", "Invalid precision qualifier." }, 239 }; 240 241 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs)); 242} 243 244} // NegativeTestShared 245} // Functional 246} // gles31 247} // deqp 248