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