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