1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2014 The Android Open Source Project 6 * Copyright (c) 2016 The Khronos Group Inc. 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 Tessellation Utilities 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktTessellationUtil.hpp" 26 #include "vkTypeUtil.hpp" 27 #include "deMath.h" 28 29 namespace vkt 30 { 31 namespace tessellation 32 { 33 34 using namespace vk; 35 36 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize bufferSize, 37 const VkBufferUsageFlags usage) 38 { 39 const VkBufferCreateInfo bufferCreateInfo = 40 { 41 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 42 DE_NULL, // const void* pNext; 43 (VkBufferCreateFlags)0, // VkBufferCreateFlags flags; 44 bufferSize, // VkDeviceSize size; 45 usage, // VkBufferUsageFlags usage; 46 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 47 0u, // deUint32 queueFamilyIndexCount; 48 DE_NULL, // const deUint32* pQueueFamilyIndices; 49 }; 50 return bufferCreateInfo; 51 } 52 53 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags srcAccessMask, 54 const VkAccessFlags dstAccessMask, 55 const VkBuffer buffer, 56 const VkDeviceSize offset, 57 const VkDeviceSize bufferSizeBytes) 58 { 59 const VkBufferMemoryBarrier barrier = 60 { 61 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 62 DE_NULL, // const void* pNext; 63 srcAccessMask, // VkAccessFlags srcAccessMask; 64 dstAccessMask, // VkAccessFlags dstAccessMask; 65 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 66 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 67 buffer, // VkBuffer buffer; 68 offset, // VkDeviceSize offset; 69 bufferSizeBytes, // VkDeviceSize size; 70 }; 71 return barrier; 72 } 73 74 VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask, 75 const VkAccessFlags dstAccessMask, 76 const VkImageLayout oldLayout, 77 const VkImageLayout newLayout, 78 const VkImage image, 79 const VkImageSubresourceRange subresourceRange) 80 { 81 const VkImageMemoryBarrier barrier = 82 { 83 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 84 DE_NULL, // const void* pNext; 85 srcAccessMask, // VkAccessFlags outputMask; 86 dstAccessMask, // VkAccessFlags inputMask; 87 oldLayout, // VkImageLayout oldLayout; 88 newLayout, // VkImageLayout newLayout; 89 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 90 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 91 image, // VkImage image; 92 subresourceRange, // VkImageSubresourceRange subresourceRange; 93 }; 94 return barrier; 95 } 96 97 Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex) 98 { 99 const VkCommandPoolCreateInfo info = 100 { 101 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; 102 DE_NULL, // const void* pNext; 103 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags; 104 queueFamilyIndex, // deUint32 queueFamilyIndex; 105 }; 106 return createCommandPool(vk, device, &info); 107 } 108 109 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool) 110 { 111 const VkCommandBufferAllocateInfo info = 112 { 113 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; 114 DE_NULL, // const void* pNext; 115 commandPool, // VkCommandPool commandPool; 116 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level; 117 1u, // deUint32 commandBufferCount; 118 }; 119 return allocateCommandBuffer(vk, device, &info); 120 } 121 122 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface& vk, 123 const VkDevice device, 124 const VkDescriptorPool descriptorPool, 125 const VkDescriptorSetLayout setLayout) 126 { 127 const VkDescriptorSetAllocateInfo info = 128 { 129 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType; 130 DE_NULL, // const void* pNext; 131 descriptorPool, // VkDescriptorPool descriptorPool; 132 1u, // deUint32 descriptorSetCount; 133 &setLayout, // const VkDescriptorSetLayout* pSetLayouts; 134 }; 135 return allocateDescriptorSet(vk, device, &info); 136 } 137 138 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk, 139 const VkDevice device, 140 const VkDescriptorSetLayout descriptorSetLayout) 141 { 142 const VkPipelineLayoutCreateInfo info = 143 { 144 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 145 DE_NULL, // const void* pNext; 146 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags; 147 1u, // deUint32 setLayoutCount; 148 &descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts; 149 0u, // deUint32 pushConstantRangeCount; 150 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 151 }; 152 return createPipelineLayout(vk, device, &info); 153 } 154 155 Move<VkPipelineLayout> makePipelineLayoutWithoutDescriptors (const DeviceInterface& vk, 156 const VkDevice device) 157 { 158 const VkPipelineLayoutCreateInfo info = 159 { 160 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 161 DE_NULL, // const void* pNext; 162 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags; 163 0u, // deUint32 setLayoutCount; 164 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; 165 0u, // deUint32 pushConstantRangeCount; 166 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 167 }; 168 return createPipelineLayout(vk, device, &info); 169 } 170 171 Move<VkPipeline> makeComputePipeline (const DeviceInterface& vk, 172 const VkDevice device, 173 const VkPipelineLayout pipelineLayout, 174 const VkShaderModule shaderModule, 175 const VkSpecializationInfo* specInfo) 176 { 177 const VkPipelineShaderStageCreateInfo shaderStageInfo = 178 { 179 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 180 DE_NULL, // const void* pNext; 181 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 182 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage; 183 shaderModule, // VkShaderModule module; 184 "main", // const char* pName; 185 specInfo, // const VkSpecializationInfo* pSpecializationInfo; 186 }; 187 const VkComputePipelineCreateInfo pipelineInfo = 188 { 189 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType; 190 DE_NULL, // const void* pNext; 191 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 192 shaderStageInfo, // VkPipelineShaderStageCreateInfo stage; 193 pipelineLayout, // VkPipelineLayout layout; 194 DE_NULL, // VkPipeline basePipelineHandle; 195 0, // deInt32 basePipelineIndex; 196 }; 197 return createComputePipeline(vk, device, DE_NULL , &pipelineInfo); 198 } 199 200 VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage, const deUint32 numArrayLayers) 201 { 202 const VkImageCreateInfo imageInfo = 203 { 204 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 205 DE_NULL, // const void* pNext; 206 (VkImageCreateFlags)0, // VkImageCreateFlags flags; 207 VK_IMAGE_TYPE_2D, // VkImageType imageType; 208 format, // VkFormat format; 209 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 210 1u, // uint32_t mipLevels; 211 numArrayLayers, // uint32_t arrayLayers; 212 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 213 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 214 usage, // VkImageUsageFlags usage; 215 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 216 0u, // uint32_t queueFamilyIndexCount; 217 DE_NULL, // const uint32_t* pQueueFamilyIndices; 218 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 219 }; 220 return imageInfo; 221 } 222 223 Move<VkImageView> makeImageView (const DeviceInterface& vk, 224 const VkDevice vkDevice, 225 const VkImage image, 226 const VkImageViewType viewType, 227 const VkFormat format, 228 const VkImageSubresourceRange subresourceRange) 229 { 230 const VkImageViewCreateInfo imageViewParams = 231 { 232 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 233 DE_NULL, // const void* pNext; 234 (VkImageViewCreateFlags)0, // VkImageViewCreateFlags flags; 235 image, // VkImage image; 236 viewType, // VkImageViewType viewType; 237 format, // VkFormat format; 238 makeComponentMappingRGBA(), // VkComponentMapping components; 239 subresourceRange, // VkImageSubresourceRange subresourceRange; 240 }; 241 return createImageView(vk, vkDevice, &imageViewParams); 242 } 243 244 VkBufferImageCopy makeBufferImageCopy (const VkExtent3D extent, 245 const VkImageSubresourceLayers subresourceLayers) 246 { 247 const VkBufferImageCopy copyParams = 248 { 249 0ull, // VkDeviceSize bufferOffset; 250 0u, // deUint32 bufferRowLength; 251 0u, // deUint32 bufferImageHeight; 252 subresourceLayers, // VkImageSubresourceLayers imageSubresource; 253 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 254 extent, // VkExtent3D imageExtent; 255 }; 256 return copyParams; 257 } 258 259 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer) 260 { 261 const VkCommandBufferBeginInfo info = 262 { 263 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 264 DE_NULL, // const void* pNext; 265 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags; 266 DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo; 267 }; 268 VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info)); 269 } 270 271 void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer) 272 { 273 VK_CHECK(vk.endCommandBuffer(commandBuffer)); 274 } 275 276 void submitCommandsAndWait (const DeviceInterface& vk, 277 const VkDevice device, 278 const VkQueue queue, 279 const VkCommandBuffer commandBuffer) 280 { 281 const VkFenceCreateInfo fenceInfo = 282 { 283 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; 284 DE_NULL, // const void* pNext; 285 (VkFenceCreateFlags)0, // VkFenceCreateFlags flags; 286 }; 287 const Unique<VkFence> fence(createFence(vk, device, &fenceInfo)); 288 289 const VkSubmitInfo submitInfo = 290 { 291 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 292 DE_NULL, // const void* pNext; 293 0u, // uint32_t waitSemaphoreCount; 294 DE_NULL, // const VkSemaphore* pWaitSemaphores; 295 DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask; 296 1u, // uint32_t commandBufferCount; 297 &commandBuffer, // const VkCommandBuffer* pCommandBuffers; 298 0u, // uint32_t signalSemaphoreCount; 299 DE_NULL, // const VkSemaphore* pSignalSemaphores; 300 }; 301 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence)); 302 VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); 303 } 304 305 void beginRenderPass (const DeviceInterface& vk, 306 const VkCommandBuffer commandBuffer, 307 const VkRenderPass renderPass, 308 const VkFramebuffer framebuffer, 309 const VkRect2D& renderArea, 310 const tcu::Vec4& clearColor) 311 { 312 const VkClearValue clearValue = makeClearValueColor(clearColor); 313 314 const VkRenderPassBeginInfo renderPassBeginInfo = { 315 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 316 DE_NULL, // const void* pNext; 317 renderPass, // VkRenderPass renderPass; 318 framebuffer, // VkFramebuffer framebuffer; 319 renderArea, // VkRect2D renderArea; 320 1u, // uint32_t clearValueCount; 321 &clearValue, // const VkClearValue* pClearValues; 322 }; 323 324 vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 325 } 326 327 void beginRenderPassWithRasterizationDisabled (const DeviceInterface& vk, 328 const VkCommandBuffer commandBuffer, 329 const VkRenderPass renderPass, 330 const VkFramebuffer framebuffer) 331 { 332 const VkRect2D renderArea = {{ 0, 0 }, { 0, 0 }}; 333 334 const VkRenderPassBeginInfo renderPassBeginInfo = { 335 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 336 DE_NULL, // const void* pNext; 337 renderPass, // VkRenderPass renderPass; 338 framebuffer, // VkFramebuffer framebuffer; 339 renderArea, // VkRect2D renderArea; 340 0u, // uint32_t clearValueCount; 341 DE_NULL, // const VkClearValue* pClearValues; 342 }; 343 344 vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 345 } 346 347 void endRenderPass (const DeviceInterface& vk, 348 const VkCommandBuffer commandBuffer) 349 { 350 vk.cmdEndRenderPass(commandBuffer); 351 } 352 353 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, 354 const VkDevice device, 355 const VkFormat colorFormat) 356 { 357 const VkAttachmentDescription colorAttachmentDescription = 358 { 359 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 360 colorFormat, // VkFormat format; 361 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 362 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 363 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 364 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 365 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 366 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; 367 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; 368 }; 369 370 const VkAttachmentReference colorAttachmentReference = 371 { 372 0u, // deUint32 attachment; 373 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 374 }; 375 376 const VkAttachmentReference depthAttachmentReference = 377 { 378 VK_ATTACHMENT_UNUSED, // deUint32 attachment; 379 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout; 380 }; 381 382 const VkSubpassDescription subpassDescription = 383 { 384 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 385 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 386 0u, // deUint32 inputAttachmentCount; 387 DE_NULL, // const VkAttachmentReference* pInputAttachments; 388 1u, // deUint32 colorAttachmentCount; 389 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments; 390 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 391 &depthAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment; 392 0u, // deUint32 preserveAttachmentCount; 393 DE_NULL // const deUint32* pPreserveAttachments; 394 }; 395 396 const VkRenderPassCreateInfo renderPassInfo = 397 { 398 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 399 DE_NULL, // const void* pNext; 400 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 401 1u, // deUint32 attachmentCount; 402 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; 403 1u, // deUint32 subpassCount; 404 &subpassDescription, // const VkSubpassDescription* pSubpasses; 405 0u, // deUint32 dependencyCount; 406 DE_NULL // const VkSubpassDependency* pDependencies; 407 }; 408 409 return createRenderPass(vk, device, &renderPassInfo); 410 } 411 412 Move<VkRenderPass> makeRenderPassWithoutAttachments (const DeviceInterface& vk, 413 const VkDevice device) 414 { 415 const VkAttachmentReference unusedAttachment = 416 { 417 VK_ATTACHMENT_UNUSED, // deUint32 attachment; 418 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout; 419 }; 420 421 const VkSubpassDescription subpassDescription = 422 { 423 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 424 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 425 0u, // deUint32 inputAttachmentCount; 426 DE_NULL, // const VkAttachmentReference* pInputAttachments; 427 0u, // deUint32 colorAttachmentCount; 428 DE_NULL, // const VkAttachmentReference* pColorAttachments; 429 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 430 &unusedAttachment, // const VkAttachmentReference* pDepthStencilAttachment; 431 0u, // deUint32 preserveAttachmentCount; 432 DE_NULL // const deUint32* pPreserveAttachments; 433 }; 434 435 const VkRenderPassCreateInfo renderPassInfo = 436 { 437 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 438 DE_NULL, // const void* pNext; 439 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 440 0u, // deUint32 attachmentCount; 441 DE_NULL, // const VkAttachmentDescription* pAttachments; 442 1u, // deUint32 subpassCount; 443 &subpassDescription, // const VkSubpassDescription* pSubpasses; 444 0u, // deUint32 dependencyCount; 445 DE_NULL // const VkSubpassDependency* pDependencies; 446 }; 447 448 return createRenderPass(vk, device, &renderPassInfo); 449 } 450 451 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk, 452 const VkDevice device, 453 const VkRenderPass renderPass, 454 const VkImageView colorAttachment, 455 const deUint32 width, 456 const deUint32 height, 457 const deUint32 layers) 458 { 459 const VkFramebufferCreateInfo framebufferInfo = { 460 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 461 DE_NULL, // const void* pNext; 462 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags; 463 renderPass, // VkRenderPass renderPass; 464 1u, // uint32_t attachmentCount; 465 &colorAttachment, // const VkImageView* pAttachments; 466 width, // uint32_t width; 467 height, // uint32_t height; 468 layers, // uint32_t layers; 469 }; 470 471 return createFramebuffer(vk, device, &framebufferInfo); 472 } 473 474 Move<VkFramebuffer> makeFramebufferWithoutAttachments (const DeviceInterface& vk, 475 const VkDevice device, 476 const VkRenderPass renderPass) 477 { 478 const VkFramebufferCreateInfo framebufferInfo = { 479 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 480 DE_NULL, // const void* pNext; 481 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags; 482 renderPass, // VkRenderPass renderPass; 483 0u, // uint32_t attachmentCount; 484 DE_NULL, // const VkImageView* pAttachments; 485 1u, // uint32_t width; 486 1u, // uint32_t height; 487 1u, // uint32_t layers; 488 }; 489 490 return createFramebuffer(vk, device, &framebufferInfo); 491 } 492 493 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface& vk, 494 const VkDevice device, 495 const VkShaderStageFlagBits stage, 496 const ProgramBinary& binary, 497 const VkSpecializationInfo* specInfo) 498 { 499 VkShaderModule module; 500 switch (stage) 501 { 502 case (VK_SHADER_STAGE_VERTEX_BIT): 503 DE_ASSERT(m_vertexShaderModule.get() == DE_NULL); 504 m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); 505 module = *m_vertexShaderModule; 506 break; 507 508 case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT): 509 DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL); 510 m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); 511 module = *m_tessControlShaderModule; 512 break; 513 514 case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT): 515 DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL); 516 m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); 517 module = *m_tessEvaluationShaderModule; 518 break; 519 520 case (VK_SHADER_STAGE_GEOMETRY_BIT): 521 DE_ASSERT(m_geometryShaderModule.get() == DE_NULL); 522 m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); 523 module = *m_geometryShaderModule; 524 break; 525 526 case (VK_SHADER_STAGE_FRAGMENT_BIT): 527 DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL); 528 m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); 529 module = *m_fragmentShaderModule; 530 break; 531 532 default: 533 DE_FATAL("Invalid shader stage"); 534 return *this; 535 } 536 537 const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo = 538 { 539 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 540 DE_NULL, // const void* pNext; 541 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 542 stage, // VkShaderStageFlagBits stage; 543 module, // VkShaderModule module; 544 "main", // const char* pName; 545 specInfo, // const VkSpecializationInfo* pSpecializationInfo; 546 }; 547 548 m_shaderStageFlags |= stage; 549 m_shaderStages.push_back(pipelineShaderStageInfo); 550 551 return *this; 552 } 553 554 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride) 555 { 556 const VkVertexInputBindingDescription bindingDesc = 557 { 558 0u, // uint32_t binding; 559 stride, // uint32_t stride; 560 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 561 }; 562 const VkVertexInputAttributeDescription attributeDesc = 563 { 564 0u, // uint32_t location; 565 0u, // uint32_t binding; 566 vertexFormat, // VkFormat format; 567 0u, // uint32_t offset; 568 }; 569 570 m_vertexInputBindings.clear(); 571 m_vertexInputBindings.push_back(bindingDesc); 572 573 m_vertexInputAttributes.clear(); 574 m_vertexInputAttributes.push_back(attributeDesc); 575 576 return *this; 577 } 578 579 template<typename T> 580 inline const T* dataPointer (const std::vector<T>& vec) 581 { 582 return (vec.size() != 0 ? &vec[0] : DE_NULL); 583 } 584 585 Move<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface& vk, 586 const VkDevice device, 587 const VkPipelineLayout pipelineLayout, 588 const VkRenderPass renderPass) 589 { 590 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 591 { 592 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 593 DE_NULL, // const void* pNext; 594 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 595 static_cast<deUint32>(m_vertexInputBindings.size()), // uint32_t vertexBindingDescriptionCount; 596 dataPointer(m_vertexInputBindings), // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 597 static_cast<deUint32>(m_vertexInputAttributes.size()), // uint32_t vertexAttributeDescriptionCount; 598 dataPointer(m_vertexInputAttributes), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 599 }; 600 601 const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST 602 : m_primitiveTopology; 603 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = 604 { 605 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 606 DE_NULL, // const void* pNext; 607 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 608 topology, // VkPrimitiveTopology topology; 609 VK_FALSE, // VkBool32 primitiveRestartEnable; 610 }; 611 612 const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo = 613 { 614 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType; 615 DE_NULL, // const void* pNext; 616 (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags; 617 m_patchControlPoints, // uint32_t patchControlPoints; 618 }; 619 620 const VkViewport viewport = makeViewport( 621 0.0f, 0.0f, 622 static_cast<float>(m_renderSize.x()), static_cast<float>(m_renderSize.y()), 623 0.0f, 1.0f); 624 625 const VkRect2D scissor = { 626 makeOffset2D(0, 0), 627 makeExtent2D(m_renderSize.x(), m_renderSize.y()), 628 }; 629 630 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = 631 { 632 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 633 DE_NULL, // const void* pNext; 634 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; 635 1u, // uint32_t viewportCount; 636 &viewport, // const VkViewport* pViewports; 637 1u, // uint32_t scissorCount; 638 &scissor, // const VkRect2D* pScissors; 639 }; 640 641 const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0); 642 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = 643 { 644 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 645 DE_NULL, // const void* pNext; 646 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 647 VK_FALSE, // VkBool32 depthClampEnable; 648 isRasterizationDisabled, // VkBool32 rasterizerDiscardEnable; 649 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 650 m_cullModeFlags, // VkCullModeFlags cullMode; 651 m_frontFace, // VkFrontFace frontFace; 652 VK_FALSE, // VkBool32 depthBiasEnable; 653 0.0f, // float depthBiasConstantFactor; 654 0.0f, // float depthBiasClamp; 655 0.0f, // float depthBiasSlopeFactor; 656 1.0f, // float lineWidth; 657 }; 658 659 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 660 { 661 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 662 DE_NULL, // const void* pNext; 663 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 664 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 665 VK_FALSE, // VkBool32 sampleShadingEnable; 666 0.0f, // float minSampleShading; 667 DE_NULL, // const VkSampleMask* pSampleMask; 668 VK_FALSE, // VkBool32 alphaToCoverageEnable; 669 VK_FALSE // VkBool32 alphaToOneEnable; 670 }; 671 672 const VkStencilOpState stencilOpState = makeStencilOpState( 673 VK_STENCIL_OP_KEEP, // stencil fail 674 VK_STENCIL_OP_KEEP, // depth & stencil pass 675 VK_STENCIL_OP_KEEP, // depth only fail 676 VK_COMPARE_OP_NEVER, // compare op 677 0u, // compare mask 678 0u, // write mask 679 0u); // reference 680 681 const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 682 { 683 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 684 DE_NULL, // const void* pNext; 685 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 686 VK_FALSE, // VkBool32 depthTestEnable; 687 VK_FALSE, // VkBool32 depthWriteEnable; 688 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 689 VK_FALSE, // VkBool32 depthBoundsTestEnable; 690 VK_FALSE, // VkBool32 stencilTestEnable; 691 stencilOpState, // VkStencilOpState front; 692 stencilOpState, // VkStencilOpState back; 693 0.0f, // float minDepthBounds; 694 1.0f, // float maxDepthBounds; 695 }; 696 697 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 698 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 699 { 700 m_blendEnable, // VkBool32 blendEnable; 701 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor; 702 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor; 703 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 704 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor; 705 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor; 706 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 707 colorComponentsAll, // VkColorComponentFlags colorWriteMask; 708 }; 709 710 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 711 { 712 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 713 DE_NULL, // const void* pNext; 714 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 715 VK_FALSE, // VkBool32 logicOpEnable; 716 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 717 1u, // deUint32 attachmentCount; 718 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 719 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 720 }; 721 722 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = 723 { 724 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 725 DE_NULL, // const void* pNext; 726 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 727 static_cast<deUint32>(m_shaderStages.size()), // deUint32 stageCount; 728 &m_shaderStages[0], // const VkPipelineShaderStageCreateInfo* pStages; 729 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 730 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 731 (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo* pTessellationState; 732 (isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo), // const VkPipelineViewportStateCreateInfo* pViewportState; 733 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 734 (isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo), // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 735 (isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo), // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 736 (isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo), // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 737 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 738 pipelineLayout, // VkPipelineLayout layout; 739 renderPass, // VkRenderPass renderPass; 740 0u, // deUint32 subpass; 741 DE_NULL, // VkPipeline basePipelineHandle; 742 0, // deInt32 basePipelineIndex; 743 }; 744 745 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); 746 } 747 748 float getClampedTessLevel (const SpacingMode mode, const float tessLevel) 749 { 750 switch (mode) 751 { 752 case SPACINGMODE_EQUAL: return de::max(1.0f, tessLevel); 753 case SPACINGMODE_FRACTIONAL_ODD: return de::max(1.0f, tessLevel); 754 case SPACINGMODE_FRACTIONAL_EVEN: return de::max(2.0f, tessLevel); 755 default: 756 DE_ASSERT(false); 757 return 0.0f; 758 } 759 } 760 761 int getRoundedTessLevel (const SpacingMode mode, const float clampedTessLevel) 762 { 763 static const int minimumMaxTessGenLevel = 64; //!< Minimum maxTessellationGenerationLevel defined by the spec. 764 765 int result = (int)deFloatCeil(clampedTessLevel); 766 767 switch (mode) 768 { 769 case SPACINGMODE_EQUAL: break; 770 case SPACINGMODE_FRACTIONAL_ODD: result += 1 - result % 2; break; 771 case SPACINGMODE_FRACTIONAL_EVEN: result += result % 2; break; 772 default: 773 DE_ASSERT(false); 774 } 775 DE_ASSERT(de::inRange<int>(result, 1, minimumMaxTessGenLevel)); 776 DE_UNREF(minimumMaxTessGenLevel); 777 778 return result; 779 } 780 781 int getClampedRoundedTessLevel (const SpacingMode mode, const float tessLevel) 782 { 783 return getRoundedTessLevel(mode, getClampedTessLevel(mode, tessLevel)); 784 } 785 786 void getClampedRoundedTriangleTessLevels (const SpacingMode spacingMode, 787 const float* innerSrc, 788 const float* outerSrc, 789 int* innerDst, 790 int* outerDst) 791 { 792 innerDst[0] = getClampedRoundedTessLevel(spacingMode, innerSrc[0]); 793 for (int i = 0; i < 3; i++) 794 outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]); 795 } 796 797 void getClampedRoundedQuadTessLevels (const SpacingMode spacingMode, 798 const float* innerSrc, 799 const float* outerSrc, 800 int* innerDst, 801 int* outerDst) 802 { 803 for (int i = 0; i < 2; i++) 804 innerDst[i] = getClampedRoundedTessLevel(spacingMode, innerSrc[i]); 805 for (int i = 0; i < 4; i++) 806 outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]); 807 } 808 809 void getClampedRoundedIsolineTessLevels (const SpacingMode spacingMode, 810 const float* outerSrc, 811 int* outerDst) 812 { 813 outerDst[0] = getClampedRoundedTessLevel(SPACINGMODE_EQUAL, outerSrc[0]); 814 outerDst[1] = getClampedRoundedTessLevel(spacingMode, outerSrc[1]); 815 } 816 817 int numOuterTessellationLevels (const TessPrimitiveType primType) 818 { 819 switch (primType) 820 { 821 case TESSPRIMITIVETYPE_TRIANGLES: return 3; 822 case TESSPRIMITIVETYPE_QUADS: return 4; 823 case TESSPRIMITIVETYPE_ISOLINES: return 2; 824 default: 825 DE_ASSERT(false); 826 return 0; 827 } 828 } 829 830 bool isPatchDiscarded (const TessPrimitiveType primitiveType, const float* outerLevels) 831 { 832 const int numOuterLevels = numOuterTessellationLevels(primitiveType); 833 for (int i = 0; i < numOuterLevels; i++) 834 if (outerLevels[i] <= 0.0f) 835 return true; 836 return false; 837 } 838 839 std::string getTessellationLevelsString (const TessLevels& tessLevels, const TessPrimitiveType primitiveType) 840 { 841 std::ostringstream str; 842 switch (primitiveType) 843 { 844 case TESSPRIMITIVETYPE_ISOLINES: 845 str << "inner: { }, " 846 << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << " }"; 847 break; 848 849 case TESSPRIMITIVETYPE_TRIANGLES: 850 str << "inner: { " << tessLevels.inner[0] << " }, " 851 << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << " }"; 852 break; 853 854 case TESSPRIMITIVETYPE_QUADS: 855 str << "inner: { " << tessLevels.inner[0] << ", " << tessLevels.inner[1] << " }, " 856 << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << ", " << tessLevels.outer[3] << " }"; 857 break; 858 859 default: 860 DE_ASSERT(false); 861 } 862 863 return str.str(); 864 } 865 866 //! Assumes array sizes inner[2] and outer[4]. 867 std::string getTessellationLevelsString (const float* inner, const float* outer) 868 { 869 const TessLevels tessLevels = 870 { 871 { inner[0], inner[1] }, 872 { outer[0], outer[1], outer[2], outer[3] } 873 }; 874 return getTessellationLevelsString(tessLevels, TESSPRIMITIVETYPE_QUADS); 875 } 876 877 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec 878 // (e.g. it may not exactly hold that u+v+w == 1.0f, or [uvw] + (1.0f-[uvw]) == 1.0f). 879 std::vector<tcu::Vec3> generateReferenceTriangleTessCoords (const SpacingMode spacingMode, 880 const int inner, 881 const int outer0, 882 const int outer1, 883 const int outer2) 884 { 885 std::vector<tcu::Vec3> tessCoords; 886 887 if (inner == 1) 888 { 889 if (outer0 == 1 && outer1 == 1 && outer2 == 1) 890 { 891 tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f)); 892 tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f)); 893 tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 1.0f)); 894 return tessCoords; 895 } 896 else 897 return generateReferenceTriangleTessCoords(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 898 outer0, outer1, outer2); 899 } 900 else 901 { 902 for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(tcu::Vec3( 0.0f, v, 1.0f - v)); } 903 for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(tcu::Vec3(1.0f - v, 0.0f, v)); } 904 for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(tcu::Vec3( v, 1.0f - v, 0.0f)); } 905 906 const int numInnerTriangles = inner/2; 907 for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++) 908 { 909 const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1); 910 911 if (curInnerTriangleLevel == 0) 912 tessCoords.push_back(tcu::Vec3(1.0f/3.0f)); 913 else 914 { 915 const float minUVW = (float)(2 * (innerTriangleNdx + 1)) / (float)(3 * inner); 916 const float maxUVW = 1.0f - 2.0f*minUVW; 917 const tcu::Vec3 corners[3] = 918 { 919 tcu::Vec3(maxUVW, minUVW, minUVW), 920 tcu::Vec3(minUVW, maxUVW, minUVW), 921 tcu::Vec3(minUVW, minUVW, maxUVW) 922 }; 923 924 for (int i = 0; i < curInnerTriangleLevel; i++) 925 { 926 const float f = (float)i / (float)curInnerTriangleLevel; 927 for (int j = 0; j < 3; j++) 928 tessCoords.push_back((1.0f - f)*corners[j] + f*corners[(j+1)%3]); 929 } 930 } 931 } 932 933 return tessCoords; 934 } 935 } 936 937 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec 938 // (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f). 939 std::vector<tcu::Vec3> generateReferenceQuadTessCoords (const SpacingMode spacingMode, 940 const int inner0, 941 const int inner1, 942 const int outer0, 943 const int outer1, 944 const int outer2, 945 const int outer3) 946 { 947 std::vector<tcu::Vec3> tessCoords; 948 949 if (inner0 == 1 || inner1 == 1) 950 { 951 if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1) 952 { 953 tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 0.0f)); 954 tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f)); 955 tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f)); 956 tessCoords.push_back(tcu::Vec3(1.0f, 1.0f, 0.0f)); 957 return tessCoords; 958 } 959 else 960 return generateReferenceQuadTessCoords(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 961 inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 962 outer0, outer1, outer2, outer3); 963 } 964 else 965 { 966 for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(tcu::Vec3( 0.0f, v, 0.0f)); } 967 for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(tcu::Vec3(1.0f - v, 0.0f, 0.0f)); } 968 for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(tcu::Vec3( 1.0f, 1.0f - v, 0.0f)); } 969 for (int i = 0; i < outer3; i++) { const float v = (float)i / (float)outer3; tessCoords.push_back(tcu::Vec3( v, 1.0f, 0.0f)); } 970 971 for (int innerVtxY = 0; innerVtxY < inner1-1; innerVtxY++) 972 for (int innerVtxX = 0; innerVtxX < inner0-1; innerVtxX++) 973 tessCoords.push_back(tcu::Vec3((float)(innerVtxX + 1) / (float)inner0, 974 (float)(innerVtxY + 1) / (float)inner1, 975 0.0f)); 976 977 return tessCoords; 978 } 979 } 980 981 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec 982 // (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f). 983 std::vector<tcu::Vec3> generateReferenceIsolineTessCoords (const int outer0, const int outer1) 984 { 985 std::vector<tcu::Vec3> tessCoords; 986 987 for (int y = 0; y < outer0; y++) 988 for (int x = 0; x < outer1+1; x++) 989 tessCoords.push_back(tcu::Vec3((float)x / (float)outer1, 990 (float)y / (float)outer0, 991 0.0f)); 992 993 return tessCoords; 994 } 995 996 static int referencePointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels) 997 { 998 if (isPatchDiscarded(primitiveType, outerLevels)) 999 return 0; 1000 1001 switch (primitiveType) 1002 { 1003 case TESSPRIMITIVETYPE_TRIANGLES: 1004 { 1005 int inner; 1006 int outer[3]; 1007 getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]); 1008 return static_cast<int>(generateReferenceTriangleTessCoords(spacingMode, inner, outer[0], outer[1], outer[2]).size()); 1009 } 1010 1011 case TESSPRIMITIVETYPE_QUADS: 1012 { 1013 int inner[2]; 1014 int outer[4]; 1015 getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]); 1016 return static_cast<int>(generateReferenceQuadTessCoords(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]).size()); 1017 } 1018 1019 case TESSPRIMITIVETYPE_ISOLINES: 1020 { 1021 int outer[2]; 1022 getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]); 1023 return static_cast<int>(generateReferenceIsolineTessCoords(outer[0], outer[1]).size()); 1024 } 1025 1026 default: 1027 DE_ASSERT(false); 1028 return 0; 1029 } 1030 } 1031 1032 static int referenceTriangleNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner, const int outer0, const int outer1, const int outer2) 1033 { 1034 if (inner == 1) 1035 { 1036 if (outer0 == 1 && outer1 == 1 && outer2 == 1) 1037 return 1; 1038 else 1039 return referenceTriangleNonPointModePrimitiveCount(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 1040 outer0, outer1, outer2); 1041 } 1042 else 1043 { 1044 int result = outer0 + outer1 + outer2; 1045 1046 const int numInnerTriangles = inner/2; 1047 for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++) 1048 { 1049 const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1); 1050 1051 if (curInnerTriangleLevel == 1) 1052 result += 4; 1053 else 1054 result += 2*3*curInnerTriangleLevel; 1055 } 1056 1057 return result; 1058 } 1059 } 1060 1061 static int referenceQuadNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner0, const int inner1, const int outer0, const int outer1, const int outer2, const int outer3) 1062 { 1063 if (inner0 == 1 || inner1 == 1) 1064 { 1065 if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1) 1066 return 2; 1067 else 1068 return referenceQuadNonPointModePrimitiveCount(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 1069 inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 1070 outer0, outer1, outer2, outer3); 1071 } 1072 else 1073 return 2*(inner0-2)*(inner1-2) + 2*(inner0-2) + 2*(inner1-2) + outer0+outer1+outer2+outer3; 1074 } 1075 1076 static inline int referenceIsolineNonPointModePrimitiveCount (const int outer0, const int outer1) 1077 { 1078 return outer0*outer1; 1079 } 1080 1081 static int referenceNonPointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels) 1082 { 1083 if (isPatchDiscarded(primitiveType, outerLevels)) 1084 return 0; 1085 1086 switch (primitiveType) 1087 { 1088 case TESSPRIMITIVETYPE_TRIANGLES: 1089 { 1090 int inner; 1091 int outer[3]; 1092 getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]); 1093 return referenceTriangleNonPointModePrimitiveCount(spacingMode, inner, outer[0], outer[1], outer[2]); 1094 } 1095 1096 case TESSPRIMITIVETYPE_QUADS: 1097 { 1098 int inner[2]; 1099 int outer[4]; 1100 getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]); 1101 return referenceQuadNonPointModePrimitiveCount(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]); 1102 } 1103 1104 case TESSPRIMITIVETYPE_ISOLINES: 1105 { 1106 int outer[2]; 1107 getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]); 1108 return referenceIsolineNonPointModePrimitiveCount(outer[0], outer[1]); 1109 } 1110 1111 default: 1112 DE_ASSERT(false); 1113 return 0; 1114 } 1115 } 1116 1117 int numVerticesPerPrimitive (const TessPrimitiveType primitiveType, const bool usePointMode) 1118 { 1119 if (usePointMode) 1120 return 1; 1121 1122 switch (primitiveType) 1123 { 1124 case TESSPRIMITIVETYPE_TRIANGLES: return 3; 1125 case TESSPRIMITIVETYPE_QUADS: return 3; // quads are composed of two triangles 1126 case TESSPRIMITIVETYPE_ISOLINES: return 2; 1127 default: 1128 DE_ASSERT(false); 1129 return 0; 1130 } 1131 } 1132 1133 int referencePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels) 1134 { 1135 return usePointMode ? referencePointModePrimitiveCount (primitiveType, spacingMode, innerLevels, outerLevels) 1136 : referenceNonPointModePrimitiveCount (primitiveType, spacingMode, innerLevels, outerLevels); 1137 } 1138 1139 //! In point mode this should return the number of unique vertices, while in non-point mode the maximum theoretical number of verticies. 1140 //! Actual implementation will likely return a much smaller number because the shader isn't required to be run for duplicate coordinates. 1141 int referenceVertexCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels) 1142 { 1143 return referencePrimitiveCount(primitiveType, spacingMode, usePointMode, innerLevels, outerLevels) 1144 * numVerticesPerPrimitive(primitiveType, usePointMode); 1145 } 1146 1147 void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags) 1148 { 1149 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice); 1150 1151 if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader) 1152 throw tcu::NotSupportedError("Tessellation shader not supported"); 1153 1154 if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader) 1155 throw tcu::NotSupportedError("Geometry shader not supported"); 1156 1157 if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64) 1158 throw tcu::NotSupportedError("Double-precision floats not supported"); 1159 1160 if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics) 1161 throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline"); 1162 1163 if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics) 1164 throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader"); 1165 1166 if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize) 1167 throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in"); 1168 } 1169 1170 } // tessellation 1171 } // vkt 1172