1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------ 2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests 3e5c31af7Sopenharmony_ci * ------------------------ 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright (c) 2014 The Android Open Source Project 6e5c31af7Sopenharmony_ci * Copyright (c) 2016 The Khronos Group Inc. 7e5c31af7Sopenharmony_ci * 8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 11e5c31af7Sopenharmony_ci * 12e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 13e5c31af7Sopenharmony_ci * 14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 18e5c31af7Sopenharmony_ci * limitations under the License. 19e5c31af7Sopenharmony_ci * 20e5c31af7Sopenharmony_ci *//*! 21e5c31af7Sopenharmony_ci * \file 22e5c31af7Sopenharmony_ci * \brief Tessellation Utilities 23e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 24e5c31af7Sopenharmony_ci 25e5c31af7Sopenharmony_ci#include "vktTessellationUtil.hpp" 26e5c31af7Sopenharmony_ci#include "vkTypeUtil.hpp" 27e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp" 28e5c31af7Sopenharmony_ci#include "deMath.h" 29e5c31af7Sopenharmony_ci 30e5c31af7Sopenharmony_cinamespace vkt 31e5c31af7Sopenharmony_ci{ 32e5c31af7Sopenharmony_cinamespace tessellation 33e5c31af7Sopenharmony_ci{ 34e5c31af7Sopenharmony_ci 35e5c31af7Sopenharmony_ciusing namespace vk; 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_ciVkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage, const deUint32 numArrayLayers) 38e5c31af7Sopenharmony_ci{ 39e5c31af7Sopenharmony_ci const VkImageCreateInfo imageInfo = 40e5c31af7Sopenharmony_ci { 41e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 42e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 43e5c31af7Sopenharmony_ci (VkImageCreateFlags)0, // VkImageCreateFlags flags; 44e5c31af7Sopenharmony_ci VK_IMAGE_TYPE_2D, // VkImageType imageType; 45e5c31af7Sopenharmony_ci format, // VkFormat format; 46e5c31af7Sopenharmony_ci makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 47e5c31af7Sopenharmony_ci 1u, // uint32_t mipLevels; 48e5c31af7Sopenharmony_ci numArrayLayers, // uint32_t arrayLayers; 49e5c31af7Sopenharmony_ci VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 50e5c31af7Sopenharmony_ci VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 51e5c31af7Sopenharmony_ci usage, // VkImageUsageFlags usage; 52e5c31af7Sopenharmony_ci VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 53e5c31af7Sopenharmony_ci 0u, // uint32_t queueFamilyIndexCount; 54e5c31af7Sopenharmony_ci DE_NULL, // const uint32_t* pQueueFamilyIndices; 55e5c31af7Sopenharmony_ci VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 56e5c31af7Sopenharmony_ci }; 57e5c31af7Sopenharmony_ci return imageInfo; 58e5c31af7Sopenharmony_ci} 59e5c31af7Sopenharmony_ci 60e5c31af7Sopenharmony_ciMove<VkRenderPass> makeRenderPassWithoutAttachments (const DeviceInterface& vk, 61e5c31af7Sopenharmony_ci const VkDevice device) 62e5c31af7Sopenharmony_ci{ 63e5c31af7Sopenharmony_ci const VkAttachmentReference unusedAttachment = 64e5c31af7Sopenharmony_ci { 65e5c31af7Sopenharmony_ci VK_ATTACHMENT_UNUSED, // deUint32 attachment; 66e5c31af7Sopenharmony_ci VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout; 67e5c31af7Sopenharmony_ci }; 68e5c31af7Sopenharmony_ci 69e5c31af7Sopenharmony_ci const VkSubpassDescription subpassDescription = 70e5c31af7Sopenharmony_ci { 71e5c31af7Sopenharmony_ci (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 72e5c31af7Sopenharmony_ci VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 73e5c31af7Sopenharmony_ci 0u, // deUint32 inputAttachmentCount; 74e5c31af7Sopenharmony_ci DE_NULL, // const VkAttachmentReference* pInputAttachments; 75e5c31af7Sopenharmony_ci 0u, // deUint32 colorAttachmentCount; 76e5c31af7Sopenharmony_ci DE_NULL, // const VkAttachmentReference* pColorAttachments; 77e5c31af7Sopenharmony_ci DE_NULL, // const VkAttachmentReference* pResolveAttachments; 78e5c31af7Sopenharmony_ci &unusedAttachment, // const VkAttachmentReference* pDepthStencilAttachment; 79e5c31af7Sopenharmony_ci 0u, // deUint32 preserveAttachmentCount; 80e5c31af7Sopenharmony_ci DE_NULL // const deUint32* pPreserveAttachments; 81e5c31af7Sopenharmony_ci }; 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_ci const VkRenderPassCreateInfo renderPassInfo = 84e5c31af7Sopenharmony_ci { 85e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 86e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 87e5c31af7Sopenharmony_ci (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 88e5c31af7Sopenharmony_ci 0u, // deUint32 attachmentCount; 89e5c31af7Sopenharmony_ci DE_NULL, // const VkAttachmentDescription* pAttachments; 90e5c31af7Sopenharmony_ci 1u, // deUint32 subpassCount; 91e5c31af7Sopenharmony_ci &subpassDescription, // const VkSubpassDescription* pSubpasses; 92e5c31af7Sopenharmony_ci 0u, // deUint32 dependencyCount; 93e5c31af7Sopenharmony_ci DE_NULL // const VkSubpassDependency* pDependencies; 94e5c31af7Sopenharmony_ci }; 95e5c31af7Sopenharmony_ci 96e5c31af7Sopenharmony_ci return createRenderPass(vk, device, &renderPassInfo); 97e5c31af7Sopenharmony_ci} 98e5c31af7Sopenharmony_ci 99e5c31af7Sopenharmony_ciGraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface& vk, 100e5c31af7Sopenharmony_ci const VkDevice device, 101e5c31af7Sopenharmony_ci const VkShaderStageFlagBits stage, 102e5c31af7Sopenharmony_ci const ProgramBinary& binary, 103e5c31af7Sopenharmony_ci const VkSpecializationInfo* specInfo) 104e5c31af7Sopenharmony_ci{ 105e5c31af7Sopenharmony_ci VkShaderModule module; 106e5c31af7Sopenharmony_ci switch (stage) 107e5c31af7Sopenharmony_ci { 108e5c31af7Sopenharmony_ci case (VK_SHADER_STAGE_VERTEX_BIT): 109e5c31af7Sopenharmony_ci DE_ASSERT(m_vertexShaderModule.get() == DE_NULL); 110e5c31af7Sopenharmony_ci m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); 111e5c31af7Sopenharmony_ci module = *m_vertexShaderModule; 112e5c31af7Sopenharmony_ci break; 113e5c31af7Sopenharmony_ci 114e5c31af7Sopenharmony_ci case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT): 115e5c31af7Sopenharmony_ci DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL); 116e5c31af7Sopenharmony_ci m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); 117e5c31af7Sopenharmony_ci module = *m_tessControlShaderModule; 118e5c31af7Sopenharmony_ci break; 119e5c31af7Sopenharmony_ci 120e5c31af7Sopenharmony_ci case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT): 121e5c31af7Sopenharmony_ci DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL); 122e5c31af7Sopenharmony_ci m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); 123e5c31af7Sopenharmony_ci module = *m_tessEvaluationShaderModule; 124e5c31af7Sopenharmony_ci break; 125e5c31af7Sopenharmony_ci 126e5c31af7Sopenharmony_ci case (VK_SHADER_STAGE_GEOMETRY_BIT): 127e5c31af7Sopenharmony_ci DE_ASSERT(m_geometryShaderModule.get() == DE_NULL); 128e5c31af7Sopenharmony_ci m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); 129e5c31af7Sopenharmony_ci module = *m_geometryShaderModule; 130e5c31af7Sopenharmony_ci break; 131e5c31af7Sopenharmony_ci 132e5c31af7Sopenharmony_ci case (VK_SHADER_STAGE_FRAGMENT_BIT): 133e5c31af7Sopenharmony_ci DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL); 134e5c31af7Sopenharmony_ci m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); 135e5c31af7Sopenharmony_ci module = *m_fragmentShaderModule; 136e5c31af7Sopenharmony_ci break; 137e5c31af7Sopenharmony_ci 138e5c31af7Sopenharmony_ci default: 139e5c31af7Sopenharmony_ci DE_FATAL("Invalid shader stage"); 140e5c31af7Sopenharmony_ci return *this; 141e5c31af7Sopenharmony_ci } 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo = 144e5c31af7Sopenharmony_ci { 145e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 146e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 147e5c31af7Sopenharmony_ci (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 148e5c31af7Sopenharmony_ci stage, // VkShaderStageFlagBits stage; 149e5c31af7Sopenharmony_ci module, // VkShaderModule module; 150e5c31af7Sopenharmony_ci "main", // const char* pName; 151e5c31af7Sopenharmony_ci specInfo, // const VkSpecializationInfo* pSpecializationInfo; 152e5c31af7Sopenharmony_ci }; 153e5c31af7Sopenharmony_ci 154e5c31af7Sopenharmony_ci m_shaderStageFlags |= stage; 155e5c31af7Sopenharmony_ci m_shaderStages.push_back(pipelineShaderStageInfo); 156e5c31af7Sopenharmony_ci 157e5c31af7Sopenharmony_ci return *this; 158e5c31af7Sopenharmony_ci} 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_ciGraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride) 161e5c31af7Sopenharmony_ci{ 162e5c31af7Sopenharmony_ci const VkVertexInputBindingDescription bindingDesc = 163e5c31af7Sopenharmony_ci { 164e5c31af7Sopenharmony_ci 0u, // uint32_t binding; 165e5c31af7Sopenharmony_ci stride, // uint32_t stride; 166e5c31af7Sopenharmony_ci VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 167e5c31af7Sopenharmony_ci }; 168e5c31af7Sopenharmony_ci const VkVertexInputAttributeDescription attributeDesc = 169e5c31af7Sopenharmony_ci { 170e5c31af7Sopenharmony_ci 0u, // uint32_t location; 171e5c31af7Sopenharmony_ci 0u, // uint32_t binding; 172e5c31af7Sopenharmony_ci vertexFormat, // VkFormat format; 173e5c31af7Sopenharmony_ci 0u, // uint32_t offset; 174e5c31af7Sopenharmony_ci }; 175e5c31af7Sopenharmony_ci 176e5c31af7Sopenharmony_ci m_vertexInputBindings.clear(); 177e5c31af7Sopenharmony_ci m_vertexInputBindings.push_back(bindingDesc); 178e5c31af7Sopenharmony_ci 179e5c31af7Sopenharmony_ci m_vertexInputAttributes.clear(); 180e5c31af7Sopenharmony_ci m_vertexInputAttributes.push_back(attributeDesc); 181e5c31af7Sopenharmony_ci 182e5c31af7Sopenharmony_ci return *this; 183e5c31af7Sopenharmony_ci} 184e5c31af7Sopenharmony_ci 185e5c31af7Sopenharmony_citemplate<typename T> 186e5c31af7Sopenharmony_ciinline const T* dataPointer (const std::vector<T>& vec) 187e5c31af7Sopenharmony_ci{ 188e5c31af7Sopenharmony_ci return (vec.size() != 0 ? &vec[0] : DE_NULL); 189e5c31af7Sopenharmony_ci} 190e5c31af7Sopenharmony_ci 191e5c31af7Sopenharmony_ciMove<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface& vk, 192e5c31af7Sopenharmony_ci const VkDevice device, 193e5c31af7Sopenharmony_ci const VkPipelineLayout pipelineLayout, 194e5c31af7Sopenharmony_ci const VkRenderPass renderPass) 195e5c31af7Sopenharmony_ci{ 196e5c31af7Sopenharmony_ci const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 197e5c31af7Sopenharmony_ci { 198e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 199e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 200e5c31af7Sopenharmony_ci (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 201e5c31af7Sopenharmony_ci static_cast<deUint32>(m_vertexInputBindings.size()), // uint32_t vertexBindingDescriptionCount; 202e5c31af7Sopenharmony_ci dataPointer(m_vertexInputBindings), // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 203e5c31af7Sopenharmony_ci static_cast<deUint32>(m_vertexInputAttributes.size()), // uint32_t vertexAttributeDescriptionCount; 204e5c31af7Sopenharmony_ci dataPointer(m_vertexInputAttributes), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 205e5c31af7Sopenharmony_ci }; 206e5c31af7Sopenharmony_ci 207e5c31af7Sopenharmony_ci const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST 208e5c31af7Sopenharmony_ci : m_primitiveTopology; 209e5c31af7Sopenharmony_ci const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = 210e5c31af7Sopenharmony_ci { 211e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 212e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 213e5c31af7Sopenharmony_ci (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 214e5c31af7Sopenharmony_ci topology, // VkPrimitiveTopology topology; 215e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 primitiveRestartEnable; 216e5c31af7Sopenharmony_ci }; 217e5c31af7Sopenharmony_ci 218e5c31af7Sopenharmony_ci const VkPipelineTessellationDomainOriginStateCreateInfo tessellationDomainOriginStateInfo = 219e5c31af7Sopenharmony_ci { 220e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, 221e5c31af7Sopenharmony_ci DE_NULL, 222e5c31af7Sopenharmony_ci (!m_tessellationDomainOrigin ? VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT : *m_tessellationDomainOrigin) 223e5c31af7Sopenharmony_ci }; 224e5c31af7Sopenharmony_ci const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo = 225e5c31af7Sopenharmony_ci { 226e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType; 227e5c31af7Sopenharmony_ci (!m_tessellationDomainOrigin ? DE_NULL : &tessellationDomainOriginStateInfo), 228e5c31af7Sopenharmony_ci (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags; 229e5c31af7Sopenharmony_ci m_patchControlPoints, // uint32_t patchControlPoints; 230e5c31af7Sopenharmony_ci }; 231e5c31af7Sopenharmony_ci 232e5c31af7Sopenharmony_ci const VkViewport viewport = makeViewport(m_renderSize); 233e5c31af7Sopenharmony_ci const VkRect2D scissor = makeRect2D(m_renderSize); 234e5c31af7Sopenharmony_ci 235e5c31af7Sopenharmony_ci const bool haveRenderSize = m_renderSize.x() > 0 && m_renderSize.y() > 0; 236e5c31af7Sopenharmony_ci 237e5c31af7Sopenharmony_ci const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = 238e5c31af7Sopenharmony_ci { 239e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 240e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 241e5c31af7Sopenharmony_ci (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; 242e5c31af7Sopenharmony_ci 1u, // uint32_t viewportCount; 243e5c31af7Sopenharmony_ci haveRenderSize ? &viewport : DE_NULL, // const VkViewport* pViewports; 244e5c31af7Sopenharmony_ci 1u, // uint32_t scissorCount; 245e5c31af7Sopenharmony_ci haveRenderSize ? &scissor : DE_NULL, // const VkRect2D* pScissors; 246e5c31af7Sopenharmony_ci }; 247e5c31af7Sopenharmony_ci 248e5c31af7Sopenharmony_ci const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0); 249e5c31af7Sopenharmony_ci const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = 250e5c31af7Sopenharmony_ci { 251e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 252e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 253e5c31af7Sopenharmony_ci (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 254e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 depthClampEnable; 255e5c31af7Sopenharmony_ci isRasterizationDisabled, // VkBool32 rasterizerDiscardEnable; 256e5c31af7Sopenharmony_ci VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 257e5c31af7Sopenharmony_ci m_cullModeFlags, // VkCullModeFlags cullMode; 258e5c31af7Sopenharmony_ci m_frontFace, // VkFrontFace frontFace; 259e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 depthBiasEnable; 260e5c31af7Sopenharmony_ci 0.0f, // float depthBiasConstantFactor; 261e5c31af7Sopenharmony_ci 0.0f, // float depthBiasClamp; 262e5c31af7Sopenharmony_ci 0.0f, // float depthBiasSlopeFactor; 263e5c31af7Sopenharmony_ci 1.0f, // float lineWidth; 264e5c31af7Sopenharmony_ci }; 265e5c31af7Sopenharmony_ci 266e5c31af7Sopenharmony_ci const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 267e5c31af7Sopenharmony_ci { 268e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 269e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 270e5c31af7Sopenharmony_ci (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 271e5c31af7Sopenharmony_ci VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 272e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 sampleShadingEnable; 273e5c31af7Sopenharmony_ci 0.0f, // float minSampleShading; 274e5c31af7Sopenharmony_ci DE_NULL, // const VkSampleMask* pSampleMask; 275e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 alphaToCoverageEnable; 276e5c31af7Sopenharmony_ci VK_FALSE // VkBool32 alphaToOneEnable; 277e5c31af7Sopenharmony_ci }; 278e5c31af7Sopenharmony_ci 279e5c31af7Sopenharmony_ci const VkStencilOpState stencilOpState = makeStencilOpState( 280e5c31af7Sopenharmony_ci VK_STENCIL_OP_KEEP, // stencil fail 281e5c31af7Sopenharmony_ci VK_STENCIL_OP_KEEP, // depth & stencil pass 282e5c31af7Sopenharmony_ci VK_STENCIL_OP_KEEP, // depth only fail 283e5c31af7Sopenharmony_ci VK_COMPARE_OP_NEVER, // compare op 284e5c31af7Sopenharmony_ci 0u, // compare mask 285e5c31af7Sopenharmony_ci 0u, // write mask 286e5c31af7Sopenharmony_ci 0u); // reference 287e5c31af7Sopenharmony_ci 288e5c31af7Sopenharmony_ci const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 289e5c31af7Sopenharmony_ci { 290e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 291e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 292e5c31af7Sopenharmony_ci (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 293e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 depthTestEnable; 294e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 depthWriteEnable; 295e5c31af7Sopenharmony_ci VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 296e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 depthBoundsTestEnable; 297e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 stencilTestEnable; 298e5c31af7Sopenharmony_ci stencilOpState, // VkStencilOpState front; 299e5c31af7Sopenharmony_ci stencilOpState, // VkStencilOpState back; 300e5c31af7Sopenharmony_ci 0.0f, // float minDepthBounds; 301e5c31af7Sopenharmony_ci 1.0f, // float maxDepthBounds; 302e5c31af7Sopenharmony_ci }; 303e5c31af7Sopenharmony_ci 304e5c31af7Sopenharmony_ci const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 305e5c31af7Sopenharmony_ci const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 306e5c31af7Sopenharmony_ci { 307e5c31af7Sopenharmony_ci m_blendEnable, // VkBool32 blendEnable; 308e5c31af7Sopenharmony_ci VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor; 309e5c31af7Sopenharmony_ci VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor; 310e5c31af7Sopenharmony_ci VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 311e5c31af7Sopenharmony_ci VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor; 312e5c31af7Sopenharmony_ci VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor; 313e5c31af7Sopenharmony_ci VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 314e5c31af7Sopenharmony_ci colorComponentsAll, // VkColorComponentFlags colorWriteMask; 315e5c31af7Sopenharmony_ci }; 316e5c31af7Sopenharmony_ci 317e5c31af7Sopenharmony_ci const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 318e5c31af7Sopenharmony_ci { 319e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 320e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 321e5c31af7Sopenharmony_ci (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 322e5c31af7Sopenharmony_ci VK_FALSE, // VkBool32 logicOpEnable; 323e5c31af7Sopenharmony_ci VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 324e5c31af7Sopenharmony_ci 1u, // deUint32 attachmentCount; 325e5c31af7Sopenharmony_ci &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 326e5c31af7Sopenharmony_ci { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 327e5c31af7Sopenharmony_ci }; 328e5c31af7Sopenharmony_ci 329e5c31af7Sopenharmony_ci std::vector<VkDynamicState> dynamicStates; 330e5c31af7Sopenharmony_ci if (!haveRenderSize && !isRasterizationDisabled) 331e5c31af7Sopenharmony_ci { 332e5c31af7Sopenharmony_ci dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT); 333e5c31af7Sopenharmony_ci dynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR); 334e5c31af7Sopenharmony_ci } 335e5c31af7Sopenharmony_ci 336e5c31af7Sopenharmony_ci const VkPipelineDynamicStateCreateInfo pipelineDynamicStateInfo = 337e5c31af7Sopenharmony_ci { 338e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType; 339e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 340e5c31af7Sopenharmony_ci 0, // VkPipelineDynamicStateCreateFlags flags; 341e5c31af7Sopenharmony_ci static_cast<deUint32>(dynamicStates.size()), // uint32_t dynamicStateCount; 342e5c31af7Sopenharmony_ci (dynamicStates.empty() ? DE_NULL : &dynamicStates[0]), // const VkDynamicState* pDynamicStates; 343e5c31af7Sopenharmony_ci }; 344e5c31af7Sopenharmony_ci 345e5c31af7Sopenharmony_ci const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = 346e5c31af7Sopenharmony_ci { 347e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 348e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 349e5c31af7Sopenharmony_ci (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 350e5c31af7Sopenharmony_ci static_cast<deUint32>(m_shaderStages.size()), // deUint32 stageCount; 351e5c31af7Sopenharmony_ci &m_shaderStages[0], // const VkPipelineShaderStageCreateInfo* pStages; 352e5c31af7Sopenharmony_ci &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 353e5c31af7Sopenharmony_ci &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 354e5c31af7Sopenharmony_ci (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo* pTessellationState; 355e5c31af7Sopenharmony_ci (isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo), // const VkPipelineViewportStateCreateInfo* pViewportState; 356e5c31af7Sopenharmony_ci &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 357e5c31af7Sopenharmony_ci (isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo), // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 358e5c31af7Sopenharmony_ci (isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo), // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 359e5c31af7Sopenharmony_ci (isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo), // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 360e5c31af7Sopenharmony_ci (dynamicStates.empty() ? DE_NULL : &pipelineDynamicStateInfo), // const VkPipelineDynamicStateCreateInfo* pDynamicState; 361e5c31af7Sopenharmony_ci pipelineLayout, // VkPipelineLayout layout; 362e5c31af7Sopenharmony_ci renderPass, // VkRenderPass renderPass; 363e5c31af7Sopenharmony_ci 0u, // deUint32 subpass; 364e5c31af7Sopenharmony_ci DE_NULL, // VkPipeline basePipelineHandle; 365e5c31af7Sopenharmony_ci 0, // deInt32 basePipelineIndex; 366e5c31af7Sopenharmony_ci }; 367e5c31af7Sopenharmony_ci 368e5c31af7Sopenharmony_ci return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); 369e5c31af7Sopenharmony_ci} 370e5c31af7Sopenharmony_ci 371e5c31af7Sopenharmony_cifloat getClampedTessLevel (const SpacingMode mode, const float tessLevel) 372e5c31af7Sopenharmony_ci{ 373e5c31af7Sopenharmony_ci switch (mode) 374e5c31af7Sopenharmony_ci { 375e5c31af7Sopenharmony_ci case SPACINGMODE_EQUAL: return de::max(1.0f, tessLevel); 376e5c31af7Sopenharmony_ci case SPACINGMODE_FRACTIONAL_ODD: return de::max(1.0f, tessLevel); 377e5c31af7Sopenharmony_ci case SPACINGMODE_FRACTIONAL_EVEN: return de::max(2.0f, tessLevel); 378e5c31af7Sopenharmony_ci default: 379e5c31af7Sopenharmony_ci DE_ASSERT(false); 380e5c31af7Sopenharmony_ci return 0.0f; 381e5c31af7Sopenharmony_ci } 382e5c31af7Sopenharmony_ci} 383e5c31af7Sopenharmony_ci 384e5c31af7Sopenharmony_ciint getRoundedTessLevel (const SpacingMode mode, const float clampedTessLevel) 385e5c31af7Sopenharmony_ci{ 386e5c31af7Sopenharmony_ci static const int minimumMaxTessGenLevel = 64; //!< Minimum maxTessellationGenerationLevel defined by the spec. 387e5c31af7Sopenharmony_ci 388e5c31af7Sopenharmony_ci int result = (int)deFloatCeil(clampedTessLevel); 389e5c31af7Sopenharmony_ci 390e5c31af7Sopenharmony_ci switch (mode) 391e5c31af7Sopenharmony_ci { 392e5c31af7Sopenharmony_ci case SPACINGMODE_EQUAL: break; 393e5c31af7Sopenharmony_ci case SPACINGMODE_FRACTIONAL_ODD: result += 1 - result % 2; break; 394e5c31af7Sopenharmony_ci case SPACINGMODE_FRACTIONAL_EVEN: result += result % 2; break; 395e5c31af7Sopenharmony_ci default: 396e5c31af7Sopenharmony_ci DE_ASSERT(false); 397e5c31af7Sopenharmony_ci } 398e5c31af7Sopenharmony_ci DE_ASSERT(de::inRange<int>(result, 1, minimumMaxTessGenLevel)); 399e5c31af7Sopenharmony_ci DE_UNREF(minimumMaxTessGenLevel); 400e5c31af7Sopenharmony_ci 401e5c31af7Sopenharmony_ci return result; 402e5c31af7Sopenharmony_ci} 403e5c31af7Sopenharmony_ci 404e5c31af7Sopenharmony_ciint getClampedRoundedTessLevel (const SpacingMode mode, const float tessLevel) 405e5c31af7Sopenharmony_ci{ 406e5c31af7Sopenharmony_ci return getRoundedTessLevel(mode, getClampedTessLevel(mode, tessLevel)); 407e5c31af7Sopenharmony_ci} 408e5c31af7Sopenharmony_ci 409e5c31af7Sopenharmony_civoid getClampedRoundedTriangleTessLevels (const SpacingMode spacingMode, 410e5c31af7Sopenharmony_ci const float* innerSrc, 411e5c31af7Sopenharmony_ci const float* outerSrc, 412e5c31af7Sopenharmony_ci int* innerDst, 413e5c31af7Sopenharmony_ci int* outerDst) 414e5c31af7Sopenharmony_ci{ 415e5c31af7Sopenharmony_ci innerDst[0] = getClampedRoundedTessLevel(spacingMode, innerSrc[0]); 416e5c31af7Sopenharmony_ci for (int i = 0; i < 3; i++) 417e5c31af7Sopenharmony_ci outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]); 418e5c31af7Sopenharmony_ci} 419e5c31af7Sopenharmony_ci 420e5c31af7Sopenharmony_civoid getClampedRoundedQuadTessLevels (const SpacingMode spacingMode, 421e5c31af7Sopenharmony_ci const float* innerSrc, 422e5c31af7Sopenharmony_ci const float* outerSrc, 423e5c31af7Sopenharmony_ci int* innerDst, 424e5c31af7Sopenharmony_ci int* outerDst) 425e5c31af7Sopenharmony_ci{ 426e5c31af7Sopenharmony_ci for (int i = 0; i < 2; i++) 427e5c31af7Sopenharmony_ci innerDst[i] = getClampedRoundedTessLevel(spacingMode, innerSrc[i]); 428e5c31af7Sopenharmony_ci for (int i = 0; i < 4; i++) 429e5c31af7Sopenharmony_ci outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]); 430e5c31af7Sopenharmony_ci} 431e5c31af7Sopenharmony_ci 432e5c31af7Sopenharmony_civoid getClampedRoundedIsolineTessLevels (const SpacingMode spacingMode, 433e5c31af7Sopenharmony_ci const float* outerSrc, 434e5c31af7Sopenharmony_ci int* outerDst) 435e5c31af7Sopenharmony_ci{ 436e5c31af7Sopenharmony_ci outerDst[0] = getClampedRoundedTessLevel(SPACINGMODE_EQUAL, outerSrc[0]); 437e5c31af7Sopenharmony_ci outerDst[1] = getClampedRoundedTessLevel(spacingMode, outerSrc[1]); 438e5c31af7Sopenharmony_ci} 439e5c31af7Sopenharmony_ci 440e5c31af7Sopenharmony_ciint numOuterTessellationLevels (const TessPrimitiveType primType) 441e5c31af7Sopenharmony_ci{ 442e5c31af7Sopenharmony_ci switch (primType) 443e5c31af7Sopenharmony_ci { 444e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_TRIANGLES: return 3; 445e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_QUADS: return 4; 446e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_ISOLINES: return 2; 447e5c31af7Sopenharmony_ci default: 448e5c31af7Sopenharmony_ci DE_ASSERT(false); 449e5c31af7Sopenharmony_ci return 0; 450e5c31af7Sopenharmony_ci } 451e5c31af7Sopenharmony_ci} 452e5c31af7Sopenharmony_ci 453e5c31af7Sopenharmony_cibool isPatchDiscarded (const TessPrimitiveType primitiveType, const float* outerLevels) 454e5c31af7Sopenharmony_ci{ 455e5c31af7Sopenharmony_ci const int numOuterLevels = numOuterTessellationLevels(primitiveType); 456e5c31af7Sopenharmony_ci for (int i = 0; i < numOuterLevels; i++) 457e5c31af7Sopenharmony_ci if (outerLevels[i] <= 0.0f) 458e5c31af7Sopenharmony_ci return true; 459e5c31af7Sopenharmony_ci return false; 460e5c31af7Sopenharmony_ci} 461e5c31af7Sopenharmony_ci 462e5c31af7Sopenharmony_cistd::string getTessellationLevelsString (const TessLevels& tessLevels, const TessPrimitiveType primitiveType) 463e5c31af7Sopenharmony_ci{ 464e5c31af7Sopenharmony_ci std::ostringstream str; 465e5c31af7Sopenharmony_ci switch (primitiveType) 466e5c31af7Sopenharmony_ci { 467e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_ISOLINES: 468e5c31af7Sopenharmony_ci str << "inner: { }, " 469e5c31af7Sopenharmony_ci << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << " }"; 470e5c31af7Sopenharmony_ci break; 471e5c31af7Sopenharmony_ci 472e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_TRIANGLES: 473e5c31af7Sopenharmony_ci str << "inner: { " << tessLevels.inner[0] << " }, " 474e5c31af7Sopenharmony_ci << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << " }"; 475e5c31af7Sopenharmony_ci break; 476e5c31af7Sopenharmony_ci 477e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_QUADS: 478e5c31af7Sopenharmony_ci str << "inner: { " << tessLevels.inner[0] << ", " << tessLevels.inner[1] << " }, " 479e5c31af7Sopenharmony_ci << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << ", " << tessLevels.outer[3] << " }"; 480e5c31af7Sopenharmony_ci break; 481e5c31af7Sopenharmony_ci 482e5c31af7Sopenharmony_ci default: 483e5c31af7Sopenharmony_ci DE_ASSERT(false); 484e5c31af7Sopenharmony_ci } 485e5c31af7Sopenharmony_ci 486e5c31af7Sopenharmony_ci return str.str(); 487e5c31af7Sopenharmony_ci} 488e5c31af7Sopenharmony_ci 489e5c31af7Sopenharmony_ci//! Assumes array sizes inner[2] and outer[4]. 490e5c31af7Sopenharmony_cistd::string getTessellationLevelsString (const float* inner, const float* outer) 491e5c31af7Sopenharmony_ci{ 492e5c31af7Sopenharmony_ci const TessLevels tessLevels = 493e5c31af7Sopenharmony_ci { 494e5c31af7Sopenharmony_ci { inner[0], inner[1] }, 495e5c31af7Sopenharmony_ci { outer[0], outer[1], outer[2], outer[3] } 496e5c31af7Sopenharmony_ci }; 497e5c31af7Sopenharmony_ci return getTessellationLevelsString(tessLevels, TESSPRIMITIVETYPE_QUADS); 498e5c31af7Sopenharmony_ci} 499e5c31af7Sopenharmony_ci 500e5c31af7Sopenharmony_ci// \note The tessellation coordinates generated by this function could break some of the rules given in the spec 501e5c31af7Sopenharmony_ci// (e.g. it may not exactly hold that u+v+w == 1.0f, or [uvw] + (1.0f-[uvw]) == 1.0f). 502e5c31af7Sopenharmony_cistd::vector<tcu::Vec3> generateReferenceTriangleTessCoords (const SpacingMode spacingMode, 503e5c31af7Sopenharmony_ci const int inner, 504e5c31af7Sopenharmony_ci const int outer0, 505e5c31af7Sopenharmony_ci const int outer1, 506e5c31af7Sopenharmony_ci const int outer2) 507e5c31af7Sopenharmony_ci{ 508e5c31af7Sopenharmony_ci std::vector<tcu::Vec3> tessCoords; 509e5c31af7Sopenharmony_ci 510e5c31af7Sopenharmony_ci if (inner == 1) 511e5c31af7Sopenharmony_ci { 512e5c31af7Sopenharmony_ci if (outer0 == 1 && outer1 == 1 && outer2 == 1) 513e5c31af7Sopenharmony_ci { 514e5c31af7Sopenharmony_ci tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f)); 515e5c31af7Sopenharmony_ci tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f)); 516e5c31af7Sopenharmony_ci tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 1.0f)); 517e5c31af7Sopenharmony_ci return tessCoords; 518e5c31af7Sopenharmony_ci } 519e5c31af7Sopenharmony_ci else 520e5c31af7Sopenharmony_ci return generateReferenceTriangleTessCoords(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 521e5c31af7Sopenharmony_ci outer0, outer1, outer2); 522e5c31af7Sopenharmony_ci } 523e5c31af7Sopenharmony_ci else 524e5c31af7Sopenharmony_ci { 525e5c31af7Sopenharmony_ci 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)); } 526e5c31af7Sopenharmony_ci 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)); } 527e5c31af7Sopenharmony_ci 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)); } 528e5c31af7Sopenharmony_ci 529e5c31af7Sopenharmony_ci const int numInnerTriangles = inner/2; 530e5c31af7Sopenharmony_ci for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++) 531e5c31af7Sopenharmony_ci { 532e5c31af7Sopenharmony_ci const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1); 533e5c31af7Sopenharmony_ci 534e5c31af7Sopenharmony_ci if (curInnerTriangleLevel == 0) 535e5c31af7Sopenharmony_ci tessCoords.push_back(tcu::Vec3(1.0f/3.0f)); 536e5c31af7Sopenharmony_ci else 537e5c31af7Sopenharmony_ci { 538e5c31af7Sopenharmony_ci const float minUVW = (float)(2 * (innerTriangleNdx + 1)) / (float)(3 * inner); 539e5c31af7Sopenharmony_ci const float maxUVW = 1.0f - 2.0f*minUVW; 540e5c31af7Sopenharmony_ci const tcu::Vec3 corners[3] = 541e5c31af7Sopenharmony_ci { 542e5c31af7Sopenharmony_ci tcu::Vec3(maxUVW, minUVW, minUVW), 543e5c31af7Sopenharmony_ci tcu::Vec3(minUVW, maxUVW, minUVW), 544e5c31af7Sopenharmony_ci tcu::Vec3(minUVW, minUVW, maxUVW) 545e5c31af7Sopenharmony_ci }; 546e5c31af7Sopenharmony_ci 547e5c31af7Sopenharmony_ci for (int i = 0; i < curInnerTriangleLevel; i++) 548e5c31af7Sopenharmony_ci { 549e5c31af7Sopenharmony_ci const float f = (float)i / (float)curInnerTriangleLevel; 550e5c31af7Sopenharmony_ci for (int j = 0; j < 3; j++) 551e5c31af7Sopenharmony_ci tessCoords.push_back((1.0f - f)*corners[j] + f*corners[(j+1)%3]); 552e5c31af7Sopenharmony_ci } 553e5c31af7Sopenharmony_ci } 554e5c31af7Sopenharmony_ci } 555e5c31af7Sopenharmony_ci 556e5c31af7Sopenharmony_ci return tessCoords; 557e5c31af7Sopenharmony_ci } 558e5c31af7Sopenharmony_ci} 559e5c31af7Sopenharmony_ci 560e5c31af7Sopenharmony_ci// \note The tessellation coordinates generated by this function could break some of the rules given in the spec 561e5c31af7Sopenharmony_ci// (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f). 562e5c31af7Sopenharmony_cistd::vector<tcu::Vec3> generateReferenceQuadTessCoords (const SpacingMode spacingMode, 563e5c31af7Sopenharmony_ci const int inner0, 564e5c31af7Sopenharmony_ci const int inner1, 565e5c31af7Sopenharmony_ci const int outer0, 566e5c31af7Sopenharmony_ci const int outer1, 567e5c31af7Sopenharmony_ci const int outer2, 568e5c31af7Sopenharmony_ci const int outer3) 569e5c31af7Sopenharmony_ci{ 570e5c31af7Sopenharmony_ci std::vector<tcu::Vec3> tessCoords; 571e5c31af7Sopenharmony_ci 572e5c31af7Sopenharmony_ci if (inner0 == 1 || inner1 == 1) 573e5c31af7Sopenharmony_ci { 574e5c31af7Sopenharmony_ci if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1) 575e5c31af7Sopenharmony_ci { 576e5c31af7Sopenharmony_ci tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 0.0f)); 577e5c31af7Sopenharmony_ci tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f)); 578e5c31af7Sopenharmony_ci tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f)); 579e5c31af7Sopenharmony_ci tessCoords.push_back(tcu::Vec3(1.0f, 1.0f, 0.0f)); 580e5c31af7Sopenharmony_ci return tessCoords; 581e5c31af7Sopenharmony_ci } 582e5c31af7Sopenharmony_ci else 583e5c31af7Sopenharmony_ci return generateReferenceQuadTessCoords(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 584e5c31af7Sopenharmony_ci inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 585e5c31af7Sopenharmony_ci outer0, outer1, outer2, outer3); 586e5c31af7Sopenharmony_ci } 587e5c31af7Sopenharmony_ci else 588e5c31af7Sopenharmony_ci { 589e5c31af7Sopenharmony_ci for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(tcu::Vec3( 0.0f, v, 0.0f)); } 590e5c31af7Sopenharmony_ci 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)); } 591e5c31af7Sopenharmony_ci 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)); } 592e5c31af7Sopenharmony_ci for (int i = 0; i < outer3; i++) { const float v = (float)i / (float)outer3; tessCoords.push_back(tcu::Vec3( v, 1.0f, 0.0f)); } 593e5c31af7Sopenharmony_ci 594e5c31af7Sopenharmony_ci for (int innerVtxY = 0; innerVtxY < inner1-1; innerVtxY++) 595e5c31af7Sopenharmony_ci for (int innerVtxX = 0; innerVtxX < inner0-1; innerVtxX++) 596e5c31af7Sopenharmony_ci tessCoords.push_back(tcu::Vec3((float)(innerVtxX + 1) / (float)inner0, 597e5c31af7Sopenharmony_ci (float)(innerVtxY + 1) / (float)inner1, 598e5c31af7Sopenharmony_ci 0.0f)); 599e5c31af7Sopenharmony_ci 600e5c31af7Sopenharmony_ci return tessCoords; 601e5c31af7Sopenharmony_ci } 602e5c31af7Sopenharmony_ci} 603e5c31af7Sopenharmony_ci 604e5c31af7Sopenharmony_ci// \note The tessellation coordinates generated by this function could break some of the rules given in the spec 605e5c31af7Sopenharmony_ci// (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f). 606e5c31af7Sopenharmony_cistd::vector<tcu::Vec3> generateReferenceIsolineTessCoords (const int outer0, const int outer1) 607e5c31af7Sopenharmony_ci{ 608e5c31af7Sopenharmony_ci std::vector<tcu::Vec3> tessCoords; 609e5c31af7Sopenharmony_ci 610e5c31af7Sopenharmony_ci for (int y = 0; y < outer0; y++) 611e5c31af7Sopenharmony_ci for (int x = 0; x < outer1+1; x++) 612e5c31af7Sopenharmony_ci tessCoords.push_back(tcu::Vec3((float)x / (float)outer1, 613e5c31af7Sopenharmony_ci (float)y / (float)outer0, 614e5c31af7Sopenharmony_ci 0.0f)); 615e5c31af7Sopenharmony_ci 616e5c31af7Sopenharmony_ci return tessCoords; 617e5c31af7Sopenharmony_ci} 618e5c31af7Sopenharmony_ci 619e5c31af7Sopenharmony_cistatic int referencePointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels) 620e5c31af7Sopenharmony_ci{ 621e5c31af7Sopenharmony_ci if (isPatchDiscarded(primitiveType, outerLevels)) 622e5c31af7Sopenharmony_ci return 0; 623e5c31af7Sopenharmony_ci 624e5c31af7Sopenharmony_ci switch (primitiveType) 625e5c31af7Sopenharmony_ci { 626e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_TRIANGLES: 627e5c31af7Sopenharmony_ci { 628e5c31af7Sopenharmony_ci int inner; 629e5c31af7Sopenharmony_ci int outer[3]; 630e5c31af7Sopenharmony_ci getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]); 631e5c31af7Sopenharmony_ci return static_cast<int>(generateReferenceTriangleTessCoords(spacingMode, inner, outer[0], outer[1], outer[2]).size()); 632e5c31af7Sopenharmony_ci } 633e5c31af7Sopenharmony_ci 634e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_QUADS: 635e5c31af7Sopenharmony_ci { 636e5c31af7Sopenharmony_ci int inner[2]; 637e5c31af7Sopenharmony_ci int outer[4]; 638e5c31af7Sopenharmony_ci getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]); 639e5c31af7Sopenharmony_ci return static_cast<int>(generateReferenceQuadTessCoords(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]).size()); 640e5c31af7Sopenharmony_ci } 641e5c31af7Sopenharmony_ci 642e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_ISOLINES: 643e5c31af7Sopenharmony_ci { 644e5c31af7Sopenharmony_ci int outer[2]; 645e5c31af7Sopenharmony_ci getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]); 646e5c31af7Sopenharmony_ci return static_cast<int>(generateReferenceIsolineTessCoords(outer[0], outer[1]).size()); 647e5c31af7Sopenharmony_ci } 648e5c31af7Sopenharmony_ci 649e5c31af7Sopenharmony_ci default: 650e5c31af7Sopenharmony_ci DE_ASSERT(false); 651e5c31af7Sopenharmony_ci return 0; 652e5c31af7Sopenharmony_ci } 653e5c31af7Sopenharmony_ci} 654e5c31af7Sopenharmony_ci 655e5c31af7Sopenharmony_cistatic int referenceTriangleNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner, const int outer0, const int outer1, const int outer2) 656e5c31af7Sopenharmony_ci{ 657e5c31af7Sopenharmony_ci if (inner == 1) 658e5c31af7Sopenharmony_ci { 659e5c31af7Sopenharmony_ci if (outer0 == 1 && outer1 == 1 && outer2 == 1) 660e5c31af7Sopenharmony_ci return 1; 661e5c31af7Sopenharmony_ci else 662e5c31af7Sopenharmony_ci return referenceTriangleNonPointModePrimitiveCount(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 663e5c31af7Sopenharmony_ci outer0, outer1, outer2); 664e5c31af7Sopenharmony_ci } 665e5c31af7Sopenharmony_ci else 666e5c31af7Sopenharmony_ci { 667e5c31af7Sopenharmony_ci int result = outer0 + outer1 + outer2; 668e5c31af7Sopenharmony_ci 669e5c31af7Sopenharmony_ci const int numInnerTriangles = inner/2; 670e5c31af7Sopenharmony_ci for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++) 671e5c31af7Sopenharmony_ci { 672e5c31af7Sopenharmony_ci const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1); 673e5c31af7Sopenharmony_ci 674e5c31af7Sopenharmony_ci if (curInnerTriangleLevel == 1) 675e5c31af7Sopenharmony_ci result += 4; 676e5c31af7Sopenharmony_ci else 677e5c31af7Sopenharmony_ci result += 2*3*curInnerTriangleLevel; 678e5c31af7Sopenharmony_ci } 679e5c31af7Sopenharmony_ci 680e5c31af7Sopenharmony_ci return result; 681e5c31af7Sopenharmony_ci } 682e5c31af7Sopenharmony_ci} 683e5c31af7Sopenharmony_ci 684e5c31af7Sopenharmony_cistatic int referenceQuadNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner0, const int inner1, const int outer0, const int outer1, const int outer2, const int outer3) 685e5c31af7Sopenharmony_ci{ 686e5c31af7Sopenharmony_ci if (inner0 == 1 || inner1 == 1) 687e5c31af7Sopenharmony_ci { 688e5c31af7Sopenharmony_ci if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1) 689e5c31af7Sopenharmony_ci return 2; 690e5c31af7Sopenharmony_ci else 691e5c31af7Sopenharmony_ci return referenceQuadNonPointModePrimitiveCount(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 692e5c31af7Sopenharmony_ci inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2, 693e5c31af7Sopenharmony_ci outer0, outer1, outer2, outer3); 694e5c31af7Sopenharmony_ci } 695e5c31af7Sopenharmony_ci else 696e5c31af7Sopenharmony_ci return 2*(inner0-2)*(inner1-2) + 2*(inner0-2) + 2*(inner1-2) + outer0+outer1+outer2+outer3; 697e5c31af7Sopenharmony_ci} 698e5c31af7Sopenharmony_ci 699e5c31af7Sopenharmony_cistatic inline int referenceIsolineNonPointModePrimitiveCount (const int outer0, const int outer1) 700e5c31af7Sopenharmony_ci{ 701e5c31af7Sopenharmony_ci return outer0*outer1; 702e5c31af7Sopenharmony_ci} 703e5c31af7Sopenharmony_ci 704e5c31af7Sopenharmony_cistatic int referenceNonPointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels) 705e5c31af7Sopenharmony_ci{ 706e5c31af7Sopenharmony_ci if (isPatchDiscarded(primitiveType, outerLevels)) 707e5c31af7Sopenharmony_ci return 0; 708e5c31af7Sopenharmony_ci 709e5c31af7Sopenharmony_ci switch (primitiveType) 710e5c31af7Sopenharmony_ci { 711e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_TRIANGLES: 712e5c31af7Sopenharmony_ci { 713e5c31af7Sopenharmony_ci int inner; 714e5c31af7Sopenharmony_ci int outer[3]; 715e5c31af7Sopenharmony_ci getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]); 716e5c31af7Sopenharmony_ci return referenceTriangleNonPointModePrimitiveCount(spacingMode, inner, outer[0], outer[1], outer[2]); 717e5c31af7Sopenharmony_ci } 718e5c31af7Sopenharmony_ci 719e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_QUADS: 720e5c31af7Sopenharmony_ci { 721e5c31af7Sopenharmony_ci int inner[2]; 722e5c31af7Sopenharmony_ci int outer[4]; 723e5c31af7Sopenharmony_ci getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]); 724e5c31af7Sopenharmony_ci return referenceQuadNonPointModePrimitiveCount(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]); 725e5c31af7Sopenharmony_ci } 726e5c31af7Sopenharmony_ci 727e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_ISOLINES: 728e5c31af7Sopenharmony_ci { 729e5c31af7Sopenharmony_ci int outer[2]; 730e5c31af7Sopenharmony_ci getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]); 731e5c31af7Sopenharmony_ci return referenceIsolineNonPointModePrimitiveCount(outer[0], outer[1]); 732e5c31af7Sopenharmony_ci } 733e5c31af7Sopenharmony_ci 734e5c31af7Sopenharmony_ci default: 735e5c31af7Sopenharmony_ci DE_ASSERT(false); 736e5c31af7Sopenharmony_ci return 0; 737e5c31af7Sopenharmony_ci } 738e5c31af7Sopenharmony_ci} 739e5c31af7Sopenharmony_ci 740e5c31af7Sopenharmony_ciint numVerticesPerPrimitive (const TessPrimitiveType primitiveType, const bool usePointMode) 741e5c31af7Sopenharmony_ci{ 742e5c31af7Sopenharmony_ci if (usePointMode) 743e5c31af7Sopenharmony_ci return 1; 744e5c31af7Sopenharmony_ci 745e5c31af7Sopenharmony_ci switch (primitiveType) 746e5c31af7Sopenharmony_ci { 747e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_TRIANGLES: return 3; 748e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_QUADS: return 3; // quads are composed of two triangles 749e5c31af7Sopenharmony_ci case TESSPRIMITIVETYPE_ISOLINES: return 2; 750e5c31af7Sopenharmony_ci default: 751e5c31af7Sopenharmony_ci DE_ASSERT(false); 752e5c31af7Sopenharmony_ci return 0; 753e5c31af7Sopenharmony_ci } 754e5c31af7Sopenharmony_ci} 755e5c31af7Sopenharmony_ci 756e5c31af7Sopenharmony_ciint referencePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels) 757e5c31af7Sopenharmony_ci{ 758e5c31af7Sopenharmony_ci return usePointMode ? referencePointModePrimitiveCount (primitiveType, spacingMode, innerLevels, outerLevels) 759e5c31af7Sopenharmony_ci : referenceNonPointModePrimitiveCount (primitiveType, spacingMode, innerLevels, outerLevels); 760e5c31af7Sopenharmony_ci} 761e5c31af7Sopenharmony_ci 762e5c31af7Sopenharmony_ci//! In point mode this should return the number of unique vertices, while in non-point mode the maximum theoretical number of verticies. 763e5c31af7Sopenharmony_ci//! Actual implementation will likely return a much smaller number because the shader isn't required to be run for duplicate coordinates. 764e5c31af7Sopenharmony_ciint referenceVertexCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels) 765e5c31af7Sopenharmony_ci{ 766e5c31af7Sopenharmony_ci return referencePrimitiveCount(primitiveType, spacingMode, usePointMode, innerLevels, outerLevels) 767e5c31af7Sopenharmony_ci * numVerticesPerPrimitive(primitiveType, usePointMode); 768e5c31af7Sopenharmony_ci} 769e5c31af7Sopenharmony_ci 770e5c31af7Sopenharmony_civoid requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags) 771e5c31af7Sopenharmony_ci{ 772e5c31af7Sopenharmony_ci const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice); 773e5c31af7Sopenharmony_ci 774e5c31af7Sopenharmony_ci if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader) 775e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Tessellation shader not supported"); 776e5c31af7Sopenharmony_ci 777e5c31af7Sopenharmony_ci if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader) 778e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Geometry shader not supported"); 779e5c31af7Sopenharmony_ci 780e5c31af7Sopenharmony_ci if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64) 781e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Double-precision floats not supported"); 782e5c31af7Sopenharmony_ci 783e5c31af7Sopenharmony_ci if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics) 784e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline"); 785e5c31af7Sopenharmony_ci 786e5c31af7Sopenharmony_ci if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics) 787e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader"); 788e5c31af7Sopenharmony_ci 789e5c31af7Sopenharmony_ci if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize) 790e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in"); 791e5c31af7Sopenharmony_ci} 792e5c31af7Sopenharmony_ci 793e5c31af7Sopenharmony_ci} // tessellation 794e5c31af7Sopenharmony_ci} // vkt 795