From 54c7f3a440813a684d8f1631565ba0a2d8b55e33 Mon Sep 17 00:00:00 2001 From: Kantoch Date: Thu, 13 Oct 2016 14:29:53 +0200 Subject: [PATCH] Multisample Shader BuiltIn Tests Tests for gl_SampleID, gl_SamplePosition, gl_SampleMaskIn[], gl_SampleMask[] New tests: - dEQP-VK.pipeline.multisample_shader_builtin.* Issue #450 Change-Id: I82875fc20d01232127f01186644a04d67ddb8833 --- android/cts/master/vk-master.txt | 76 ++ .../modules/vulkan/pipeline/CMakeLists.txt | 8 + .../vulkan/pipeline/vktPipelineMultisampleBase.cpp | 166 +++ .../vulkan/pipeline/vktPipelineMultisampleBase.hpp | 146 +++ .../pipeline/vktPipelineMultisampleBaseResolve.cpp | 550 +++++++++ .../pipeline/vktPipelineMultisampleBaseResolve.hpp | 67 ++ ...lineMultisampleBaseResolveAndPerSampleFetch.cpp | 1026 ++++++++++++++++ ...lineMultisampleBaseResolveAndPerSampleFetch.hpp | 77 ++ .../vktPipelineMultisampleInterpolationTests.cpp | 1259 +++----------------- .../vktPipelineMultisampleInterpolationTests.hpp | 3 +- .../vktPipelineMultisampleShaderBuiltInTests.cpp | 1077 +++++++++++++++++ .../vktPipelineMultisampleShaderBuiltInTests.hpp | 38 + .../pipeline/vktPipelineMultisampleTestsUtil.cpp | 8 +- .../pipeline/vktPipelineMultisampleTestsUtil.hpp | 4 +- .../modules/vulkan/pipeline/vktPipelineTests.cpp | 2 + external/vulkancts/mustpass/1.0.2/vk-default.txt | 76 ++ 16 files changed, 3507 insertions(+), 1076 deletions(-) create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.cpp create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.hpp create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.cpp create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.hpp create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.cpp create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.hpp diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index d2bfa17..3076317 100644 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -87177,6 +87177,82 @@ dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_16 dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_32 dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_32 dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_unorm_rate_vertex dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_unorm_rate_instance dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_snorm_rate_vertex diff --git a/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt b/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt index d3c7850..6b36ec2 100644 --- a/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt @@ -29,8 +29,16 @@ set(DEQP_VK_PIPELINE_SRCS vktPipelineMultisampleTestsUtil.hpp vktPipelineMultisampleTests.cpp vktPipelineMultisampleTests.hpp + vktPipelineMultisampleBase.cpp + vktPipelineMultisampleBase.hpp + vktPipelineMultisampleBaseResolve.cpp + vktPipelineMultisampleBaseResolve.hpp + vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp + vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp vktPipelineMultisampleInterpolationTests.cpp vktPipelineMultisampleInterpolationTests.hpp + vktPipelineMultisampleShaderBuiltInTests.cpp + vktPipelineMultisampleShaderBuiltInTests.hpp vktPipelineMultisampleImageTests.cpp vktPipelineMultisampleImageTests.hpp vktPipelineInputAssemblyTests.cpp diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.cpp new file mode 100644 index 0000000..07c3729 --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.cpp @@ -0,0 +1,166 @@ +/*------------------------------------------------------------------------ +* Vulkan Conformance Tests +* ------------------------ +* +* 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 vktPipelineMultisampleBase.cpp +* \brief Multisample Tests Base Classes +*//*--------------------------------------------------------------------*/ + +#include "vktPipelineMultisampleBase.hpp" +#include "vkQueryUtil.hpp" + +namespace vkt +{ +namespace pipeline +{ +namespace multisample +{ + +using namespace vk; + +void MultisampleInstanceBase::validateImageSize (const InstanceInterface& instance, + const VkPhysicalDevice physicalDevice, + const ImageType imageType, + const tcu::UVec3& imageSize) const +{ + const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice); + + bool isImageSizeValid = true; + + switch (imageType) + { + case IMAGE_TYPE_1D: + isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension1D; + break; + case IMAGE_TYPE_1D_ARRAY: + isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension1D && + imageSize.z() <= deviceProperties.limits.maxImageArrayLayers; + break; + case IMAGE_TYPE_2D: + isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension2D && + imageSize.y() <= deviceProperties.limits.maxImageDimension2D; + break; + case IMAGE_TYPE_2D_ARRAY: + isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension2D && + imageSize.y() <= deviceProperties.limits.maxImageDimension2D && + imageSize.z() <= deviceProperties.limits.maxImageArrayLayers; + break; + case IMAGE_TYPE_CUBE: + isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimensionCube && + imageSize.y() <= deviceProperties.limits.maxImageDimensionCube; + break; + case IMAGE_TYPE_CUBE_ARRAY: + isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimensionCube && + imageSize.y() <= deviceProperties.limits.maxImageDimensionCube && + imageSize.z() <= deviceProperties.limits.maxImageArrayLayers; + break; + case IMAGE_TYPE_3D: + isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension3D && + imageSize.y() <= deviceProperties.limits.maxImageDimension3D && + imageSize.z() <= deviceProperties.limits.maxImageDimension3D; + break; + default: + DE_FATAL("Unknown image type"); + } + + if (!isImageSizeValid) + { + std::ostringstream notSupportedStream; + + notSupportedStream << "Image type (" << getImageTypeName(imageType) << ") with size (" << imageSize.x() << ", " << imageSize.y() << ", " << imageSize.z() << ") not supported by device" << std::endl; + + const std::string notSupportedString = notSupportedStream.str(); + + TCU_THROW(NotSupportedError, notSupportedString.c_str()); + } +} + +void MultisampleInstanceBase::validateImageFeatureFlags (const InstanceInterface& instance, + const VkPhysicalDevice physicalDevice, + const VkFormat format, + const VkFormatFeatureFlags featureFlags) const +{ + const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format); + + if ((formatProperties.optimalTilingFeatures & featureFlags) != featureFlags) + { + std::ostringstream notSupportedStream; + + notSupportedStream << "Device does not support image format " << format << " for feature flags " << featureFlags << std::endl; + + const std::string notSupportedString = notSupportedStream.str(); + + TCU_THROW(NotSupportedError, notSupportedString.c_str()); + } +} + +void MultisampleInstanceBase::validateImageInfo (const InstanceInterface& instance, + const VkPhysicalDevice physicalDevice, + const VkImageCreateInfo& imageInfo) const +{ + VkImageFormatProperties imageFormatProps; + instance.getPhysicalDeviceImageFormatProperties(physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &imageFormatProps); + + if (imageFormatProps.maxExtent.width < imageInfo.extent.width || + imageFormatProps.maxExtent.height < imageInfo.extent.height || + imageFormatProps.maxExtent.depth < imageInfo.extent.depth) + { + std::ostringstream notSupportedStream; + + notSupportedStream << "Image extent (" + << imageInfo.extent.width << ", " + << imageInfo.extent.height << ", " + << imageInfo.extent.depth + << ") exceeds allowed maximum (" + << imageFormatProps.maxExtent.width << ", " + << imageFormatProps.maxExtent.height << ", " + << imageFormatProps.maxExtent.depth + << ")" + << std::endl; + + const std::string notSupportedString = notSupportedStream.str(); + + TCU_THROW(NotSupportedError, notSupportedString.c_str()); + } + + if (imageFormatProps.maxArrayLayers < imageInfo.arrayLayers) + { + std::ostringstream notSupportedStream; + + notSupportedStream << "Image layers count of " << imageInfo.arrayLayers << " exceeds allowed maximum which is " << imageFormatProps.maxArrayLayers << std::endl; + + const std::string notSupportedString = notSupportedStream.str(); + + TCU_THROW(NotSupportedError, notSupportedString.c_str()); + } + + if (!(imageFormatProps.sampleCounts & imageInfo.samples)) + { + std::ostringstream notSupportedStream; + + notSupportedStream << "Samples count of " << imageInfo.samples << " not supported for image" << std::endl; + + const std::string notSupportedString = notSupportedStream.str(); + + TCU_THROW(NotSupportedError, notSupportedString.c_str()); + } +} + +} // multisample +} // pipeline +} // vkt diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.hpp new file mode 100644 index 0000000..ed20661 --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.hpp @@ -0,0 +1,146 @@ +#ifndef _VKTPIPELINEMULTISAMPLEBASE_HPP +#define _VKTPIPELINEMULTISAMPLEBASE_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * 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 vktPipelineMultisampleBase.hpp + * \brief Multisample Tests Base Classes + *//*--------------------------------------------------------------------*/ + +#include "vktPipelineMultisampleTestsUtil.hpp" +#include "vktTestCase.hpp" +#include "tcuVector.hpp" + +namespace vkt +{ +namespace pipeline +{ +namespace multisample +{ + +struct ImageMSParams +{ + ImageMSParams(const vk::VkSampleCountFlagBits samples, const tcu::UVec3& size) : numSamples(samples), imageSize(size) {} + + vk::VkSampleCountFlagBits numSamples; + tcu::UVec3 imageSize; +}; + +class MultisampleCaseBase : public TestCase +{ +public: + MultisampleCaseBase (tcu::TestContext& testCtx, + const std::string& name, + const ImageMSParams& imageMSParams) + : TestCase(testCtx, name, "") + , m_imageMSParams(imageMSParams) + {} + +protected: + const ImageMSParams m_imageMSParams; +}; + +typedef MultisampleCaseBase* (*MultisampleCaseFuncPtr)(tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams); + +class MultisampleInstanceBase : public TestInstance +{ +public: + MultisampleInstanceBase (Context& context, + const ImageMSParams& imageMSParams) + : TestInstance (context) + , m_imageMSParams (imageMSParams) + , m_imageType (IMAGE_TYPE_2D) + , m_imageFormat (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)) + {} + + typedef std::vector VertexAttribDescVec; + + struct VertexDataDesc + { + vk::VkPrimitiveTopology primitiveTopology; + deUint32 verticesCount; + deUint32 dataStride; + vk::VkDeviceSize dataSize; + VertexAttribDescVec vertexAttribDescVec; + }; + +protected: + + void validateImageSize (const vk::InstanceInterface& instance, + const vk::VkPhysicalDevice physicalDevice, + const ImageType imageType, + const tcu::UVec3& imageSize) const; + + void validateImageFeatureFlags (const vk::InstanceInterface& instance, + const vk::VkPhysicalDevice physicalDevice, + const vk::VkFormat format, + const vk::VkFormatFeatureFlags featureFlags) const; + + void validateImageInfo (const vk::InstanceInterface& instance, + const vk::VkPhysicalDevice physicalDevice, + const vk::VkImageCreateInfo& imageInfo) const; + + virtual VertexDataDesc getVertexDataDescripton (void) const = 0; + + virtual void uploadVertexData (const vk::Allocation& vertexBufferAllocation, + const VertexDataDesc& vertexDataDescripton) const = 0; +protected: + const ImageMSParams m_imageMSParams; + const ImageType m_imageType; + const tcu::TextureFormat m_imageFormat; +}; + +} // multisample + +template +tcu::TestCaseGroup* makeMSGroup (tcu::TestContext& testCtx, + const std::string groupName, + const tcu::UVec3 imageSizes[], + const deUint32 imageSizesElemCount, + const vk::VkSampleCountFlagBits imageSamples[], + const deUint32 imageSamplesElemCount) +{ + de::MovePtr caseGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str(), "")); + + for (deUint32 imageSizeNdx = 0u; imageSizeNdx < imageSizesElemCount; ++imageSizeNdx) + { + const tcu::UVec3 imageSize = imageSizes[imageSizeNdx]; + std::ostringstream imageSizeStream; + + imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z(); + + de::MovePtr sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), "")); + + for (deUint32 imageSamplesNdx = 0u; imageSamplesNdx < imageSamplesElemCount; ++imageSamplesNdx) + { + const vk::VkSampleCountFlagBits samples = imageSamples[imageSamplesNdx]; + const multisample::ImageMSParams imageMSParams = multisample::ImageMSParams(samples, imageSize); + + sizeGroup->addChild(CaseClass::createCase(testCtx, "samples_" + de::toString(samples), imageMSParams)); + } + + caseGroup->addChild(sizeGroup.release()); + } + return caseGroup.release(); +} + +} // pipeline +} // vkt + +#endif // _VKTPIPELINEMULTISAMPLEBASE_HPP diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.cpp new file mode 100644 index 0000000..4ad1644 --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.cpp @@ -0,0 +1,550 @@ +/*------------------------------------------------------------------------ +* Vulkan Conformance Tests +* ------------------------ +* +* 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 vktPipelineMultisampleBaseResolve.cpp +* \brief Base class for tests that check results of multisample resolve +*//*--------------------------------------------------------------------*/ + +#include "vktPipelineMultisampleBaseResolve.hpp" +#include "vktPipelineMakeUtil.hpp" +#include "vkBuilderUtil.hpp" +#include "vkQueryUtil.hpp" +#include + +namespace vkt +{ +namespace pipeline +{ +namespace multisample +{ + +using namespace vk; + +tcu::TestStatus MSInstanceBaseResolve::iterate (void) +{ + const InstanceInterface& instance = m_context.getInstanceInterface(); + const DeviceInterface& deviceInterface = m_context.getDeviceInterface(); + const VkDevice device = m_context.getDevice(); + const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); + Allocator& allocator = m_context.getDefaultAllocator(); + const VkQueue queue = m_context.getUniversalQueue(); + const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); + + VkImageCreateInfo imageMSInfo; + VkImageCreateInfo imageRSInfo; + + // Check if image size does not exceed device limits + validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize); + + // Check if device supports image format as color attachment + validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); + + imageMSInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageMSInfo.pNext = DE_NULL; + imageMSInfo.flags = 0u; + imageMSInfo.imageType = mapImageType(m_imageType); + imageMSInfo.format = mapTextureFormat(m_imageFormat); + imageMSInfo.extent = makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize)); + imageMSInfo.arrayLayers = getNumLayers(m_imageType, m_imageMSParams.imageSize); + imageMSInfo.mipLevels = 1u; + imageMSInfo.samples = m_imageMSParams.numSamples; + imageMSInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageMSInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageMSInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + imageMSInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageMSInfo.queueFamilyIndexCount = 0u; + imageMSInfo.pQueueFamilyIndices = DE_NULL; + + if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY) + { + imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + } + + validateImageInfo(instance, physicalDevice, imageMSInfo); + + const de::UniquePtr imageMS(new Image(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any)); + + imageRSInfo = imageMSInfo; + imageRSInfo.samples = VK_SAMPLE_COUNT_1_BIT; + + validateImageInfo(instance, physicalDevice, imageRSInfo); + + const de::UniquePtr imageRS(new Image(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any)); + + // Create render pass + const VkAttachmentDescription attachmentMSDesc = + { + (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags; + imageMSInfo.format, // VkFormat format; + imageMSInfo.samples, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; + }; + + const VkAttachmentDescription attachmentRSDesc = + { + (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags; + imageRSInfo.format, // VkFormat format; + imageRSInfo.samples, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; + }; + + const VkAttachmentDescription attachments[] = { attachmentMSDesc, attachmentRSDesc }; + + const VkAttachmentReference attachmentMSRef = + { + 0u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + + const VkAttachmentReference attachmentRSRef = + { + 1u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + + const VkAttachmentReference* resolveAttachment = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? DE_NULL : &attachmentRSRef; + + const VkSubpassDescription subpassDescription = + { + (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags; + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + 0u, // deUint32 inputAttachmentCount; + DE_NULL, // const VkAttachmentReference* pInputAttachments; + 1u, // deUint32 colorAttachmentCount; + &attachmentMSRef, // const VkAttachmentReference* pColorAttachments; + resolveAttachment, // const VkAttachmentReference* pResolveAttachments; + DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; + 0u, // deUint32 preserveAttachmentCount; + DE_NULL // const deUint32* pPreserveAttachments; + }; + + const VkRenderPassCreateInfo renderPassInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags; + 2u, // deUint32 attachmentCount; + attachments, // const VkAttachmentDescription* pAttachments; + 1u, // deUint32 subpassCount; + &subpassDescription, // const VkSubpassDescription* pSubpasses; + 0u, // deUint32 dependencyCount; + DE_NULL // const VkSubpassDependency* pDependencies; + }; + + const Unique renderPass(createRenderPass(deviceInterface, device, &renderPassInfo)); + + const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers); + + // Create color attachments image views + const Unique imageMSView(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange)); + const Unique imageRSView(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange)); + + const VkImageView attachmentsViews[] = { *imageMSView, *imageRSView }; + + // Create framebuffer + const VkFramebufferCreateInfo framebufferInfo = + { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkFramebufferCreateFlags)0u, // VkFramebufferCreateFlags flags; + *renderPass, // VkRenderPass renderPass; + 2u, // uint32_t attachmentCount; + attachmentsViews, // const VkImageView* pAttachments; + imageMSInfo.extent.width, // uint32_t width; + imageMSInfo.extent.height, // uint32_t height; + imageMSInfo.arrayLayers, // uint32_t layers; + }; + + const Unique framebuffer(createFramebuffer(deviceInterface, device, &framebufferInfo)); + + // Create pipeline layout + const VkPipelineLayoutCreateInfo pipelineLayoutParams = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineLayoutCreateFlags)0u, // VkPipelineLayoutCreateFlags flags; + 0u, // deUint32 setLayoutCount; + DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; + 0u, // deUint32 pushConstantRangeCount; + DE_NULL, // const VkPushConstantRange* pPushConstantRanges; + }; + + const Unique pipelineLayout(createPipelineLayout(deviceInterface, device, &pipelineLayoutParams)); + + // Create vertex attributes data + const VertexDataDesc vertexDataDesc = getVertexDataDescripton(); + + de::SharedPtr vertexBuffer = de::SharedPtr(new Buffer(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible)); + const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation(); + + uploadVertexData(vertexBufferAllocation, vertexDataDesc); + + flushMappedMemoryRange(deviceInterface, device, vertexBufferAllocation.getMemory(), vertexBufferAllocation.getOffset(), VK_WHOLE_SIZE); + + const VkVertexInputBindingDescription vertexBinding = + { + 0u, // deUint32 binding; + vertexDataDesc.dataStride, // deUint32 stride; + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate; + }; + + const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineVertexInputStateCreateFlags)0u, // VkPipelineVertexInputStateCreateFlags flags; + 1u, // uint32_t vertexBindingDescriptionCount; + &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + static_cast(vertexDataDesc.vertexAttribDescVec.size()), // uint32_t vertexAttributeDescriptionCount; + dataPointer(vertexDataDesc.vertexAttribDescVec), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineInputAssemblyStateCreateFlags)0u, // VkPipelineInputAssemblyStateCreateFlags flags; + vertexDataDesc.primitiveTopology, // VkPrimitiveTopology topology; + VK_FALSE, // VkBool32 primitiveRestartEnable; + }; + + const VkViewport viewport = + { + 0.0f, 0.0f, + static_cast(imageMSInfo.extent.width), static_cast(imageMSInfo.extent.height), + 0.0f, 1.0f + }; + + const VkRect2D scissor = + { + makeOffset2D(0, 0), + makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height), + }; + + const VkPipelineViewportStateCreateInfo viewportStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineViewportStateCreateFlags)0u, // VkPipelineViewportStateCreateFlags flags; + 1u, // uint32_t viewportCount; + &viewport, // const VkViewport* pViewports; + 1u, // uint32_t scissorCount; + &scissor, // const VkRect2D* pScissors; + }; + + const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineRasterizationStateCreateFlags)0u, // VkPipelineRasterizationStateCreateFlags flags; + VK_FALSE, // VkBool32 depthClampEnable; + VK_FALSE, // VkBool32 rasterizerDiscardEnable; + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; + VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; + VK_FALSE, // VkBool32 depthBiasEnable; + 0.0f, // float depthBiasConstantFactor; + 0.0f, // float depthBiasClamp; + 0.0f, // float depthBiasSlopeFactor; + 1.0f, // float lineWidth; + }; + + const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags; + imageMSInfo.samples, // VkSampleCountFlagBits rasterizationSamples; + VK_TRUE, // VkBool32 sampleShadingEnable; + 1.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_ALWAYS, // compare op + 0u, // compare mask + 0u, // write mask + 0u // reference + ); + + const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineDepthStencilStateCreateFlags)0u, // 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 colorBlendAttachmentState = + { + VK_FALSE, // VkBool32 blendEnable; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; + colorComponentsAll, // VkColorComponentFlags colorWriteMask; + }; + + const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineColorBlendStateCreateFlags)0u, // VkPipelineColorBlendStateCreateFlags flags; + VK_FALSE, // VkBool32 logicOpEnable; + VK_LOGIC_OP_COPY, // VkLogicOp logicOp; + 1u, // deUint32 attachmentCount; + &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; + { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; + }; + + const Unique vsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0)); + + const VkPipelineShaderStageCreateInfo vsShaderStageInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; + *vsModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }; + + const Unique fsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0)); + + const VkPipelineShaderStageCreateInfo fsShaderStageInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; + *fsModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }; + + const VkPipelineShaderStageCreateInfo shaderStageInfos[] = { vsShaderStageInfo, fsShaderStageInfo }; + + const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; + 2u, // deUint32 stageCount; + shaderStageInfos, // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &inputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; + &viewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; + &rasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + &multisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + &depthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + &colorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + *pipelineLayout, // VkPipelineLayout layout; + *renderPass, // VkRenderPass renderPass; + 0u, // deUint32 subpass; + DE_NULL, // VkPipeline basePipelineHandle; + 0u, // deInt32 basePipelineIndex; + }; + + // Create graphics pipeline + const Unique graphicsPipeline(createGraphicsPipeline(deviceInterface, device, DE_NULL, &graphicsPipelineInfo)); + + // Create command buffer for compute and transfer oparations + const Unique commandPool(makeCommandPool(deviceInterface, device, queueFamilyIndex)); + const Unique commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool)); + + // Start recording commands + beginCommandBuffer(deviceInterface, *commandBuffer); + + { + VkImageMemoryBarrier imageOutputAttachmentBarriers[2]; + + imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier + ( + 0u, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + **imageMS, + fullImageRange + ); + + imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier + ( + 0u, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + **imageRS, + fullImageRange + ); + + deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputAttachmentBarriers); + } + + { + const VkDeviceSize vertexStartOffset = 0u; + + std::vector clearValues; + clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))); + clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))); + + const vk::VkRect2D renderArea = + { + makeOffset2D(0u, 0u), + makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height), + }; + + // Begin render pass + const VkRenderPassBeginInfo renderPassBeginInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + *renderPass, // VkRenderPass renderPass; + *framebuffer, // VkFramebuffer framebuffer; + renderArea, // VkRect2D renderArea; + static_cast(clearValues.size()), // deUint32 clearValueCount; + &clearValues[0], // const VkClearValue* pClearValues; + }; + + deviceInterface.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + // Bind graphics pipeline + deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline); + + // Bind vertex buffer + deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset); + + // Draw full screen quad + deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u); + + // End render pass + deviceInterface.cmdEndRenderPass(*commandBuffer); + } + + const VkImage sourceImage = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? **imageMS : **imageRS; + + { + const VkImageMemoryBarrier imageTransferSrcBarrier = makeImageMemoryBarrier + ( + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + sourceImage, + fullImageRange + ); + + deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageTransferSrcBarrier); + } + + // Copy data from resolve image to buffer + const deUint32 imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels); + + const VkBufferCreateInfo bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT); + const de::UniquePtr bufferRS(new Buffer(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible)); + + { + const VkBufferImageCopy bufferImageCopy = + { + 0u, // VkDeviceSize bufferOffset; + 0u, // deUint32 bufferRowLength; + 0u, // deUint32 bufferImageHeight; + makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource; + makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; + imageRSInfo.extent, // VkExtent3D imageExtent; + }; + + deviceInterface.cmdCopyImageToBuffer(*commandBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy); + } + + { + const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier + ( + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_HOST_READ_BIT, + bufferRS->get(), + 0u, + imageRSSizeInBytes + ); + + deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL); + } + + // End recording commands + VK_CHECK(deviceInterface.endCommandBuffer(*commandBuffer)); + + // Submit commands for execution and wait for completion + submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer); + + // Retrieve data from buffer to host memory + const Allocation& bufferRSAllocation = bufferRS->getAllocation(); + + invalidateMappedMemoryRange(deviceInterface, device, bufferRSAllocation.getMemory(), bufferRSAllocation.getOffset(), VK_WHOLE_SIZE); + + const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat, + imageRSInfo.extent.width, + imageRSInfo.extent.height, + imageRSInfo.extent.depth * imageRSInfo.arrayLayers, + bufferRSAllocation.getHostPtr()); + + std::stringstream imageName; + imageName << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl; + + m_context.getTestContext().getLog() + << tcu::TestLog::Section(imageName.str(), imageName.str()) + << tcu::LogImage("image", "", bufferRSData) + << tcu::TestLog::EndSection; + + return verifyImageData(imageRSInfo, bufferRSData); +} + +} // multisample +} // pipeline +} // vkt diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.hpp new file mode 100644 index 0000000..c123a15 --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.hpp @@ -0,0 +1,67 @@ +#ifndef _VKTPIPELINEMULTISAMPLEBASERESOLVE_HPP +#define _VKTPIPELINEMULTISAMPLEBASERESOLVE_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * 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 vktPipelineMultisampleBaseResolve.hpp + * \brief Base class for tests that check results of multisample resolve + *//*--------------------------------------------------------------------*/ + +#include "vktPipelineMultisampleBase.hpp" +#include "vktTestCase.hpp" +#include "tcuVector.hpp" + +namespace vkt +{ +namespace pipeline +{ +namespace multisample +{ + +class MSCaseBaseResolve : public MultisampleCaseBase +{ +public: + MSCaseBaseResolve (tcu::TestContext& testCtx, + const std::string& name, + const ImageMSParams& imageMSParams) + : MultisampleCaseBase(testCtx, name, imageMSParams) + {} +}; + +class MSInstanceBaseResolve : public MultisampleInstanceBase +{ +public: + MSInstanceBaseResolve (Context& context, + const ImageMSParams& imageMSParams) + : MultisampleInstanceBase(context, imageMSParams) + {} + +protected: + + tcu::TestStatus iterate (void); + + virtual tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, + const tcu::ConstPixelBufferAccess& dataRS) const = 0; +}; + +} // multisample +} // pipeline +} // vkt + +#endif // _VKTPIPELINEMULTISAMPLEBASERESOLVE_HPP diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp new file mode 100644 index 0000000..6b670ca --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp @@ -0,0 +1,1026 @@ +/*------------------------------------------------------------------------ +* Vulkan Conformance Tests +* ------------------------ +* +* 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 vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp +* \brief Base class for tests that check results of multisample resolve +* and/or values of individual samples +*//*--------------------------------------------------------------------*/ + +#include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp" +#include "vktPipelineMakeUtil.hpp" +#include "vkBuilderUtil.hpp" +#include "vkQueryUtil.hpp" +#include + +namespace vkt +{ +namespace pipeline +{ +namespace multisample +{ + +using namespace vk; + +void MSCaseBaseResolveAndPerSampleFetch::initPrograms (vk::SourceCollections& programCollection) const +{ + // Create vertex shader + std::ostringstream vs; + + vs << "#version 440\n" + << "layout(location = 0) in vec4 vs_in_position_ndc;\n" + << "\n" + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = vs_in_position_ndc;\n" + << "}\n"; + + programCollection.glslSources.add("per_sample_fetch_vs") << glu::VertexSource(vs.str()); + + // Create fragment shader + std::ostringstream fs; + + fs << "#version 440\n" + << "\n" + << "layout(location = 0) out vec4 fs_out_color;\n" + << "\n" + << "layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInputMS imageMS;\n" + << "\n" + << "layout(set = 0, binding = 1, std140) uniform SampleBlock {\n" + << " int sampleNdx;\n" + << "};\n" + << "void main (void)\n" + << "{\n" + << " fs_out_color = subpassLoad(imageMS, sampleNdx);\n" + << "}\n"; + + programCollection.glslSources.add("per_sample_fetch_fs") << glu::FragmentSource(fs.str()); +} + +VkPipelineMultisampleStateCreateInfo MSInstanceBaseResolveAndPerSampleFetch::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const +{ + const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags; + imageMSParams.numSamples, // VkSampleCountFlagBits rasterizationSamples; + VK_TRUE, // VkBool32 sampleShadingEnable; + 1.0f, // float minSampleShading; + DE_NULL, // const VkSampleMask* pSampleMask; + VK_FALSE, // VkBool32 alphaToCoverageEnable; + VK_FALSE, // VkBool32 alphaToOneEnable; + }; + + return multisampleStateInfo; +} + +const VkDescriptorSetLayout* MSInstanceBaseResolveAndPerSampleFetch::createMSPassDescSetLayout(const ImageMSParams& imageMSParams) +{ + DE_UNREF(imageMSParams); + + return DE_NULL; +} + +const VkDescriptorSet* MSInstanceBaseResolveAndPerSampleFetch::createMSPassDescSet(const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout) +{ + DE_UNREF(imageMSParams); + DE_UNREF(descSetLayout); + + return DE_NULL; +} + +tcu::TestStatus MSInstanceBaseResolveAndPerSampleFetch::iterate (void) +{ + const InstanceInterface& instance = m_context.getInstanceInterface(); + const DeviceInterface& deviceInterface = m_context.getDeviceInterface(); + const VkDevice device = m_context.getDevice(); + const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); + Allocator& allocator = m_context.getDefaultAllocator(); + const VkQueue queue = m_context.getUniversalQueue(); + const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); + + VkImageCreateInfo imageMSInfo; + VkImageCreateInfo imageRSInfo; + const deUint32 firstSubpassAttachmentsCount = 2u; + + // Check if image size does not exceed device limits + validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize); + + // Check if device supports image format as color attachment + validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); + + imageMSInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageMSInfo.pNext = DE_NULL; + imageMSInfo.flags = 0u; + imageMSInfo.imageType = mapImageType(m_imageType); + imageMSInfo.format = mapTextureFormat(m_imageFormat); + imageMSInfo.extent = makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize)); + imageMSInfo.arrayLayers = getNumLayers(m_imageType, m_imageMSParams.imageSize); + imageMSInfo.mipLevels = 1u; + imageMSInfo.samples = m_imageMSParams.numSamples; + imageMSInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageMSInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageMSInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + imageMSInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageMSInfo.queueFamilyIndexCount = 0u; + imageMSInfo.pQueueFamilyIndices = DE_NULL; + + if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY) + { + imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + } + + validateImageInfo(instance, physicalDevice, imageMSInfo); + + const de::UniquePtr imageMS(new Image(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any)); + + imageRSInfo = imageMSInfo; + imageRSInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageRSInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + + validateImageInfo(instance, physicalDevice, imageRSInfo); + + const de::UniquePtr imageRS(new Image(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any)); + + const deUint32 numSamples = static_cast(imageMSInfo.samples); + + std::vector > imagesPerSampleVec(numSamples); + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + imagesPerSampleVec[sampleNdx] = de::SharedPtr(new Image(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any)); + } + + // Create render pass + std::vector attachments(firstSubpassAttachmentsCount + numSamples); + + { + const VkAttachmentDescription attachmentMSDesc = + { + (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags; + imageMSInfo.format, // VkFormat format; + imageMSInfo.samples, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout; + }; + + attachments[0] = attachmentMSDesc; + + const VkAttachmentDescription attachmentRSDesc = + { + (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags; + imageRSInfo.format, // VkFormat format; + imageRSInfo.samples, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; + }; + + attachments[1] = attachmentRSDesc; + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + attachments[firstSubpassAttachmentsCount + sampleNdx] = attachmentRSDesc; + } + } + + const VkAttachmentReference attachmentMSColorRef = + { + 0u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + + const VkAttachmentReference attachmentMSInputRef = + { + 0u, // deUint32 attachment; + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout layout; + }; + + const VkAttachmentReference attachmentRSColorRef = + { + 1u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + + std::vector perSampleAttachmentRef(numSamples); + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + const VkAttachmentReference attachmentRef = + { + firstSubpassAttachmentsCount + sampleNdx, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + + perSampleAttachmentRef[sampleNdx] = attachmentRef; + } + + std::vector preserveAttachments(1u + numSamples); + + for (deUint32 attachNdx = 0u; attachNdx < 1u + numSamples; ++attachNdx) + { + preserveAttachments[attachNdx] = 1u + attachNdx; + } + + std::vector subpasses(1u + numSamples); + std::vector subpassDependencies(numSamples); + + const VkSubpassDescription firstSubpassDesc = + { + (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags; + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + 0u, // deUint32 inputAttachmentCount; + DE_NULL, // const VkAttachmentReference* pInputAttachments; + 1u, // deUint32 colorAttachmentCount; + &attachmentMSColorRef, // const VkAttachmentReference* pColorAttachments; + &attachmentRSColorRef, // const VkAttachmentReference* pResolveAttachments; + DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; + 0u, // deUint32 preserveAttachmentCount; + DE_NULL // const deUint32* pPreserveAttachments; + }; + + subpasses[0] = firstSubpassDesc; + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + const VkSubpassDescription subpassDesc = + { + (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags; + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + 1u, // deUint32 inputAttachmentCount; + &attachmentMSInputRef, // const VkAttachmentReference* pInputAttachments; + 1u, // deUint32 colorAttachmentCount; + &perSampleAttachmentRef[sampleNdx], // const VkAttachmentReference* pColorAttachments; + DE_NULL, // const VkAttachmentReference* pResolveAttachments; + DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; + 1u + sampleNdx, // deUint32 preserveAttachmentCount; + dataPointer(preserveAttachments) // const deUint32* pPreserveAttachments; + }; + + subpasses[1u + sampleNdx] = subpassDesc; + + const VkSubpassDependency subpassDependency = + { + 0u, // uint32_t srcSubpass; + 1u + sampleNdx, // uint32_t dstSubpass; + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask; + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask; + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask; + 0u, // VkDependencyFlags dependencyFlags; + }; + + subpassDependencies[sampleNdx] = subpassDependency; + } + + const VkRenderPassCreateInfo renderPassInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags; + static_cast(attachments.size()), // deUint32 attachmentCount; + dataPointer(attachments), // const VkAttachmentDescription* pAttachments; + static_cast(subpasses.size()), // deUint32 subpassCount; + dataPointer(subpasses), // const VkSubpassDescription* pSubpasses; + static_cast(subpassDependencies.size()), // deUint32 dependencyCount; + dataPointer(subpassDependencies) // const VkSubpassDependency* pDependencies; + }; + + const Unique renderPass(createRenderPass(deviceInterface, device, &renderPassInfo)); + + const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers); + + // Create color attachments image views + typedef de::SharedPtr > VkImageViewSp; + std::vector imageViewsShPtrs(firstSubpassAttachmentsCount + numSamples); + std::vector imageViews(firstSubpassAttachmentsCount + numSamples); + + imageViewsShPtrs[0] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange)); + imageViewsShPtrs[1] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageRSInfo.format, fullImageRange)); + + imageViews[0] = **imageViewsShPtrs[0]; + imageViews[1] = **imageViewsShPtrs[1]; + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + imageViewsShPtrs[firstSubpassAttachmentsCount + sampleNdx] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imagesPerSampleVec[sampleNdx], mapImageViewType(m_imageType), imageRSInfo.format, fullImageRange)); + imageViews[firstSubpassAttachmentsCount + sampleNdx] = **imageViewsShPtrs[firstSubpassAttachmentsCount + sampleNdx]; + } + + // Create framebuffer + const VkFramebufferCreateInfo framebufferInfo = + { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkFramebufferCreateFlags)0u, // VkFramebufferCreateFlags flags; + *renderPass, // VkRenderPass renderPass; + static_cast(imageViews.size()), // uint32_t attachmentCount; + dataPointer(imageViews), // const VkImageView* pAttachments; + imageMSInfo.extent.width, // uint32_t width; + imageMSInfo.extent.height, // uint32_t height; + imageMSInfo.arrayLayers, // uint32_t layers; + }; + + const Unique framebuffer(createFramebuffer(deviceInterface, device, &framebufferInfo)); + + const VkDescriptorSetLayout* descriptorSetLayoutMSPass = createMSPassDescSetLayout(m_imageMSParams); + + // Create pipeline layout + const VkPipelineLayoutCreateInfo pipelineLayoutMSPassParams = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineLayoutCreateFlags)0u, // VkPipelineLayoutCreateFlags flags; + descriptorSetLayoutMSPass ? 1u : 0u, // deUint32 setLayoutCount; + descriptorSetLayoutMSPass, // const VkDescriptorSetLayout* pSetLayouts; + 0u, // deUint32 pushConstantRangeCount; + DE_NULL, // const VkPushConstantRange* pPushConstantRanges; + }; + + const Unique pipelineLayoutMSPass(createPipelineLayout(deviceInterface, device, &pipelineLayoutMSPassParams)); + + // Create vertex attributes data + const VertexDataDesc vertexDataDesc = getVertexDataDescripton(); + + de::SharedPtr vertexBuffer = de::SharedPtr(new Buffer(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible)); + const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation(); + + uploadVertexData(vertexBufferAllocation, vertexDataDesc); + + flushMappedMemoryRange(deviceInterface, device, vertexBufferAllocation.getMemory(), vertexBufferAllocation.getOffset(), VK_WHOLE_SIZE); + + const VkVertexInputBindingDescription vertexBinding = + { + 0u, // deUint32 binding; + vertexDataDesc.dataStride, // deUint32 stride; + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate; + }; + + const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineVertexInputStateCreateFlags)0u, // VkPipelineVertexInputStateCreateFlags flags; + 1u, // uint32_t vertexBindingDescriptionCount; + &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + static_cast(vertexDataDesc.vertexAttribDescVec.size()), // uint32_t vertexAttributeDescriptionCount; + dataPointer(vertexDataDesc.vertexAttribDescVec), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineInputAssemblyStateCreateFlags)0u, // VkPipelineInputAssemblyStateCreateFlags flags; + vertexDataDesc.primitiveTopology, // VkPrimitiveTopology topology; + VK_FALSE, // VkBool32 primitiveRestartEnable; + }; + + const VkViewport viewport = + { + 0.0f, 0.0f, + static_cast(imageMSInfo.extent.width), static_cast(imageMSInfo.extent.height), + 0.0f, 1.0f + }; + + const VkRect2D scissor = + { + makeOffset2D(0, 0), + makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height), + }; + + const VkPipelineViewportStateCreateInfo viewportStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineViewportStateCreateFlags)0u, // VkPipelineViewportStateCreateFlags flags; + 1u, // uint32_t viewportCount; + &viewport, // const VkViewport* pViewports; + 1u, // uint32_t scissorCount; + &scissor, // const VkRect2D* pScissors; + }; + + const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineRasterizationStateCreateFlags)0u, // VkPipelineRasterizationStateCreateFlags flags; + VK_FALSE, // VkBool32 depthClampEnable; + VK_FALSE, // VkBool32 rasterizerDiscardEnable; + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; + VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; + VK_FALSE, // VkBool32 depthBiasEnable; + 0.0f, // float depthBiasConstantFactor; + 0.0f, // float depthBiasClamp; + 0.0f, // float depthBiasSlopeFactor; + 1.0f, // float lineWidth; + }; + + const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = getMSStateCreateInfo(m_imageMSParams); + + 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_ALWAYS, // compare op + 0u, // compare mask + 0u, // write mask + 0u // reference + ); + + const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineDepthStencilStateCreateFlags)0u, // 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 colorBlendAttachmentState = + { + VK_FALSE, // VkBool32 blendEnable; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; + colorComponentsAll, // VkColorComponentFlags colorWriteMask; + }; + + const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineColorBlendStateCreateFlags)0u, // VkPipelineColorBlendStateCreateFlags flags; + VK_FALSE, // VkBool32 logicOpEnable; + VK_LOGIC_OP_COPY, // VkLogicOp logicOp; + 1u, // deUint32 attachmentCount; + &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; + { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; + }; + + // Create graphics pipeline for multisample pass + const Unique vsMSPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0u)); + + const VkPipelineShaderStageCreateInfo vsMSPassShaderStageInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; + *vsMSPassModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }; + + const Unique fsMSPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0u)); + + const VkPipelineShaderStageCreateInfo fsMSPassShaderStageInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; + *fsMSPassModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }; + + const VkPipelineShaderStageCreateInfo shaderStageInfosMSPass[] = { vsMSPassShaderStageInfo, fsMSPassShaderStageInfo }; + + const VkGraphicsPipelineCreateInfo graphicsPipelineInfoMSPass = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineCreateFlags)0u, // VkPipelineCreateFlags flags; + 2u, // deUint32 stageCount; + shaderStageInfosMSPass, // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &inputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; + &viewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; + &rasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + &multisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + &depthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + &colorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + *pipelineLayoutMSPass, // VkPipelineLayout layout; + *renderPass, // VkRenderPass renderPass; + 0u, // deUint32 subpass; + DE_NULL, // VkPipeline basePipelineHandle; + 0u, // deInt32 basePipelineIndex; + }; + + const Unique graphicsPipelineMSPass(createGraphicsPipeline(deviceInterface, device, DE_NULL, &graphicsPipelineInfoMSPass)); + + typedef de::SharedPtr > VkPipelineSp; + std::vector graphicsPipelinesPerSampleFetch(numSamples); + + // Create descriptor set layout + const Unique descriptorSetLayout( + DescriptorSetLayoutBuilder() + .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT) + .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_FRAGMENT_BIT) + .build(deviceInterface, device)); + + const Unique pipelineLayoutPerSampleFetchPass(makePipelineLayout(deviceInterface, device, *descriptorSetLayout)); + + const deUint32 bufferPerSampleFetchPassSize = 4u * (deUint32)sizeof(tcu::Vec4); + + de::SharedPtr vertexBufferPerSampleFetchPass = de::SharedPtr(new Buffer(deviceInterface, device, allocator, makeBufferCreateInfo(bufferPerSampleFetchPassSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible)); + + // Create graphics pipelines for per sample texel fetch passes + { + const Unique vsPerSampleFetchPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("per_sample_fetch_vs"), (VkShaderModuleCreateFlags)0u)); + + const VkPipelineShaderStageCreateInfo vsPerSampleFetchPassShaderStageInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; + *vsPerSampleFetchPassModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }; + + const Unique fsPerSampleFetchPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("per_sample_fetch_fs"), (VkShaderModuleCreateFlags)0u)); + + const VkPipelineShaderStageCreateInfo fsPerSampleFetchPassShaderStageInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; + *fsPerSampleFetchPassModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }; + + const VkPipelineShaderStageCreateInfo shaderStageInfosPerSampleFetchPass[] = { vsPerSampleFetchPassShaderStageInfo, fsPerSampleFetchPassShaderStageInfo }; + + std::vector vertices; + + vertices.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)); + vertices.push_back(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f)); + vertices.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f)); + vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f)); + + const Allocation& vertexAllocPerSampleFetchPass = vertexBufferPerSampleFetchPass->getAllocation(); + + deMemcpy(vertexAllocPerSampleFetchPass.getHostPtr(), dataPointer(vertices), static_cast(bufferPerSampleFetchPassSize)); + + flushMappedMemoryRange(deviceInterface, device, vertexAllocPerSampleFetchPass.getMemory(), vertexAllocPerSampleFetchPass.getOffset(), VK_WHOLE_SIZE); + + const VkVertexInputBindingDescription vertexBindingPerSampleFetchPass = + { + 0u, // deUint32 binding; + sizeof(tcu::Vec4), // deUint32 stride; + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate; + }; + + const VkVertexInputAttributeDescription vertexAttribPositionNdc = + { + 0u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + 0u, // deUint32 offset; + }; + + const VkPipelineVertexInputStateCreateInfo vertexInputStatePerSampleFetchPass = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineVertexInputStateCreateFlags)0u, // VkPipelineVertexInputStateCreateFlags flags; + 1u, // uint32_t vertexBindingDescriptionCount; + &vertexBindingPerSampleFetchPass, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + 1u, // uint32_t vertexAttributeDescriptionCount; + &vertexAttribPositionNdc, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStatePerSampleFetchPass = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineInputAssemblyStateCreateFlags)0u, // VkPipelineInputAssemblyStateCreateFlags flags; + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology; + VK_FALSE, // VkBool32 primitiveRestartEnable; + }; + + const VkPipelineMultisampleStateCreateInfo multisampleStatePerSampleFetchPass = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineMultisampleStateCreateFlags)0u, // 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; + }; + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineCreateFlags)0u, // VkPipelineCreateFlags flags; + 2u, // deUint32 stageCount; + shaderStageInfosPerSampleFetchPass, // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputStatePerSampleFetchPass, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &inputAssemblyStatePerSampleFetchPass, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; + &viewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; + &rasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + &multisampleStatePerSampleFetchPass, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + &depthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + &colorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + *pipelineLayoutPerSampleFetchPass, // VkPipelineLayout layout; + *renderPass, // VkRenderPass renderPass; + 1u + sampleNdx, // deUint32 subpass; + DE_NULL, // VkPipeline basePipelineHandle; + 0u, // deInt32 basePipelineIndex; + }; + + graphicsPipelinesPerSampleFetch[sampleNdx] = makeVkSharedPtr(createGraphicsPipeline(deviceInterface, device, DE_NULL, &graphicsPipelineInfo)); + } + } + + // Create descriptor pool + const Unique descriptorPool( + DescriptorPoolBuilder() + .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u) + .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1u) + .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); + + // Create descriptor set + const Unique descriptorSet(makeDescriptorSet(deviceInterface, device, *descriptorPool, *descriptorSetLayout)); + + const VkPhysicalDeviceLimits deviceLimits = getPhysicalDeviceProperties(instance, physicalDevice).limits; + + VkDeviceSize uboOffsetAlignment = sizeof(deInt32) < deviceLimits.minUniformBufferOffsetAlignment ? deviceLimits.minUniformBufferOffsetAlignment : sizeof(deInt32); + + uboOffsetAlignment += (deviceLimits.minUniformBufferOffsetAlignment - uboOffsetAlignment % deviceLimits.minUniformBufferOffsetAlignment) % deviceLimits.minUniformBufferOffsetAlignment; + + const VkBufferCreateInfo bufferSampleIDInfo = makeBufferCreateInfo(uboOffsetAlignment * numSamples, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + const de::UniquePtr bufferSampleID(new Buffer(deviceInterface, device, allocator, bufferSampleIDInfo, MemoryRequirement::HostVisible)); + + std::vector sampleIDsOffsets(numSamples); + + { + deInt8* sampleIDs = new deInt8[uboOffsetAlignment * numSamples]; + + for (deInt32 sampleNdx = 0u; sampleNdx < static_cast(numSamples); ++sampleNdx) + { + sampleIDsOffsets[sampleNdx] = static_cast(sampleNdx * uboOffsetAlignment); + deInt8* samplePtr = sampleIDs + sampleIDsOffsets[sampleNdx]; + + deMemcpy(samplePtr, &sampleNdx, sizeof(deInt32)); + } + + deMemcpy(bufferSampleID->getAllocation().getHostPtr(), sampleIDs, static_cast(uboOffsetAlignment * numSamples)); + + flushMappedMemoryRange(deviceInterface, device, bufferSampleID->getAllocation().getMemory(), bufferSampleID->getAllocation().getOffset(), VK_WHOLE_SIZE); + + delete[] sampleIDs; + } + + { + const VkDescriptorImageInfo descImageInfo = makeDescriptorImageInfo(DE_NULL, imageViews[0], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**bufferSampleID, 0u, sizeof(deInt32)); + + DescriptorSetUpdateBuilder() + .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descImageInfo) + .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, &descBufferInfo) + .update(deviceInterface, device); + } + + // Create command buffer for compute and transfer oparations + const Unique commandPool(makeCommandPool(deviceInterface, device, queueFamilyIndex)); + const Unique commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool)); + + // Start recording commands + beginCommandBuffer(deviceInterface, *commandBuffer); + + { + std::vector imageOutputAttachmentBarriers(firstSubpassAttachmentsCount + numSamples); + + imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier + ( + 0u, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + **imageMS, + fullImageRange + ); + + imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier + ( + 0u, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + **imageRS, + fullImageRange + ); + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + imageOutputAttachmentBarriers[firstSubpassAttachmentsCount + sampleNdx] = makeImageMemoryBarrier + ( + 0u, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + **imagesPerSampleVec[sampleNdx], + fullImageRange + ); + } + + deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, + static_cast(imageOutputAttachmentBarriers.size()), dataPointer(imageOutputAttachmentBarriers)); + } + + { + const VkDeviceSize vertexStartOffset = 0u; + + std::vector clearValues(firstSubpassAttachmentsCount + numSamples); + for (deUint32 attachmentNdx = 0u; attachmentNdx < firstSubpassAttachmentsCount + numSamples; ++attachmentNdx) + { + clearValues[attachmentNdx] = makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); + } + + const vk::VkRect2D renderArea = + { + makeOffset2D(0u, 0u), + makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height), + }; + + // Begin render pass + const VkRenderPassBeginInfo renderPassBeginInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + *renderPass, // VkRenderPass renderPass; + *framebuffer, // VkFramebuffer framebuffer; + renderArea, // VkRect2D renderArea; + static_cast(clearValues.size()), // deUint32 clearValueCount; + dataPointer(clearValues), // const VkClearValue* pClearValues; + }; + + deviceInterface.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + // Bind graphics pipeline + deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineMSPass); + + const VkDescriptorSet* descriptorSetMSPass = createMSPassDescSet(m_imageMSParams, descriptorSetLayoutMSPass); + + if (descriptorSetMSPass) + { + // Bind descriptor set + deviceInterface.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutMSPass, 0u, 1u, descriptorSetMSPass, 0u, DE_NULL); + } + + // Bind vertex buffer + deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset); + + // Perform a draw + deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u); + + // Change imageMS layout for input attachment compatibility + const VkImageMemoryBarrier imageMSInputAttachmentBarrier = makeImageMemoryBarrier + ( + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + **imageMS, + fullImageRange + ); + + deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageMSInputAttachmentBarrier); + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + deviceInterface.cmdNextSubpass(*commandBuffer, VK_SUBPASS_CONTENTS_INLINE); + + // Bind graphics pipeline + deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **graphicsPipelinesPerSampleFetch[sampleNdx]); + + // Bind descriptor set + deviceInterface.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutPerSampleFetchPass, 0u, 1u, &descriptorSet.get(), 1u, &sampleIDsOffsets[sampleNdx]); + + // Bind vertex buffer + deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBufferPerSampleFetchPass->get(), &vertexStartOffset); + + // Perform a draw + deviceInterface.cmdDraw(*commandBuffer, 4u, 1u, 0u, 0u); + } + + // End render pass + deviceInterface.cmdEndRenderPass(*commandBuffer); + } + + { + const VkImageMemoryBarrier imageRSTransferBarrier = makeImageMemoryBarrier + ( + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + **imageRS, + fullImageRange + ); + + deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageRSTransferBarrier); + } + + // Copy data from imageRS to buffer + const deUint32 imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels, 1u); + + const VkBufferCreateInfo bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT); + const de::UniquePtr bufferRS(new Buffer(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible)); + + { + const VkBufferImageCopy bufferImageCopy = + { + 0u, // VkDeviceSize bufferOffset; + 0u, // deUint32 bufferRowLength; + 0u, // deUint32 bufferImageHeight; + makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource; + makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; + imageRSInfo.extent, // VkExtent3D imageExtent; + }; + + deviceInterface.cmdCopyImageToBuffer(*commandBuffer, **imageRS, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy); + } + + { + const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier + ( + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_HOST_READ_BIT, + bufferRS->get(), + 0u, + imageRSSizeInBytes + ); + + deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL); + } + + // Copy data from per sample images to buffers + std::vector imagesPerSampleTransferBarriers(numSamples); + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + imagesPerSampleTransferBarriers[sampleNdx] = makeImageMemoryBarrier + ( + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + **imagesPerSampleVec[sampleNdx], + fullImageRange + ); + } + + deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, + static_cast(imagesPerSampleTransferBarriers.size()), dataPointer(imagesPerSampleTransferBarriers)); + + std::vector > buffersPerSample(numSamples); + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + buffersPerSample[sampleNdx] = de::SharedPtr(new Buffer(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible)); + + const VkBufferImageCopy bufferImageCopy = + { + 0u, // VkDeviceSize bufferOffset; + 0u, // deUint32 bufferRowLength; + 0u, // deUint32 bufferImageHeight; + makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource; + makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; + imageRSInfo.extent, // VkExtent3D imageExtent; + }; + + deviceInterface.cmdCopyImageToBuffer(*commandBuffer, **imagesPerSampleVec[sampleNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **buffersPerSample[sampleNdx], 1u, &bufferImageCopy); + } + + std::vector buffersPerSampleHostReadBarriers(numSamples); + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + buffersPerSampleHostReadBarriers[sampleNdx] = makeBufferMemoryBarrier + ( + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_HOST_READ_BIT, + **buffersPerSample[sampleNdx], + 0u, + imageRSSizeInBytes + ); + } + + deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, + static_cast(buffersPerSampleHostReadBarriers.size()), dataPointer(buffersPerSampleHostReadBarriers), 0u, DE_NULL); + + // End recording commands + VK_CHECK(deviceInterface.endCommandBuffer(*commandBuffer)); + + // Submit commands for execution and wait for completion + submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer); + + // Retrieve data from bufferRS to host memory + const Allocation& bufferRSAlloc = bufferRS->getAllocation(); + + invalidateMappedMemoryRange(deviceInterface, device, bufferRSAlloc.getMemory(), bufferRSAlloc.getOffset(), VK_WHOLE_SIZE); + + const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat, + imageRSInfo.extent.width, + imageRSInfo.extent.height, + imageRSInfo.extent.depth * imageRSInfo.arrayLayers, + bufferRSAlloc.getHostPtr()); + + std::stringstream resolveName; + resolveName << "Resolve image " << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl; + + m_context.getTestContext().getLog() + << tcu::TestLog::Section(resolveName.str(), resolveName.str()) + << tcu::LogImage("resolve", "", bufferRSData) + << tcu::TestLog::EndSection; + + std::vector buffersPerSampleData(numSamples); + + // Retrieve data from per sample buffers to host memory + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + const Allocation& bufferAlloc = buffersPerSample[sampleNdx]->getAllocation(); + + invalidateMappedMemoryRange(deviceInterface, device, bufferAlloc.getMemory(), bufferAlloc.getOffset(), VK_WHOLE_SIZE); + + buffersPerSampleData[sampleNdx] = tcu::ConstPixelBufferAccess + ( + m_imageFormat, + imageRSInfo.extent.width, + imageRSInfo.extent.height, + imageRSInfo.extent.depth * imageRSInfo.arrayLayers, + bufferAlloc.getHostPtr() + ); + + std::stringstream sampleName; + sampleName << "Sample " << sampleNdx << " image" << std::endl; + + m_context.getTestContext().getLog() + << tcu::TestLog::Section(sampleName.str(), sampleName.str()) + << tcu::LogImage("sample", "", buffersPerSampleData[sampleNdx]) + << tcu::TestLog::EndSection; + } + + return verifyImageData(imageMSInfo, imageRSInfo, buffersPerSampleData, bufferRSData); +} + +} // multisample +} // pipeline +} // vkt diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp new file mode 100644 index 0000000..158b80b --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp @@ -0,0 +1,77 @@ +#ifndef _VKTPIPELINEMULTISAMPLEBASERESOLVEANDPERSAMPLEFETCH_HPP +#define _VKTPIPELINEMULTISAMPLEBASERESOLVEANDPERSAMPLEFETCH_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * 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 vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp + * \brief Base class for tests that check results of multisample resolve + * and/or values of individual samples + *//*--------------------------------------------------------------------*/ + +#include "vktPipelineMultisampleBase.hpp" +#include "vktTestCase.hpp" +#include "tcuVector.hpp" + +namespace vkt +{ +namespace pipeline +{ +namespace multisample +{ + +class MSCaseBaseResolveAndPerSampleFetch : public MultisampleCaseBase +{ +public: + MSCaseBaseResolveAndPerSampleFetch (tcu::TestContext& testCtx, + const std::string& name, + const ImageMSParams& imageMSParams) + : MultisampleCaseBase(testCtx, name, imageMSParams) {} + + void initPrograms (vk::SourceCollections& programCollection) const; +}; + +class MSInstanceBaseResolveAndPerSampleFetch : public MultisampleInstanceBase +{ +public: + MSInstanceBaseResolveAndPerSampleFetch (Context& context, + const ImageMSParams& imageMSParams) + : MultisampleInstanceBase(context, imageMSParams) {} + +protected: + + tcu::TestStatus iterate (void); + + virtual vk::VkPipelineMultisampleStateCreateInfo getMSStateCreateInfo (const ImageMSParams& imageMSParams) const; + + virtual const vk::VkDescriptorSetLayout* createMSPassDescSetLayout (const ImageMSParams& imageMSParams); + + virtual const vk::VkDescriptorSet* createMSPassDescSet (const ImageMSParams& imageMSParams, + const vk::VkDescriptorSetLayout* descSetLayout); + + virtual tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, + const vk::VkImageCreateInfo& imageRSInfo, + const std::vector& dataPerSample, + const tcu::ConstPixelBufferAccess& dataRS) const = 0; +}; + +} // multisample +} // pipeline +} // vkt + +#endif // _VKTPIPELINEMULTISAMPLEBASERESOLVEANDPERSAMPLEFETCH_HPP diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleInterpolationTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleInterpolationTests.cpp index 63a1bb1..7a6174b 100644 --- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleInterpolationTests.cpp +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleInterpolationTests.cpp @@ -22,11 +22,11 @@ *//*--------------------------------------------------------------------*/ #include "vktPipelineMultisampleInterpolationTests.hpp" +#include "vktPipelineMultisampleBaseResolve.hpp" #include "vktPipelineMultisampleTestsUtil.hpp" #include "vktPipelineMakeUtil.hpp" #include "vkQueryUtil.hpp" - -#include +#include namespace vkt { @@ -37,745 +37,90 @@ namespace multisample using namespace vk; -struct ImageMSParams +struct VertexDataNdc { - ImageMSParams(const VkSampleCountFlagBits samples, const tcu::UVec3& size) : numSamples(samples), imageSize(size) {} + VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {} - VkSampleCountFlagBits numSamples; - tcu::UVec3 imageSize; + tcu::Vec4 positionNdc; }; -class MSInterpolationCaseBase : public TestCase +struct VertexDataNdcScreen { -public: - MSInterpolationCaseBase (tcu::TestContext& testCtx, - const std::string& name, - const ImageMSParams& imageMSParams) - : TestCase(testCtx, name, "") - , m_imageMSParams(imageMSParams) - {} - -protected: - const ImageMSParams m_imageMSParams; -}; + VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {} -typedef MSInterpolationCaseBase* (*MSInterpolationCaseFuncPtr)(tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams); + tcu::Vec4 positionNdc; + tcu::Vec2 positionScreen; +}; -class MSInterpolationInstanceBase : public TestInstance +struct VertexDataNdcBarycentric { -public: - MSInterpolationInstanceBase (Context& context, - const ImageMSParams& imageMSParams) - : TestInstance (context) - , m_imageMSParams (imageMSParams) - , m_imageType (IMAGE_TYPE_2D) - , m_imageFormat (tcu::TextureFormat(tcu::TextureFormat::RG, tcu::TextureFormat::UNORM_INT8)) - {} + VertexDataNdcBarycentric (const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {} - tcu::TestStatus iterate (void); - -protected: - - typedef std::vector VertexAttribDescVec; - - struct VertexDataDesc - { - VkPrimitiveTopology primitiveTopology; - deUint32 verticesCount; - deUint32 dataStride; - VkDeviceSize dataSize; - VertexAttribDescVec vertexAttribDescVec; - }; - - void validateImageSize (const InstanceInterface& instance, - const VkPhysicalDevice physicalDevice, - const ImageType imageType, - const tcu::UVec3& imageSize) const; - - void validateImageFeatureFlags (const InstanceInterface& instance, - const VkPhysicalDevice physicalDevice, - const VkFormat format, - const VkFormatFeatureFlags featureFlags) const; - - void validateImageInfo (const InstanceInterface& instance, - const VkPhysicalDevice physicalDevice, - const VkImageCreateInfo& imageInfo) const; - - virtual VertexDataDesc getVertexDataDescripton (void) const = 0; - - virtual void uploadVertexData (const Allocation& vertexBufferAllocation, - const VertexDataDesc& vertexDataDescripton) const = 0; - - virtual tcu::TestStatus verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const = 0; -protected: - const ImageMSParams m_imageMSParams; - const ImageType m_imageType; - const tcu::TextureFormat m_imageFormat; + tcu::Vec4 positionNdc; + tcu::Vec3 barycentricCoord; }; -void MSInterpolationInstanceBase::validateImageSize (const InstanceInterface& instance, - const VkPhysicalDevice physicalDevice, - const ImageType imageType, - const tcu::UVec3& imageSize) const +bool checkForError (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx) { - const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice); - - bool isImageSizeValid = true; - - switch (imageType) + for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) + for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) + for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) { - case IMAGE_TYPE_1D: - isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension1D; - break; - case IMAGE_TYPE_1D_ARRAY: - isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension1D && - imageSize.z() <= deviceProperties.limits.maxImageArrayLayers; - break; - case IMAGE_TYPE_2D: - isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension2D && - imageSize.y() <= deviceProperties.limits.maxImageDimension2D; - break; - case IMAGE_TYPE_2D_ARRAY: - isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension2D && - imageSize.y() <= deviceProperties.limits.maxImageDimension2D && - imageSize.z() <= deviceProperties.limits.maxImageArrayLayers; - break; - case IMAGE_TYPE_CUBE: - isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimensionCube && - imageSize.y() <= deviceProperties.limits.maxImageDimensionCube; - break; - case IMAGE_TYPE_CUBE_ARRAY: - isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimensionCube && - imageSize.y() <= deviceProperties.limits.maxImageDimensionCube && - imageSize.z() <= deviceProperties.limits.maxImageArrayLayers; - break; - case IMAGE_TYPE_3D: - isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension3D && - imageSize.y() <= deviceProperties.limits.maxImageDimension3D && - imageSize.z() <= deviceProperties.limits.maxImageDimension3D; - break; - default: - DE_FATAL("Unknown image type"); - } - - if (!isImageSizeValid) - { - std::ostringstream notSupportedStream; - - notSupportedStream << "Image type (" << getImageTypeName(imageType) << ") with size (" << imageSize.x() << ", " << imageSize.y() << ", " << imageSize.z() << ") not supported by device" << std::endl; + const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx]; - const std::string notSupportedString = notSupportedStream.str(); - - TCU_THROW(NotSupportedError, notSupportedString.c_str()); + if (errorComponent > 0) + return true; } -} - -void MSInterpolationInstanceBase::validateImageFeatureFlags (const InstanceInterface& instance, - const VkPhysicalDevice physicalDevice, - const VkFormat format, - const VkFormatFeatureFlags featureFlags) const -{ - const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format); - if ((formatProperties.optimalTilingFeatures & featureFlags) != featureFlags) - { - std::ostringstream notSupportedStream; - - notSupportedStream << "Device does not support image format " << format << " for feature flags " << featureFlags << std::endl; - - const std::string notSupportedString = notSupportedStream.str(); - - TCU_THROW(NotSupportedError, notSupportedString.c_str()); - } + return false; } -void MSInterpolationInstanceBase::validateImageInfo (const InstanceInterface& instance, - const VkPhysicalDevice physicalDevice, - const VkImageCreateInfo& imageInfo) const +template +class MSCase : public MultisampleCaseBase { - VkImageFormatProperties imageFormatProps; - instance.getPhysicalDeviceImageFormatProperties(physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &imageFormatProps); - - if (imageFormatProps.maxExtent.width < imageInfo.extent.width || - imageFormatProps.maxExtent.height < imageInfo.extent.height || - imageFormatProps.maxExtent.depth < imageInfo.extent.depth) - { - std::ostringstream notSupportedStream; - - notSupportedStream << "Image extent (" - << imageInfo.extent.width << ", " - << imageInfo.extent.height << ", " - << imageInfo.extent.depth - << ") exceeds allowed maximum (" - << imageFormatProps.maxExtent.width << ", " - << imageFormatProps.maxExtent.height << ", " - << imageFormatProps.maxExtent.depth - << ")" - << std::endl; - - const std::string notSupportedString = notSupportedStream.str(); - - TCU_THROW(NotSupportedError, notSupportedString.c_str()); - } - - if (imageFormatProps.maxArrayLayers < imageInfo.arrayLayers) - { - std::ostringstream notSupportedStream; - - notSupportedStream << "Image layers count of " << imageInfo.arrayLayers << " exceeds allowed maximum which is " << imageFormatProps.maxArrayLayers << std::endl; - - const std::string notSupportedString = notSupportedStream.str(); - - TCU_THROW(NotSupportedError, notSupportedString.c_str()); - } - - if (!(imageFormatProps.sampleCounts & imageInfo.samples)) - { - std::ostringstream notSupportedStream; - - notSupportedStream << "Samples count of " << imageInfo.samples << " not supported for image" << std::endl; - - const std::string notSupportedString = notSupportedStream.str(); - - TCU_THROW(NotSupportedError, notSupportedString.c_str()); - } -} +public: + MSCase (tcu::TestContext& testCtx, + const std::string& name, + const ImageMSParams& imageMSParams) + : MultisampleCaseBase(testCtx, name, imageMSParams) {} + + void init (void); + void initPrograms (vk::SourceCollections& programCollection) const; + TestInstance* createInstance (Context& context) const; + static MultisampleCaseBase* createCase (tcu::TestContext& testCtx, + const std::string& name, + const ImageMSParams& imageMSParams); +}; -tcu::TestStatus MSInterpolationInstanceBase::iterate (void) +template +MultisampleCaseBase* MSCase::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) { - const InstanceInterface& instance = m_context.getInstanceInterface(); - const DeviceInterface& deviceInterface = m_context.getDeviceInterface(); - const VkDevice device = m_context.getDevice(); - const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); - Allocator& allocator = m_context.getDefaultAllocator(); - const VkQueue queue = m_context.getUniversalQueue(); - const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); - - VkImageCreateInfo imageMSInfo; - VkImageCreateInfo imageRSInfo; - - // Check if image size does not exceed device limits - validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize); - - // Check if device supports image format as color attachment - validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); - - imageMSInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageMSInfo.pNext = DE_NULL; - imageMSInfo.flags = 0u; - imageMSInfo.imageType = mapImageType(m_imageType); - imageMSInfo.format = mapTextureFormat(m_imageFormat); - imageMSInfo.extent = makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize)); - imageMSInfo.arrayLayers = getNumLayers(m_imageType, m_imageMSParams.imageSize); - imageMSInfo.mipLevels = 1u; - imageMSInfo.samples = m_imageMSParams.numSamples; - imageMSInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageMSInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageMSInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - imageMSInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageMSInfo.queueFamilyIndexCount = 0u; - imageMSInfo.pQueueFamilyIndices = DE_NULL; - - if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY) - { - imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - } - - validateImageInfo(instance, physicalDevice, imageMSInfo); - - const de::UniquePtr imageMS(new Image(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any)); - - imageRSInfo = imageMSInfo; - imageRSInfo.samples = VK_SAMPLE_COUNT_1_BIT; - - validateImageInfo(instance, physicalDevice, imageRSInfo); - - const de::UniquePtr imageRS(new Image(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any)); - - // Create render pass - const VkAttachmentDescription attachmentMSDesc = - { - (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags; - imageMSInfo.format, // VkFormat format; - imageMSInfo.samples, // VkSampleCountFlagBits samples; - VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; - VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; - }; - - const VkAttachmentDescription attachmentRSDesc = - { - (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags; - imageRSInfo.format, // VkFormat format; - imageRSInfo.samples, // VkSampleCountFlagBits samples; - VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; - VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; - }; - - const VkAttachmentDescription attachments[] = { attachmentMSDesc, attachmentRSDesc }; - - const VkAttachmentReference attachmentMSRef = - { - 0u, // deUint32 attachment; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; - }; - - const VkAttachmentReference attachmentRSRef = - { - 1u, // deUint32 attachment; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; - }; - - const VkAttachmentReference* resolveAttachment = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? DE_NULL : &attachmentRSRef; - - const VkSubpassDescription subpassDescription = - { - (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags; - VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; - 0u, // deUint32 inputAttachmentCount; - DE_NULL, // const VkAttachmentReference* pInputAttachments; - 1u, // deUint32 colorAttachmentCount; - &attachmentMSRef, // const VkAttachmentReference* pColorAttachments; - resolveAttachment, // const VkAttachmentReference* pResolveAttachments; - DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; - 0u, // deUint32 preserveAttachmentCount; - DE_NULL // const deUint32* pPreserveAttachments; - }; - - const VkRenderPassCreateInfo renderPassInfo = - { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags; - 2u, // deUint32 attachmentCount; - attachments, // const VkAttachmentDescription* pAttachments; - 1u, // deUint32 subpassCount; - &subpassDescription, // const VkSubpassDescription* pSubpasses; - 0u, // deUint32 dependencyCount; - DE_NULL // const VkSubpassDependency* pDependencies; - }; - - const Unique renderPass(createRenderPass(deviceInterface, device, &renderPassInfo)); - - const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers); - - // Create color attachments image views - const Unique imageMSView(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange)); - const Unique imageRSView(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange)); - - const VkImageView attachmentsViews[] = { *imageMSView, *imageRSView }; - - // Create framebuffer - const VkFramebufferCreateInfo framebufferInfo = - { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkFramebufferCreateFlags)0u, // VkFramebufferCreateFlags flags; - *renderPass, // VkRenderPass renderPass; - 2u, // uint32_t attachmentCount; - attachmentsViews, // const VkImageView* pAttachments; - imageMSInfo.extent.width, // uint32_t width; - imageMSInfo.extent.height, // uint32_t height; - imageMSInfo.arrayLayers, // uint32_t layers; - }; - - const Unique framebuffer(createFramebuffer(deviceInterface, device, &framebufferInfo)); - - // Create pipeline layout - const VkPipelineLayoutCreateInfo pipelineLayoutParams = - { - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineLayoutCreateFlags)0u, // VkPipelineLayoutCreateFlags flags; - 0u, // deUint32 setLayoutCount; - DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; - 0u, // deUint32 pushConstantRangeCount; - DE_NULL, // const VkPushConstantRange* pPushConstantRanges; - }; - - const Unique pipelineLayout(createPipelineLayout(deviceInterface, device, &pipelineLayoutParams)); - - // Create vertex attributes data - const VertexDataDesc vertexDataDesc = getVertexDataDescripton(); - - de::SharedPtr vertexBuffer = de::SharedPtr(new Buffer(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible)); - const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation(); - - uploadVertexData(vertexBufferAllocation, vertexDataDesc); - - flushMappedMemoryRange(deviceInterface, device, vertexBufferAllocation.getMemory(), vertexBufferAllocation.getOffset(), vertexDataDesc.dataSize); - - const VkVertexInputBindingDescription vertexBinding = - { - 0u, // deUint32 binding; - vertexDataDesc.dataStride, // deUint32 stride; - VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate; - }; - - const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = - { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineVertexInputStateCreateFlags)0u, // VkPipelineVertexInputStateCreateFlags flags; - 1u, // uint32_t vertexBindingDescriptionCount; - &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; - static_cast(vertexDataDesc.vertexAttribDescVec.size()), // uint32_t vertexAttributeDescriptionCount; - dataPointer(vertexDataDesc.vertexAttribDescVec), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; - }; - - const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo = - { - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineInputAssemblyStateCreateFlags)0u, // VkPipelineInputAssemblyStateCreateFlags flags; - vertexDataDesc.primitiveTopology, // VkPrimitiveTopology topology; - VK_FALSE, // VkBool32 primitiveRestartEnable; - }; - - const VkViewport viewport = - { - 0.0f, 0.0f, - static_cast(imageMSInfo.extent.width), static_cast(imageMSInfo.extent.height), - 0.0f, 1.0f - }; - - const VkRect2D scissor = - { - makeOffset2D(0, 0), - makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height), - }; - - const VkPipelineViewportStateCreateInfo viewportStateInfo = - { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineViewportStateCreateFlags)0u, // VkPipelineViewportStateCreateFlags flags; - 1u, // uint32_t viewportCount; - &viewport, // const VkViewport* pViewports; - 1u, // uint32_t scissorCount; - &scissor, // const VkRect2D* pScissors; - }; - - const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = - { - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineRasterizationStateCreateFlags)0u, // VkPipelineRasterizationStateCreateFlags flags; - VK_FALSE, // VkBool32 depthClampEnable; - VK_FALSE, // VkBool32 rasterizerDiscardEnable; - VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; - VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; - VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; - VK_FALSE, // VkBool32 depthBiasEnable; - 0.0f, // float depthBiasConstantFactor; - 0.0f, // float depthBiasClamp; - 0.0f, // float depthBiasSlopeFactor; - 1.0f, // float lineWidth; - }; - - const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = - { - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags; - imageMSInfo.samples, // VkSampleCountFlagBits rasterizationSamples; - VK_TRUE, // VkBool32 sampleShadingEnable; - 1.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_ALWAYS, // compare op - 0u, // compare mask - 0u, // write mask - 0u // reference - ); - - const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = - { - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineDepthStencilStateCreateFlags)0u, // 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 colorBlendAttachmentState = - { - VK_FALSE, // VkBool32 blendEnable; - VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor; - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor; - VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; - VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor; - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstAlphaBlendFactor; - VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; - colorComponentsAll, // VkColorComponentFlags colorWriteMask; - }; - - const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = - { - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineColorBlendStateCreateFlags)0u, // VkPipelineColorBlendStateCreateFlags flags; - VK_FALSE, // VkBool32 logicOpEnable; - VK_LOGIC_OP_COPY, // VkLogicOp logicOp; - 1u, // deUint32 attachmentCount; - &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; - { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; - }; - - const Unique vsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0)); - - const VkPipelineShaderStageCreateInfo vsShaderStageInfo = - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags; - VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; - *vsModule, // VkShaderModule module; - "main", // const char* pName; - DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; - }; - - const Unique fsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0)); - - const VkPipelineShaderStageCreateInfo fsShaderStageInfo = - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags; - VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; - *fsModule, // VkShaderModule module; - "main", // const char* pName; - DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; - }; - - const VkPipelineShaderStageCreateInfo shaderStageInfos[] = { vsShaderStageInfo, fsShaderStageInfo }; - - const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = - { - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; - 2u, // deUint32 stageCount; - shaderStageInfos, // const VkPipelineShaderStageCreateInfo* pStages; - &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; - &inputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; - DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; - &viewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; - &rasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; - &multisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; - &depthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; - &colorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; - DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; - *pipelineLayout, // VkPipelineLayout layout; - *renderPass, // VkRenderPass renderPass; - 0u, // deUint32 subpass; - DE_NULL, // VkPipeline basePipelineHandle; - 0u, // deInt32 basePipelineIndex; - }; - - // Create graphics pipeline - const Unique graphicsPipeline(createGraphicsPipeline(deviceInterface, device, DE_NULL, &graphicsPipelineInfo)); - - // Create command buffer for compute and transfer oparations - const Unique commandPool(makeCommandPool(deviceInterface, device, queueFamilyIndex)); - const Unique commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool)); - - // Start recording commands - beginCommandBuffer(deviceInterface, *commandBuffer); - - { - VkImageMemoryBarrier imageOutputAttachmentBarriers[2]; - - imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier - ( - 0u, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - **imageMS, - fullImageRange - ); - - imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier - ( - 0u, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - **imageRS, - fullImageRange - ); - - deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputAttachmentBarriers); - } - - { - const VkDeviceSize vertexStartOffset = 0u; - - std::vector clearValues; - clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))); - clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))); - - const vk::VkRect2D renderArea = - { - makeOffset2D(0u, 0u), - makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height), - }; - - // Begin render pass - const VkRenderPassBeginInfo renderPassBeginInfo = - { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - *renderPass, // VkRenderPass renderPass; - *framebuffer, // VkFramebuffer framebuffer; - renderArea, // VkRect2D renderArea; - static_cast(clearValues.size()), // deUint32 clearValueCount; - &clearValues[0], // const VkClearValue* pClearValues; - }; - - deviceInterface.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - // Bind graphics pipeline - deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline); - - // Bind vertex buffer - deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset); - - // Draw full screen quad - deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u); - - // End render pass - deviceInterface.cmdEndRenderPass(*commandBuffer); - } - - const VkImage sourceImage = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? **imageMS : **imageRS; - - { - const VkImageMemoryBarrier imageTransferSrcBarrier = makeImageMemoryBarrier - ( - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - sourceImage, - fullImageRange - ); - - deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageTransferSrcBarrier); - } - - // Copy data from resolve image to buffer - const deUint32 imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels); - - const VkBufferCreateInfo bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT); - const de::UniquePtr bufferRS(new Buffer(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible)); - - { - const VkBufferImageCopy bufferImageCopy = - { - 0u, // VkDeviceSize bufferOffset; - 0u, // deUint32 bufferRowLength; - 0u, // deUint32 bufferImageHeight; - makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource; - makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; - imageRSInfo.extent, // VkExtent3D imageExtent; - }; - - deviceInterface.cmdCopyImageToBuffer(*commandBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy); - } - - { - const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier - ( - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_HOST_READ_BIT, - bufferRS->get(), - 0u, - imageRSSizeInBytes - ); - - deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL); - } - - // End recording commands - VK_CHECK(deviceInterface.endCommandBuffer(*commandBuffer)); - - // Submit commands for execution and wait for completion - submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer); - - // Retrieve data from buffer to host memory - const Allocation& bufferRSAllocation = bufferRS->getAllocation(); - - invalidateMappedMemoryRange(deviceInterface, device, bufferRSAllocation.getMemory(), bufferRSAllocation.getOffset(), imageRSSizeInBytes); - - const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat, - imageRSInfo.extent.width, - imageRSInfo.extent.height, - imageRSInfo.extent.depth * imageRSInfo.arrayLayers, - bufferRSAllocation.getHostPtr()); - - std::stringstream imageName; - imageName << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl; - - m_context.getTestContext().getLog() - << tcu::TestLog::Section(imageName.str(), imageName.str()) - << tcu::LogImage("image", "", bufferRSData) - << tcu::TestLog::EndSection; - - return verifyResolvedImage(bufferRSData); + return new MSCase(testCtx, name, imageMSParams); } -class MSInstanceDistinctValues : public MSInterpolationInstanceBase +template +class MSInstance : public MSInstanceBaseResolve { public: - MSInstanceDistinctValues(Context& context, - const ImageMSParams& imageMSParams) - : MSInterpolationInstanceBase(context, imageMSParams) {} + MSInstance (Context& context, + const ImageMSParams& imageMSParams) + : MSInstanceBaseResolve(context, imageMSParams) {} VertexDataDesc getVertexDataDescripton (void) const; - void uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const; - tcu::TestStatus verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const; - -protected: - struct VertexData - { - VertexData(const tcu::Vec4& posNdc) : positionNdc(posNdc) {} - - tcu::Vec4 positionNdc; - }; + void uploadVertexData (const Allocation& vertexBufferAllocation, + const VertexDataDesc& vertexDataDescripton) const; + tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, + const tcu::ConstPixelBufferAccess& dataRS) const; }; -MSInterpolationInstanceBase::VertexDataDesc MSInstanceDistinctValues::getVertexDataDescripton (void) const +class MSInstanceDistinctValues; + +template<> MultisampleInstanceBase::VertexDataDesc MSInstance::getVertexDataDescripton (void) const { VertexDataDesc vertexDataDesc; vertexDataDesc.verticesCount = 3u; - vertexDataDesc.dataStride = sizeof(VertexData); + vertexDataDesc.dataStride = sizeof(VertexDataNdc); vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; @@ -784,7 +129,7 @@ MSInterpolationInstanceBase::VertexDataDesc MSInstanceDistinctValues::getVertexD 0u, // deUint32 location; 0u, // deUint32 binding; VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; - DE_OFFSET_OF(VertexData, positionNdc), // deUint32 offset; + DE_OFFSET_OF(VertexDataNdc, positionNdc), // deUint32 offset; }; vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); @@ -792,28 +137,28 @@ MSInterpolationInstanceBase::VertexDataDesc MSInstanceDistinctValues::getVertexD return vertexDataDesc; } -void MSInstanceDistinctValues::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const +template<> void MSInstance::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const { - std::vector vertices; + std::vector vertices; - vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f))); - vertices.push_back(VertexData(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f))); - vertices.push_back(VertexData(tcu::Vec4( 4.0f,-1.0f, 0.0f, 1.0f))); + vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f))); + vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f))); + vertices.push_back(VertexDataNdc(tcu::Vec4( 4.0f, -1.0f, 0.0f, 1.0f))); deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast(vertexDataDescripton.dataSize)); } -tcu::TestStatus MSInstanceDistinctValues::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const +template<> tcu::TestStatus MSInstance::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const { const deUint32 distinctValuesExpected = static_cast(m_imageMSParams.numSamples) + 1u; std::vector distinctValues; - for (deInt32 z = 0u; z < imageData.getDepth(); ++z) - for (deInt32 y = 0u; y < imageData.getHeight(); ++y) - for (deInt32 x = 0u; x < imageData.getWidth(); ++x) + for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) + for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) + for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) { - const tcu::IVec4 pixel = imageData.getPixelInt(x, y, z); + const tcu::IVec4 pixel = dataRS.getPixelInt(x, y, z); if (std::find(distinctValues.begin(), distinctValues.end(), pixel) == distinctValues.end()) distinctValues.push_back(pixel); @@ -822,28 +167,12 @@ tcu::TestStatus MSInstanceDistinctValues::verifyResolvedImage (const tcu::ConstP if (distinctValues.size() >= distinctValuesExpected) return tcu::TestStatus::pass("Passed"); else - return tcu::TestStatus::fail("Failed"); + return tcu::TestStatus::fail("Expected numSamples+1 different colors in the output image"); } -class MSCaseSampleQualifierDistinctValues : public MSInterpolationCaseBase -{ -public: - MSCaseSampleQualifierDistinctValues (tcu::TestContext& testCtx, - const std::string& name, - const ImageMSParams& imageMSParams) - : MSInterpolationCaseBase(testCtx, name, imageMSParams) {} - - void init (void); - void initPrograms (vk::SourceCollections& programCollection) const; - TestInstance* createInstance (Context& context) const; -}; +class MSCaseSampleQualifierDistinctValues; -MSInterpolationCaseBase* createMSCaseSampleQualifierDistinctValues (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) -{ - return new MSCaseSampleQualifierDistinctValues(testCtx, name, imageMSParams); -} - -void MSCaseSampleQualifierDistinctValues::init (void) +template<> void MSCase::init (void) { m_testCtx.getLog() << tcu::TestLog::Message @@ -852,10 +181,10 @@ void MSCaseSampleQualifierDistinctValues::init (void) << " => Resulting image should contain n+1 different colors, where n = sample count.\n" << tcu::TestLog::EndMessage; - MSInterpolationCaseBase::init(); + MultisampleCaseBase::init(); } -void MSCaseSampleQualifierDistinctValues::initPrograms (vk::SourceCollections& programCollection) const +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const { // Create vertex shader std::ostringstream vs; @@ -882,43 +211,27 @@ void MSCaseSampleQualifierDistinctValues::initPrograms (vk::SourceCollections& p fs << "#version 440\n" << "layout(location = 0) sample in vec4 fs_in_position_ndc;\n" << "\n" - << "layout(location = 0) out vec2 fs_out_color;\n" + << "layout(location = 0) out vec4 fs_out_color;\n" << "\n" << "void main (void)\n" << "{\n" << " if(fs_in_position_ndc.y < -2.0*pow(0.5*(fs_in_position_ndc.x + 1.0), 2.0) + 1.0)\n" - << " fs_out_color = vec2(1.0, 0.0);\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" << " else\n" - << " fs_out_color = vec2(0.0, 1.0);\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" << "}\n"; programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); } -TestInstance* MSCaseSampleQualifierDistinctValues::createInstance (Context& context) const +template<> TestInstance* MSCase::createInstance (Context& context) const { - return new MSInstanceDistinctValues(context, m_imageMSParams); + return new MSInstance(context, m_imageMSParams); } -class MSCaseInterpolateAtSampleDistinctValues : public MSInterpolationCaseBase -{ -public: - MSCaseInterpolateAtSampleDistinctValues (tcu::TestContext& testCtx, - const std::string& name, - const ImageMSParams& imageMSParams) - : MSInterpolationCaseBase(testCtx, name, imageMSParams) {} - - void init (void); - void initPrograms (vk::SourceCollections& programCollection) const; - TestInstance* createInstance (Context& context) const; -}; - -MSInterpolationCaseBase* createMSCaseInterpolateAtSampleDistinctValues (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) -{ - return new MSCaseInterpolateAtSampleDistinctValues(testCtx, name, imageMSParams); -} +class MSCaseInterpolateAtSampleDistinctValues; -void MSCaseInterpolateAtSampleDistinctValues::init (void) +template<> void MSCase::init (void) { m_testCtx.getLog() << tcu::TestLog::Message @@ -927,10 +240,10 @@ void MSCaseInterpolateAtSampleDistinctValues::init (void) << " => Resulting image should contain n+1 different colors, where n = sample count.\n" << tcu::TestLog::EndMessage; - MSInterpolationCaseBase::init(); + MultisampleCaseBase::init(); } -void MSCaseInterpolateAtSampleDistinctValues::initPrograms (vk::SourceCollections& programCollection) const +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const { // Create vertex shader std::ostringstream vs; @@ -957,61 +270,42 @@ void MSCaseInterpolateAtSampleDistinctValues::initPrograms (vk::SourceCollection fs << "#version 440\n" << "layout(location = 0) in vec4 fs_in_position_ndc;\n" << "\n" - << "layout(location = 0) out vec2 fs_out_color;\n" + << "layout(location = 0) out vec4 fs_out_color;\n" << "\n" << "void main (void)\n" << "{\n" << " const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n" << " if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n" - << " fs_out_color = vec2(0.0, 1.0);\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" << " else\n" - << " fs_out_color = vec2(1.0, 0.0);\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" << "}\n"; programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); } -TestInstance* MSCaseInterpolateAtSampleDistinctValues::createInstance (Context& context) const +template<> TestInstance* MSCase::createInstance (Context& context) const { - return new MSInstanceDistinctValues(context, m_imageMSParams); + return new MSInstance(context, m_imageMSParams); } -class MSInstanceInterpolateScreenPosition : public MSInterpolationInstanceBase -{ -public: - MSInstanceInterpolateScreenPosition (Context& context, - const ImageMSParams& imageMSParams) - : MSInterpolationInstanceBase(context, imageMSParams) {} - - VertexDataDesc getVertexDataDescripton (void) const; - void uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const; - tcu::TestStatus verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const; - -protected: - struct VertexData - { - VertexData(const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {} - - tcu::Vec4 positionNdc; - tcu::Vec2 positionScreen; - }; -}; +class MSInstanceInterpolateScreenPosition; -MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateScreenPosition::getVertexDataDescripton (void) const +template<> MSInstanceBaseResolve::VertexDataDesc MSInstance::getVertexDataDescripton (void) const { VertexDataDesc vertexDataDesc; vertexDataDesc.verticesCount = 4u; - vertexDataDesc.dataStride = sizeof(VertexData); + vertexDataDesc.dataStride = sizeof(VertexDataNdcScreen); vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; const VkVertexInputAttributeDescription vertexAttribPositionNdc = { - 0u, // deUint32 location; - 0u, // deUint32 binding; - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; - DE_OFFSET_OF(VertexData, positionNdc), // deUint32 offset; + 0u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + DE_OFFSET_OF(VertexDataNdcScreen, positionNdc), // deUint32 offset; }; vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); @@ -1021,7 +315,7 @@ MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateScreenPosition: 1u, // deUint32 location; 0u, // deUint32 binding; VK_FORMAT_R32G32_SFLOAT, // VkFormat format; - DE_OFFSET_OF(VertexData, positionScreen), // deUint32 offset; + DE_OFFSET_OF(VertexDataNdcScreen, positionScreen), // deUint32 offset; }; vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen); @@ -1029,50 +323,33 @@ MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateScreenPosition: return vertexDataDesc; } -void MSInstanceInterpolateScreenPosition::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const +template<> void MSInstance::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const { const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize); const float screenSizeX = static_cast(layerSize.x()); const float screenSizeY = static_cast(layerSize.y()); - std::vector vertices; + std::vector vertices; - vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f))); - vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f))); - vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSizeY))); - vertices.push_back(VertexData(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY))); + vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f))); + vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f))); + vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSizeY))); + vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY))); deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast(vertexDataDescripton.dataSize)); } -tcu::TestStatus MSInstanceInterpolateScreenPosition::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const +template<> tcu::TestStatus MSInstance::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const { - for (deInt32 z = 0u; z < imageData.getDepth(); ++z) - for (deInt32 y = 0u; y < imageData.getHeight(); ++y) - for (deInt32 x = 0u; x < imageData.getWidth(); ++x) - { - const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x(); + if (checkForError(imageRSInfo, dataRS, 0)) + return tcu::TestStatus::fail("Failed"); - if (firstComponent > 0) - return tcu::TestStatus::fail("Failed"); - } return tcu::TestStatus::pass("Passed"); } -class MSCaseInterpolateAtSampleSingleSample : public MSInterpolationCaseBase -{ -public: - MSCaseInterpolateAtSampleSingleSample (tcu::TestContext& testCtx, - const std::string& name, - tcu::UVec3 imageSize) - : MSInterpolationCaseBase(testCtx, name, ImageMSParams(VK_SAMPLE_COUNT_1_BIT, imageSize)) {} - - void init (void); - void initPrograms (vk::SourceCollections& programCollection) const; - TestInstance* createInstance (Context& context) const; -}; +class MSCaseInterpolateAtSampleSingleSample; -void MSCaseInterpolateAtSampleSingleSample::init (void) +template<> void MSCase::init (void) { m_testCtx.getLog() << tcu::TestLog::Message @@ -1081,10 +358,10 @@ void MSCaseInterpolateAtSampleSingleSample::init (void) << " => fract(screen space location) should be (about) (0.5, 0.5)\n" << tcu::TestLog::EndMessage; - MSInterpolationCaseBase::init(); + MultisampleCaseBase::init(); } -void MSCaseInterpolateAtSampleSingleSample::initPrograms (vk::SourceCollections& programCollection) const +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const { // Create vertex shader std::ostringstream vs; @@ -1112,7 +389,7 @@ void MSCaseInterpolateAtSampleSingleSample::initPrograms (vk::SourceCollections& fs << "#version 440\n" << "layout(location = 0) in vec2 fs_in_position_screen;\n" << "\n" - << "layout(location = 0) out vec2 fs_out_color;\n" + << "layout(location = 0) out vec4 fs_out_color;\n" << "\n" << "void main (void)\n" << "{\n" @@ -1121,38 +398,22 @@ void MSCaseInterpolateAtSampleSingleSample::initPrograms (vk::SourceCollections& << " const vec2 position_inside_pixel = fract(position_screen_at_sample);\n" << "\n" << " if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= threshold)\n" - << " fs_out_color = vec2(0.0, 1.0);\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" << " else\n" - << " fs_out_color = vec2(1.0, 0.0);\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" << "}\n"; programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); } -TestInstance* MSCaseInterpolateAtSampleSingleSample::createInstance (Context& context) const +template<> TestInstance* MSCase::createInstance (Context& context) const { - return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams); + return new MSInstance(context, m_imageMSParams); } -class MSCaseInterpolateAtSampleIgnoresCentroid : public MSInterpolationCaseBase -{ -public: - MSCaseInterpolateAtSampleIgnoresCentroid(tcu::TestContext& testCtx, - const std::string& name, - const ImageMSParams& imageMSParams) - : MSInterpolationCaseBase(testCtx, name, imageMSParams) {} - - void init (void); - void initPrograms (vk::SourceCollections& programCollection) const; - TestInstance* createInstance (Context& context) const; -}; - -MSInterpolationCaseBase* createMSCaseInterpolateAtSampleIgnoresCentroid (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) -{ - return new MSCaseInterpolateAtSampleIgnoresCentroid(testCtx, name, imageMSParams); -} +class MSCaseInterpolateAtSampleIgnoresCentroid; -void MSCaseInterpolateAtSampleIgnoresCentroid::init (void) +template<> void MSCase::init (void) { m_testCtx.getLog() << tcu::TestLog::Message @@ -1161,10 +422,10 @@ void MSCaseInterpolateAtSampleIgnoresCentroid::init (void) << " => interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n" << tcu::TestLog::EndMessage; - MSInterpolationCaseBase::init(); + MultisampleCaseBase::init(); } -void MSCaseInterpolateAtSampleIgnoresCentroid::initPrograms (vk::SourceCollections& programCollection) const +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const { // Create vertex shader std::ostringstream vs; @@ -1195,7 +456,7 @@ void MSCaseInterpolateAtSampleIgnoresCentroid::initPrograms (vk::SourceCollectio << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n" << "layout(location = 1) in vec2 fs_in_pos_screen_fragment;\n" << "\n" - << "layout(location = 0) out vec2 fs_out_color;\n" + << "layout(location = 0) out vec4 fs_out_color;\n" << "\n" << "void main (void)\n" << "{\n" @@ -1206,38 +467,22 @@ void MSCaseInterpolateAtSampleIgnoresCentroid::initPrograms (vk::SourceCollectio << " const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n" << "\n" << " if (valuesEqual)\n" - << " fs_out_color = vec2(0.0, 1.0);\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" << " else\n" - << " fs_out_color = vec2(1.0, 0.0);\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" << "}\n"; programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); } -TestInstance* MSCaseInterpolateAtSampleIgnoresCentroid::createInstance (Context& context) const +template<> TestInstance* MSCase::createInstance (Context& context) const { - return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams); + return new MSInstance(context, m_imageMSParams); } -class MSCaseInterpolateAtSampleConsistency : public MSInterpolationCaseBase -{ -public: - MSCaseInterpolateAtSampleConsistency (tcu::TestContext& testCtx, - const std::string& name, - const ImageMSParams& imageMSParams) - : MSInterpolationCaseBase(testCtx, name, imageMSParams) {} - - void init (void); - void initPrograms (vk::SourceCollections& programCollection) const; - TestInstance* createInstance (Context& context) const; -}; +class MSCaseInterpolateAtSampleConsistency; -MSInterpolationCaseBase* createMSCaseInterpolateAtSampleConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) -{ - return new MSCaseInterpolateAtSampleConsistency(testCtx, name, imageMSParams); -} - -void MSCaseInterpolateAtSampleConsistency::init (void) +template<> void MSCase::init (void) { m_testCtx.getLog() << tcu::TestLog::Message @@ -1246,10 +491,10 @@ void MSCaseInterpolateAtSampleConsistency::init (void) << " => interpolateAtSample(screenCentroid, sampleID) = screenSample\n" << tcu::TestLog::EndMessage; - MSInterpolationCaseBase::init(); + MultisampleCaseBase::init(); } -void MSCaseInterpolateAtSampleConsistency::initPrograms (vk::SourceCollections& programCollection) const +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const { // Create vertex shader std::ostringstream vs; @@ -1280,7 +525,7 @@ void MSCaseInterpolateAtSampleConsistency::initPrograms (vk::SourceCollections& << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n" << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n" << "\n" - << "layout(location = 0) out vec2 fs_out_color;\n" + << "layout(location = 0) out vec4 fs_out_color;\n" << "\n" << "void main (void)\n" << "{\n" @@ -1290,38 +535,22 @@ void MSCaseInterpolateAtSampleConsistency::initPrograms (vk::SourceCollections& << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_sample - fs_in_pos_screen_sample), vec2(threshold)));\n" << "\n" << " if (valuesEqual)\n" - << " fs_out_color = vec2(0.0, 1.0);\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" << " else\n" - << " fs_out_color = vec2(1.0, 0.0);\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" << "}\n"; programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); } -TestInstance* MSCaseInterpolateAtSampleConsistency::createInstance (Context& context) const +template<> TestInstance* MSCase::createInstance (Context& context) const { - return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams); + return new MSInstance(context, m_imageMSParams); } -class MSCaseInterpolateAtCentroidConsistency : public MSInterpolationCaseBase -{ -public: - MSCaseInterpolateAtCentroidConsistency (tcu::TestContext& testCtx, - const std::string& name, - const ImageMSParams& imageMSParams) - : MSInterpolationCaseBase(testCtx, name, imageMSParams) {} - - void init (void); - void initPrograms (vk::SourceCollections& programCollection) const; - TestInstance* createInstance (Context& context) const; -}; - -MSInterpolationCaseBase* createMSCaseInterpolateAtCentroidConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) -{ - return new MSCaseInterpolateAtCentroidConsistency(testCtx, name, imageMSParams); -} +class MSCaseInterpolateAtCentroidConsistency; -void MSCaseInterpolateAtCentroidConsistency::init (void) +template<> void MSCase::init (void) { m_testCtx.getLog() << tcu::TestLog::Message @@ -1330,10 +559,10 @@ void MSCaseInterpolateAtCentroidConsistency::init (void) << " => interpolateAtCentroid(screenSample) = screenCentroid\n" << tcu::TestLog::EndMessage; - MSInterpolationCaseBase::init(); + MultisampleCaseBase::init(); } -void MSCaseInterpolateAtCentroidConsistency::initPrograms (vk::SourceCollections& programCollection) const +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const { // Create vertex shader std::ostringstream vs; @@ -1364,7 +593,7 @@ void MSCaseInterpolateAtCentroidConsistency::initPrograms (vk::SourceCollections << "layout(location = 0) sample in vec2 fs_in_pos_screen_sample;\n" << "layout(location = 1) centroid in vec2 fs_in_pos_screen_centroid;\n" << "\n" - << "layout(location = 0) out vec2 fs_out_color;\n" + << "layout(location = 0) out vec4 fs_out_color;\n" << "\n" << "void main (void)\n" << "{\n" @@ -1374,38 +603,22 @@ void MSCaseInterpolateAtCentroidConsistency::initPrograms (vk::SourceCollections << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid), vec2(threshold)));\n" << "\n" << " if (valuesEqual)\n" - << " fs_out_color = vec2(0.0, 1.0);\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" << " else\n" - << " fs_out_color = vec2(1.0, 0.0);\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" << "}\n"; programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); } -TestInstance* MSCaseInterpolateAtCentroidConsistency::createInstance (Context& context) const +template<> TestInstance* MSCase::createInstance (Context& context) const { - return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams); + return new MSInstance(context, m_imageMSParams); } -class MSCaseInterpolateAtOffsetPixelCenter : public MSInterpolationCaseBase -{ -public: - MSCaseInterpolateAtOffsetPixelCenter(tcu::TestContext& testCtx, - const std::string& name, - const ImageMSParams& imageMSParams) - : MSInterpolationCaseBase(testCtx, name, imageMSParams) {} - - void init (void); - void initPrograms (vk::SourceCollections& programCollection) const; - TestInstance* createInstance (Context& context) const; -}; - -MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetPixelCenter (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) -{ - return new MSCaseInterpolateAtOffsetPixelCenter(testCtx, name, imageMSParams); -} +class MSCaseInterpolateAtOffsetPixelCenter; -void MSCaseInterpolateAtOffsetPixelCenter::init (void) +template<> void MSCase::init (void) { m_testCtx.getLog() << tcu::TestLog::Message @@ -1414,10 +627,10 @@ void MSCaseInterpolateAtOffsetPixelCenter::init (void) << " => interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset" << tcu::TestLog::EndMessage; - MSInterpolationCaseBase::init(); + MultisampleCaseBase::init(); } -void MSCaseInterpolateAtOffsetPixelCenter::initPrograms (vk::SourceCollections& programCollection) const +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const { // Create vertex shader std::ostringstream vs; @@ -1448,7 +661,7 @@ void MSCaseInterpolateAtOffsetPixelCenter::initPrograms (vk::SourceCollections& << "layout(location = 0) in vec2 fs_in_pos_screen;\n" << "layout(location = 1) in vec2 fs_in_offset;\n" << "\n" - << "layout(location = 0) out vec2 fs_out_color;\n" + << "layout(location = 0) out vec4 fs_out_color;\n" << "\n" << "void main (void)\n" << "{\n" @@ -1465,38 +678,22 @@ void MSCaseInterpolateAtOffsetPixelCenter::initPrograms (vk::SourceCollections& << " }\n" << "\n" << " if (valuesEqual)\n" - << " fs_out_color = vec2(0.0, 1.0);\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" << " else\n" - << " fs_out_color = vec2(1.0, 0.0);\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" << "}\n"; programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); } -TestInstance* MSCaseInterpolateAtOffsetPixelCenter::createInstance (Context& context) const +template<> TestInstance* MSCase::createInstance (Context& context) const { - return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams); + return new MSInstance(context, m_imageMSParams); } -class MSCaseInterpolateAtOffsetSamplePosition : public MSInterpolationCaseBase -{ -public: - MSCaseInterpolateAtOffsetSamplePosition (tcu::TestContext& testCtx, - const std::string& name, - const ImageMSParams& imageMSParams) - : MSInterpolationCaseBase(testCtx, name, imageMSParams) {} - - void init (void); - void initPrograms (vk::SourceCollections& programCollection) const; - TestInstance* createInstance (Context& context) const; -}; - -MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetSamplePosition (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) -{ - return new MSCaseInterpolateAtOffsetSamplePosition(testCtx, name, imageMSParams); -} +class MSCaseInterpolateAtOffsetSamplePosition; -void MSCaseInterpolateAtOffsetSamplePosition::init (void) +template<> void MSCase::init (void) { m_testCtx.getLog() << tcu::TestLog::Message @@ -1506,10 +703,10 @@ void MSCaseInterpolateAtOffsetSamplePosition::init (void) << " => interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample" << tcu::TestLog::EndMessage; - MSInterpolationCaseBase::init(); + MultisampleCaseBase::init(); } -void MSCaseInterpolateAtOffsetSamplePosition::initPrograms (vk::SourceCollections& programCollection) const +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const { // Create vertex shader std::ostringstream vs; @@ -1540,7 +737,7 @@ void MSCaseInterpolateAtOffsetSamplePosition::initPrograms (vk::SourceCollection << "layout(location = 0) in vec2 fs_in_pos_screen_fragment;\n" << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n" << "\n" - << "layout(location = 0) out vec2 fs_out_color;\n" + << "layout(location = 0) out vec4 fs_out_color;\n" << "\n" << "void main (void)\n" << "{\n" @@ -1551,65 +748,46 @@ void MSCaseInterpolateAtOffsetSamplePosition::initPrograms (vk::SourceCollection << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - fs_in_pos_screen_sample), vec2(threshold)));\n" << "\n" << " if (valuesEqual)\n" - << " fs_out_color = vec2(0.0, 1.0);\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" << " else\n" - << " fs_out_color = vec2(1.0, 0.0);\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" << "}\n"; programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); } -TestInstance* MSCaseInterpolateAtOffsetSamplePosition::createInstance (Context& context) const +template<> TestInstance* MSCase::createInstance (Context& context) const { - return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams); + return new MSInstance(context, m_imageMSParams); } -class MSInstanceInterpolateBarycentricCoordinates : public MSInterpolationInstanceBase -{ -public: - MSInstanceInterpolateBarycentricCoordinates (Context& context, - const ImageMSParams& imageMSParams) - : MSInterpolationInstanceBase(context, imageMSParams) {} - - VertexDataDesc getVertexDataDescripton (void) const; - void uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const; - tcu::TestStatus verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const; - -protected: - struct VertexData - { - VertexData(const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {} +class MSInstanceInterpolateBarycentricCoordinates; - tcu::Vec4 positionNdc; - tcu::Vec3 barycentricCoord; - }; -}; - -MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateBarycentricCoordinates::getVertexDataDescripton (void) const +template<> MSInstanceBaseResolve::VertexDataDesc MSInstance::getVertexDataDescripton (void) const { VertexDataDesc vertexDataDesc; vertexDataDesc.verticesCount = 3u; - vertexDataDesc.dataStride = sizeof(VertexData); + vertexDataDesc.dataStride = sizeof(VertexDataNdcBarycentric); vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; const VkVertexInputAttributeDescription vertexAttribPositionNdc = { - 0u, // deUint32 location; - 0u, // deUint32 binding; - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; - DE_OFFSET_OF(VertexData, positionNdc), // deUint32 offset; + 0u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + DE_OFFSET_OF(VertexDataNdcBarycentric, positionNdc), // deUint32 offset; }; vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); const VkVertexInputAttributeDescription vertexAttrBarCoord = { - 1u, // deUint32 location; - 0u, // deUint32 binding; - VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format; - DE_OFFSET_OF(VertexData, barycentricCoord), // deUint32 offset; + 1u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format; + DE_OFFSET_OF(VertexDataNdcBarycentric, barycentricCoord), // deUint32 offset; }; vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord); @@ -1617,52 +795,29 @@ MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateBarycentricCoor return vertexDataDesc; } -void MSInstanceInterpolateBarycentricCoordinates::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const +template<> void MSInstance::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const { // Create buffer storing vertex data - std::vector vertices; + std::vector vertices; - vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f))); - vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f))); - vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f))); + vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f))); + vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f))); + vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f))); deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast(vertexDataDescripton.dataSize)); } -tcu::TestStatus MSInstanceInterpolateBarycentricCoordinates::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const +template<> tcu::TestStatus MSInstance::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const { - for (deInt32 z = 0u; z < imageData.getDepth(); ++z) - for (deInt32 y = 0u; y < imageData.getHeight(); ++y) - for (deInt32 x = 0u; x < imageData.getWidth(); ++x) - { - const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x(); - - if (firstComponent > 0) - return tcu::TestStatus::fail("Failed"); - } + if (checkForError(imageRSInfo, dataRS, 0)) + return tcu::TestStatus::fail("Failed"); return tcu::TestStatus::pass("Passed"); } -class MSCaseCentroidQualifierInsidePrimitive : public MSInterpolationCaseBase -{ -public: - MSCaseCentroidQualifierInsidePrimitive (tcu::TestContext& testCtx, - const std::string& name, - const ImageMSParams& imageMSParams) - : MSInterpolationCaseBase(testCtx, name, imageMSParams) {} - - void init (void); - void initPrograms (vk::SourceCollections& programCollection) const; - TestInstance* createInstance (Context& context) const; -}; - -MSInterpolationCaseBase* createMSCaseCentroidQualifierInsidePrimitive (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) -{ - return new MSCaseCentroidQualifierInsidePrimitive(testCtx, name, imageMSParams); -} +class MSCaseCentroidQualifierInsidePrimitive; -void MSCaseCentroidQualifierInsidePrimitive::init (void) +template<> void MSCase::init (void) { m_testCtx.getLog() << tcu::TestLog::Message @@ -1671,10 +826,10 @@ void MSCaseCentroidQualifierInsidePrimitive::init (void) << " => After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n" << tcu::TestLog::EndMessage; - MSInterpolationCaseBase::init(); + MultisampleCaseBase::init(); } -void MSCaseCentroidQualifierInsidePrimitive::initPrograms (vk::SourceCollections& programCollection) const +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const { // Create vertex shader std::ostringstream vs; @@ -1702,58 +857,26 @@ void MSCaseCentroidQualifierInsidePrimitive::initPrograms (vk::SourceCollections fs << "#version 440\n" << "layout(location = 0) centroid in vec3 fs_in_barCoord;\n" << "\n" - << "layout(location = 0) out vec2 fs_out_color;\n" + << "layout(location = 0) out vec4 fs_out_color;\n" << "\n" << "void main (void)\n" << "{\n" << " if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) )\n" - << " fs_out_color = vec2(0.0, 1.0);\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" << " else\n" - << " fs_out_color = vec2(1.0, 0.0);\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" << "}\n"; programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); } -TestInstance* MSCaseCentroidQualifierInsidePrimitive::createInstance (Context& context) const +template<> TestInstance* MSCase::createInstance (Context& context) const { - return new MSInstanceInterpolateBarycentricCoordinates(context, m_imageMSParams); + return new MSInstance(context, m_imageMSParams); } } // multisample -tcu::TestCaseGroup* makeGroup( multisample::MSInterpolationCaseFuncPtr createCaseFuncPtr, - tcu::TestContext& testCtx, - const std::string groupName, - const tcu::UVec3 imageSizes[], - const deUint32 imageSizesElemCount, - const vk::VkSampleCountFlagBits imageSamples[], - const deUint32 imageSamplesElemCount) -{ - de::MovePtr caseGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str(), "")); - - for (deUint32 imageSizeNdx = 0u; imageSizeNdx < imageSizesElemCount; ++imageSizeNdx) - { - const tcu::UVec3 imageSize = imageSizes[imageSizeNdx]; - std::ostringstream imageSizeStream; - - imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z(); - - de::MovePtr sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), "")); - - for (deUint32 imageSamplesNdx = 0u; imageSamplesNdx < imageSamplesElemCount; ++imageSamplesNdx) - { - const vk::VkSampleCountFlagBits samples = imageSamples[imageSamplesNdx]; - const multisample::ImageMSParams imageMSParams = multisample::ImageMSParams(samples, imageSize); - - sizeGroup->addChild(createCaseFuncPtr(testCtx, "samples_" + de::toString(samples), imageMSParams)); - } - - caseGroup->addChild(sizeGroup.release()); - } - return caseGroup.release(); -} - tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testCtx) { de::MovePtr testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation", "Multisample Interpolation")); @@ -1789,21 +912,21 @@ tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testC de::MovePtr sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), "")); - sizeGroup->addChild(new multisample::MSCaseInterpolateAtSampleSingleSample(testCtx, "samples_" + de::toString(1), imageSize)); + sizeGroup->addChild(multisample::MSCase::createCase(testCtx, "samples_" + de::toString(1), multisample::ImageMSParams(vk::VK_SAMPLE_COUNT_1_BIT, imageSize))); caseGroup->addChild(sizeGroup.release()); } testGroup->addChild(caseGroup.release()); - testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleDistinctValues, testCtx, "sample_interpolate_at_distinct_values", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); - testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleIgnoresCentroid, testCtx, "sample_interpolate_at_ignores_centroid", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); - testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleConsistency, testCtx, "sample_interpolate_at_consistency", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); - testGroup->addChild(makeGroup(multisample::createMSCaseSampleQualifierDistinctValues, testCtx, "sample_qualifier_distinct_values", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); - testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtCentroidConsistency, testCtx, "centroid_interpolate_at_consistency", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); - testGroup->addChild(makeGroup(multisample::createMSCaseCentroidQualifierInsidePrimitive, testCtx, "centroid_qualifier_inside_primitive", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); - testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetPixelCenter, testCtx, "offset_interpolate_at_pixel_center", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); - testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetSamplePosition, testCtx, "offset_interpolate_at_sample_position", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); + testGroup->addChild(makeMSGroup > (testCtx, "sample_interpolate_at_distinct_values", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); + testGroup->addChild(makeMSGroup >(testCtx, "sample_interpolate_at_ignores_centroid", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); + testGroup->addChild(makeMSGroup > (testCtx, "sample_interpolate_at_consistency", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); + testGroup->addChild(makeMSGroup > (testCtx, "sample_qualifier_distinct_values", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); + testGroup->addChild(makeMSGroup > (testCtx, "centroid_interpolate_at_consistency", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); + testGroup->addChild(makeMSGroup > (testCtx, "centroid_qualifier_inside_primitive", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); + testGroup->addChild(makeMSGroup > (testCtx, "offset_interpolate_at_pixel_center", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); + testGroup->addChild(makeMSGroup > (testCtx, "offset_interpolate_at_sample_position", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); return testGroup.release(); } diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleInterpolationTests.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleInterpolationTests.hpp index c4052ca..74ae7ca 100644 --- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleInterpolationTests.hpp +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleInterpolationTests.hpp @@ -4,8 +4,7 @@ * Vulkan Conformance Tests * ------------------------ * - * Copyright (c) 2015 The Khronos Group Inc. - * Copyright (c) 2015 Imagination Technologies Ltd. + * 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. diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.cpp new file mode 100644 index 0000000..344cf9e --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.cpp @@ -0,0 +1,1077 @@ +/*------------------------------------------------------------------------ +* Vulkan Conformance Tests +* ------------------------ +* +* 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 vktPipelineMultisampleShaderBuiltInTests.cpp +* \brief Multisample Shader BuiltIn Tests +*//*--------------------------------------------------------------------*/ + +#include "vktPipelineMultisampleShaderBuiltInTests.hpp" +#include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp" +#include "vktPipelineMakeUtil.hpp" +#include "vkBuilderUtil.hpp" +#include "vkQueryUtil.hpp" +#include "tcuVectorUtil.hpp" + +namespace vkt +{ +namespace pipeline +{ +namespace multisample +{ + +using namespace vk; + +struct VertexDataNdc +{ + VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {} + + tcu::Vec4 positionNdc; +}; + +MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdc (void) +{ + MultisampleInstanceBase::VertexDataDesc vertexDataDesc; + + vertexDataDesc.verticesCount = 4u; + vertexDataDesc.dataStride = sizeof(VertexDataNdc); + vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; + vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + + const VkVertexInputAttributeDescription vertexAttribPositionNdc = + { + 0u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + DE_OFFSET_OF(VertexDataNdc, positionNdc), // deUint32 offset; + }; + + vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); + + return vertexDataDesc; +} + +void uploadVertexDataNdc (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton) +{ + std::vector vertices; + + vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f))); + vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f))); + vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f))); + vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f))); + + deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast(vertexDataDescripton.dataSize)); +} + +struct VertexDataNdcScreen +{ + VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {} + + tcu::Vec4 positionNdc; + tcu::Vec2 positionScreen; +}; + +MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdcScreen (void) +{ + MultisampleInstanceBase::VertexDataDesc vertexDataDesc; + + vertexDataDesc.verticesCount = 4u; + vertexDataDesc.dataStride = sizeof(VertexDataNdcScreen); + vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; + vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + + const VkVertexInputAttributeDescription vertexAttribPositionNdc = + { + 0u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + DE_OFFSET_OF(VertexDataNdcScreen, positionNdc), // deUint32 offset; + }; + + vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); + + const VkVertexInputAttributeDescription vertexAttribPositionScreen = + { + 1u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32_SFLOAT, // VkFormat format; + DE_OFFSET_OF(VertexDataNdcScreen, positionScreen), // deUint32 offset; + }; + + vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen); + + return vertexDataDesc; +} + +void uploadVertexDataNdcScreen (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton, const tcu::Vec2& screenSize) +{ + std::vector vertices; + + vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f))); + vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), 0.0f))); + vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSize.y()))); + vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), screenSize.y()))); + + deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast(vertexDataDescripton.dataSize)); +} + +bool checkForErrorMS (const vk::VkImageCreateInfo& imageMSInfo, const std::vector& dataPerSample, const deUint32 errorCompNdx) +{ + const deUint32 numSamples = static_cast(imageMSInfo.samples); + + for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) + for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) + for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) + { + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[errorCompNdx]; + + if (errorComponent > 0) + return true; + } + } + + return false; +} + +bool checkForErrorRS (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx) +{ + for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) + for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) + for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) + { + const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx]; + + if (errorComponent > 0) + return true; + } + + return false; +} + +template +class MSCase : public MSCaseBaseResolveAndPerSampleFetch +{ +public: + MSCase (tcu::TestContext& testCtx, + const std::string& name, + const ImageMSParams& imageMSParams) + : MSCaseBaseResolveAndPerSampleFetch(testCtx, name, imageMSParams) {} + + void init (void); + void initPrograms (vk::SourceCollections& programCollection) const; + TestInstance* createInstance (Context& context) const; + static MultisampleCaseBase* createCase (tcu::TestContext& testCtx, + const std::string& name, + const ImageMSParams& imageMSParams); +}; + +template +MultisampleCaseBase* MSCase::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) +{ + return new MSCase(testCtx, name, imageMSParams); +} + +template +class MSInstance : public MSInstanceBaseResolveAndPerSampleFetch +{ +public: + MSInstance (Context& context, + const ImageMSParams& imageMSParams) + : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) {} + + VertexDataDesc getVertexDataDescripton (void) const; + void uploadVertexData (const Allocation& vertexBufferAllocation, + const VertexDataDesc& vertexDataDescripton) const; + + tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, + const vk::VkImageCreateInfo& imageRSInfo, + const std::vector& dataPerSample, + const tcu::ConstPixelBufferAccess& dataRS) const; +}; + +class MSInstanceSampleID; + +template<> MultisampleInstanceBase::VertexDataDesc MSInstance::getVertexDataDescripton (void) const +{ + return getVertexDataDescriptonNdc(); +} + +template<> void MSInstance::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const +{ + uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); +} + +template<> tcu::TestStatus MSInstance::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, + const vk::VkImageCreateInfo& imageRSInfo, + const std::vector& dataPerSample, + const tcu::ConstPixelBufferAccess& dataRS) const +{ + DE_UNREF(imageRSInfo); + DE_UNREF(dataRS); + + const deUint32 numSamples = static_cast(imageMSInfo.samples); + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) + for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) + for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) + { + const deUint32 sampleID = dataPerSample[sampleNdx].getPixelUint(x, y, z).x(); + + if (sampleID != sampleNdx) + return tcu::TestStatus::fail("gl_SampleID does not have correct value"); + } + } + + return tcu::TestStatus::pass("Passed"); +} + +class MSCaseSampleID; + +template<> void MSCase::init (void) +{ + m_testCtx.getLog() + << tcu::TestLog::Message + << "Writing gl_SampleID to the red channel of the texture and verifying texture values.\n" + << "Expecting value N at sample index N of a multisample texture.\n" + << tcu::TestLog::EndMessage; + + MultisampleCaseBase::init(); +} + +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const +{ + MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); + + // Create vertex shader + std::ostringstream vs; + + vs << "#version 440\n" + << "layout(location = 0) in vec4 vs_in_position_ndc;\n" + << "\n" + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = vs_in_position_ndc;\n" + << "}\n"; + + programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); + + // Create fragment shader + std::ostringstream fs; + + fs << "#version 440\n" + << "\n" + << "layout(location = 0) out vec4 fs_out_color;\n" + << "\n" + << "void main (void)\n" + << "{\n" + << " fs_out_color = vec4(float(gl_SampleID) / float(255), 0.0, 0.0, 1.0);\n" + << "}\n"; + + programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); +} + +template<> TestInstance* MSCase::createInstance (Context& context) const +{ + return new MSInstance(context, m_imageMSParams); +} + +class MSInstanceSamplePosDistribution; + +template<> MultisampleInstanceBase::VertexDataDesc MSInstance::getVertexDataDescripton (void) const +{ + return getVertexDataDescriptonNdc(); +} + +template<> void MSInstance::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const +{ + uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); +} + +template<> tcu::TestStatus MSInstance::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, + const vk::VkImageCreateInfo& imageRSInfo, + const std::vector& dataPerSample, + const tcu::ConstPixelBufferAccess& dataRS) const +{ + const deUint32 numSamples = static_cast(imageMSInfo.samples); + + // approximate Bates distribution as normal + const float variance = (1.0f / (12.0f * (float)numSamples)); + const float standardDeviation = deFloatSqrt(variance); + + // 95% of means of sample positions are within 2 standard deviations if + // they were randomly assigned. Sample patterns are expected to be more + // uniform than a random pattern. + const float distanceThreshold = 2.0f * standardDeviation; + + for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) + for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) + for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) + { + const deUint32 errorComponent = dataRS.getPixelUint(x, y, z).z(); + + if (errorComponent > 0) + return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]"); + + if (numSamples >= VK_SAMPLE_COUNT_4_BIT) + { + const tcu::Vec2 averageSamplePos = tcu::Vec2((float)dataRS.getPixelUint(x, y, z).x() / 255.0f, (float)dataRS.getPixelUint(x, y, z).y() / 255.0f); + const tcu::Vec2 distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f)); + + if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold) + return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel"); + } + } + + for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) + for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) + for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) + { + std::vector samplePositions(numSamples); + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z).z(); + + if (errorComponent > 0) + return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]"); + + samplePositions[sampleNdx] = tcu::Vec2( (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).x() / 255.0f, + (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).y() / 255.0f); + } + + for (deUint32 sampleNdxA = 0u; sampleNdxA < numSamples; ++sampleNdxA) + for (deUint32 sampleNdxB = sampleNdxA + 1u; sampleNdxB < numSamples; ++sampleNdxB) + { + if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB]) + return tcu::TestStatus::fail("Two samples have the same position"); + } + + if (numSamples >= VK_SAMPLE_COUNT_4_BIT) + { + tcu::Vec2 averageSamplePos(0.0f, 0.0f); + + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + averageSamplePos.x() += samplePositions[sampleNdx].x(); + averageSamplePos.y() += samplePositions[sampleNdx].y(); + } + + averageSamplePos.x() /= (float)numSamples; + averageSamplePos.y() /= (float)numSamples; + + const tcu::Vec2 distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f)); + + if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold) + return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel"); + } + } + + return tcu::TestStatus::pass("Passed"); +} + +class MSCaseSamplePosDistribution; + +template<> void MSCase::init (void) +{ + m_testCtx.getLog() + << tcu::TestLog::Message + << "Verifying gl_SamplePosition value with multisample targets:\n" + << " a) Expect legal sample position.\n" + << " b) Sample position is unique within the set of all sample positions of a pixel.\n" + << " c) Sample position distribution is uniform or almost uniform.\n" + << tcu::TestLog::EndMessage; + + MultisampleCaseBase::init(); +} + +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const +{ + MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); + + // Create vertex shader + std::ostringstream vs; + + vs << "#version 440\n" + << "layout(location = 0) in vec4 vs_in_position_ndc;\n" + << "\n" + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = vs_in_position_ndc;\n" + << "}\n"; + + programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); + + // Create fragment shader + std::ostringstream fs; + + fs << "#version 440\n" + << "\n" + << "layout(location = 0) out vec4 fs_out_color;\n" + << "\n" + << "void main (void)\n" + << "{\n" + << " if (gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0 || gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0)\n" + " fs_out_color = vec4(0.0, 0.0, 1.0, 1.0);\n" + " else\n" + " fs_out_color = vec4(gl_SamplePosition.x, gl_SamplePosition.y, 0.0, 1.0);\n" + "}\n"; + + programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); +} + +template<> TestInstance* MSCase::createInstance (Context& context) const +{ + return new MSInstance(context, m_imageMSParams); +} + +class MSInstanceSamplePosCorrectness; + +template<> MultisampleInstanceBase::VertexDataDesc MSInstance::getVertexDataDescripton (void) const +{ + return getVertexDataDescriptonNdcScreen(); +} + +template<> void MSInstance::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const +{ + const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize); + + uploadVertexDataNdcScreen(vertexBufferAllocation, vertexDataDescripton, tcu::Vec2(static_cast(layerSize.x()), static_cast(layerSize.y()))); +} + +template<> tcu::TestStatus MSInstance::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, + const vk::VkImageCreateInfo& imageRSInfo, + const std::vector& dataPerSample, + const tcu::ConstPixelBufferAccess& dataRS) const +{ + if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) + return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition"); + + if (checkForErrorRS(imageRSInfo, dataRS, 0)) + return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition"); + + return tcu::TestStatus::pass("Passed"); +} + +class MSCaseSamplePosCorrectness; + +template<> void MSCase::init (void) +{ + m_testCtx.getLog() + << tcu::TestLog::Message + << "Verifying gl_SamplePosition correctness:\n" + << " 1) Varying values should be sampled at the sample position.\n" + << " => fract(position_screen) == gl_SamplePosition\n" + << tcu::TestLog::EndMessage; + + MultisampleCaseBase::init(); +} + +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const +{ + MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); + + // Create vertex shaders + std::ostringstream vs; + + vs << "#version 440\n" + << "layout(location = 0) in vec4 vs_in_position_ndc;\n" + << "layout(location = 1) in vec2 vs_in_position_screen;\n" + << "\n" + << "layout(location = 0) sample out vec2 vs_out_position_screen;\n" + << "\n" + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = vs_in_position_ndc;\n" + << " vs_out_position_screen = vs_in_position_screen;\n" + << "}\n"; + + programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); + + // Create fragment shader + std::ostringstream fs; + + fs << "#version 440\n" + << "layout(location = 0) sample in vec2 fs_in_position_screen;\n" + << "\n" + << "layout(location = 0) out vec4 fs_out_color;\n" + << "\n" + << "void main (void)\n" + << "{\n" + << " const float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" + << " const ivec2 nearby_pixel = ivec2(floor(fs_in_position_screen));\n" + << " bool ok = false;\n" + << "\n" + << " // sample at edge + inaccuaries may cause us to round to any neighboring pixel\n" + << " // check all neighbors for any match\n" + << " for (int dy = -1; dy <= 1; ++dy)\n" + << " for (int dx = -1; dx <= 1; ++dx)\n" + << " {\n" + << " ivec2 current_pixel = nearby_pixel + ivec2(dx, dy);\n" + << " vec2 position_inside_pixel = vec2(current_pixel) + gl_SamplePosition;\n" + << " vec2 position_diff = abs(position_inside_pixel - fs_in_position_screen);\n" + << "\n" + << " if (all(lessThan(position_diff, vec2(threshold))))\n" + << " ok = true;\n" + << " }\n" + << "\n" + << " if (ok)\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" + << " else\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" + << "}\n"; + + programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); +} + +template<> TestInstance* MSCase::createInstance (Context& context) const +{ + return new MSInstance(context, m_imageMSParams); +} + +class MSInstanceSampleMaskPattern : public MSInstanceBaseResolveAndPerSampleFetch +{ +public: + MSInstanceSampleMaskPattern (Context& context, + const ImageMSParams& imageMSParams); + + VkPipelineMultisampleStateCreateInfo getMSStateCreateInfo (const ImageMSParams& imageMSParams) const; + + const VkDescriptorSetLayout* createMSPassDescSetLayout (const ImageMSParams& imageMSParams); + + const VkDescriptorSet* createMSPassDescSet (const ImageMSParams& imageMSParams, + const VkDescriptorSetLayout* descSetLayout); + + VertexDataDesc getVertexDataDescripton (void) const; + + void uploadVertexData (const Allocation& vertexBufferAllocation, + const VertexDataDesc& vertexDataDescripton) const; + + tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, + const vk::VkImageCreateInfo& imageRSInfo, + const std::vector& dataPerSample, + const tcu::ConstPixelBufferAccess& dataRS) const; +protected: + + VkSampleMask m_sampleMask; + Move m_descriptorSetLayout; + Move m_descriptorPool; + Move m_descriptorSet; + de::MovePtr m_buffer; +}; + +MSInstanceSampleMaskPattern::MSInstanceSampleMaskPattern (Context& context, const ImageMSParams& imageMSParams) : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) +{ + m_sampleMask = 0xAAAAAAAAu & ((1u << imageMSParams.numSamples) - 1u); +} + +VkPipelineMultisampleStateCreateInfo MSInstanceSampleMaskPattern::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const +{ + const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags; + imageMSParams.numSamples, // VkSampleCountFlagBits rasterizationSamples; + VK_TRUE, // VkBool32 sampleShadingEnable; + 1.0f, // float minSampleShading; + &m_sampleMask, // const VkSampleMask* pSampleMask; + VK_FALSE, // VkBool32 alphaToCoverageEnable; + VK_FALSE, // VkBool32 alphaToOneEnable; + }; + + return multisampleStateInfo; +} + +const VkDescriptorSetLayout* MSInstanceSampleMaskPattern::createMSPassDescSetLayout (const ImageMSParams& imageMSParams) +{ + DE_UNREF(imageMSParams); + + const DeviceInterface& deviceInterface = m_context.getDeviceInterface(); + const VkDevice device = m_context.getDevice(); + + // Create descriptor set layout + m_descriptorSetLayout = DescriptorSetLayoutBuilder() + .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT) + .build(deviceInterface, device); + + return &m_descriptorSetLayout.get(); +} + +const VkDescriptorSet* MSInstanceSampleMaskPattern::createMSPassDescSet (const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout) +{ + DE_UNREF(imageMSParams); + + const DeviceInterface& deviceInterface = m_context.getDeviceInterface(); + const VkDevice device = m_context.getDevice(); + Allocator& allocator = m_context.getDefaultAllocator(); + + // Create descriptor pool + m_descriptorPool = DescriptorPoolBuilder() + .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u) + .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); + + // Create descriptor set + m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *descSetLayout); + + const VkBufferCreateInfo bufferSampleMaskInfo = makeBufferCreateInfo(sizeof(VkSampleMask), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + m_buffer = de::MovePtr(new Buffer(deviceInterface, device, allocator, bufferSampleMaskInfo, MemoryRequirement::HostVisible)); + + deMemcpy(m_buffer->getAllocation().getHostPtr(), &m_sampleMask, sizeof(VkSampleMask)); + + flushMappedMemoryRange(deviceInterface, device, m_buffer->getAllocation().getMemory(), m_buffer->getAllocation().getOffset(), VK_WHOLE_SIZE); + + const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**m_buffer, 0u, sizeof(VkSampleMask)); + + DescriptorSetUpdateBuilder() + .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descBufferInfo) + .update(deviceInterface, device); + + return &m_descriptorSet.get(); +} + +MultisampleInstanceBase::VertexDataDesc MSInstanceSampleMaskPattern::getVertexDataDescripton (void) const +{ + return getVertexDataDescriptonNdc(); +} + +void MSInstanceSampleMaskPattern::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const +{ + uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); +} + +tcu::TestStatus MSInstanceSampleMaskPattern::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, + const vk::VkImageCreateInfo& imageRSInfo, + const std::vector& dataPerSample, + const tcu::ConstPixelBufferAccess& dataRS) const +{ + DE_UNREF(imageRSInfo); + DE_UNREF(dataRS); + + if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) + return tcu::TestStatus::fail("gl_SampleMaskIn bits have not been killed by pSampleMask state"); + + return tcu::TestStatus::pass("Passed"); +} + +class MSCaseSampleMaskPattern; + +template<> void MSCase::init (void) +{ + m_testCtx.getLog() + << tcu::TestLog::Message + << "Verifying gl_SampleMaskIn value with pSampleMask state. gl_SampleMaskIn does not contain any bits set that are have been killed by pSampleMask state. Expecting:\n" + << "Expected result: gl_SampleMaskIn AND ~(pSampleMask) should be zero.\n" + << tcu::TestLog::EndMessage; + + MultisampleCaseBase::init(); +} + +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const +{ + MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); + + // Create vertex shader + std::ostringstream vs; + + vs << "#version 440\n" + << "layout(location = 0) in vec4 vs_in_position_ndc;\n" + << "\n" + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = vs_in_position_ndc;\n" + << "}\n"; + + programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); + + // Create fragment shader + std::ostringstream fs; + + fs << "#version 440\n" + << "\n" + << "layout(location = 0) out vec4 fs_out_color;\n" + << "\n" + << "layout(set = 0, binding = 0, std140) uniform SampleMaskBlock\n" + << "{\n" + << " int sampleMaskPattern;\n" + << "};" + << "\n" + << "void main (void)\n" + << "{\n" + << " if ((gl_SampleMaskIn[0] & ~sampleMaskPattern) != 0)\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" + << " else\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" + << "}\n"; + + programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); +} + +template<> TestInstance* MSCase::createInstance (Context& context) const +{ + return new MSInstanceSampleMaskPattern(context, m_imageMSParams); +} + +class MSInstanceSampleMaskBitCount; + +template<> MultisampleInstanceBase::VertexDataDesc MSInstance::getVertexDataDescripton (void) const +{ + return getVertexDataDescriptonNdc(); +} + +template<> void MSInstance::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const +{ + uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); +} + +template<> tcu::TestStatus MSInstance::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, + const vk::VkImageCreateInfo& imageRSInfo, + const std::vector& dataPerSample, + const tcu::ConstPixelBufferAccess& dataRS) const +{ + DE_UNREF(imageRSInfo); + DE_UNREF(dataRS); + + if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) + return tcu::TestStatus::fail("gl_SampleMaskIn has more than one bit set for some shader invocations"); + + return tcu::TestStatus::pass("Passed"); +} + +class MSCaseSampleMaskBitCount; + +template<> void MSCase::init (void) +{ + m_testCtx.getLog() + << tcu::TestLog::Message + << "Verifying gl_SampleMaskIn.\n" + << " Fragment shader will be invoked numSamples times.\n" + << " => gl_SampleMaskIn should have only one bit set for each shader invocation.\n" + << tcu::TestLog::EndMessage; + + MultisampleCaseBase::init(); +} + +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const +{ + MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); + + // Create vertex shader + std::ostringstream vs; + + vs << "#version 440\n" + << "layout(location = 0) in vec4 vs_in_position_ndc;\n" + << "\n" + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = vs_in_position_ndc;\n" + << "}\n"; + + programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); + + // Create fragment shader + std::ostringstream fs; + + fs << "#version 440\n" + << "\n" + << "layout(location = 0) out vec4 fs_out_color;\n" + << "\n" + << "void main (void)\n" + << "{\n" + << " uint maskBitCount = 0u;\n" + << "\n" + << " for (int i = 0; i < 32; ++i)\n" + << " if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n" + << " ++maskBitCount;\n" + << "\n" + << " if (maskBitCount != 1u)\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" + << " else\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" + << "}\n"; + + programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); +} + +template<> TestInstance* MSCase::createInstance (Context& context) const +{ + return new MSInstance(context, m_imageMSParams); +} + +class MSInstanceSampleMaskCorrectBit; + +template<> MultisampleInstanceBase::VertexDataDesc MSInstance::getVertexDataDescripton (void) const +{ + return getVertexDataDescriptonNdc(); +} + +template<> void MSInstance::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const +{ + uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); +} + +template<> tcu::TestStatus MSInstance::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, + const vk::VkImageCreateInfo& imageRSInfo, + const std::vector& dataPerSample, + const tcu::ConstPixelBufferAccess& dataRS) const +{ + DE_UNREF(imageRSInfo); + DE_UNREF(dataRS); + + if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) + return tcu::TestStatus::fail("The bit corresponsing to current gl_SampleID is not set in gl_SampleMaskIn"); + + return tcu::TestStatus::pass("Passed"); +} + +class MSCaseSampleMaskCorrectBit; + +template<> void MSCase::init (void) +{ + m_testCtx.getLog() + << tcu::TestLog::Message + << "Verifying gl_SampleMaskIn.\n" + << " Fragment shader will be invoked numSamples times.\n" + << " => In each invocation gl_SampleMaskIn should have the bit set that corresponds to gl_SampleID.\n" + << tcu::TestLog::EndMessage; + + MultisampleCaseBase::init(); +} + +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const +{ + MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); + + // Create vertex shader + std::ostringstream vs; + + vs << "#version 440\n" + << "layout(location = 0) in vec4 vs_in_position_ndc;\n" + << "\n" + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = vs_in_position_ndc;\n" + << "}\n"; + + programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); + + // Create fragment shader + std::ostringstream fs; + + fs << "#version 440\n" + << "\n" + << "layout(location = 0) out vec4 fs_out_color;\n" + << "\n" + << "void main (void)\n" + << "{\n" + << " if (((gl_SampleMaskIn[0] >> gl_SampleID) & 0x01) == 0x01)\n" + << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" + << " else\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" + << "}\n"; + + programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); +} + +template<> TestInstance* MSCase::createInstance (Context& context) const +{ + return new MSInstance(context, m_imageMSParams); +} + +class MSInstanceSampleMaskWrite; + +template<> MultisampleInstanceBase::VertexDataDesc MSInstance::getVertexDataDescripton (void) const +{ + return getVertexDataDescriptonNdc(); +} + +template<> void MSInstance::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const +{ + uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); +} + +template<> tcu::TestStatus MSInstance::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, + const vk::VkImageCreateInfo& imageRSInfo, + const std::vector& dataPerSample, + const tcu::ConstPixelBufferAccess& dataRS) const +{ + const deUint32 numSamples = static_cast(imageMSInfo.samples); + + for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) + for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) + for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) + { + for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) + { + const deUint32 firstComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[0]; + + if (firstComponent != 0u && firstComponent != 255u) + return tcu::TestStatus::fail("Expected color to be zero or saturated on the first channel"); + } + } + + for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) + for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) + for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) + { + const float firstComponent = dataRS.getPixel(x, y, z)[0]; + + if (deFloatAbs(firstComponent - 0.5f) > 0.02f) + return tcu::TestStatus::fail("Expected resolve color to be half intensity on the first channel"); + } + + return tcu::TestStatus::pass("Passed"); +} + +class MSCaseSampleMaskWrite; + +template<> void MSCase::init (void) +{ + m_testCtx.getLog() + << tcu::TestLog::Message + << "Discarding half of the samples using gl_SampleMask." + << "Expecting half intensity on multisample targets (numSamples > 1)\n" + << tcu::TestLog::EndMessage; + + MultisampleCaseBase::init(); +} + +template<> void MSCase::initPrograms (vk::SourceCollections& programCollection) const +{ + MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); + + // Create vertex shader + std::ostringstream vs; + + vs << "#version 440\n" + << "layout(location = 0) in vec4 vs_in_position_ndc;\n" + << "\n" + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = vs_in_position_ndc;\n" + << "}\n"; + + programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); + + // Create fragment shader + std::ostringstream fs; + + fs << "#version 440\n" + << "\n" + << "layout(location = 0) out vec4 fs_out_color;\n" + << "\n" + << "void main (void)\n" + << "{\n" + << " gl_SampleMask[0] = 0xAAAAAAAA;\n" + << "\n" + << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" + << "}\n"; + + programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); +} + +template<> TestInstance* MSCase::createInstance (Context& context) const +{ + return new MSInstance(context, m_imageMSParams); +} + +} // multisample + +tcu::TestCaseGroup* createMultisampleShaderBuiltInTests (tcu::TestContext& testCtx) +{ + de::MovePtr testGroup(new tcu::TestCaseGroup(testCtx, "multisample_shader_builtin", "Multisample Shader BuiltIn Tests")); + + const tcu::UVec3 imageSizes[] = + { + tcu::UVec3(128u, 128u, 1u), + tcu::UVec3(137u, 191u, 1u), + }; + + const deUint32 sizesElemCount = static_cast(sizeof(imageSizes) / sizeof(tcu::UVec3)); + + const vk::VkSampleCountFlagBits samplesSetFull[] = + { + vk::VK_SAMPLE_COUNT_2_BIT, + vk::VK_SAMPLE_COUNT_4_BIT, + vk::VK_SAMPLE_COUNT_8_BIT, + vk::VK_SAMPLE_COUNT_16_BIT, + vk::VK_SAMPLE_COUNT_32_BIT, + vk::VK_SAMPLE_COUNT_64_BIT, + }; + + const deUint32 samplesSetFullCount = static_cast(sizeof(samplesSetFull) / sizeof(vk::VkSampleCountFlagBits)); + + testGroup->addChild(makeMSGroup >(testCtx, "sample_id", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount)); + + de::MovePtr samplePositionGroup(new tcu::TestCaseGroup(testCtx, "sample_position", "Sample Position Tests")); + + samplePositionGroup->addChild(makeMSGroup >(testCtx, "distribution", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount)); + samplePositionGroup->addChild(makeMSGroup > (testCtx, "correctness", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount)); + + testGroup->addChild(samplePositionGroup.release()); + + const vk::VkSampleCountFlagBits samplesSetReduced[] = + { + vk::VK_SAMPLE_COUNT_2_BIT, + vk::VK_SAMPLE_COUNT_4_BIT, + vk::VK_SAMPLE_COUNT_8_BIT, + vk::VK_SAMPLE_COUNT_16_BIT, + vk::VK_SAMPLE_COUNT_32_BIT, + }; + + const deUint32 samplesSetReducedCount = static_cast(sizeof(samplesSetReduced) / sizeof(vk::VkSampleCountFlagBits)); + + de::MovePtr sampleMaskGroup(new tcu::TestCaseGroup(testCtx, "sample_mask", "Sample Mask Tests")); + + sampleMaskGroup->addChild(makeMSGroup > (testCtx, "pattern", imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); + sampleMaskGroup->addChild(makeMSGroup > (testCtx, "bit_count", imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); + sampleMaskGroup->addChild(makeMSGroup >(testCtx, "correct_bit",imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); + sampleMaskGroup->addChild(makeMSGroup > (testCtx, "write", imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); + + testGroup->addChild(sampleMaskGroup.release()); + + return testGroup.release(); +} + +} // pipeline +} // vkt diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.hpp new file mode 100644 index 0000000..607c7d9e --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleShaderBuiltInTests.hpp @@ -0,0 +1,38 @@ +#ifndef _VKTPIPELINEMULTISAMPLESHADERBUILTINTESTS_HPP +#define _VKTPIPELINEMULTISAMPLESHADERBUILTINTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * 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 vktPipelineMultisampleShaderBuiltInTests.hpp + * \brief Multisample Shader BuiltIn Tests + *//*--------------------------------------------------------------------*/ + +#include "vktTestCase.hpp" + +namespace vkt +{ +namespace pipeline +{ + +tcu::TestCaseGroup* createMultisampleShaderBuiltInTests (tcu::TestContext& testCtx); + +} // pipeline +} // vkt + +#endif // _VKTPIPELINEMULTISAMPLESHADERBUILTINTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTestsUtil.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTestsUtil.cpp index f1493e2..792873d 100644 --- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTestsUtil.cpp +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTestsUtil.cpp @@ -371,19 +371,19 @@ deUint32 getImageMaxMipLevels (const VkImageFormatProperties& imageFormatPropert return std::min(static_cast(deFloatLog2(static_cast(widestEdge))) + 1u, imageFormatProperties.maxMipLevels); } -deUint32 getImageMipLevelSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel) +deUint32 getImageMipLevelSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel, const deUint32 numSamples) { const VkExtent3D extents = mipLevelExtents(baseExtents, mipmapLevel); - return extents.width * extents.height * extents.depth * layersCount * tcu::getPixelSize(format); + return extents.width * extents.height * extents.depth * layersCount * numSamples * tcu::getPixelSize(format); } -deUint32 getImageSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount) +deUint32 getImageSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount, const deUint32 numSamples) { deUint32 imageSizeInBytes = 0; for (deUint32 mipmapLevel = 0; mipmapLevel < mipmapLevelsCount; ++mipmapLevel) { - imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, format, mipmapLevel); + imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, format, mipmapLevel, numSamples); } return imageSizeInBytes; diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTestsUtil.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTestsUtil.hpp index 03e721e..97a5248 100644 --- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTestsUtil.hpp +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTestsUtil.hpp @@ -75,8 +75,8 @@ deUint32 getDimensions (const ImageType imageType); deUint32 getLayerDimensions (const ImageType imageType); vk::VkExtent3D mipLevelExtents (const vk::VkExtent3D& baseExtents, const deUint32 mipLevel); tcu::UVec3 mipLevelExtents (const tcu::UVec3& baseExtents, const deUint32 mipLevel); -deUint32 getImageMipLevelSizeInBytes (const vk::VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel); -deUint32 getImageSizeInBytes (const vk::VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount = 1u); +deUint32 getImageMipLevelSizeInBytes (const vk::VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel, const deUint32 numSamples = 1u); +deUint32 getImageSizeInBytes (const vk::VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount = 1u, const deUint32 numSamples = 1u); deUint32 getImageMaxMipLevels (const vk::VkImageFormatProperties& imageFormatProperties, const vk::VkExtent3D& extent); enum FeatureFlagBits diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp index 1cb900a..148f197 100644 --- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp @@ -34,6 +34,7 @@ #include "vktPipelineSpecConstantTests.hpp" #include "vktPipelineMultisampleTests.hpp" #include "vktPipelineMultisampleInterpolationTests.hpp" +#include "vktPipelineMultisampleShaderBuiltInTests.hpp" #include "vktPipelineVertexInputTests.hpp" #include "vktPipelineTimestampTests.hpp" #include "vktPipelineCacheTests.hpp" @@ -62,6 +63,7 @@ void createChildren (tcu::TestCaseGroup* pipelineTests) pipelineTests->addChild(createSpecConstantTests (testCtx)); pipelineTests->addChild(createMultisampleTests (testCtx)); pipelineTests->addChild(createMultisampleInterpolationTests (testCtx)); + pipelineTests->addChild(createMultisampleShaderBuiltInTests (testCtx)); pipelineTests->addChild(createVertexInputTests (testCtx)); pipelineTests->addChild(createInputAssemblyTests (testCtx)); pipelineTests->addChild(createTimestampTests (testCtx)); diff --git a/external/vulkancts/mustpass/1.0.2/vk-default.txt b/external/vulkancts/mustpass/1.0.2/vk-default.txt index 08642d9..ae00cda 100644 --- a/external/vulkancts/mustpass/1.0.2/vk-default.txt +++ b/external/vulkancts/mustpass/1.0.2/vk-default.txt @@ -87189,6 +87189,82 @@ dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_16 dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_32 dEQP-VK.pipeline.multisample_interpolation.offset_interpolate_at_sample_position.137_191_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.128_128_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_id.137_191_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.128_128_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.distribution.137_191_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.128_128_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_position.correctness.137_191_1.samples_64 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.bit_count.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.correct_bit.137_191_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.128_128_1.samples_32 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_2 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_4 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_8 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_16 +dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.write.137_191_1.samples_32 dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_unorm_rate_vertex dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_unorm_rate_instance dEQP-VK.pipeline.vertex_input.single_attribute.float_as_r8_snorm_rate_vertex -- 2.7.4