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 42 #include "tcuTestLog.hpp" 43 #include "tcuVector.hpp" 44 #include "tcuImageCompare.hpp" 45 #include "tcuTextureUtil.hpp" 46 47 #include "deUniquePtr.hpp" 48 #include "deMath.h" 49 50 #include <vector> 51 52 namespace vkt 53 { 54 namespace Draw 55 { 56 using namespace vk; 57 using de::UniquePtr; 58 using de::MovePtr; 59 using de::SharedPtr; 60 using tcu::Vec4; 61 using tcu::Vec2; 62 using tcu::UVec2; 63 using tcu::UVec4; 64 65 namespace 66 { 67 68 enum Constants 69 { 70 MIN_MAX_VIEWPORTS = 16, //!< Minimum number of viewports for an implementation supporting multiViewport. 71 }; 72 73 template<typename T> sizeInBytes(const std::vector<T> & vec)74 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec) 75 { 76 return vec.size() * sizeof(vec[0]); 77 } 78 makeBufferCreateInfo(const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)79 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize bufferSize, 80 const VkBufferUsageFlags usage) 81 { 82 const VkBufferCreateInfo bufferCreateInfo = 83 { 84 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 85 DE_NULL, // const void* pNext; 86 (VkBufferCreateFlags)0, // VkBufferCreateFlags flags; 87 bufferSize, // VkDeviceSize size; 88 usage, // VkBufferUsageFlags usage; 89 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 90 0u, // deUint32 queueFamilyIndexCount; 91 DE_NULL, // const deUint32* pQueueFamilyIndices; 92 }; 93 return bufferCreateInfo; 94 } 95 makePipelineLayout(const DeviceInterface & vk,const VkDevice device)96 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk, 97 const VkDevice device) 98 { 99 const VkPipelineLayoutCreateInfo info = 100 { 101 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 102 DE_NULL, // const void* pNext; 103 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags; 104 0u, // deUint32 setLayoutCount; 105 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; 106 0u, // deUint32 pushConstantRangeCount; 107 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 108 }; 109 return createPipelineLayout(vk, device, &info); 110 } 111 makeImageView(const DeviceInterface & vk,const VkDevice vkDevice,const VkImage image,const VkImageViewType viewType,const VkFormat format,const VkImageSubresourceRange subresourceRange)112 Move<VkImageView> makeImageView (const DeviceInterface& vk, 113 const VkDevice vkDevice, 114 const VkImage image, 115 const VkImageViewType viewType, 116 const VkFormat format, 117 const VkImageSubresourceRange subresourceRange) 118 { 119 const VkImageViewCreateInfo imageViewParams = 120 { 121 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 122 DE_NULL, // const void* pNext; 123 (VkImageViewCreateFlags)0, // VkImageViewCreateFlags flags; 124 image, // VkImage image; 125 viewType, // VkImageViewType viewType; 126 format, // VkFormat format; 127 makeComponentMappingRGBA(), // VkComponentMapping components; 128 subresourceRange, // VkImageSubresourceRange subresourceRange; 129 }; 130 return createImageView(vk, vkDevice, &imageViewParams); 131 } 132 makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const deUint32 attachmentCount,const VkImageView * pAttachments,const deUint32 width,const deUint32 height,const deUint32 layers=1u)133 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk, 134 const VkDevice device, 135 const VkRenderPass renderPass, 136 const deUint32 attachmentCount, 137 const VkImageView* pAttachments, 138 const deUint32 width, 139 const deUint32 height, 140 const deUint32 layers = 1u) 141 { 142 const VkFramebufferCreateInfo framebufferInfo = { 143 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 144 DE_NULL, // const void* pNext; 145 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags; 146 renderPass, // VkRenderPass renderPass; 147 attachmentCount, // uint32_t attachmentCount; 148 pAttachments, // const VkImageView* pAttachments; 149 width, // uint32_t width; 150 height, // uint32_t height; 151 layers, // uint32_t layers; 152 }; 153 154 return createFramebuffer(vk, device, &framebufferInfo); 155 } 156 bindImage(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkImage image,const MemoryRequirement requirement)157 MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement) 158 { 159 MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement); 160 VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset())); 161 return alloc; 162 } 163 makeImage(const vk::DeviceInterface & vk,const vk::VkDevice device,const vk::VkImageCreateInfo & createInfo)164 inline vk::Move<vk::VkImage> makeImage (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkImageCreateInfo& createInfo) 165 { 166 return createImage(vk, device, &createInfo); 167 } 168 makeImageCreateInfo(const VkFormat format,const UVec2 & size,VkImageUsageFlags usage)169 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, VkImageUsageFlags usage) 170 { 171 const VkImageCreateInfo imageParams = 172 { 173 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 174 DE_NULL, // const void* pNext; 175 (VkImageCreateFlags)0, // VkImageCreateFlags flags; 176 VK_IMAGE_TYPE_2D, // VkImageType imageType; 177 format, // VkFormat format; 178 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 179 1u, // deUint32 mipLevels; 180 1u, // deUint32 arrayLayers; 181 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 182 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 183 usage, // VkImageUsageFlags usage; 184 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 185 0u, // deUint32 queueFamilyIndexCount; 186 DE_NULL, // const deUint32* pQueueFamilyIndices; 187 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 188 }; 189 return imageParams; 190 } 191 makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule tessellationControlModule,const VkShaderModule tessellationEvaluationModule,const VkShaderModule fragmentModule,const UVec2 renderSize,const int numViewports,const std::vector<UVec4> cells)192 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk, 193 const VkDevice device, 194 const VkPipelineLayout pipelineLayout, 195 const VkRenderPass renderPass, 196 const VkShaderModule vertexModule, 197 const VkShaderModule tessellationControlModule, 198 const VkShaderModule tessellationEvaluationModule, 199 const VkShaderModule fragmentModule, 200 const UVec2 renderSize, 201 const int numViewports, 202 const std::vector<UVec4> cells) 203 { 204 const VkVertexInputBindingDescription vertexInputBindingDescription = 205 { 206 0u, // uint32_t binding; 207 sizeof(PositionColorVertex), // uint32_t stride; 208 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 209 }; 210 211 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = 212 { 213 { 214 0u, // uint32_t location; 215 0u, // uint32_t binding; 216 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 217 0u, // uint32_t offset; 218 }, 219 { 220 1u, // uint32_t location; 221 0u, // uint32_t binding; 222 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 223 sizeof(Vec4), // uint32_t offset; 224 }, 225 }; 226 227 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 228 { 229 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 230 DE_NULL, // const void* pNext; 231 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 232 1u, // uint32_t vertexBindingDescriptionCount; 233 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 234 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount; 235 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 236 }; 237 238 const bool useTessellationShaders = (tessellationControlModule != DE_NULL) && (tessellationEvaluationModule != DE_NULL); 239 240 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = 241 { 242 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 243 DE_NULL, // const void* pNext; 244 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 245 useTessellationShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology; 246 VK_FALSE, // VkBool32 primitiveRestartEnable; 247 }; 248 249 DE_ASSERT(numViewports == static_cast<int>(cells.size())); 250 251 std::vector<VkViewport> viewports; 252 viewports.reserve(numViewports); 253 254 std::vector<VkRect2D> rectScissors; 255 rectScissors.reserve(numViewports); 256 257 for (std::vector<UVec4>::const_iterator it = cells.begin(); it != cells.end(); ++it) { 258 const VkViewport viewport = makeViewport(float(it->x()), float(it->y()), float(it->z()), float(it->w()), 0.0f, 1.0f); 259 viewports.push_back(viewport); 260 const VkRect2D rect = makeRect2D(renderSize); 261 rectScissors.push_back(rect); 262 } 263 264 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = 265 { 266 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 267 DE_NULL, // const void* pNext; 268 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; 269 static_cast<deUint32>(numViewports), // uint32_t viewportCount; 270 &viewports[0], // const VkViewport* pViewports; 271 static_cast<deUint32>(numViewports), // uint32_t scissorCount; 272 &rectScissors[0], // const VkRect2D* pScissors; 273 }; 274 275 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = 276 { 277 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 278 DE_NULL, // const void* pNext; 279 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 280 VK_FALSE, // VkBool32 depthClampEnable; 281 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 282 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 283 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 284 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 285 VK_FALSE, // VkBool32 depthBiasEnable; 286 0.0f, // float depthBiasConstantFactor; 287 0.0f, // float depthBiasClamp; 288 0.0f, // float depthBiasSlopeFactor; 289 1.0f, // float lineWidth; 290 }; 291 292 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 293 { 294 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 295 DE_NULL, // const void* pNext; 296 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 297 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 298 VK_FALSE, // VkBool32 sampleShadingEnable; 299 0.0f, // float minSampleShading; 300 DE_NULL, // const VkSampleMask* pSampleMask; 301 VK_FALSE, // VkBool32 alphaToCoverageEnable; 302 VK_FALSE // VkBool32 alphaToOneEnable; 303 }; 304 305 const VkStencilOpState stencilOpState = makeStencilOpState( 306 VK_STENCIL_OP_KEEP, // stencil fail 307 VK_STENCIL_OP_KEEP, // depth & stencil pass 308 VK_STENCIL_OP_KEEP, // depth only fail 309 VK_COMPARE_OP_ALWAYS, // compare op 310 0u, // compare mask 311 0u, // write mask 312 0u); // reference 313 314 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 315 { 316 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 317 DE_NULL, // const void* pNext; 318 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 319 VK_FALSE, // VkBool32 depthTestEnable; 320 VK_FALSE, // VkBool32 depthWriteEnable; 321 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 322 VK_FALSE, // VkBool32 depthBoundsTestEnable; 323 VK_FALSE, // VkBool32 stencilTestEnable; 324 stencilOpState, // VkStencilOpState front; 325 stencilOpState, // VkStencilOpState back; 326 0.0f, // float minDepthBounds; 327 1.0f, // float maxDepthBounds; 328 }; 329 330 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 331 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 332 { 333 VK_FALSE, // VkBool32 blendEnable; 334 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 335 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 336 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 337 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 338 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 339 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 340 colorComponentsAll, // VkColorComponentFlags colorWriteMask; 341 }; 342 343 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 344 { 345 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 346 DE_NULL, // const void* pNext; 347 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 348 VK_FALSE, // VkBool32 logicOpEnable; 349 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 350 1u, // deUint32 attachmentCount; 351 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 352 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 353 }; 354 355 const VkPipelineShaderStageCreateInfo pShaderStages[] = 356 { 357 { 358 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 359 DE_NULL, // const void* pNext; 360 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 361 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 362 vertexModule, // VkShaderModule module; 363 "main", // const char* pName; 364 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 365 }, 366 { 367 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 368 DE_NULL, // const void* pNext; 369 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 370 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 371 fragmentModule, // VkShaderModule module; 372 "main", // const char* pName; 373 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 374 }, 375 { 376 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 377 DE_NULL, // const void* pNext; 378 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 379 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBits stage; 380 tessellationControlModule, // VkShaderModule module; 381 "main", // const char* pName; 382 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 383 }, 384 { 385 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 386 DE_NULL, // const void* pNext; 387 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 388 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, // VkShaderStageFlagBits stage; 389 tessellationEvaluationModule, // VkShaderModule module; 390 "main", // const char* pName; 391 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 392 }, 393 }; 394 395 const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo = 396 { 397 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType; 398 DE_NULL, // const void* pNext; 399 (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags; 400 3, // uint32_t patchControlPoints; 401 }; 402 403 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = 404 { 405 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 406 DE_NULL, // const void* pNext; 407 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 408 useTessellationShaders ? deUint32(4) : deUint32(2), // deUint32 stageCount; 409 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 410 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 411 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 412 useTessellationShaders ? &pipelineTessellationStateInfo : DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 413 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; 414 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 415 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 416 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 417 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 418 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 419 pipelineLayout, // VkPipelineLayout layout; 420 renderPass, // VkRenderPass renderPass; 421 0u, // deUint32 subpass; 422 DE_NULL, // VkPipeline basePipelineHandle; 423 0, // deInt32 basePipelineIndex; 424 }; 425 426 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); 427 } 428 generateGrid(const int numCells,const UVec2 & renderSize)429 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize) 430 { 431 const int numCols = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells))); 432 const int numRows = deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols)); 433 const int rectWidth = renderSize.x() / numCols; 434 const int rectHeight = renderSize.y() / numRows; 435 436 std::vector<UVec4> cells; 437 cells.reserve(numCells); 438 439 int x = 0; 440 int y = 0; 441 442 for (int cellNdx = 0; cellNdx < numCells; ++cellNdx) 443 { 444 const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0); 445 if (nextRow) 446 { 447 x = 0; 448 y += rectHeight; 449 } 450 451 cells.push_back(UVec4(x, y, rectWidth, rectHeight)); 452 453 x += rectWidth; 454 } 455 456 return cells; 457 } 458 generateColors(const int numColors)459 std::vector<Vec4> generateColors (const int numColors) 460 { 461 const Vec4 colors[] = 462 { 463 Vec4(0.18f, 0.42f, 0.17f, 1.0f), 464 Vec4(0.29f, 0.62f, 0.28f, 1.0f), 465 Vec4(0.59f, 0.84f, 0.44f, 1.0f), 466 Vec4(0.96f, 0.95f, 0.72f, 1.0f), 467 Vec4(0.94f, 0.55f, 0.39f, 1.0f), 468 Vec4(0.82f, 0.19f, 0.12f, 1.0f), 469 Vec4(0.46f, 0.15f, 0.26f, 1.0f), 470 Vec4(0.24f, 0.14f, 0.24f, 1.0f), 471 Vec4(0.49f, 0.31f, 0.26f, 1.0f), 472 Vec4(0.78f, 0.52f, 0.33f, 1.0f), 473 Vec4(0.94f, 0.82f, 0.31f, 1.0f), 474 Vec4(0.98f, 0.65f, 0.30f, 1.0f), 475 Vec4(0.22f, 0.65f, 0.53f, 1.0f), 476 Vec4(0.67f, 0.81f, 0.91f, 1.0f), 477 Vec4(0.43f, 0.44f, 0.75f, 1.0f), 478 Vec4(0.26f, 0.24f, 0.48f, 1.0f), 479 }; 480 481 DE_ASSERT(numColors <= DE_LENGTH_OF_ARRAY(colors)); 482 483 return std::vector<Vec4>(colors, colors + numColors); 484 } 485 486 //! Renders a colorful grid of rectangles. generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const Vec4 & clearColor,const std::vector<UVec4> & cells,const std::vector<Vec4> & cellColors)487 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format, 488 const UVec2& renderSize, 489 const Vec4& clearColor, 490 const std::vector<UVec4>& cells, 491 const std::vector<Vec4>& cellColors) 492 { 493 DE_ASSERT(cells.size() == cellColors.size()); 494 495 tcu::TextureLevel image(format, renderSize.x(), renderSize.y()); 496 tcu::clear(image.getAccess(), clearColor); 497 498 for (std::size_t i = 0; i < cells.size(); ++i) 499 { 500 const UVec4& cell = cells[i]; 501 tcu::clear( 502 tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()), 503 cellColors[i]); 504 } 505 506 return image; 507 } 508 initVertexTestPrograms(SourceCollections & programCollection,const int numViewports)509 void initVertexTestPrograms (SourceCollections& programCollection, const int numViewports) 510 { 511 DE_UNREF(numViewports); 512 513 // Vertex shader 514 { 515 std::ostringstream src; 516 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 517 << "#extension GL_ARB_shader_viewport_layer_array : require\n" 518 << "\n" 519 << "layout(location = 0) in vec4 in_position;\n" 520 << "layout(location = 1) in vec4 in_color;\n" 521 << "layout(location = 0) out vec4 out_color;\n" 522 << "\n" 523 << "void main(void)\n" 524 << "{\n" 525 << " gl_ViewportIndex = gl_VertexIndex / 6;\n" 526 << " gl_Position = in_position;\n" 527 << " out_color = in_color;\n" 528 << "}\n"; 529 530 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 531 } 532 533 // Fragment shader 534 { 535 std::ostringstream src; 536 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 537 << "\n" 538 << "layout(location = 0) in vec4 in_color;\n" 539 << "layout(location = 0) out vec4 out_color;\n" 540 << "\n" 541 << "void main(void)\n" 542 << "{\n" 543 << " out_color = in_color;\n" 544 << "}\n"; 545 546 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 547 } 548 } 549 initTessellationTestPrograms(SourceCollections & programCollection,const int numViewports)550 void initTessellationTestPrograms (SourceCollections& programCollection, const int numViewports) 551 { 552 DE_UNREF(numViewports); 553 554 // Vertex shader 555 { 556 std::ostringstream src; 557 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 558 << "\n" 559 << "layout(location = 0) in vec4 in_position;\n" 560 << "layout(location = 1) in vec4 in_color;\n" 561 << "layout(location = 0) out vec4 out_color;\n" 562 << "\n" 563 << "void main(void)\n" 564 << "{\n" 565 << " gl_Position = in_position;\n" 566 << " out_color = in_color;\n" 567 << "}\n"; 568 569 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 570 } 571 572 // Tessellation control shader 573 { 574 std::ostringstream src; 575 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 576 << "\n" 577 << "layout(vertices = 3) out;\n" 578 << "\n" 579 << "layout(location = 0) in vec4 in_color[];\n" 580 << "layout(location = 0) out vec4 out_color[];\n" 581 << "\n" 582 << "void main(void)\n" 583 << "{\n" 584 << " if (gl_InvocationID == 0) {\n" 585 << " gl_TessLevelInner[0] = 1.0;\n" 586 << " gl_TessLevelInner[1] = 1.0;\n" 587 << " gl_TessLevelOuter[0] = 1.0;\n" 588 << " gl_TessLevelOuter[1] = 1.0;\n" 589 << " gl_TessLevelOuter[2] = 1.0;\n" 590 << " gl_TessLevelOuter[3] = 1.0;\n" 591 << " }\n" 592 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 593 << " out_color[gl_InvocationID] = in_color[gl_InvocationID];\n" 594 << "}\n"; 595 596 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()); 597 } 598 599 // Tessellation evaluation shader 600 { 601 std::ostringstream src; 602 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 603 << "#extension GL_ARB_shader_viewport_layer_array : require\n" 604 << "\n" 605 << "layout(triangles, equal_spacing, cw) in;\n" 606 << "\n" 607 << "layout(location = 0) in vec4 in_color[];\n" 608 << "layout(location = 0) out vec4 out_color;\n" 609 << "\n" 610 << "void main(void)\n" 611 << "{\n" 612 << " gl_ViewportIndex = gl_PrimitiveID / 2;\n" 613 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n" 614 << " gl_in[1].gl_Position * gl_TessCoord.y +\n" 615 << " gl_in[2].gl_Position * gl_TessCoord.z;\n" 616 << "\n" 617 << " out_color = in_color[0] * gl_TessCoord.x +\n" 618 << " in_color[1] * gl_TessCoord.y +\n" 619 << " in_color[2] * gl_TessCoord.z;\n" 620 << "}\n"; 621 622 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()); 623 } 624 625 // Fragment shader 626 { 627 std::ostringstream src; 628 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 629 << "\n" 630 << "layout(location = 0) in vec4 in_color;\n" 631 << "layout(location = 0) out vec4 out_color;\n" 632 << "\n" 633 << "void main(void)\n" 634 << "{\n" 635 << " out_color = in_color;\n" 636 << "}\n"; 637 638 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 639 } 640 } 641 generateVertices(const std::vector<Vec4> & colors)642 std::vector<PositionColorVertex> generateVertices (const std::vector<Vec4>& colors) 643 { 644 // Two triangles for each color (viewport). 645 std::size_t total = colors.size() * 6; 646 647 std::vector<PositionColorVertex> result; 648 result.reserve(total); 649 650 for (std::size_t i = 0; i < total; ++i) 651 { 652 Vec4 pos; 653 pos.z() = 0.0; 654 pos.w() = 1.0; 655 656 switch (i % 6) { 657 case 0: pos.xy() = Vec2(-1.0, 1.0); break; 658 case 1: pos.xy() = Vec2( 1.0, 1.0); break; 659 case 2: pos.xy() = Vec2(-1.0, -1.0); break; 660 case 3: pos.xy() = Vec2( 1.0, -1.0); break; 661 case 4: pos.xy() = Vec2( 1.0, 1.0); break; 662 case 5: pos.xy() = Vec2(-1.0, -1.0); break; 663 } 664 665 result.push_back(PositionColorVertex(pos, colors[i/6])); 666 } 667 668 return result; 669 } 670 671 // Renderer generates two triangles per viewport, each pair using a different color. The 672 // numViewports are positioned to form a grid. 673 class Renderer 674 { 675 public: 676 enum Shader { 677 VERTEX, 678 TESSELLATION, 679 }; 680 Renderer(Context & context,const UVec2 & renderSize,const int numViewports,const std::vector<UVec4> & cells,const VkFormat colorFormat,const Vec4 & clearColor,const std::vector<Vec4> & colors,const Shader shader)681 Renderer (Context& context, 682 const UVec2& renderSize, 683 const int numViewports, 684 const std::vector<UVec4>& cells, 685 const VkFormat colorFormat, 686 const Vec4& clearColor, 687 const std::vector<Vec4>& colors, 688 const Shader shader) 689 : m_renderSize (renderSize) 690 , m_colorFormat (colorFormat) 691 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)) 692 , m_clearColor (clearColor) 693 , m_numViewports (numViewports) 694 , m_vertices (generateVertices(colors)) 695 { 696 const DeviceInterface& vk = context.getDeviceInterface(); 697 const VkDevice device = context.getDevice(); 698 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 699 Allocator& allocator = context.getDefaultAllocator(); 700 const VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices); 701 702 m_colorImage = makeImage (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)); 703 m_colorImageAlloc = bindImage (vk, device, allocator, *m_colorImage, MemoryRequirement::Any); 704 m_colorAttachment = makeImageView (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange); 705 706 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible); 707 708 { 709 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize)); 710 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory()); 711 } 712 713 if (shader == TESSELLATION) 714 { 715 m_tessellationControlModule = createShaderModule (vk, device, context.getBinaryCollection().get("tesc"), 0u); 716 m_tessellationEvaluationModule = createShaderModule (vk, device, context.getBinaryCollection().get("tese"), 0u); 717 } 718 719 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u); 720 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u); 721 m_renderPass = makeRenderPass (vk, device, m_colorFormat); 722 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, 1u, &m_colorAttachment.get(), 723 static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y())); 724 m_pipelineLayout = makePipelineLayout (vk, device); 725 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule, 726 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize, m_numViewports, cells); 727 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex); 728 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 729 } 730 draw(Context & context,const VkBuffer colorBuffer) const731 void draw (Context& context, const VkBuffer colorBuffer) const 732 { 733 const DeviceInterface& vk = context.getDeviceInterface(); 734 const VkDevice device = context.getDevice(); 735 const VkQueue queue = context.getUniversalQueue(); 736 737 beginCommandBuffer(vk, *m_cmdBuffer); 738 739 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), m_clearColor); 740 741 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline); 742 { 743 const VkBuffer vertexBuffer = m_vertexBuffer->object(); 744 const VkDeviceSize vertexBufferOffset = 0ull; 745 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset); 746 } 747 vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_numViewports * 6), 1u, 0u, 0u); // two triangles per viewport 748 endRenderPass(vk, *m_cmdBuffer); 749 750 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y())); 751 752 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer)); 753 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer); 754 } 755 756 private: 757 const UVec2 m_renderSize; 758 const VkFormat m_colorFormat; 759 const VkImageSubresourceRange m_colorSubresourceRange; 760 const Vec4 m_clearColor; 761 const int m_numViewports; 762 const std::vector<PositionColorVertex> m_vertices; 763 764 Move<VkImage> m_colorImage; 765 MovePtr<Allocation> m_colorImageAlloc; 766 Move<VkImageView> m_colorAttachment; 767 SharedPtr<Buffer> m_vertexBuffer; 768 Move<VkShaderModule> m_vertexModule; 769 Move<VkShaderModule> m_tessellationControlModule; 770 Move<VkShaderModule> m_tessellationEvaluationModule; 771 Move<VkShaderModule> m_fragmentModule; 772 Move<VkRenderPass> m_renderPass; 773 Move<VkFramebuffer> m_framebuffer; 774 Move<VkPipelineLayout> m_pipelineLayout; 775 Move<VkPipeline> m_pipeline; 776 Move<VkCommandPool> m_cmdPool; 777 Move<VkCommandBuffer> m_cmdBuffer; 778 779 // "deleted" 780 Renderer (const Renderer&); 781 Renderer& operator= (const Renderer&); 782 }; 783 requireShaderViewportIndexLayer(const Context & context)784 void requireShaderViewportIndexLayer (const Context& context) 785 { 786 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice()); 787 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits; 788 789 if (!features.multiViewport) 790 TCU_THROW(NotSupportedError, "Required feature is not supported: multiViewport"); 791 792 if (limits.maxViewports < MIN_MAX_VIEWPORTS) 793 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required"); 794 795 const std::vector<std::string>& extensions = context.getDeviceExtensions(); 796 if (!isDeviceExtensionSupported(context.getUsedApiVersion(), extensions, "VK_EXT_shader_viewport_index_layer")) 797 TCU_THROW(NotSupportedError, "Extension VK_EXT_shader_viewport_index_layer not supported"); 798 799 } 800 testVertexShader(Context & context,const int numViewports)801 tcu::TestStatus testVertexShader (Context& context, const int numViewports) 802 { 803 requireShaderViewportIndexLayer(context); 804 805 const DeviceInterface& vk = context.getDeviceInterface(); 806 const VkDevice device = context.getDevice(); 807 Allocator& allocator = context.getDefaultAllocator(); 808 809 const UVec2 renderSize (128, 128); 810 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 811 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f); 812 const std::vector<Vec4> colors = generateColors(numViewports); 813 const std::vector<UVec4> cells = generateGrid(numViewports, renderSize); 814 815 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); 816 817 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible); 818 819 // Zero buffer. 820 { 821 const Allocation alloc = colorBuffer->getBoundMemory(); 822 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize)); 823 flushAlloc(vk, device, alloc); 824 } 825 826 { 827 context.getTestContext().getLog() 828 << tcu::TestLog::Message << "Rendering a colorful grid of " << numViewports << " rectangle(s)." << tcu::TestLog::EndMessage 829 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage; 830 } 831 832 // Draw 833 { 834 const Renderer renderer (context, renderSize, numViewports, cells, colorFormat, clearColor, colors, Renderer::VERTEX); 835 renderer.draw(context, colorBuffer->object()); 836 } 837 838 // Log image 839 { 840 const Allocation alloc = colorBuffer->getBoundMemory(); 841 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), 0ull, colorBufferSize); 842 843 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr()); 844 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors); 845 846 // Images should now match. 847 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT)) 848 TCU_FAIL("Rendered image is not correct"); 849 } 850 851 return tcu::TestStatus::pass("OK"); 852 } 853 testTessellationShader(Context & context,const int numViewports)854 tcu::TestStatus testTessellationShader (Context& context, const int numViewports) 855 { 856 requireShaderViewportIndexLayer(context); 857 858 const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures(); 859 if (!features.tessellationShader) 860 TCU_THROW(NotSupportedError, "Required feature is not supported: tessellationShader"); 861 862 const DeviceInterface& vk = context.getDeviceInterface(); 863 const VkDevice device = context.getDevice(); 864 Allocator& allocator = context.getDefaultAllocator(); 865 866 const UVec2 renderSize (128, 128); 867 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 868 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f); 869 const std::vector<Vec4> colors = generateColors(numViewports); 870 const std::vector<UVec4> cells = generateGrid(numViewports, renderSize); 871 872 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); 873 874 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible); 875 876 // Zero buffer. 877 { 878 const Allocation alloc = colorBuffer->getBoundMemory(); 879 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize)); 880 flushAlloc(vk, device, alloc); 881 } 882 883 { 884 context.getTestContext().getLog() 885 << tcu::TestLog::Message << "Rendering a colorful grid of " << numViewports << " rectangle(s)." << tcu::TestLog::EndMessage 886 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage; 887 } 888 889 // Draw 890 { 891 const Renderer renderer (context, renderSize, numViewports, cells, colorFormat, clearColor, colors, Renderer::TESSELLATION); 892 renderer.draw(context, colorBuffer->object()); 893 } 894 895 // Log image 896 { 897 const Allocation alloc = colorBuffer->getBoundMemory(); 898 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), 0ull, colorBufferSize); 899 900 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr()); 901 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors); 902 903 // Images should now match. 904 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT)) 905 TCU_FAIL("Rendered image is not correct"); 906 } 907 908 return tcu::TestStatus::pass("OK"); 909 } 910 911 912 } // anonymous 913 createShaderViewportIndexTests(tcu::TestContext & testCtx)914 tcu::TestCaseGroup* createShaderViewportIndexTests (tcu::TestContext& testCtx) 915 { 916 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_viewport_index", "")); 917 918 for (int numViewports = 1; numViewports <= MIN_MAX_VIEWPORTS; ++numViewports) 919 addFunctionCaseWithPrograms(group.get(), "vertex_shader_" + de::toString(numViewports), "", initVertexTestPrograms, testVertexShader, numViewports); 920 921 for (int numViewports = 1; numViewports <= MIN_MAX_VIEWPORTS; ++numViewports) 922 addFunctionCaseWithPrograms(group.get(), "tessellation_shader_" + de::toString(numViewports), "", initTessellationTestPrograms, testTessellationShader, numViewports); 923 924 return group.release(); 925 } 926 927 } // Draw 928 } // vkt 929