blob: 709e21d42481538f935bde52af7a9453c1a3eb42 [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (c) 2016 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Geometry Utilities
*//*--------------------------------------------------------------------*/
#include "vktGeometryTestsUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkDefs.hpp"
#include "tcuImageCompare.hpp"
#include "tcuImageIO.hpp"
#include "deMath.h"
using namespace vk;
namespace vkt
{
namespace geometry
{
GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface& vk,
const VkDevice device,
const VkShaderStageFlagBits stage,
const ProgramBinary& binary,
const VkSpecializationInfo* specInfo)
{
VkShaderModule module;
switch (stage)
{
case (VK_SHADER_STAGE_VERTEX_BIT):
DE_ASSERT(m_vertexShaderModule.get() == DE_NULL);
m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
module = *m_vertexShaderModule;
break;
case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT):
DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL);
m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
module = *m_tessControlShaderModule;
break;
case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT):
DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL);
m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
module = *m_tessEvaluationShaderModule;
break;
case (VK_SHADER_STAGE_GEOMETRY_BIT):
DE_ASSERT(m_geometryShaderModule.get() == DE_NULL);
m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
module = *m_geometryShaderModule;
break;
case (VK_SHADER_STAGE_FRAGMENT_BIT):
DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL);
m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
module = *m_fragmentShaderModule;
break;
default:
DE_FATAL("Invalid shader stage");
return *this;
}
const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
stage, // VkShaderStageFlagBits stage;
module, // VkShaderModule module;
"main", // const char* pName;
specInfo, // const VkSpecializationInfo* pSpecializationInfo;
};
m_shaderStageFlags |= stage;
m_shaderStages.push_back(pipelineShaderStageInfo);
return *this;
}
GraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride)
{
const VkVertexInputBindingDescription bindingDesc =
{
0u, // uint32_t binding;
stride, // uint32_t stride;
VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
};
const VkVertexInputAttributeDescription attributeDesc =
{
0u, // uint32_t location;
0u, // uint32_t binding;
vertexFormat, // VkFormat format;
0u, // uint32_t offset;
};
m_vertexInputBindings.clear();
m_vertexInputBindings.push_back(bindingDesc);
m_vertexInputAttributes.clear();
m_vertexInputAttributes.push_back(attributeDesc);
return *this;
}
template<typename T>
inline const T* dataPointer (const std::vector<T>& vec)
{
return (vec.size() != 0 ? &vec[0] : DE_NULL);
}
Move<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface& vk,
const VkDevice device,
const VkPipelineLayout pipelineLayout,
const VkRenderPass renderPass)
{
const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
static_cast<deUint32>(m_vertexInputBindings.size()), // uint32_t vertexBindingDescriptionCount;
dataPointer(m_vertexInputBindings), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
static_cast<deUint32>(m_vertexInputAttributes.size()), // uint32_t vertexAttributeDescriptionCount;
dataPointer(m_vertexInputAttributes), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
};
const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
: m_primitiveTopology;
VkBool32 primitiveRestartEnable = VK_TRUE;
switch(m_primitiveTopology)
{
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
primitiveRestartEnable = VK_FALSE;
break;
default:
break;
};
const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
topology, // VkPrimitiveTopology topology;
primitiveRestartEnable, // VkBool32 primitiveRestartEnable;
};
const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags;
m_patchControlPoints, // uint32_t patchControlPoints;
};
const VkViewport viewport = makeViewport(m_renderSize);
const VkRect2D scissor = makeRect2D(m_renderSize);
const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
1u, // uint32_t viewportCount;
&viewport, // const VkViewport* pViewports;
1u, // uint32_t scissorCount;
&scissor, // const VkRect2D* pScissors;
};
const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0);
const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
VK_FALSE, // VkBool32 depthClampEnable;
isRasterizationDisabled, // VkBool32 rasterizerDiscardEnable;
VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
m_cullModeFlags, // VkCullModeFlags cullMode;
m_frontFace, // VkFrontFace frontFace;
VK_FALSE, // VkBool32 depthBiasEnable;
0.0f, // float depthBiasConstantFactor;
0.0f, // float depthBiasClamp;
0.0f, // float depthBiasSlopeFactor;
1.0f, // float lineWidth;
};
const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
VK_FALSE, // VkBool32 sampleShadingEnable;
0.0f, // float minSampleShading;
DE_NULL, // const VkSampleMask* pSampleMask;
VK_FALSE, // VkBool32 alphaToCoverageEnable;
VK_FALSE // VkBool32 alphaToOneEnable;
};
const VkStencilOpState stencilOpState = makeStencilOpState(
VK_STENCIL_OP_KEEP, // stencil fail
VK_STENCIL_OP_KEEP, // depth & stencil pass
VK_STENCIL_OP_KEEP, // depth only fail
VK_COMPARE_OP_NEVER, // compare op
0u, // compare mask
0u, // write mask
0u); // reference
const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
VK_FALSE, // VkBool32 depthTestEnable;
VK_FALSE, // VkBool32 depthWriteEnable;
VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
VK_FALSE, // VkBool32 depthBoundsTestEnable;
VK_FALSE, // VkBool32 stencilTestEnable;
stencilOpState, // VkStencilOpState front;
stencilOpState, // VkStencilOpState back;
0.0f, // float minDepthBounds;
1.0f, // float maxDepthBounds;
};
const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
{
m_blendEnable, // VkBool32 blendEnable;
VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor;
VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor;
VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor;
VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor;
VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
colorComponentsAll, // VkColorComponentFlags colorWriteMask;
};
const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
VK_FALSE, // VkBool32 logicOpEnable;
VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
1u, // deUint32 attachmentCount;
&pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
{ 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
};
const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
{
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
static_cast<deUint32>(m_shaderStages.size()), // deUint32 stageCount;
&m_shaderStages[0], // const VkPipelineShaderStageCreateInfo* pStages;
&vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
&pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
(m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo* pTessellationState;
(isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo), // const VkPipelineViewportStateCreateInfo* pViewportState;
&pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
(isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo), // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
(isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo), // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
(isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo), // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
pipelineLayout, // VkPipelineLayout layout;
renderPass, // VkRenderPass renderPass;
0u, // deUint32 subpass;
DE_NULL, // VkPipeline basePipelineHandle;
0, // deInt32 basePipelineIndex;
};
return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
}
std::string inputTypeToGLString (const VkPrimitiveTopology& inputType)
{
switch (inputType)
{
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
return "points";
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
return "lines";
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
return "lines_adjacency";
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
return "triangles";
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
return "triangles_adjacency";
default:
DE_ASSERT(DE_FALSE);
return "error";
}
}
std::string outputTypeToGLString (const VkPrimitiveTopology& outputType)
{
switch (outputType)
{
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
return "points";
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
return "line_strip";
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
return "triangle_strip";
default:
DE_ASSERT(DE_FALSE);
return "error";
}
}
size_t calcOutputVertices (const VkPrimitiveTopology& inputType)
{
switch (inputType)
{
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
return 1 * 3;
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
return 2 * 3;
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
return 4 * 3;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
return 3 * 3;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
return 6 * 3;
default:
DE_ASSERT(DE_FALSE);
return 0;
}
}
VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage, const deUint32 numArrayLayers)
{
const VkImageCreateInfo imageInfo =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkImageCreateFlags)0, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
format, // VkFormat format;
makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
1u, // uint32_t mipLevels;
numArrayLayers, // uint32_t arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
usage, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
0u, // uint32_t queueFamilyIndexCount;
DE_NULL, // const uint32_t* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
};
return imageInfo;
}
VkBufferImageCopy makeBufferImageCopy (const vk::VkDeviceSize& bufferOffset,
const vk::VkImageSubresourceLayers& imageSubresource,
const vk::VkOffset3D& imageOffset,
const vk::VkExtent3D& imageExtent)
{
const VkBufferImageCopy copyParams =
{
bufferOffset, // VkDeviceSize bufferOffset;
0u, // deUint32 bufferRowLength;
0u, // deUint32 bufferImageHeight;
imageSubresource, // VkImageSubresourceLayers imageSubresource;
imageOffset, // VkOffset3D imageOffset;
imageExtent, // VkExtent3D imageExtent;
};
return copyParams;
}
bool compareWithFileImage (Context& context, const tcu::ConstPixelBufferAccess& resultImage, std::string testName)
{
tcu::TextureLevel referenceImage;
std::string fileName="vulkan/data/geometry/"+testName+".png";
tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), fileName.c_str());
if (tcu::fuzzyCompare(context.getTestContext().getLog(), "ImageComparison", "Image Comparison",
referenceImage.getAccess(), resultImage, 0.001f, tcu::COMPARE_LOG_RESULT))
return tcu::intThresholdPositionDeviationCompare(context.getTestContext().getLog(), "ImageComparison", "Image Comparison",
referenceImage.getAccess(), resultImage, tcu::UVec4(1u, 1u, 1u, 1u), tcu::IVec3(2,2,2), false, tcu::COMPARE_LOG_RESULT);
else
return false;
}
void fillBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize offset, const VkDeviceSize size, const VkFormat format, const tcu::Vec4& color)
{
const tcu::TextureFormat textureFormat = mapVkFormat(format);
const deUint32 colorPixelSize = static_cast<deUint32>(tcu::getPixelSize(textureFormat));
tcu::TextureLevel colorPixelBuffer (textureFormat, 1, 1);
tcu::PixelBufferAccess colorPixel (colorPixelBuffer);
colorPixel.setPixel(color, 0, 0);
const deUint8* src = static_cast<deUint8*>(colorPixel.getDataPtr());
deUint8* dstBase = static_cast<deUint8*>(alloc.getHostPtr());
deUint8* dst = &dstBase[offset];
for (deUint32 pixelPos = 0; pixelPos < size; pixelPos += colorPixelSize)
deMemcpy(&dst[pixelPos], src, colorPixelSize);
flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset() + offset, size);
}
void fillBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize offset, const VkDeviceSize size, const VkFormat format, const float depth)
{
const tcu::TextureFormat textureFormat = mapVkFormat(format);
const deUint32 colorPixelSize = static_cast<deUint32>(tcu::getPixelSize(textureFormat));
tcu::TextureLevel colorPixelBuffer (textureFormat, 1, 1);
tcu::PixelBufferAccess colorPixel (colorPixelBuffer);
colorPixel.setPixDepth(depth, 0, 0);
const deUint8* src = static_cast<deUint8*>(colorPixel.getDataPtr());
deUint8* dstBase = static_cast<deUint8*>(alloc.getHostPtr());
deUint8* dst = &dstBase[offset];
for (deUint32 pixelPos = 0; pixelPos < size; pixelPos += colorPixelSize)
deMemcpy(&dst[pixelPos], src, colorPixelSize);
flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset() + offset, size);
}
VkBool32 checkPointSize (const InstanceInterface& vki, const VkPhysicalDevice physDevice)
{
const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures (vki, physDevice);
return features.shaderTessellationAndGeometryPointSize;
}
} //geometry
} //vkt