1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2018 The Khronos Group Inc. 6 * Copyright (c) 2018 The Android Open Source Project 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Use of gl_ViewportIndex in Vertex and Tessellation Shaders 23 * (part of VK_EXT_ShaderViewportIndexLayer) 24 *//*--------------------------------------------------------------------*/ 25 26#include "vktDrawShaderViewportIndexTests.hpp" 27 28#include "vktDrawBaseClass.hpp" 29#include "vktTestCaseUtil.hpp" 30 31#include "vkDefs.hpp" 32#include "vkRef.hpp" 33#include "vkRefUtil.hpp" 34#include "vkTypeUtil.hpp" 35#include "vkMemUtil.hpp" 36#include "vkPrograms.hpp" 37#include "vkImageUtil.hpp" 38#include "vkQueryUtil.hpp" 39#include "vkCmdUtil.hpp" 40#include "vkObjUtil.hpp" 41#include "vkBuilderUtil.hpp" 42#include "vkBufferWithMemory.hpp" 43 44#include "tcuTestLog.hpp" 45#include "tcuVector.hpp" 46#include "tcuImageCompare.hpp" 47#include "tcuTextureUtil.hpp" 48 49#include "deUniquePtr.hpp" 50#include "deMath.h" 51 52#include <vector> 53#include <memory> 54 55namespace vkt 56{ 57namespace Draw 58{ 59using namespace vk; 60using de::UniquePtr; 61using de::MovePtr; 62using de::SharedPtr; 63using tcu::Vec4; 64using tcu::Vec2; 65using tcu::UVec2; 66using tcu::UVec4; 67 68namespace 69{ 70 71enum Constants 72{ 73 MIN_MAX_VIEWPORTS = 16, //!< Minimum number of viewports for an implementation supporting multiViewport. 74}; 75 76struct TestParams 77{ 78 int numViewports; 79 bool writeFromVertex; 80 const SharedGroupParams groupParams; 81 bool useTessellationShader; 82}; 83 84template<typename T> 85inline VkDeviceSize sizeInBytes(const std::vector<T>& vec) 86{ 87 return vec.size() * sizeof(vec[0]); 88} 89 90VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, VkImageUsageFlags usage) 91{ 92 const VkImageCreateInfo imageParams = 93 { 94 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 95 DE_NULL, // const void* pNext; 96 (VkImageCreateFlags)0, // VkImageCreateFlags flags; 97 VK_IMAGE_TYPE_2D, // VkImageType imageType; 98 format, // VkFormat format; 99 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 100 1u, // deUint32 mipLevels; 101 1u, // deUint32 arrayLayers; 102 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 103 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 104 usage, // VkImageUsageFlags usage; 105 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 106 0u, // deUint32 queueFamilyIndexCount; 107 DE_NULL, // const deUint32* pQueueFamilyIndices; 108 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 109 }; 110 return imageParams; 111} 112 113Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk, 114 const VkDevice device, 115 const VkPipelineLayout pipelineLayout, 116 const VkRenderPass renderPass, 117 const VkShaderModule vertexModule, 118 const VkShaderModule tessellationControlModule, 119 const VkShaderModule tessellationEvaluationModule, 120 const VkShaderModule fragmentModule, 121 const UVec2 renderSize, 122 const int numViewports, 123 const std::vector<UVec4> cells) 124{ 125 const VkVertexInputBindingDescription vertexInputBindingDescription = 126 { 127 0u, // uint32_t binding; 128 sizeof(PositionColorVertex), // uint32_t stride; 129 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 130 }; 131 132 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = 133 { 134 { 135 0u, // uint32_t location; 136 0u, // uint32_t binding; 137 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 138 0u, // uint32_t offset; 139 }, 140 { 141 1u, // uint32_t location; 142 0u, // uint32_t binding; 143 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 144 sizeof(Vec4), // uint32_t offset; 145 }, 146 }; 147 148 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 149 { 150 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 151 DE_NULL, // const void* pNext; 152 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 153 1u, // uint32_t vertexBindingDescriptionCount; 154 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 155 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount; 156 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 157 }; 158 159 const bool useTessellationShaders = (tessellationControlModule != DE_NULL) && (tessellationEvaluationModule != DE_NULL); 160 161 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = 162 { 163 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 164 DE_NULL, // const void* pNext; 165 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 166 useTessellationShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology; 167 VK_FALSE, // VkBool32 primitiveRestartEnable; 168 }; 169 170 DE_ASSERT(numViewports == static_cast<int>(cells.size())); 171 172 std::vector<VkViewport> viewports; 173 viewports.reserve(numViewports); 174 175 std::vector<VkRect2D> rectScissors; 176 rectScissors.reserve(numViewports); 177 178 for (std::vector<UVec4>::const_iterator it = cells.begin(); it != cells.end(); ++it) { 179 const VkViewport viewport = makeViewport(float(it->x()), float(it->y()), float(it->z()), float(it->w()), 0.0f, 1.0f); 180 viewports.push_back(viewport); 181 const VkRect2D rect = makeRect2D(renderSize); 182 rectScissors.push_back(rect); 183 } 184 185 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = 186 { 187 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 188 DE_NULL, // const void* pNext; 189 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; 190 static_cast<deUint32>(numViewports), // uint32_t viewportCount; 191 &viewports[0], // const VkViewport* pViewports; 192 static_cast<deUint32>(numViewports), // uint32_t scissorCount; 193 &rectScissors[0], // const VkRect2D* pScissors; 194 }; 195 196 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = 197 { 198 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 199 DE_NULL, // const void* pNext; 200 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 201 VK_FALSE, // VkBool32 depthClampEnable; 202 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 203 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 204 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 205 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 206 VK_FALSE, // VkBool32 depthBiasEnable; 207 0.0f, // float depthBiasConstantFactor; 208 0.0f, // float depthBiasClamp; 209 0.0f, // float depthBiasSlopeFactor; 210 1.0f, // float lineWidth; 211 }; 212 213 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 214 { 215 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 216 DE_NULL, // const void* pNext; 217 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 218 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 219 VK_FALSE, // VkBool32 sampleShadingEnable; 220 0.0f, // float minSampleShading; 221 DE_NULL, // const VkSampleMask* pSampleMask; 222 VK_FALSE, // VkBool32 alphaToCoverageEnable; 223 VK_FALSE // VkBool32 alphaToOneEnable; 224 }; 225 226 const VkStencilOpState stencilOpState = makeStencilOpState( 227 VK_STENCIL_OP_KEEP, // stencil fail 228 VK_STENCIL_OP_KEEP, // depth & stencil pass 229 VK_STENCIL_OP_KEEP, // depth only fail 230 VK_COMPARE_OP_ALWAYS, // compare op 231 0u, // compare mask 232 0u, // write mask 233 0u); // reference 234 235 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 236 { 237 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 238 DE_NULL, // const void* pNext; 239 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 240 VK_FALSE, // VkBool32 depthTestEnable; 241 VK_FALSE, // VkBool32 depthWriteEnable; 242 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 243 VK_FALSE, // VkBool32 depthBoundsTestEnable; 244 VK_FALSE, // VkBool32 stencilTestEnable; 245 stencilOpState, // VkStencilOpState front; 246 stencilOpState, // VkStencilOpState back; 247 0.0f, // float minDepthBounds; 248 1.0f, // float maxDepthBounds; 249 }; 250 251 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 252 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 253 { 254 VK_FALSE, // VkBool32 blendEnable; 255 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 256 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 257 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 258 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 259 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 260 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 261 colorComponentsAll, // VkColorComponentFlags colorWriteMask; 262 }; 263 264 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 265 { 266 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 267 DE_NULL, // const void* pNext; 268 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 269 VK_FALSE, // VkBool32 logicOpEnable; 270 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 271 1u, // deUint32 attachmentCount; 272 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 273 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 274 }; 275 276 const VkPipelineShaderStageCreateInfo pShaderStages[] = 277 { 278 { 279 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 280 DE_NULL, // const void* pNext; 281 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 282 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 283 vertexModule, // VkShaderModule module; 284 "main", // const char* pName; 285 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 286 }, 287 { 288 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 289 DE_NULL, // const void* pNext; 290 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 291 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 292 fragmentModule, // VkShaderModule module; 293 "main", // const char* pName; 294 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 295 }, 296 { 297 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 298 DE_NULL, // const void* pNext; 299 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 300 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBits stage; 301 tessellationControlModule, // VkShaderModule module; 302 "main", // const char* pName; 303 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 304 }, 305 { 306 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 307 DE_NULL, // const void* pNext; 308 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 309 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, // VkShaderStageFlagBits stage; 310 tessellationEvaluationModule, // VkShaderModule module; 311 "main", // const char* pName; 312 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 313 }, 314 }; 315 316 const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo = 317 { 318 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType; 319 DE_NULL, // const void* pNext; 320 (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags; 321 3, // uint32_t patchControlPoints; 322 }; 323 324 VkGraphicsPipelineCreateInfo graphicsPipelineInfo 325 { 326 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 327 DE_NULL, // const void* pNext; 328 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 329 useTessellationShaders ? deUint32(4) : deUint32(2), // deUint32 stageCount; 330 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 331 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 332 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 333 useTessellationShaders ? &pipelineTessellationStateInfo : DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 334 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; 335 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 336 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 337 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 338 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 339 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 340 pipelineLayout, // VkPipelineLayout layout; 341 renderPass, // VkRenderPass renderPass; 342 0u, // deUint32 subpass; 343 DE_NULL, // VkPipeline basePipelineHandle; 344 0, // deInt32 basePipelineIndex; 345 }; 346 347#ifndef CTS_USES_VULKANSC 348 VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM; 349 VkPipelineRenderingCreateInfoKHR renderingCreateInfo 350 { 351 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, 352 DE_NULL, 353 0u, 354 1u, 355 &colorAttachmentFormat, 356 VK_FORMAT_UNDEFINED, 357 VK_FORMAT_UNDEFINED 358 }; 359 360 // when pipeline is created without render pass we are using dynamic rendering 361 if (renderPass == DE_NULL) 362 graphicsPipelineInfo.pNext = &renderingCreateInfo; 363#endif // CTS_USES_VULKANSC 364 365 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); 366} 367 368std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize) 369{ 370 const int numCols = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells))); 371 const int numRows = deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols)); 372 const int rectWidth = renderSize.x() / numCols; 373 const int rectHeight = renderSize.y() / numRows; 374 375 std::vector<UVec4> cells; 376 cells.reserve(numCells); 377 378 int x = 0; 379 int y = 0; 380 381 for (int cellNdx = 0; cellNdx < numCells; ++cellNdx) 382 { 383 const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0); 384 if (nextRow) 385 { 386 x = 0; 387 y += rectHeight; 388 } 389 390 cells.push_back(UVec4(x, y, rectWidth, rectHeight)); 391 392 x += rectWidth; 393 } 394 395 return cells; 396} 397 398std::vector<Vec4> generateColors (const int numColors) 399{ 400 const Vec4 colors[] = 401 { 402 Vec4(0.18f, 0.42f, 0.17f, 1.0f), 403 Vec4(0.29f, 0.62f, 0.28f, 1.0f), 404 Vec4(0.59f, 0.84f, 0.44f, 1.0f), 405 Vec4(0.96f, 0.95f, 0.72f, 1.0f), 406 Vec4(0.94f, 0.55f, 0.39f, 1.0f), 407 Vec4(0.82f, 0.19f, 0.12f, 1.0f), 408 Vec4(0.46f, 0.15f, 0.26f, 1.0f), 409 Vec4(0.24f, 0.14f, 0.24f, 1.0f), 410 Vec4(0.49f, 0.31f, 0.26f, 1.0f), 411 Vec4(0.78f, 0.52f, 0.33f, 1.0f), 412 Vec4(0.94f, 0.82f, 0.31f, 1.0f), 413 Vec4(0.98f, 0.65f, 0.30f, 1.0f), 414 Vec4(0.22f, 0.65f, 0.53f, 1.0f), 415 Vec4(0.67f, 0.81f, 0.91f, 1.0f), 416 Vec4(0.43f, 0.44f, 0.75f, 1.0f), 417 Vec4(0.26f, 0.24f, 0.48f, 1.0f), 418 }; 419 420 DE_ASSERT(numColors <= DE_LENGTH_OF_ARRAY(colors)); 421 422 return std::vector<Vec4>(colors, colors + numColors); 423} 424 425//! Renders a colorful grid of rectangles. 426tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format, 427 const UVec2& renderSize, 428 const Vec4& clearColor, 429 const std::vector<UVec4>& cells, 430 const std::vector<Vec4>& cellColors) 431{ 432 DE_ASSERT(cells.size() == cellColors.size()); 433 434 tcu::TextureLevel image(format, renderSize.x(), renderSize.y()); 435 tcu::clear(image.getAccess(), clearColor); 436 437 for (std::size_t i = 0; i < cells.size(); ++i) 438 { 439 const UVec4& cell = cells[i]; 440 tcu::clear( 441 tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()), 442 cellColors[i]); 443 } 444 445 return image; 446} 447 448void initVertexTestPrograms (SourceCollections& programCollection, const TestParams) 449{ 450 // Vertex shader 451 { 452 std::ostringstream src; 453 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 454 << "#extension GL_ARB_shader_viewport_layer_array : require\n" 455 << "\n" 456 << "layout(location = 0) in vec4 in_position;\n" 457 << "layout(location = 1) in vec4 in_color;\n" 458 << "layout(location = 0) out vec4 out_color;\n" 459 << "\n" 460 << "void main(void)\n" 461 << "{\n" 462 << " gl_ViewportIndex = gl_VertexIndex / 6;\n" 463 << " gl_Position = in_position;\n" 464 << " out_color = in_color;\n" 465 << "}\n"; 466 467 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 468 programCollection.glslSources.add("vert_1_2") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true); 469 } 470 471 // Fragment shader 472 { 473 std::ostringstream src; 474 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 475 << "\n" 476 << "layout(location = 0) in vec4 in_color;\n" 477 << "layout(location = 0) out vec4 out_color;\n" 478 << "\n" 479 << "void main(void)\n" 480 << "{\n" 481 << " out_color = in_color;\n" 482 << "}\n"; 483 484 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 485 } 486} 487 488void initFragmentTestPrograms (SourceCollections& programCollection, const TestParams testParams) 489{ 490 // Vertex shader. 491 { 492 std::ostringstream src; 493 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 494 << "#extension GL_ARB_shader_viewport_layer_array : require\n" 495 << "\n" 496 << "layout(location = 0) in vec4 in_position;\n" 497 << "layout(location = 1) in vec4 in_color;\n" 498 << "layout(location = 0) out vec4 out_color;\n" 499 << "\n" 500 << "void main(void)\n" 501 << "{\n" 502 << (testParams.writeFromVertex ? " gl_ViewportIndex = gl_VertexIndex / 6;\n" : "") 503 << " gl_Position = in_position;\n" 504 << " out_color = in_color;\n" 505 << "}\n"; 506 507 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 508 programCollection.glslSources.add("vert_1_2") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true); 509 } 510 511 // Fragment shader 512 { 513 // Ignore input color and choose one using the viewport index. 514 std::ostringstream src; 515 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 516 << "\n" 517 << "layout(location = 0) in vec4 in_color;\n" 518 << "layout(location = 0) out vec4 out_color;\n" 519 << "layout(set=0, binding=0) uniform Colors {\n" 520 << " vec4 color[" << testParams.numViewports << "];\n" 521 << "};\n" 522 << "\n" 523 << "void main(void)\n" 524 << "{\n" 525 << " out_color = color[gl_ViewportIndex];\n" 526 << "}\n"; 527 528 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 529 } 530} 531 532void initTessellationTestPrograms (SourceCollections& programCollection, const TestParams) 533{ 534 // Vertex shader 535 { 536 std::ostringstream src; 537 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 538 << "\n" 539 << "layout(location = 0) in vec4 in_position;\n" 540 << "layout(location = 1) in vec4 in_color;\n" 541 << "layout(location = 0) out vec4 out_color;\n" 542 << "\n" 543 << "void main(void)\n" 544 << "{\n" 545 << " gl_Position = in_position;\n" 546 << " out_color = in_color;\n" 547 << "}\n"; 548 549 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 550 programCollection.glslSources.add("vert_1_2") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true); 551 } 552 553 // Tessellation control shader 554 { 555 std::ostringstream src; 556 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 557 << "\n" 558 << "layout(vertices = 3) out;\n" 559 << "\n" 560 << "layout(location = 0) in vec4 in_color[];\n" 561 << "layout(location = 0) out vec4 out_color[];\n" 562 << "\n" 563 << "void main(void)\n" 564 << "{\n" 565 << " if (gl_InvocationID == 0) {\n" 566 << " gl_TessLevelInner[0] = 1.0;\n" 567 << " gl_TessLevelInner[1] = 1.0;\n" 568 << " gl_TessLevelOuter[0] = 1.0;\n" 569 << " gl_TessLevelOuter[1] = 1.0;\n" 570 << " gl_TessLevelOuter[2] = 1.0;\n" 571 << " gl_TessLevelOuter[3] = 1.0;\n" 572 << " }\n" 573 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 574 << " out_color[gl_InvocationID] = in_color[gl_InvocationID];\n" 575 << "}\n"; 576 577 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()); 578 } 579 580 // Tessellation evaluation shader 581 { 582 std::ostringstream src; 583 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 584 << "#extension GL_ARB_shader_viewport_layer_array : require\n" 585 << "\n" 586 << "layout(triangles, equal_spacing, cw) in;\n" 587 << "\n" 588 << "layout(location = 0) in vec4 in_color[];\n" 589 << "layout(location = 0) out vec4 out_color;\n" 590 << "\n" 591 << "void main(void)\n" 592 << "{\n" 593 << " gl_ViewportIndex = gl_PrimitiveID / 2;\n" 594 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n" 595 << " gl_in[1].gl_Position * gl_TessCoord.y +\n" 596 << " gl_in[2].gl_Position * gl_TessCoord.z;\n" 597 << "\n" 598 << " out_color = in_color[0] * gl_TessCoord.x +\n" 599 << " in_color[1] * gl_TessCoord.y +\n" 600 << " in_color[2] * gl_TessCoord.z;\n" 601 << "}\n"; 602 603 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()); 604 programCollection.glslSources.add("tese_1_2") << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true); 605 } 606 607 // Fragment shader 608 { 609 std::ostringstream src; 610 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 611 << "\n" 612 << "layout(location = 0) in vec4 in_color;\n" 613 << "layout(location = 0) out vec4 out_color;\n" 614 << "\n" 615 << "void main(void)\n" 616 << "{\n" 617 << " out_color = in_color;\n" 618 << "}\n"; 619 620 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 621 } 622} 623 624std::vector<PositionColorVertex> generateVertices (const std::vector<Vec4>& colors) 625{ 626 // Two triangles for each color (viewport). 627 std::size_t total = colors.size() * 6; 628 629 std::vector<PositionColorVertex> result; 630 result.reserve(total); 631 632 for (std::size_t i = 0; i < total; ++i) 633 { 634 Vec4 pos; 635 pos.z() = 0.0; 636 pos.w() = 1.0; 637 638 switch (i % 6) { 639 case 0: pos.xy() = Vec2(-1.0, 1.0); break; 640 case 1: pos.xy() = Vec2( 1.0, 1.0); break; 641 case 2: pos.xy() = Vec2(-1.0, -1.0); break; 642 case 3: pos.xy() = Vec2( 1.0, -1.0); break; 643 case 4: pos.xy() = Vec2( 1.0, 1.0); break; 644 case 5: pos.xy() = Vec2(-1.0, -1.0); break; 645 } 646 647 result.push_back(PositionColorVertex(pos, colors[i/6])); 648 } 649 650 return result; 651} 652 653// Renderer generates two triangles per viewport, each pair using a different color. The 654// numViewports are positioned to form a grid. 655class Renderer 656{ 657public: 658 enum Shader { 659 VERTEX, 660 TESSELLATION, 661 FRAGMENT, 662 }; 663 664 Renderer (Context& context, 665 const UVec2& renderSize, 666 const TestParams& testParams, 667 const std::vector<UVec4>& cells, 668 const VkFormat colorFormat, 669 const Vec4& clearColor, 670 const std::vector<Vec4>& colors, 671 const Shader shader) 672 : m_groupParams (testParams.groupParams) 673 , m_renderSize (renderSize) 674 , m_colorFormat (colorFormat) 675 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)) 676 , m_clearValue (makeClearValueColor(clearColor)) 677 , m_numViewports (testParams.numViewports) 678 , m_colors (colors) 679 , m_vertices (generateVertices(colors)) 680 , m_shader (shader) 681 { 682 const DeviceInterface& vk = context.getDeviceInterface(); 683 const VkDevice device = context.getDevice(); 684 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 685 Allocator& allocator = context.getDefaultAllocator(); 686 const VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices); 687 688 m_colorImage = makeImage (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)); 689 m_colorImageAlloc = bindImage (vk, device, allocator, *m_colorImage, MemoryRequirement::Any); 690 m_colorAttachment = makeImageView (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange); 691 692 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible); 693 694 { 695 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize)); 696 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory()); 697 } 698 699 if (shader == TESSELLATION) 700 { 701 m_tessellationControlModule = createShaderModule (vk, device, context.getBinaryCollection().get("tesc"), 0u); 702 m_tessellationEvaluationModule = createShaderModule (vk, device, context.getBinaryCollection().get(context.contextSupports(VK_API_VERSION_1_2) ? "tese_1_2" : "tese"), 0u); 703 } 704 705 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get(context.contextSupports(VK_API_VERSION_1_2) ? "vert_1_2" : "vert"), 0u); 706 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u); 707 708 if (!m_groupParams->useDynamicRendering) 709 { 710 m_renderPass = makeRenderPass (vk, device, m_colorFormat); 711 712 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, m_colorAttachment.get(), 713 static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y())); 714 } 715 716 if (shader == FRAGMENT) 717 { 718 vk::DescriptorSetLayoutBuilder builder; 719 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT); 720 m_descriptorSetLayout = builder.build(vk, device); 721 } 722 723 m_pipelineLayout = makePipelineLayout (vk, device, (shader == FRAGMENT ? m_descriptorSetLayout.get() : DE_NULL)); 724 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule, 725 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize, m_numViewports, cells); 726 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex); 727 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 728 m_secCmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); 729 } 730 731 void draw (Context& context, const VkBuffer colorBuffer) 732 { 733 const DeviceInterface& vk = context.getDeviceInterface(); 734 const VkDevice device = context.getDevice(); 735 const VkQueue queue = context.getUniversalQueue(); 736 const VkRect2D renderArea 737 { 738 makeOffset2D(0, 0), 739 makeExtent2D(m_renderSize.x(), m_renderSize.y()), 740 }; 741 742#ifndef CTS_USES_VULKANSC 743 if (m_groupParams->useSecondaryCmdBuffer) 744 { 745 // record secondary command buffer 746 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass) 747 { 748 beginSecondaryCmdBuffer(context, *m_secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT); 749 beginRendering(vk, *m_secCmdBuffer, *m_colorAttachment, renderArea, m_clearValue, 750 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR); 751 } 752 else 753 beginSecondaryCmdBuffer(context, *m_secCmdBuffer); 754 755 drawCommands(context, *m_secCmdBuffer); 756 757 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass) 758 endRendering(vk, *m_secCmdBuffer); 759 760 endCommandBuffer(vk, *m_secCmdBuffer); 761 762 // record primary command buffer 763 beginCommandBuffer(vk, *m_cmdBuffer, 0u); 764 765 preRenderCommands(context, *m_cmdBuffer); 766 767 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass) 768 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, m_clearValue, 769 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR); 770 771 vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer); 772 773 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass) 774 endRendering(vk, *m_cmdBuffer); 775 776 postRenderCommands(context, colorBuffer); 777 endCommandBuffer(vk, *m_cmdBuffer); 778 } 779 else if (m_groupParams->useDynamicRendering) 780 { 781 beginCommandBuffer(vk, *m_cmdBuffer); 782 783 preRenderCommands(context, *m_cmdBuffer); 784 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, m_clearValue, 785 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR); 786 drawCommands(context, *m_cmdBuffer); 787 endRendering(vk, *m_cmdBuffer); 788 postRenderCommands(context, colorBuffer); 789 790 endCommandBuffer(vk, *m_cmdBuffer); 791 } 792#endif // CTS_USES_VULKANSC 793 794 if (!m_groupParams->useDynamicRendering) 795 { 796 beginCommandBuffer(vk, *m_cmdBuffer); 797 798 preRenderCommands(context, *m_cmdBuffer); 799 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, m_clearValue); 800 drawCommands(context, *m_cmdBuffer); 801 endRenderPass(vk, *m_cmdBuffer); 802 postRenderCommands(context, colorBuffer); 803 804 endCommandBuffer(vk, *m_cmdBuffer); 805 } 806 807 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer); 808 } 809 810protected: 811 812#ifndef CTS_USES_VULKANSC 813 void beginSecondaryCmdBuffer(Context& context, VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const 814 { 815 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo 816 { 817 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType; 818 DE_NULL, // const void* pNext; 819 renderingFlags, // VkRenderingFlagsKHR flags; 820 0u, // uint32_t viewMask; 821 1u, // uint32_t colorAttachmentCount; 822 &m_colorFormat, // const VkFormat* pColorAttachmentFormats; 823 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat; 824 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat; 825 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 826 }; 827 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo); 828 829 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 830 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass) 831 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; 832 833 const VkCommandBufferBeginInfo commandBufBeginParams 834 { 835 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 836 DE_NULL, // const void* pNext; 837 usageFlags, // VkCommandBufferUsageFlags flags; 838 &bufferInheritanceInfo 839 }; 840 841 const DeviceInterface& vk = context.getDeviceInterface(); 842 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams)); 843 } 844#endif // CTS_USES_VULKANSC 845 846 void preRenderCommands(Context& context, VkCommandBuffer cmdBuffer) const 847 { 848 if (m_groupParams->useDynamicRendering) 849 { 850 const DeviceInterface& vk = context.getDeviceInterface(); 851 initialTransitionColor2DImage(vk, cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 852 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); 853 } 854 } 855 856 void postRenderCommands(Context& context, VkBuffer colorBuffer) const 857 { 858 const DeviceInterface& vk = context.getDeviceInterface(); 859 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y())); 860 } 861 862 void drawCommands(Context& context, VkCommandBuffer cmdBuffer) 863 { 864 const DeviceInterface& vk = context.getDeviceInterface(); 865 const VkDevice device = context.getDevice(); 866 Allocator& allocator = context.getDefaultAllocator(); 867 const VkBuffer vertexBuffer = m_vertexBuffer->object(); 868 const VkDeviceSize vertexBufferOffset = 0ull; 869 870 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline); 871 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset); 872 873 // Prepare colors buffer if needed. 874 if (m_shader == FRAGMENT) 875 { 876 // Create buffer. 877 const auto colorsBufferSize = m_colors.size() * sizeof(decltype(m_colors)::value_type); 878 const auto colorsBufferCreateInfo = vk::makeBufferCreateInfo(static_cast<VkDeviceSize>(colorsBufferSize), vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); 879 m_colorsBuffer = SharedPtr<BufferWithMemory>(new vk::BufferWithMemory{ vk, device, allocator, colorsBufferCreateInfo, MemoryRequirement::HostVisible }); 880 881 // Copy colors and flush allocation. 882 auto& colorsBufferAlloc = m_colorsBuffer->getAllocation(); 883 deMemcpy(colorsBufferAlloc.getHostPtr(), m_colors.data(), colorsBufferSize); 884 vk::flushAlloc(vk, device, colorsBufferAlloc); 885 886 // Descriptor pool. 887 DescriptorPoolBuilder poolBuilder; 888 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u); 889 m_descriptorPool = poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 890 891 // Descriptor set. 892 m_descriptorSet = vk::makeDescriptorSet(vk, device, m_descriptorPool.get(), m_descriptorSetLayout.get()); 893 894 // Update and bind descriptor set. 895 const auto colorsBufferDescriptorInfo = vk::makeDescriptorBufferInfo(m_colorsBuffer->get(), 0ull, VK_WHOLE_SIZE); 896 vk::DescriptorSetUpdateBuilder updateBuilder; 897 updateBuilder.writeSingle(m_descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &colorsBufferDescriptorInfo); 898 updateBuilder.update(vk, device); 899 900 vk.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u, nullptr); 901 } 902 903 vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numViewports * 6), 1u, 0u, 0u); // two triangles per viewport 904 } 905 906private: 907 const SharedGroupParams m_groupParams; 908 const UVec2 m_renderSize; 909 const VkFormat m_colorFormat; 910 const VkImageSubresourceRange m_colorSubresourceRange; 911 const VkClearValue m_clearValue; 912 const int m_numViewports; 913 const std::vector<Vec4> m_colors; 914 const std::vector<PositionColorVertex> m_vertices; 915 const Shader m_shader; 916 917 Move<VkImage> m_colorImage; 918 MovePtr<Allocation> m_colorImageAlloc; 919 Move<VkImageView> m_colorAttachment; 920 SharedPtr<BufferWithMemory> m_colorsBuffer; 921 SharedPtr<Buffer> m_vertexBuffer; 922 Move<VkShaderModule> m_vertexModule; 923 Move<VkShaderModule> m_tessellationControlModule; 924 Move<VkShaderModule> m_tessellationEvaluationModule; 925 Move<VkShaderModule> m_fragmentModule; 926 Move<VkRenderPass> m_renderPass; 927 Move<VkFramebuffer> m_framebuffer; 928 Move<VkDescriptorPool> m_descriptorPool; 929 Move<VkDescriptorSet> m_descriptorSet; 930 Move<VkDescriptorSetLayout> m_descriptorSetLayout; 931 Move<VkPipelineLayout> m_pipelineLayout; 932 Move<VkPipeline> m_pipeline; 933 Move<VkCommandPool> m_cmdPool; 934 Move<VkCommandBuffer> m_cmdBuffer; 935 Move<VkCommandBuffer> m_secCmdBuffer; 936 937 // "deleted" 938 Renderer (const Renderer&); 939 Renderer& operator= (const Renderer&); 940}; 941 942tcu::TestStatus testVertexFragmentShader (Context& context, const TestParams& testParams, Renderer::Shader shader) 943{ 944 const DeviceInterface& vk = context.getDeviceInterface(); 945 const VkDevice device = context.getDevice(); 946 Allocator& allocator = context.getDefaultAllocator(); 947 948 const UVec2 renderSize (128, 128); 949 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 950 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f); 951 const std::vector<Vec4> colors = generateColors(testParams.numViewports); 952 const std::vector<UVec4> cells = generateGrid(testParams.numViewports, renderSize); 953 954 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); 955 956 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible); 957 958 // Zero buffer. 959 { 960 const Allocation alloc = colorBuffer->getBoundMemory(); 961 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize)); 962 flushAlloc(vk, device, alloc); 963 } 964 965 { 966 context.getTestContext().getLog() 967 << tcu::TestLog::Message << "Rendering a colorful grid of " << testParams.numViewports << " rectangle(s)." << tcu::TestLog::EndMessage 968 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage; 969 } 970 971 // Draw 972 { 973 Renderer renderer (context, renderSize, testParams, cells, colorFormat, clearColor, colors, shader); 974 renderer.draw(context, colorBuffer->object()); 975 } 976 977 // Log image 978 { 979 const Allocation alloc = colorBuffer->getBoundMemory(); 980 invalidateAlloc(vk, device, alloc); 981 982 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr()); 983 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors); 984 985 // Images should now match. 986 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT)) 987 TCU_FAIL("Rendered image is not correct"); 988 } 989 990 return tcu::TestStatus::pass("OK"); 991} 992 993tcu::TestStatus testVertexShader (Context& context, const TestParams testParams) 994{ 995 return testVertexFragmentShader(context, testParams, Renderer::VERTEX); 996} 997 998tcu::TestStatus testFragmentShader (Context& context, const TestParams testParams) 999{ 1000 return testVertexFragmentShader(context, testParams, Renderer::FRAGMENT); 1001} 1002 1003tcu::TestStatus testTessellationShader (Context& context, const TestParams testParams) 1004{ 1005 const DeviceInterface& vk = context.getDeviceInterface(); 1006 const VkDevice device = context.getDevice(); 1007 Allocator& allocator = context.getDefaultAllocator(); 1008 1009 const UVec2 renderSize (128, 128); 1010 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 1011 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f); 1012 const std::vector<Vec4> colors = generateColors(testParams.numViewports); 1013 const std::vector<UVec4> cells = generateGrid(testParams.numViewports, renderSize); 1014 1015 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); 1016 1017 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible); 1018 1019 // Zero buffer. 1020 { 1021 const Allocation alloc = colorBuffer->getBoundMemory(); 1022 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize)); 1023 flushAlloc(vk, device, alloc); 1024 } 1025 1026 { 1027 context.getTestContext().getLog() 1028 << tcu::TestLog::Message << "Rendering a colorful grid of " << testParams.numViewports << " rectangle(s)." << tcu::TestLog::EndMessage 1029 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage; 1030 } 1031 1032 // Draw 1033 { 1034 Renderer renderer (context, renderSize, testParams, cells, colorFormat, clearColor, colors, Renderer::TESSELLATION); 1035 renderer.draw(context, colorBuffer->object()); 1036 } 1037 1038 // Log image 1039 { 1040 const Allocation alloc = colorBuffer->getBoundMemory(); 1041 invalidateAlloc(vk, device, alloc); 1042 1043 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr()); 1044 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors); 1045 1046 // Images should now match. 1047 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT)) 1048 TCU_FAIL("Rendered image is not correct"); 1049 } 1050 1051 return tcu::TestStatus::pass("OK"); 1052} 1053 1054void checkSupport (Context& context, TestParams params) 1055{ 1056 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT); 1057 context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer"); 1058 1059 if (context.getDeviceProperties().limits.maxViewports < MIN_MAX_VIEWPORTS) 1060 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required"); 1061 1062 if (params.useTessellationShader) 1063 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER); 1064 1065 if (params.groupParams->useDynamicRendering) 1066 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering"); 1067} 1068 1069} // anonymous 1070 1071tcu::TestCaseGroup* createShaderViewportIndexTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams) 1072{ 1073 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_viewport_index")); 1074 1075 TestParams testParams 1076 { 1077 1, // int numViewports; 1078 false, // bool writeFromVertex; 1079 groupParams, // SharedGroupParams groupParams; 1080 false // bool useTessellationShader; 1081 }; 1082 1083 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports) 1084 addFunctionCaseWithPrograms(group.get(), "vertex_shader_" + de::toString(testParams.numViewports), checkSupport, initVertexTestPrograms, testVertexShader, testParams); 1085 1086 testParams.numViewports = 1; 1087 addFunctionCaseWithPrograms(group.get(), "fragment_shader_implicit", checkSupport, initFragmentTestPrograms, testFragmentShader, testParams); 1088 testParams.writeFromVertex = true; 1089 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports) 1090 addFunctionCaseWithPrograms(group.get(), "fragment_shader_" + de::toString(testParams.numViewports), checkSupport, initFragmentTestPrograms, testFragmentShader, testParams); 1091 testParams.writeFromVertex = false; 1092 1093 testParams.useTessellationShader = true; 1094 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports) 1095 addFunctionCaseWithPrograms(group.get(), "tessellation_shader_" + de::toString(testParams.numViewports), checkSupport, initTessellationTestPrograms, testTessellationShader, testParams); 1096 1097 return group.release(); 1098} 1099 1100} // Draw 1101} // vkt 1102