1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2017 The Khronos Group Inc. 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 22 */ /*-------------------------------------------------------------------*/ 23 24 /** 25 */ /*! 26 * \file gl4cShaderViewportLayerArrayTests.cpp 27 * \brief Conformance tests for the ARB_shader_viewport_layer_array functionality. 28 */ /*-------------------------------------------------------------------*/ 29 30 #include "gl4cShaderViewportLayerArrayTests.hpp" 31 #include "gluContextInfo.hpp" 32 #include "gluDefs.hpp" 33 #include "gluDrawUtil.hpp" 34 #include "gluObjectWrapper.hpp" 35 #include "gluShaderProgram.hpp" 36 #include "glwEnums.hpp" 37 #include "glwFunctions.hpp" 38 #include "tcuRenderTarget.hpp" 39 40 #include <sstream> 41 #include <string> 42 #include <vector> 43 44 using namespace glw; 45 46 namespace gl4cts 47 { 48 49 ShaderViewportLayerArrayUtils::ShaderPipeline::ShaderPipeline(bool tessellationShader, bool geometryShader, 50 int maxViewportsLayers, const std::string& varName) 51 : m_program(NULL) 52 , m_hasTessellationShader(tessellationShader) 53 , m_hasGeometryShader(geometryShader) 54 , m_viewportLayerOffset(m_hasGeometryShader ? OFFSET_GEOMETRY : 55 m_hasTessellationShader ? OFFSET_TESSELLATION : OFFSET_VERTEX) 56 , m_varName(varName) 57 { 58 m_vs = "#version 450 core\n" 59 "#extension GL_ARB_shader_viewport_layer_array: require\n" 60 "in highp vec2 inPosition;\n" 61 "in int in<var_name>;\n" 62 "in highp vec4 inColor;\n" 63 "out int vs<var_name>;\n" 64 "out highp vec3 vsPosition;\n" 65 "out highp vec4 vsColor;\n" 66 "void main()\n" 67 "{\n" 68 " gl_Position = vec4(inPosition, 0.0, 1.0);\n" 69 " gl_<var_name> = (in<var_name> + <viewport_layer_offset>) % <viewport_layer_max>;\n" 70 " vs<var_name> = in<var_name>;\n" 71 " vsPosition = vec3(inPosition, 0.0);\n" 72 " vsColor = inColor;\n" 73 "}\n"; 74 75 m_tcs = "#version 450 core\n" 76 "layout(vertices = 3) out;\n" 77 "in highp vec3 vsPosition[];\n" 78 "in highp vec4 vsColor[];\n" 79 "in int vs<var_name>[];\n" 80 "out highp vec3 tcsPosition[];\n" 81 "out highp vec4 tcsColor[];\n" 82 "out int tcs<var_name>[];\n" 83 "void main()\n" 84 "{\n" 85 " tcsPosition[gl_InvocationID] = vsPosition[gl_InvocationID];\n" 86 " tcsColor[gl_InvocationID] = vsColor[gl_InvocationID];\n" 87 " tcs<var_name>[gl_InvocationID] = vs<var_name>[gl_InvocationID];\n" 88 " gl_TessLevelInner[0] = 3;\n" 89 " gl_TessLevelOuter[0] = 3;\n" 90 " gl_TessLevelOuter[1] = 3;\n" 91 " gl_TessLevelOuter[2] = 3;\n" 92 "}\n"; 93 94 m_tes = "#version 450 core\n" 95 "#extension GL_ARB_shader_viewport_layer_array: require\n" 96 "layout(triangles, equal_spacing, cw) in;\n" 97 "in highp vec3 tcsPosition[];\n" 98 "in highp vec4 tcsColor[];\n" 99 "in int tcs<var_name>[];\n" 100 "out highp vec4 tesColor;\n" 101 "out highp int tes<var_name>;\n" 102 "void main()\n" 103 "{\n" 104 " vec3 p0 = gl_TessCoord.x * tcsPosition[0];\n" 105 " vec3 p1 = gl_TessCoord.y * tcsPosition[1];\n" 106 " vec3 p2 = gl_TessCoord.z * tcsPosition[2];\n" 107 " tesColor = tcsColor[0];\n" 108 " tes<var_name> = tcs<var_name>[0];\n" 109 " gl_<var_name> = (tcs<var_name>[0] + <viewport_layer_offset>) % <viewport_layer_max>;\n" 110 " gl_Position = vec4(normalize(p0 + p1 + p2), 1.0);\n" 111 "}\n"; 112 113 m_gs = "#version 450 core\n" 114 "#extension GL_ARB_shader_viewport_layer_array: require\n" 115 "layout(triangles) in;\n" 116 "layout(triangle_strip, max_vertices = 3) out;\n" 117 "in highp vec4 tesColor[];\n" 118 "in int tes<var_name>[];\n" 119 "out highp vec4 gsColor;\n" 120 "void main()\n" 121 "{\n" 122 " for (int i = 0; i<3; i++)\n" 123 " {\n" 124 " gl_Position = gl_in[i].gl_Position;\n" 125 " gl_<var_name> = (tes<var_name>[i] + <viewport_layer_offset>) % <viewport_layer_max>;\n" 126 " gsColor = tesColor[i];\n" 127 " EmitVertex();\n" 128 " }\n" 129 " EndPrimitive();\n" 130 "}\n"; 131 132 m_fs = "#version 450 core\n" 133 "in highp vec4 <input_color>;\n" 134 "out vec4 finalOutColor;\n" 135 "void main()\n" 136 "{\n" 137 " finalOutColor = <input_color>;\n" 138 "}\n"; 139 140 this->adaptShaderToPipeline(m_vs, "<var_name>", varName); 141 this->adaptShaderToPipeline(m_vs, "<viewport_layer_offset>", OFFSET_VERTEX); 142 this->adaptShaderToPipeline(m_vs, "<viewport_layer_max>", maxViewportsLayers); 143 144 this->adaptShaderToPipeline(m_tes, "<var_name>", varName); 145 this->adaptShaderToPipeline(m_tes, "<viewport_layer_offset>", OFFSET_TESSELLATION); 146 this->adaptShaderToPipeline(m_tes, "<viewport_layer_max>", maxViewportsLayers); 147 148 this->adaptShaderToPipeline(m_tcs, "<var_name>", varName); 149 150 this->adaptShaderToPipeline(m_gs, "<var_name>", varName); 151 this->adaptShaderToPipeline(m_gs, "<viewport_layer_offset>", OFFSET_GEOMETRY); 152 this->adaptShaderToPipeline(m_gs, "<viewport_layer_max>", maxViewportsLayers); 153 154 this->adaptShaderToPipeline(m_fs, "<input_color>", "vsColor", "tesColor", "gsColor"); 155 } 156 157 void ShaderViewportLayerArrayUtils::ShaderPipeline::adaptShaderToPipeline(std::string& shader, 158 const std::string& varKey, 159 const std::string& vsVersion, 160 const std::string& tesVersion, 161 const std::string& gsVersion) 162 { 163 std::string varName = m_hasGeometryShader ? gsVersion : m_hasTessellationShader ? tesVersion : vsVersion; 164 165 size_t start = 0; 166 while ((start = shader.find(varKey, start)) != std::string::npos) 167 { 168 shader.replace(start, varKey.length(), varName); 169 start += varName.length(); 170 } 171 } 172 173 void ShaderViewportLayerArrayUtils::ShaderPipeline::adaptShaderToPipeline(std::string& shader, 174 const std::string& varKey, 175 const std::string& value) 176 { 177 this->adaptShaderToPipeline(shader, varKey, value, value, value); 178 } 179 180 void ShaderViewportLayerArrayUtils::ShaderPipeline::adaptShaderToPipeline(std::string& shader, 181 const std::string& varKey, int value) 182 { 183 std::ostringstream valueStr; 184 valueStr << value; 185 186 this->adaptShaderToPipeline(shader, varKey, valueStr.str(), valueStr.str(), valueStr.str()); 187 } 188 189 ShaderViewportLayerArrayUtils::ShaderPipeline::~ShaderPipeline() 190 { 191 if (m_program) 192 { 193 delete m_program; 194 } 195 } 196 197 void ShaderViewportLayerArrayUtils::ShaderPipeline::create(const glu::RenderContext& context) 198 { 199 glu::ProgramSources sources; 200 sources.sources[glu::SHADERTYPE_VERTEX].push_back(m_vs); 201 if (m_hasTessellationShader) 202 { 203 sources.sources[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(m_tcs); 204 sources.sources[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back(m_tes); 205 } 206 if (m_hasGeometryShader) 207 { 208 sources.sources[glu::SHADERTYPE_GEOMETRY].push_back(m_gs); 209 } 210 sources.sources[glu::SHADERTYPE_FRAGMENT].push_back(m_fs); 211 212 m_program = new glu::ShaderProgram(context, sources); 213 if (!m_program->isOk()) 214 { 215 TCU_FAIL("Shader compilation failed"); 216 } 217 } 218 219 void ShaderViewportLayerArrayUtils::ShaderPipeline::use(const glu::RenderContext& context) 220 { 221 const glw::Functions& gl = context.getFunctions(); 222 gl.useProgram(m_program->getProgram()); 223 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram failed"); 224 } 225 226 void ShaderViewportLayerArrayUtils::renderQuad(const glu::RenderContext& context, ShaderPipeline& shaderPipeline, 227 int viewportLayerIndex, tcu::Vec4 color) 228 { 229 const glw::Functions& gl = context.getFunctions(); 230 231 deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 }; 232 233 float const position[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f }; 234 235 int const viewportLayerIndices[] = { viewportLayerIndex, viewportLayerIndex, viewportLayerIndex, 236 viewportLayerIndex }; 237 238 float const colors[] = { color.x(), color.y(), color.z(), color.w(), color.x(), color.y(), color.z(), color.w(), 239 color.x(), color.y(), color.z(), color.w(), color.x(), color.y(), color.z(), color.w() }; 240 241 std::string varName = "in"; 242 varName += shaderPipeline.getVarName(); 243 244 glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("inPosition", 2, 4, 0, position), 245 glu::va::Int32(varName, 1, 4, 0, viewportLayerIndices), 246 glu::va::Float("inColor", 4, 4, 0, colors) }; 247 248 shaderPipeline.use(context); 249 250 glu::PrimitiveList primitiveList = shaderPipeline.hasTessellationShader() ? 251 glu::pr::Patches(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices) : 252 glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices); 253 254 glu::draw(context, shaderPipeline.getShaderProgram()->getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays, 255 primitiveList, (glu::DrawUtilCallback*)DE_NULL); 256 257 GLU_EXPECT_NO_ERROR(gl.getError(), "glu::draw error"); 258 } 259 260 bool ShaderViewportLayerArrayUtils::validateColor(tcu::Vec4 renderedColor, tcu::Vec4 referenceColor) 261 { 262 const float epsilon = 0.008f; 263 return de::abs(renderedColor.x() - referenceColor.x()) < epsilon && 264 de::abs(renderedColor.y() - referenceColor.y()) < epsilon && 265 de::abs(renderedColor.z() - referenceColor.z()) < epsilon && 266 de::abs(renderedColor.w() - referenceColor.w()) < epsilon; 267 } 268 269 glw::GLint ShaderViewportIndexTestCase::createMaxViewports() 270 { 271 const Functions& gl = m_context.getRenderContext().getFunctions(); 272 const tcu::RenderTarget renderTarget = m_context.getRenderContext().getRenderTarget(); 273 const GLfloat targetWidth = (GLfloat)renderTarget.getWidth(); 274 275 GLint maxViewports = 0; 276 gl.getIntegerv(GL_MAX_VIEWPORTS, &maxViewports); 277 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv error"); 278 279 const int viewportDataSize = 4; // x + y + w + h 280 std::vector<glw::GLfloat> data(maxViewports * viewportDataSize); 281 282 GLfloat viewportWidth = 16.0f; 283 GLfloat viewportHeight = 16.0f; 284 285 int currentX = 0; 286 int currentY = 0; 287 for (GLint i = 0; i < maxViewports; ++i) 288 { 289 GLfloat x = (GLfloat)currentX * viewportWidth; 290 if (x > (targetWidth - viewportWidth)) 291 { 292 x = 0.0f; 293 currentX = 0; 294 currentY++; 295 } 296 GLfloat y = (GLfloat)currentY * viewportHeight; 297 298 data[i * viewportDataSize + 0] = x; 299 data[i * viewportDataSize + 1] = y; 300 data[i * viewportDataSize + 2] = viewportWidth; 301 data[i * viewportDataSize + 3] = viewportHeight; 302 303 m_viewportData.push_back(tcu::Vec4(x, y, viewportWidth, viewportHeight)); 304 305 currentX++; 306 } 307 308 gl.viewportArrayv(0, maxViewports, data.data()); 309 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv"); 310 311 return maxViewports; 312 } 313 314 /** Constructor. 315 * 316 * @param context Rendering context 317 */ 318 ShaderViewportIndexTestCase::ShaderViewportIndexTestCase(deqp::Context& context) 319 : TestCase(context, "ShaderViewportIndexTestCase", 320 "Implements gl_ViewportIndex tests described in CTS_ARB_shader_viewport_layer_array") 321 , m_maxViewports(0) 322 , m_currentViewport(0) 323 { 324 m_isExtensionSupported = context.getContextInfo().isExtensionSupported("GL_ARB_shader_viewport_layer_array"); 325 } 326 327 void ShaderViewportIndexTestCase::init() 328 { 329 if (!m_isExtensionSupported) 330 return; 331 332 m_maxViewports = this->createMaxViewports(); 333 334 m_shaderPipelines.push_back( 335 ShaderViewportLayerArrayUtils::ShaderPipeline(false, false, m_maxViewports, "ViewportIndex")); 336 m_shaderPipelines.push_back( 337 ShaderViewportLayerArrayUtils::ShaderPipeline(true, false, m_maxViewports, "ViewportIndex")); 338 m_shaderPipelines.push_back( 339 ShaderViewportLayerArrayUtils::ShaderPipeline(true, true, m_maxViewports, "ViewportIndex")); 340 341 for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter) 342 { 343 iter->create(m_context.getRenderContext()); 344 } 345 } 346 347 void ShaderViewportIndexTestCase::deinit() 348 { 349 const Functions& gl = m_context.getRenderContext().getFunctions(); 350 const tcu::RenderTarget renderTarget = m_context.getRenderContext().getRenderTarget(); 351 352 gl.viewport(0, 0, renderTarget.getWidth(), renderTarget.getHeight()); 353 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport"); 354 } 355 356 /** Executes test iteration. 357 * 358 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 359 */ 360 tcu::TestNode::IterateResult ShaderViewportIndexTestCase::iterate() 361 { 362 if (!m_isExtensionSupported) 363 { 364 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported"); 365 return STOP; 366 } 367 368 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 369 const glu::RenderContext& renderContext = m_context.getRenderContext(); 370 371 tcu::Vec4 renderColor((m_currentViewport + 1) / (float)m_maxViewports, 0.0f, 0.0f, 1.0f); 372 tcu::Vec4 backgroundColor(0.0f, 0.0f, 0.0f, 1.0f); 373 374 for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end(); 375 ++pipelineIter) 376 { 377 // rendering 378 379 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 380 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor"); 381 gl.clear(GL_COLOR_BUFFER_BIT); 382 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear"); 383 ShaderViewportLayerArrayUtils::renderQuad(renderContext, *pipelineIter, m_currentViewport, renderColor); 384 gl.flush(); 385 GLU_EXPECT_NO_ERROR(gl.getError(), "Flush"); 386 387 // verification 388 389 std::vector<std::pair<tcu::Vec2, tcu::Vec4> > expectedPixels; 390 391 for (size_t i = 0; i < m_viewportData.size(); ++i) 392 { 393 tcu::Vec4 viewportData = m_viewportData[i]; 394 395 int currentViewportWithOffset = 396 (m_currentViewport + pipelineIter->getViewportLayerOffset()) % m_maxViewports; 397 398 tcu::Vec2 center(viewportData.x() + viewportData.z() * 0.5f, viewportData.y() + viewportData.w() * 0.5f); 399 400 if (i == (unsigned int)currentViewportWithOffset) 401 { 402 expectedPixels.push_back(std::make_pair(center, renderColor)); 403 } 404 else 405 { 406 expectedPixels.push_back(std::make_pair(center, backgroundColor)); 407 } 408 } 409 410 for (size_t i = 0; i < expectedPixels.size(); ++i) 411 { 412 glw::GLfloat rgba[4] = { -1.f, -1.f, -1.f, -1.f }; 413 gl.readPixels((glw::GLint)expectedPixels[i].first.x(), (glw::GLint)expectedPixels[i].first.y(), 1, 1, 414 GL_RGBA, GL_FLOAT, rgba); 415 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels"); 416 bool validationResult = ShaderViewportLayerArrayUtils::validateColor( 417 tcu::Vec4(rgba[0], rgba[1], rgba[2], rgba[3]), expectedPixels[i].second); 418 TCU_CHECK_MSG(validationResult, "Expected pixel color did not match rendered one."); 419 } 420 } 421 422 if (m_currentViewport < (m_maxViewports - 1)) 423 { 424 m_currentViewport++; 425 return CONTINUE; 426 } 427 428 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 429 return STOP; 430 } 431 432 ShaderLayerFramebufferTestCaseBase::ShaderLayerFramebufferTestCaseBase(deqp::Context& context, const char* name, 433 const char* description, bool layered) 434 : TestCase(context, name, description) 435 , m_layersNum(layered ? 4 : 1) 436 , m_fboSize(512) 437 , m_texture(0) 438 , m_mainFbo(0) 439 , m_currentLayer(0) 440 { 441 m_isExtensionSupported = context.getContextInfo().isExtensionSupported("GL_ARB_shader_viewport_layer_array"); 442 } 443 444 void ShaderLayerFramebufferTestCaseBase::init() 445 { 446 if (!m_isExtensionSupported) 447 return; 448 449 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 450 451 this->createFBO(); 452 453 m_shaderPipelines.push_back(ShaderViewportLayerArrayUtils::ShaderPipeline(false, false, m_layersNum, "Layer")); 454 m_shaderPipelines.push_back(ShaderViewportLayerArrayUtils::ShaderPipeline(true, false, m_layersNum, "Layer")); 455 m_shaderPipelines.push_back(ShaderViewportLayerArrayUtils::ShaderPipeline(true, true, m_layersNum, "Layer")); 456 457 for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter) 458 { 459 iter->create(m_context.getRenderContext()); 460 } 461 462 gl.viewport(0, 0, m_fboSize, m_fboSize); 463 } 464 465 void ShaderLayerFramebufferTestCaseBase::deinit() 466 { 467 const Functions& gl = m_context.getRenderContext().getFunctions(); 468 const tcu::RenderTarget renderTarget = m_context.getRenderContext().getRenderTarget(); 469 470 gl.viewport(0, 0, renderTarget.getWidth(), renderTarget.getHeight()); 471 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport"); 472 } 473 474 475 tcu::TestNode::IterateResult ShaderLayerFramebufferTestCaseBase::iterate() 476 { 477 if (!m_isExtensionSupported) 478 { 479 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported"); 480 return STOP; 481 } 482 483 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 484 const glu::RenderContext& renderContext = m_context.getRenderContext(); 485 486 tcu::Vec4 renderColor((m_currentLayer + 1) / (float)m_layersNum, 0.0f, 0.0f, 1.0f); 487 488 for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end(); 489 ++pipelineIter) 490 { 491 // bind main framebuffer (layered) 492 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_mainFbo); 493 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer"); 494 495 // render 496 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 497 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor"); 498 gl.clear(GL_COLOR_BUFFER_BIT); 499 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear"); 500 ShaderViewportLayerArrayUtils::renderQuad(renderContext, *pipelineIter, m_currentLayer, renderColor); 501 gl.flush(); 502 GLU_EXPECT_NO_ERROR(gl.getError(), "Flush"); 503 504 // calculate layer offset (same value as gl_Layer in shader) 505 int currentLayerWithOffset = (m_currentLayer + pipelineIter->getViewportLayerOffset()) % m_layersNum; 506 507 // bind framebuffer of this layer 508 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbos[currentLayerWithOffset]); 509 GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer() call failed."); 510 511 // verification 512 glw::GLfloat rgba[4] = { -1.f, -1.f, -1.f, -1.f }; 513 gl.readPixels(m_fboSize / 2, m_fboSize / 2, 1, 1, GL_RGBA, GL_FLOAT, rgba); 514 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels"); 515 bool validationResult = 516 ShaderViewportLayerArrayUtils::validateColor(tcu::Vec4(rgba[0], rgba[1], rgba[2], rgba[3]), renderColor); 517 518 TCU_CHECK_MSG(validationResult, "Expected pixel color did not match rendered one."); 519 } 520 521 if (m_currentLayer < (m_layersNum - 1)) 522 { 523 m_currentLayer++; 524 return CONTINUE; 525 } 526 527 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 528 return STOP; 529 } 530 531 /** Constructor. 532 * 533 * @param context Rendering context 534 */ 535 ShaderLayerFramebufferLayeredTestCase::ShaderLayerFramebufferLayeredTestCase(deqp::Context& context) 536 : ShaderLayerFramebufferTestCaseBase( 537 context, "ShaderLayerFramebufferLayeredTestCase", 538 "Implements gl_Layer tests for layered framebuffer described in CTS_ARB_shader_viewport_layer_array", true) 539 { 540 } 541 542 void ShaderLayerFramebufferLayeredTestCase::createFBO() 543 { 544 const Functions& gl = m_context.getRenderContext().getFunctions(); 545 546 gl.genTextures(1, &m_texture); 547 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures"); 548 549 gl.bindTexture(GL_TEXTURE_3D, m_texture); 550 GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture() call failed."); 551 552 gl.texImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, m_fboSize, m_fboSize, m_layersNum, 0, GL_RGBA, GL_FLOAT, 0); 553 GLU_EXPECT_NO_ERROR(gl.getError(), "texImage3D() call failed."); 554 555 // create main FBO 556 557 gl.genFramebuffers(1, &m_mainFbo); 558 GLU_EXPECT_NO_ERROR(gl.getError(), "genFramebuffers() call failed."); 559 gl.bindFramebuffer(GL_FRAMEBUFFER, m_mainFbo); 560 GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer() call failed."); 561 gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture, 0); 562 GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture() call failed."); 563 564 // create FBO for each layer 565 566 for (int i = 0; i < m_layersNum; ++i) 567 { 568 deUint32 layerFbo; 569 570 gl.genFramebuffers(1, &layerFbo); 571 GLU_EXPECT_NO_ERROR(gl.getError(), "genFramebuffers() call failed."); 572 gl.bindFramebuffer(GL_FRAMEBUFFER, layerFbo); 573 GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer() call failed."); 574 gl.framebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture, 0, i); 575 GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTextureLayer() call failed."); 576 577 m_fbos.push_back(layerFbo); 578 } 579 } 580 581 void ShaderLayerFramebufferLayeredTestCase::deleteFBO() 582 { 583 const Functions& gl = m_context.getRenderContext().getFunctions(); 584 585 gl.deleteFramebuffers(1, &m_mainFbo); 586 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteFramebuffers"); 587 for (int i = 0; i < m_layersNum; ++i) 588 { 589 gl.deleteFramebuffers(1, &(m_fbos[i])); 590 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteFramebuffers"); 591 } 592 gl.deleteTextures(1, &m_texture); 593 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteTextures"); 594 } 595 596 /** Constructor. 597 * 598 * @param context Rendering context 599 */ 600 ShaderLayerFramebufferNonLayeredTestCase::ShaderLayerFramebufferNonLayeredTestCase(deqp::Context& context) 601 : ShaderLayerFramebufferTestCaseBase( 602 context, "ShaderLayerFramebufferNonLayeredTestCase", 603 "Implements gl_Layer tests for non-layered framebuffer described in CTS_ARB_shader_viewport_layer_array", 604 false) 605 { 606 } 607 608 void ShaderLayerFramebufferNonLayeredTestCase::createFBO() 609 { 610 const Functions& gl = m_context.getRenderContext().getFunctions(); 611 deUint32 tex; 612 613 gl.genTextures(1, &tex); 614 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures"); 615 616 gl.bindTexture(GL_TEXTURE_2D, tex); 617 GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture() call failed."); 618 619 gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_fboSize, m_fboSize, 0, GL_RGBA, GL_FLOAT, 0); 620 GLU_EXPECT_NO_ERROR(gl.getError(), "texImage2D() call failed."); 621 622 // create main FBO 623 624 gl.genFramebuffers(1, &m_mainFbo); 625 GLU_EXPECT_NO_ERROR(gl.getError(), "genFramebuffers() call failed."); 626 gl.bindFramebuffer(GL_FRAMEBUFFER, m_mainFbo); 627 GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer() call failed."); 628 gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0); 629 GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture() call failed."); 630 631 // main FBO is only layer 632 633 m_fbos.push_back(m_mainFbo); 634 } 635 636 void ShaderLayerFramebufferNonLayeredTestCase::deleteFBO() 637 { 638 const Functions& gl = m_context.getRenderContext().getFunctions(); 639 640 gl.deleteFramebuffers(1, &m_mainFbo); 641 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteFramebuffers"); 642 gl.deleteTextures(1, &m_texture); 643 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteTextures"); 644 } 645 646 /** Constructor. 647 * 648 * @param context Rendering context. 649 */ 650 ShaderViewportLayerArray::ShaderViewportLayerArray(deqp::Context& context) 651 : TestCaseGroup(context, "shader_viewport_layer_array", 652 "Verify conformance of CTS_ARB_shader_viewport_layer_array implementation") 653 { 654 } 655 656 /** Initializes the test group contents. */ 657 void ShaderViewportLayerArray::init() 658 { 659 addChild(new ShaderViewportIndexTestCase(m_context)); 660 addChild(new ShaderLayerFramebufferLayeredTestCase(m_context)); 661 addChild(new ShaderLayerFramebufferNonLayeredTestCase(m_context)); 662 } 663 } /* gl4cts namespace */ 664